hyper-html-api 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -0
- package/conformance/MANIFEST.json +2 -2
- package/conformance/cases/no-data-list-skipped.expected.json +6 -0
- package/conformance/cases/no-data-list-skipped.html +1 -0
- package/conformance/cases/no-data-list-skipped.meta +4 -0
- package/conformance/cases/no-data-list-skipped.parsed.json +3 -0
- package/conformance/cases/no-data-list-skipped.rules +1 -0
- package/conformance/cases/no-data-text-projected.expected.json +3 -0
- package/conformance/cases/no-data-text-projected.html +1 -0
- package/conformance/cases/no-data-text-projected.meta +4 -0
- package/conformance/cases/no-data-text-projected.parsed.json +3 -0
- package/conformance/cases/no-data-text-projected.rules +1 -0
- package/conformance/cases/props-type-is-attribute.expected.json +5 -0
- package/conformance/cases/props-type-is-attribute.meta +4 -0
- package/conformance/cases/write-attr-app-scheme.after.html +1 -0
- package/conformance/cases/write-attr-app-scheme.after.json +3 -0
- package/conformance/cases/write-attr-app-scheme.data.json +1 -0
- package/conformance/cases/write-attr-app-scheme.html +1 -0
- package/conformance/cases/write-attr-app-scheme.meta +4 -0
- package/conformance/cases/write-attr-app-scheme.write.json +4 -0
- package/conformance/cases/write-attr-href.after.html +1 -0
- package/conformance/cases/write-attr-href.after.json +3 -0
- package/conformance/cases/write-attr-href.data.json +1 -0
- package/conformance/cases/write-attr-href.html +1 -0
- package/conformance/cases/write-attr-href.meta +4 -0
- package/conformance/cases/write-attr-href.write.json +4 -0
- package/conformance/cases/write-checked-false.after.html +1 -0
- package/conformance/cases/write-checked-false.after.json +3 -0
- package/conformance/cases/write-checked-false.data.json +1 -0
- package/conformance/cases/write-checked-false.html +1 -0
- package/conformance/cases/write-checked-false.meta +4 -0
- package/conformance/cases/write-checked-false.write.json +4 -0
- package/conformance/cases/write-checked-true.after.html +1 -0
- package/conformance/cases/write-checked-true.after.json +3 -0
- package/conformance/cases/write-checked-true.data.json +1 -0
- package/conformance/cases/write-checked-true.html +1 -0
- package/conformance/cases/write-checked-true.meta +4 -0
- package/conformance/cases/write-checked-true.write.json +4 -0
- package/conformance/cases/write-crlf-multi.after.html +12 -0
- package/conformance/cases/write-crlf-multi.after.json +8 -0
- package/conformance/cases/write-crlf-multi.data.json +1 -0
- package/conformance/cases/write-crlf-multi.html +12 -0
- package/conformance/cases/write-crlf-multi.meta +4 -0
- package/conformance/cases/write-crlf-multi.write.json +4 -0
- package/conformance/cases/write-fallback-implied.after.html +1 -0
- package/conformance/cases/write-fallback-implied.after.json +3 -0
- package/conformance/cases/write-fallback-implied.data.json +1 -0
- package/conformance/cases/write-fallback-implied.html +1 -0
- package/conformance/cases/write-fallback-implied.meta +4 -0
- package/conformance/cases/write-fallback-implied.write.json +4 -0
- package/conformance/cases/write-flatten.after.html +1 -0
- package/conformance/cases/write-flatten.after.json +3 -0
- package/conformance/cases/write-flatten.data.json +1 -0
- package/conformance/cases/write-flatten.html +1 -0
- package/conformance/cases/write-flatten.meta +4 -0
- package/conformance/cases/write-flatten.write.json +4 -0
- package/conformance/cases/write-list-empty-no-seed.data.json +1 -0
- package/conformance/cases/write-list-empty-no-seed.error.json +8 -0
- package/conformance/cases/write-list-empty-no-seed.html +1 -0
- package/conformance/cases/write-list-empty-no-seed.meta +4 -0
- package/conformance/cases/write-list-grow-from-template.after.html +1 -0
- package/conformance/cases/write-list-grow-from-template.after.json +5 -0
- package/conformance/cases/write-list-grow-from-template.data.json +1 -0
- package/conformance/cases/write-list-grow-from-template.html +1 -0
- package/conformance/cases/write-list-grow-from-template.meta +4 -0
- package/conformance/cases/write-list-grow-from-template.write.json +4 -0
- package/conformance/cases/write-list-object-clone.after.html +1 -0
- package/conformance/cases/write-list-object-clone.after.json +12 -0
- package/conformance/cases/write-list-object-clone.data.json +1 -0
- package/conformance/cases/write-list-object-clone.html +1 -0
- package/conformance/cases/write-list-object-clone.meta +4 -0
- package/conformance/cases/write-list-object-clone.write.json +4 -0
- package/conformance/cases/write-list-scalar-grow.after.html +4 -0
- package/conformance/cases/write-list-scalar-grow.after.json +7 -0
- package/conformance/cases/write-list-scalar-grow.data.json +1 -0
- package/conformance/cases/write-list-scalar-grow.html +4 -0
- package/conformance/cases/write-list-scalar-grow.meta +4 -0
- package/conformance/cases/write-list-scalar-grow.write.json +4 -0
- package/conformance/cases/write-list-scalar-shrink.after.html +4 -0
- package/conformance/cases/write-list-scalar-shrink.after.json +5 -0
- package/conformance/cases/write-list-scalar-shrink.data.json +1 -0
- package/conformance/cases/write-list-scalar-shrink.html +4 -0
- package/conformance/cases/write-list-scalar-shrink.meta +4 -0
- package/conformance/cases/write-list-scalar-shrink.write.json +4 -0
- package/conformance/cases/write-list-shrink-zero.after.html +1 -0
- package/conformance/cases/write-list-shrink-zero.after.json +3 -0
- package/conformance/cases/write-list-shrink-zero.data.json +1 -0
- package/conformance/cases/write-list-shrink-zero.html +1 -0
- package/conformance/cases/write-list-shrink-zero.meta +4 -0
- package/conformance/cases/write-list-shrink-zero.write.json +4 -0
- package/conformance/cases/write-no-data-kept.after.html +1 -0
- package/conformance/cases/write-no-data-kept.after.json +3 -0
- package/conformance/cases/write-no-data-kept.data.json +1 -0
- package/conformance/cases/write-no-data-kept.html +1 -0
- package/conformance/cases/write-no-data-kept.meta +4 -0
- package/conformance/cases/write-no-data-kept.write.json +4 -0
- package/conformance/cases/write-no-rules-tag.data.json +1 -0
- package/conformance/cases/write-no-rules-tag.error.json +6 -0
- package/conformance/cases/write-no-rules-tag.html +1 -0
- package/conformance/cases/write-no-rules-tag.meta +4 -0
- package/conformance/cases/write-noop.after.html +3 -0
- package/conformance/cases/write-noop.after.json +3 -0
- package/conformance/cases/write-noop.data.json +1 -0
- package/conformance/cases/write-noop.html +3 -0
- package/conformance/cases/write-noop.meta +4 -0
- package/conformance/cases/write-noop.write.json +4 -0
- package/conformance/cases/write-outerhtml-unchanged.after.html +1 -0
- package/conformance/cases/write-outerhtml-unchanged.after.json +3 -0
- package/conformance/cases/write-outerhtml-unchanged.data.json +1 -0
- package/conformance/cases/write-outerhtml-unchanged.html +1 -0
- package/conformance/cases/write-outerhtml-unchanged.meta +4 -0
- package/conformance/cases/write-outerhtml-unchanged.write.json +4 -0
- package/conformance/cases/write-readonly-changed.data.json +1 -0
- package/conformance/cases/write-readonly-changed.error.json +6 -0
- package/conformance/cases/write-readonly-changed.html +1 -0
- package/conformance/cases/write-readonly-changed.meta +4 -0
- package/conformance/cases/write-readonly-unchanged.after.html +1 -0
- package/conformance/cases/write-readonly-unchanged.after.json +4 -0
- package/conformance/cases/write-readonly-unchanged.data.json +1 -0
- package/conformance/cases/write-readonly-unchanged.html +1 -0
- package/conformance/cases/write-readonly-unchanged.meta +4 -0
- package/conformance/cases/write-readonly-unchanged.write.json +4 -0
- package/conformance/cases/write-refused-animate.data.json +1 -0
- package/conformance/cases/write-refused-animate.error.json +11 -0
- package/conformance/cases/write-refused-animate.html +1 -0
- package/conformance/cases/write-refused-animate.meta +4 -0
- package/conformance/cases/write-refused-attr-name.data.json +1 -0
- package/conformance/cases/write-refused-attr-name.error.json +11 -0
- package/conformance/cases/write-refused-attr-name.html +1 -0
- package/conformance/cases/write-refused-attr-name.meta +4 -0
- package/conformance/cases/write-refused-data-url.data.json +1 -0
- package/conformance/cases/write-refused-data-url.error.json +11 -0
- package/conformance/cases/write-refused-data-url.html +1 -0
- package/conformance/cases/write-refused-data-url.meta +4 -0
- package/conformance/cases/write-refused-innerhtml.data.json +1 -0
- package/conformance/cases/write-refused-innerhtml.error.json +11 -0
- package/conformance/cases/write-refused-innerhtml.html +1 -0
- package/conformance/cases/write-refused-innerhtml.meta +4 -0
- package/conformance/cases/write-refused-javascript-url.data.json +1 -0
- package/conformance/cases/write-refused-javascript-url.error.json +11 -0
- package/conformance/cases/write-refused-javascript-url.html +1 -0
- package/conformance/cases/write-refused-javascript-url.meta +4 -0
- package/conformance/cases/write-refused-list-removes-rules-tag.data.json +1 -0
- package/conformance/cases/write-refused-list-removes-rules-tag.error.json +11 -0
- package/conformance/cases/write-refused-list-removes-rules-tag.html +1 -0
- package/conformance/cases/write-refused-list-removes-rules-tag.meta +4 -0
- package/conformance/cases/write-refused-multiple.data.json +1 -0
- package/conformance/cases/write-refused-multiple.error.json +15 -0
- package/conformance/cases/write-refused-multiple.html +1 -0
- package/conformance/cases/write-refused-multiple.meta +4 -0
- package/conformance/cases/write-refused-onclick.data.json +1 -0
- package/conformance/cases/write-refused-onclick.error.json +11 -0
- package/conformance/cases/write-refused-onclick.html +1 -0
- package/conformance/cases/write-refused-onclick.meta +4 -0
- package/conformance/cases/write-refused-rules-tag-ancestor.data.json +1 -0
- package/conformance/cases/write-refused-rules-tag-ancestor.error.json +11 -0
- package/conformance/cases/write-refused-rules-tag-ancestor.html +1 -0
- package/conformance/cases/write-refused-rules-tag-ancestor.meta +4 -0
- package/conformance/cases/write-refused-script.data.json +1 -0
- package/conformance/cases/write-refused-script.error.json +11 -0
- package/conformance/cases/write-refused-script.html +1 -0
- package/conformance/cases/write-refused-script.meta +4 -0
- package/conformance/cases/write-shape-mismatch.data.json +1 -0
- package/conformance/cases/write-shape-mismatch.error.json +12 -0
- package/conformance/cases/write-shape-mismatch.html +1 -0
- package/conformance/cases/write-shape-mismatch.meta +4 -0
- package/conformance/cases/write-text-basic.after.html +3 -0
- package/conformance/cases/write-text-basic.after.json +3 -0
- package/conformance/cases/write-text-basic.data.json +1 -0
- package/conformance/cases/write-text-basic.html +3 -0
- package/conformance/cases/write-text-basic.meta +4 -0
- package/conformance/cases/write-text-basic.write.json +4 -0
- package/conformance/cases/write-text-escape.after.html +1 -0
- package/conformance/cases/write-text-escape.after.json +3 -0
- package/conformance/cases/write-text-escape.data.json +1 -0
- package/conformance/cases/write-text-escape.html +1 -0
- package/conformance/cases/write-text-escape.meta +4 -0
- package/conformance/cases/write-text-escape.write.json +4 -0
- package/conformance/cases/write-text-null-clears.after.html +1 -0
- package/conformance/cases/write-text-null-clears.after.json +3 -0
- package/conformance/cases/write-text-null-clears.data.json +1 -0
- package/conformance/cases/write-text-null-clears.html +1 -0
- package/conformance/cases/write-text-null-clears.meta +4 -0
- package/conformance/cases/write-text-null-clears.write.json +4 -0
- package/conformance/cases/write-type-attribute.after.html +1 -0
- package/conformance/cases/write-type-attribute.after.json +3 -0
- package/conformance/cases/write-type-attribute.data.json +1 -0
- package/conformance/cases/write-type-attribute.html +1 -0
- package/conformance/cases/write-type-attribute.meta +4 -0
- package/conformance/cases/write-type-attribute.write.json +4 -0
- package/conformance/cases/write-unknown-key.data.json +1 -0
- package/conformance/cases/write-unknown-key.error.json +11 -0
- package/conformance/cases/write-unknown-key.html +3 -0
- package/conformance/cases/write-unknown-key.meta +4 -0
- package/conformance/cases/write-unmatched.data.json +1 -0
- package/conformance/cases/write-unmatched.error.json +14 -0
- package/conformance/cases/write-unmatched.html +1 -0
- package/conformance/cases/write-unmatched.meta +4 -0
- package/conformance/write-policy.json +78 -0
- package/dist/hyper-html-api.engine.min.js +1 -1
- package/dist/hyper-html-api.min.js +5 -4
- package/dist/hyper-html-api.upgrade.min.js +2 -2
- package/package.json +5 -3
- package/packed-contract.json +1 -0
- package/src/adapters/cheerio.js +109 -10
- package/src/adapters/dom.js +191 -0
- package/src/dom-api.js +17 -6
- package/src/engine/apply.js +16 -2
- package/src/engine/errors.js +25 -0
- package/src/engine/extract.js +3 -0
- package/src/engine/index.js +4 -1
- package/src/engine/splice.js +118 -0
- package/src/engine/write-plan.js +52 -0
- package/src/engine/write-policy.js +136 -0
- package/src/lib/content-dom.js +110 -0
- package/src/lib/region-capabilities.js +71 -0
- package/src/write.js +29 -0
- package/conformance/cases/props-type-is-node-type.expected.json +0 -5
- package/conformance/cases/props-type-is-node-type.meta +0 -11
- /package/conformance/cases/{props-type-is-node-type.html → props-type-is-attribute.html} +0 -0
- /package/conformance/cases/{props-type-is-node-type.parsed.json → props-type-is-attribute.parsed.json} +0 -0
- /package/conformance/cases/{props-type-is-node-type.rules → props-type-is-attribute.rules} +0 -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 re=Object.defineProperty;var Xe=Object.getOwnPropertyDescriptor;var Ge=Object.getOwnPropertyNames;var Ze=Object.prototype.hasOwnProperty;var Ee=(e,t)=>{for(var r in t)re(e,r,{get:t[r],enumerable:!0})},Qe=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Ge(t))!Ze.call(e,n)&&n!==r&&re(e,n,{get:()=>t[n],enumerable:!(o=Xe(t,n))||o.enumerable});return e};var et=e=>Qe(re({},"__esModule",{value:!0}),e);var jt={};Ee(jt,{default:()=>Nt,engine:()=>ye,upgrade:()=>Je});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),Ae=new Set(["textContent","innerText","innerHTML","value","checked","selected","disabled","readOnly","type","id","className","title"]),oe=new Set(["tagName","nodeName","nodeType","nodeValue","childElementCount","classList","baseURI","documentURI","contentType","offsetWidth","offsetHeight","clientWidth","clientHeight","scrollWidth","scrollHeight","currentSrc","duration","paused","dataset"]);var X={};Ee(X,{EmptyListInsert:()=>U,MAX_RULE_DEPTH:()=>_,MaxRuleDepthExceeded:()=>I,NoRulesTag:()=>ie,RuleTargetReadOnly:()=>W,RulesParseError:()=>D,ShapeMismatch:()=>H,UnknownRulesVersion:()=>j,WriteRefused:()=>Y,WriteRejected:()=>se});var D=class extends Error{constructor(t,r){super(t),this.name="RulesParseError",this.cause=r}},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}},H=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}},W=class extends Error{constructor(t){super(`cannot write to read-only DOM property "${t}"`),this.name="RuleTargetReadOnly",this.target=t}},Y=class extends Error{constructor(t){super(`write refused: ${t.length} write(s) broke the content-only policy`),this.name="WriteRefused",this.refusals=t}},ie=class extends Error{constructor(t){super(`no <script data-rules-name~="${t}"> rules tag in this document`),this.name="NoRulesTag",this.token=t}},se=class extends Error{constructor(t,r){super(`write rejected: ${t.length} unknown key(s), ${r.length} rule(s) with no matching element`),this.name="WriteRejected",this.unknownKeys=t,this.unmatched=r}};function C(e){let t=0,r=null,o=-1;for(let n=0;n<e.length;n++){let i=e[n];i==="\\"?n++:r?i===r&&(r=null):i==='"'||i==="'"?r=i:i==="["||i==="("?t++:i==="]"||i===")"?t>0&&t--:i==="@"&&t===0&&(o=n)}return o}function ce(e){let t=C(e);return t===-1?{selector:e,prop:null}:{selector:e.slice(0,t),prop:e.slice(t+1)||null}}function M(e,t,r,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 le(e,t,r,{depth:0,path:[]},o)}function le(e,t,r,o,n){if(o.depth>_)throw new I(o.path);if(typeof r=="string")return tt(e,t,r,o,n);if(Array.isArray(r)){let[i,l]=r,s=e.find(t,i,n);return be(n,o,s),s.map((c,a)=>le(e,c,l,{depth:o.depth+1,path:[...o.path,a]},n))}if(typeof r=="object"&&r!==null){let i={};for(let[l,s]of Object.entries(r))i[l]=le(e,t,s,{depth:o.depth+1,path:[...o.path,l]},n);return i}return null}function tt(e,t,r,o,n){if(r.endsWith("[]")){let s=r.slice(0,-2),c=e.find(t,s,n);return be(n,o,c),c.map(a=>e.text(a))}if(r.startsWith("@"))return Oe(e,t,r.slice(1));let i=C(r);if(i!==-1){let s=r.slice(0,i),c=r.slice(i+1),a=s?e.find(t,s,n):[t];return a.length===0?null:Oe(e,a[0],c)}if(r===".")return e.text(t);let l=e.find(t,r,n);return l.length===0?null:e.text(l[0])}function be(e,t,r){if(typeof e.onRowsRead=="function")try{e.onRowsRead(t.path.slice(),r)}catch(o){console.warn(`[hyper-html-api] onRowsRead threw at "${t.path.join(".")||"(root)"}"`,o)}}function Oe(e,t,r){if(ne.has(r)){let n=e.prop(t,r);return n==null?null:String(n)}let o=e.attr(t,r);return o||null}function Ce(e,t,r,o){let n=e.length,i=t.length,l=new Array(n).fill(-1);if(o){let u=new Set;for(let p=0;p<n;p++){let g=o[p];!(g>=0&&g<i)||u.has(g)||(l[p]=g,u.add(g))}}if(n===0||i===0)return l;let s=e.map(u=>Se(u,r)),c=t.map(u=>Se(u,r)),a=new Array(i).fill(!1);for(let u of l)u>=0&&(a[u]=!0);let f=new Map;c.forEach((u,p)=>{a[p]||f.set(u,f.has(u)?-1:p)});let y=new Map;s.forEach((u,p)=>{l[p]>=0||y.set(u,(y.get(u)||0)+1)}),s.forEach((u,p)=>{if(l[p]>=0||y.get(u)!==1)return;let g=f.get(u);g===void 0||g===-1||a[g]||(l[p]=g,a[g]=!0)});let d=[];for(let u=0;u<n;u++)l[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 l;let h=n*i+1,m=(u,p)=>rt(e[u],t[p],r)*h+Math.abs(u-p);for(let[u,p]of nt(d,T,m))l[u]=p;return l}var Me=e=>typeof e=="object"&&e!==null;function Se(e,t){if(!Me(t))return e==null?" null":String(e);let r=Object.keys(t);return JSON.stringify(r.map(o=>{let n=JSON.stringify(e?.[o]);return n===void 0?" undef":n}))}function rt(e,t,r){if(!Me(r))return e===t?0:1;let o=Object.keys(r);if(o.length===0)return 0;let n=0;for(let i of o){let l=JSON.stringify(e?.[i]),s=JSON.stringify(t?.[i]);l!==s&&n++}return n}function nt(e,t,r){return e.length<=t.length?Re(e,t,r,!1):Re(t,e,(o,n)=>r(n,o),!0)}function Re(e,t,r,o){let n=e.length,i=t.length,l=[];for(let y=0;y<=n;y++)l.push(new Float64Array(i+1).fill(1/0));let s=[];for(let y=0;y<=n;y++)s.push(new Uint8Array(i+1));for(let y=0;y<=i;y++)l[n][y]=0;for(let y=n-1;y>=0;y--)for(let d=i-1;d>=0;d--){let T=r(e[y],t[d])+l[y+1][d+1],h=l[y][d+1];T<=h?(l[y][d]=T,s[y][d]=1):l[y][d]=h}let c=[],a=0,f=0;for(;a<n&&f<i;)s[a][f]&&(c.push(o?[t[f],e[a]]:[e[a],t[f]]),a++),f++;return c}function ue(e,t,r,o,n,i,l,s={}){let c=e.find(t,r,s);if(n.length===0){c.forEach(w=>e.remove(w)),fe(s,"onRowsApplied",i.path,[]);return}let a=n.length>c.length,f=c[0]||null;if(a&&!f&&(f=ct(e,t,r,s),!f))throw new U(i.path);let y=c.map(w=>st(e,w,o,s)),d=null;if(a&&f){d=e.clone(f),s.templateAttr&&e.removeAttr(d,s.templateAttr);let w=e.stripIds(d);w>0&&console.warn(`[hyper-html-api] stripped ${w} id attribute(s) from cloned template at "${i.path.join(".")||"(root)"}"`)}let T=Ce(n,y,o,ot(e,c,n,i,s)),h=c[0]||f,m=e.parent(h),u=c.length>0?Ne(e,m,h):0,p=lt(e,c),g=new Set,O=[],A=n.map((w,E)=>{let x=T[E];if(x>=0)return g.add(x),O.push(!1),c[x];O.push(!0);let R=e.clone(d);return e.stripIds(R),R});c.forEach((w,E)=>{g.has(E)||e.remove(w)}),p?A.forEach((w,E)=>{let x=u+E;e.children(m).findIndex(Ye=>e.sameNode(Ye,w))!==x&&e.insertAt(m,w,x)}):ft(e,A,O,m,u),it(e,A,o,n,i,l,s),fe(s,"onRowsApplied",i.path,A)}function fe(e,t,r,o){if(typeof e[t]=="function")try{return e[t](r.slice(),o)}catch(n){console.warn(`[hyper-html-api] ${t} threw at "${r.join(".")||"(root)"}"`,n);return}}function ot(e,t,r,o,n){let i=fe(n,"identifyRows",o.path,r);if(!Array.isArray(i))return null;let l=new Array(r.length).fill(-1),s=new Set;for(let c=0;c<r.length;c++)if(i[c]){for(let a=0;a<t.length;a++)if(!(s.has(a)||!e.sameNode(t[a],i[c]))){l[c]=a,s.add(a);break}}return l}function it(e,t,r,o,n,i,l){t.forEach((s,c)=>{if(r===null){let a=o[c],f=a==null?"":String(a);e.text(s)!==f&&e.text(s,f)}else{let a=i(e,s,r,o[c],{depth:n.depth+1,path:[...n.path,c]},l);a&&a!==s&&(t[c]=a)}})}function st(e,t,r,o){return r===null?e.text(t):M(e,t,r,o.onRowsRead?{...o,onRowsRead:void 0}:o)}function Ne(e,t,r){let o=e.children(t);for(let n=0;n<o.length;n++)if(e.sameNode(o[n],r))return n;return-1}function ct(e,t,r,o){if(!o.templateAttr)return null;let n=t;for(;n;){let i=e.find(n,r,{includeRulesTag:!1,templateAttr:null});for(let l of i)if(e.attr(l,o.templateAttr)!=null)return l;n=e.parent(n)}return null}function lt(e,t){if(t.length<=1)return!0;let r=e.parent(t[0]);if(!r)return!1;let o=e.children(r),n=[];for(let i of t){let l=o.findIndex(s=>e.sameNode(s,i));if(l===-1)return!1;n.push(l)}return n.sort((i,l)=>i-l),n[n.length-1]-n[0]===n.length-1}function ft(e,t,r,o,n){let i=null,l=n;for(let s=0;s<t.length;s++){if(!r[s]){i=t[s];continue}let c=i?e.parent(i):o;if(!c)continue;let a=i?Ne(e,c,i)+1:l++;e.insertAt(c,t[s],a),i=t[s]}}var je=new Set(["checked","selected","disabled","readOnly","paused"]);function L(e,t,r,o,n={}){if(Object.prototype.hasOwnProperty.call(n,"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(ae(r,o,[],i),i.length)throw new H(i);G(e,t,r,o,{depth:0,path:[]},n)}function G(e,t,r,o,n,i={}){if(n.depth>_)throw new I(n.path);if(o===void 0)return t;if(typeof r=="string")return ut(e,t,r,o,n,i);if(Array.isArray(r)){let[l,s]=r;return ue(e,t,l,s,o,n,G,i),t}if(typeof r=="object"&&r!==null){for(let[l,s]of Object.entries(r)){let c=G(e,t,s,o==null?o:o[l],{depth:n.depth+1,path:[...n.path,l]},i);c&&c!==t&&(t=c)}return t}return t}function ut(e,t,r,o,n,i){if(r.endsWith("[]")){let c=r.slice(0,-2);return ue(e,t,c,null,o,n,G,i),t}if(r.startsWith("@"))return Le(e,t,r.slice(1),o);let l=C(r);if(l!==-1){let c=r.slice(0,l),a=r.slice(l+1),f=c?e.find(t,c,i):[t];return f.length===0||Le(e,f[0],a,o),t}if(r===".")return Ie(e,t,o),t;let s=e.find(t,r,i);return s.length===0||Ie(e,s[0],o),t}function Ie(e,t,r){let o=r==null?"":String(r);e.text(t)!==o&&e.text(t,o)}function Le(e,t,r,o){if(oe.has(r)){let i=e.prop(t,r);if(i===o||i!=null&&o!=null&&String(i)===String(o))return t;throw new W(r)}if(r==="outerHTML"){let i=o==null?"":String(o);return e.replaceWith(t,i)}if(Ae.has(r)){let i=at(r,o);return e.prop(t,r)!==i&&e.prop(t,r,i),t}let n=o==null?"":String(o);return e.attr(t,r)!==n&&e.attr(t,r,n),t}function at(e,t){return t==null?je.has(e)?!1:"":je.has(e)?t==="false"?!1:!!t:t}function ae(e,t,r,o){if(t!==void 0){if(typeof e=="string"){if(e.endsWith("[]")){Array.isArray(t)?t.forEach((n,i)=>{typeof n=="object"&&n!==null&&o.push({path:q([...r,i]),expected:"scalar",got:v(n)})}):o.push({path:q(r),expected:"array",got:v(t)});return}t!==null&&typeof t=="object"&&o.push({path:q(r),expected:"scalar",got:v(t)});return}if(Array.isArray(e)){if(!Array.isArray(t)){o.push({path:q(r),expected:"array",got:v(t)});return}let n=e[1];t.forEach((i,l)=>ae(n,i,[...r,l],o));return}if(typeof e=="object"&&e!==null){if(t===null||Array.isArray(t)||typeof t!="object"){o.push({path:q(r),expected:"object",got:v(t)});return}for(let[n,i]of Object.entries(e))ae(i,t[n],[...r,n],o)}}}function v(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function q(e){return e.join(".")}function de(e){try{return JSON.parse(e)}catch(t){throw new D(`Invalid strict JSON: ${t.message}`,t)}}function k(e){try{return JSON.parse(e)}catch{}let t={BRACE_OPEN:"{",BRACE_CLOSE:"}",BRACKET_OPEN:"[",BRACKET_CLOSE:"]",COLON:":",COMMA:",",STRING:"STRING",SELECTOR:"SELECTOR",IDENTIFIER:"IDENTIFIER",NUMBER:"NUMBER",BOOLEAN:"BOOLEAN"};function r(n){let i=[],l=0;for(;l<n.length;){let s=n[l];if(/\s/.test(s)){l++;continue}if("{}".includes(s)){i.push({type:s,value:s}),l++;continue}if(s==="["){let y=!1,d=l+1;for(;d<n.length&&/\s/.test(n[d]);)d++;if(d<n.length&&/[a-zA-Z_]/.test(n[d])&&(y=!0),!y){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 y=s,d=l+1;for(;d<n.length&&n[d]!==y;)n[d]==="\\"&&d++,d++;i.push({type:t.STRING,value:n.substring(l+1,d),quoted:!0,sourceQuote:y}),l=d+1;continue}let c=l,a;for(;c<n.length&&!/[{},]/.test(n[c]);)if(n[c]===":"){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(n.substring(c+1,c+1+h.length)===h){d=!0,c+=h.length;break}}if(!d)break}else if(n[c]==="["){for(c++;c<n.length&&n[c]!=="]";){if(n[c]==='"'||n[c]==="'"){let y=n[c];for(c++;c<n.length&&n[c]!==y;)n[c]==="\\"&&c++,c++}c++}c<n.length&&n[c]==="]"&&c++}else c++;a=n.substring(l,c);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}),l=c}return i}function o(n){let i="";for(let l=0;l<n.length;l++){let s=n[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=n[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,(a,f)=>f.length%2===0?f+'\\"':a)),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 n=r(e),i=o(n);return JSON.parse(i)}catch(n){throw new D("Invalid extraction rules syntax: "+n.message,n)}}var pe="1",ke=/^[a-zA-Z0-9_-]+$/;function B(e,t,r){let o;if(r===void 0)o="script[data-rules-name]";else{if(typeof r!="string"||!ke.test(r))throw new Error(`hyper-html-api: invalid rules token ${JSON.stringify(r)} (must match ${ke})`);o=`script[data-rules-name~="${r}"]`}let n=e.find(t,o,{includeRulesTag:!0});if(n.length===0)return null;r!==void 0&&n.length>1&&console.warn(`hyper-html-api: ${n.length} rules tags match data-rules-name~="${r}"; using the first.`);let i=n[0],l=e.attr(i,"data-rules-version");if(l!==pe)throw new j(l);return{rules:k(e.text(i)),tagNode:i}}var Pe=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"]})}),dt=Object.freeze({"editor-ui":Object.freeze(["no-data","no-save","no-snapshot","no-watch","no-undo"])}),De=Object.freeze(["no-save","no-snapshot","no-trigger-autosave","no-dirty","no-watch","no-undo","no-data","freeze","editor-ui"]);function he(e,t){if(!e||e.nodeType!==1)return!1;let r=e.getAttribute?.("clay");return!!(r&&r.split(/\s+/).includes(t)||e.hasAttribute?.(t))}function pt(e,t){if(he(e,t))return!0;for(let[r,o]of Object.entries(dt))if(o.includes(t)&&he(e,r))return!0;return!1}function z(e){let t=Pe[e];if(!t)throw new Error(`Unknown region capability: ${e}`);return[...t.tokens,...t.bundles].flatMap(r=>[`[clay~="${r}"]`,`[${r}]`]).join(", ")}function ht(e,t){let r=e&&e.nodeType===1?e:e?.parentElement;for(;r&&r.nodeType===1;){let o=Pe[t];if(!o)throw new Error(`Unknown region capability: ${t}`);if(o.tokens.some(n=>pt(r,n))||o.bundles.some(n=>he(r,n)))return r;r=r.parentElement}return null}function _e(e,t){return!!ht(e,t)}var mt=Object.freeze({refusedRuleForms:["innerHTML","outerHTML"],refusedTargets:["script","style","template","noscript","iframe","object","embed","xmp","plaintext","noembed","noframes","meta","link","base","animate","set","animatemotion","animatetransform"],refusedAttributes:["style","srcdoc","is","http-equiv","sandbox","allow","nonce","integrity","charset","htmlclaytoken","htmlclayid","data-rules-name","data-rules-version","clay","contenteditable",...De],refusedAttributePrefixes:["on"],urlAttributes:["href","src","srcset","action","formaction","poster","cite","data","ping","background","longdesc","usemap","xlink:href","manifest","codebase","icon"],refusedSchemes:["javascript","vbscript","data"]});function me(e,t,r){if(r&&typeof r=="object")return{rules:r,tagNode:null};if(typeof r=="string"){let o=t&&t.ownerDocument?t.ownerDocument:t;return B(e,o,r)}return null}var gt=/:(?:focus(?:-within|-visible)?|hover|active|visited|defined)\b/i;function $e(e,t){if(!/^(INPUT|TEXTAREA|SELECT|OPTION)$/.test(e.tagName||""))return;let r=(e.getAttribute?.("type")||"").toLowerCase();if("value"in e&&"value"in t&&e.tagName!=="OPTION"&&r!=="checkbox"&&r!=="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 He(e,t,r,o){if(o)return!!e.closest?.(t);let n=e;for(;n?.nodeType===1;){if(n.matches(t))return!0;if(n===r)break;n=n.parentElement}return!1}function Ue(e,t,r,o,n,i,l,s){if(e.nodeType===1&&((l?_e(e,r):He(e,o,i,!1))||n&&He(e,n,i,l)))return null;let c=t.importNode(e,!1);s.cloneToLive.set(c,e),s.liveToClone.set(e,c);let a=e.nodeType===1&&e.tagName==="TEMPLATE"?e.content:e,f=c.nodeType===1&&c.tagName==="TEMPLATE"?c.content:c;a!==e&&(s.cloneToLive.set(f,a),s.liveToClone.set(a,f));for(let y of a.childNodes||[]){let d=Ue(y,t,r,o,n,i,l,s);d&&(f.appendChild(d),y.nodeType===1&&$e(y,d))}return e.nodeType===1&&$e(e,c),c}function F(e,{capability:t="data",exclude:r=null,inherit:o=!0}={}){if(!e)throw new TypeError("createContentView requires a DOM context");let n=e.nodeType===9?e:e.ownerDocument;if(!n?.implementation?.createHTMLDocument)throw new TypeError("createContentView requires an HTML DOM implementation");let i=n.implementation.createHTMLDocument(""),l=new WeakMap,s=new WeakMap,c=e.nodeType===9?e.documentElement:e;r&&i.documentElement.matches(r);let a=z(t),f=Ue(c,i,t,a,r,c,o,{cloneToLive:l,liveToClone:s});e.nodeType===9&&f&&(i.replaceChild(f,i.documentElement),s.set(e,i),l.set(i,e));let y=d=>{if(gt.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:l,liveToClone:s,original(d){return l.get(d)||null},cloneOf(d){return s.get(d)||null},query(d,T=f){return y(d),Array.from(T.querySelectorAll(d),h=>l.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 We(e){return e&&e.nodeType===1&&e.tagName==="SCRIPT"&&e.hasAttribute&&e.hasAttribute("data-rules-name")}function wt(e){return e?(e.nodeType===9||e.nodeType===11,e):null}var b={semanticExclude:!0,find(e,t,r={}){let o=wt(e);if(!o||!o.querySelectorAll)return[];let n=Array.from(o.querySelectorAll(t));r.includeRulesTag||(n=n.filter(s=>!We(s)));let i=[];r.skip&&i.push(r.skip);let l=r.templateAttr===null?null:r.templateAttr||"cms-template";if(l&&i.push("["+l+"]"),i.length){let s=i.join(", ");n=n.filter(c=>!c.closest||!c.closest(s))}return n},parent(e){return e?e.parentElement:null},children(e){return e?Array.from(e.children):[]},text(e,t){if(t===void 0)return(e.textContent||"").trim();e.textContent=t},attr(e,t,r){if(r===void 0)return e.hasAttribute&&e.hasAttribute(t)?e.getAttribute(t):null;e.setAttribute(t,r)},removeAttr(e,t){e&&e.removeAttribute&&e.removeAttribute(t)},prop(e,t,r){if(r===void 0){let o=e?e[t]:void 0;return o!==void 0?o:null}e[t]=r},clone(e){return e.cloneNode(!0)},insertAt(e,t,r){let o=e.children[r]||null;e.insertBefore(t,o)},remove(e){e&&e.parentNode&&e.parentNode.removeChild(e)},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 n=o.content.firstElementChild;if(!n)throw new Error("dom.replaceWith: html did not parse to an element");return e.parentNode.replaceChild(n,e),n},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 r=[z("data"),t.exclude].filter(Boolean).join(", "),o=e.nodeType===9?e:e.ownerDocument||e,n=e.nodeType===9?e.documentElement:e;if(!t._write&&!n?.matches?.(r)&&!n?.querySelector?.(r)&&!o?.querySelector?.(r))return b;let i=e.nodeType===9||!e.isConnected?e:e.ownerDocument,l=e.nodeType===9?e:e.ownerDocument,s=null,c=()=>s||(s=F(i,{capability:"data",exclude:t.exclude||null})),a=h=>{let m=c();return h===e?m.cloneOf(e):m.cloneOf(h)||h},f=h=>s?.original(h)||h,y=(h,m)=>{c().liveToClone.set(h,m),c().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(x=>s.cloneOf(x)),A=g[0];for(;A&&g.includes(A);)A=A.nextSibling;for(let x of g)x.remove();if(u==="innerHTML"){let x=l.createElement("template");x.innerHTML=p;for(let R of Array.from(x.content.childNodes))h.insertBefore(R,A||null)}else h.insertBefore(l.createTextNode(p),A||null);let w=F(h,{capability:"data",exclude:t.exclude||null});m.replaceChildren(...Array.from(w.root?.childNodes||[]));let E=x=>{let R=w.original(x);R&&(s.liveToClone.set(R,x),s.cloneToLive.set(x,R));for(let Te of Array.from(x.childNodes||[]))E(Te)};for(let x of Array.from(m.childNodes))E(x)},T={...b,find(h,m,u={}){let p=a(h);if(!p?.querySelectorAll)return[];let g=c().query(m,p);u.includeRulesTag||(g=g.filter(w=>!We(w)));let O=[];u.skip&&O.push(u.skip);let A=u.templateAttr===null?null:u.templateAttr||"cms-template";if(A&&O.push(`[${A}]`),O.length){let w=O.join(", ");g=g.filter(E=>!E.closest?.(w))}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?.(r)&&!g?.querySelector?.(r)?b.text(g):(a(h)?.textContent||"").trim()}let u=f(h);if(!u?.matches?.(r)&&!u?.querySelector?.(r)&&!s){b.text(u,m);return}let p=c().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",O=g?c().cloneOf(p):s?.cloneOf(p);O&&g?d(p,O,m,u):(b.prop(p,m,u),O&&b.prop(O,m,u))},clone(h){let m=a(h);return m===h?b.clone(h):l.importNode(m,!0)},insertAt(h,m,u){let p=f(h),O=T.children(p)[u]||(()=>{for(let E=p.children.length-1;E>=0;E--){let x=p.children[E];if(c().cloneOf(x))return x.nextElementSibling}return p.firstElementChild})(),A=f(m);p.insertBefore(A,O||null);let w=c().cloneOf(p);if(w){let E=c().cloneOf(A);E||(E=l.importNode(A,!0),y(A,E));let x=Array.from(w.children);w.insertBefore(E,x[u]||null)}},remove(h){let m=f(h),u=c().cloneOf(m);b.remove(m),u&&b.remove(u)},replaceWith(h,m){let u=f(h),p=c().cloneOf(u),g=b.replaceWith(u,m);if(p){let O=F(g,{capability:"data",exclude:t.exclude||null});if(!O.root)p.remove();else{p.replaceWith(O.root);let A=w=>{let E=O.original(w);E&&(s.liveToClone.set(E,w),s.cloneToLive.set(w,E));for(let x of Array.from(w.childNodes||[]))A(x)};A(O.root)}}return g}};return T}var S=b;var ye={extract:(e,t,r={})=>M(K(e,r),e,t,r),apply:(e,t,r,o={})=>L(K(e,{...o,_write:!0}),e,t,r,o),findRulesIn:(e,t)=>B(S,e,t),findRules:(e,t)=>me(S,e,t),bind:(e,t,r={})=>{let o=me(S,e,t);if(!o){let n=typeof t=="string"?`data-rules-name~="${t}"`:"the provided rules object";throw new Error(`hyper-html-api: could not resolve rules for ${n}`)}return{...o,get:()=>M(K(e,r),e,o.rules,r),set:n=>L(K(e,{...r,_write:!0}),e,o.rules,n,r)}},parseStrict:de,parseRelaxed:k,ruleAttrIndex:C,splitRule:ce,errors:X,DOM_PROPERTIES:J};var xt="hha:upgrade-check:";function N(e,t){let r=e.querySelector(`meta[name="${t}"]`),o=r?r.getAttribute("content"):null;return o&&o.trim()?o.trim():null}function ve(e){if(typeof e!="string")return null;let t=e.trim().replace(/^v/,"");return/^\d+(\.\d+)*$/.test(t)?t.split(".").map(Number):null}function Tt(e,t){let r=ve(e),o=ve(t);if(!r||!o)return!1;let n=Math.max(r.length,o.length);for(let i=0;i<n;i++){let l=r[i]||0,s=o[i]||0;if(l!==s)return l>s}return!1}function Et(e){try{let t=globalThis.localStorage.getItem(e);return t?JSON.parse(t):null}catch{return null}}function At(e,t){try{globalThis.localStorage.setItem(e,JSON.stringify(t))}catch{}}async function qe({force:e=!1,doc:t,loc:r,fetchFn:o,now:n,ttlMs:i=864e5}={}){if(t=t||(typeof document<"u"?document:null),r=r||(typeof location<"u"?location:null),o=o||(d=>fetch(d)),n=n??Date.now(),!t)return null;let l=N(t,"hyper-source");if(!l)return null;let s=N(t,"hyper-version"),c;try{c=new URL(l,r?r.href:void 0)}catch{return null}if(r&&c.origin===r.origin&&c.pathname===r.pathname)return null;let a=`${xt}${c.href}:${s||"none"}`,f,y=e?null:Et(a);if(y&&typeof y.checkedAt=="number"&&n-y.checkedAt<i)f=y.sourceVersion;else{try{let d=await o(c.href);if(!d.ok)throw new Error(`HTTP ${d.status}`);let T=await d.text(),h=new DOMParser().parseFromString(T,"text/html");f=N(h,"hyper-version")}catch{f=null}At(a,{checkedAt:n,sourceVersion:f})}return f?{available:Tt(f,s||"0.0.0"),currentVersion:s,sourceVersion:f,sourceUrl:c.href}:null}var Ot="script[data-rules-name]";function bt(e){return typeof e=="string"?e.trim().replace(/\s+/g," "):""}function Z(e,t){let r=e.find(t,Ot,{includeRulesTag:!0}),o=new Set,n=[];for(let i of r){let l=bt(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!==pe)throw new j(s);o.add(l),n.push({name:l,rules:k(e.text(i))})}return n}function ge(e,t){let r={};for(let{name:o,rules:n}of Z(e,t))r[o]=M(e,t,n);return r}function Be(e){let t=e||document,r=t.nodeType===9?t:t.ownerDocument||t;return{dataByName:ge(S,t),version:N(r,"hyper-version")}}var V=class extends Error{constructor(t,r){super(`could not fetch upgrade source: ${t}`),this.name="UpgradeSourceUnreachable",this.sourceUrl=t,this.cause=r}},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}},P=class extends Error{constructor(t,r){super(t),this.name="UpgradeTransformInvalid",this.cause=r}},ee=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 St="text/hyper-upgrade";function ze(e,t){let r=e.find(t,`script[type="${St}"]`);if(r.length===0)return null;if(r.length>1)throw new ee(r.length);return e.text(r[0])||null}var Rt=new Function("url","return import(url)");async function Fe(e){let t=new Blob([e],{type:"text/javascript"}),r=URL.createObjectURL(t),o;try{o=await Rt(r)}catch(n){throw new P(`transform failed to load: ${n&&n.message?n.message:n}`,n)}finally{URL.revokeObjectURL(r)}if(typeof o.default!="function")throw new P("transform must `export default` a function");return o.default}function te(e,t){let r={carriedOver:0,discarded:0,listItems:0},o=we(t,e,r);return xe(t,e,r),{data:o,summary:r}}function we(e,t,r){if(typeof e=="string")return e.endsWith("[]")?Array.isArray(t)?(r.listItems+=t.length,r.carriedOver+=t.length,t):void 0:t==null||typeof t=="object"?void 0:(r.carriedOver++,t);if(Array.isArray(e)){let[,o]=e;return Array.isArray(t)?(r.listItems+=t.length,t.map(n=>we(o,n,r))):void 0}if(typeof e=="object"&&e!==null){let o={};for(let[n,i]of Object.entries(e)){let l=we(i,t?.[n],r);l!==void 0&&(o[n]=l)}return o}}function xe(e,t,r){if(t!=null){if(typeof e=="object"&&e!==null&&!Array.isArray(e)){if(typeof t!="object"||Array.isArray(t))return;let o=new Set(Object.keys(e));for(let n of Object.keys(t))o.has(n)?xe(e[n],t[n],r):r.discarded+=$(t[n]);return}if(Array.isArray(e)&&Array.isArray(t)){let o=e[1];t.forEach(n=>xe(o,n,r));return}typeof e=="string"&&!e.endsWith("[]")&&typeof t=="object"&&t!==null&&(r.discarded+=$(t))}}function $(e){return e==null?0:Array.isArray(e)?e.reduce((t,r)=>t+$(r),0):typeof e=="object"?Object.values(e).reduce((t,r)=>t+$(r),0):1}function Ke(e,t,r){let o=Z(e,t),n={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(r,s)){i[s]={carriedOver:0,discarded:0,listItems:0};continue}let{data:a,summary:f}=te(r[s],c);L(e,t,c,a),i[s]=f,n.carriedOver+=f.carriedOver,n.discarded+=f.discarded,n.listItems+=f.listItems}for(let s of Object.keys(r))l.has(s)||(n.discarded+=$(r[s]));return{totals:n,byName:i,rulesTagCount:o.length}}async function Ve({sourceUrl:e,dataByName:t,fromVersion:r,doc:o,loc:n,fetchFn:i}={}){if(o=o||(typeof document<"u"?document:null),n=n||(typeof location<"u"?location:null),i=i||(p=>fetch(p)),!o)throw new Error("upgrade.run requires a document context");if(e=e||N(o,"hyper-source"),!e)throw new Error("upgrade.run: no sourceUrl given and no hyper-source meta tag found");let l=new URL(e,n?n.href:void 0);r=r!==void 0?r:N(o,"hyper-version"),t=t||ge(S,o);let s;try{s=await i(l.href)}catch(p){throw new V(l.href,p)}if(!s.ok)throw new V(l.href,new Error(`HTTP ${s.status}`));let c=await s.text(),a=new DOMParser().parseFromString(c,"text/html"),f=N(a,"hyper-version"),y=t,d=!1,T=ze(S,a);if(T){let g=await(await Fe(T))(y,{fromVersion:r,toVersion:f});if(!g||typeof g!="object"||Array.isArray(g))throw new P("transform must return a plain object map of { rulesName: data }");y=g,d=!0}let{totals:h,byName:m,rulesTagCount:u}=Ke(S,a,y);if(u===0&&Object.keys(y).length>0)throw new Q(l.href);return{html:Ct(a),fromVersion:r,toVersion:f,summary:{transformApplied:d,totals:h,byName:m}}}function Ct(e){return`<!DOCTYPE ${e.doctype&&e.doctype.name?e.doctype.name:"html"}>
|
|
2
|
+
`+e.documentElement.outerHTML}var Je={checkForUpdate:qe,run:Ve,extractAll:Be,shapeMatch:te};var Mt={engine:ye,upgrade:Je},Nt=Mt;return et(jt);})();
|
package/package.json
CHANGED
|
@@ -9,13 +9,14 @@
|
|
|
9
9
|
"apply",
|
|
10
10
|
"CMS"
|
|
11
11
|
],
|
|
12
|
-
"version": "0.
|
|
12
|
+
"version": "0.9.0",
|
|
13
13
|
"homepage": "https://github.com/panphora/hyper-html-api",
|
|
14
14
|
"bugs": {
|
|
15
15
|
"url": "https://github.com/panphora/hyper-html-api/issues"
|
|
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",
|
|
@@ -32,7 +33,8 @@
|
|
|
32
33
|
"./cheerio": "./src/adapters/cheerio.js",
|
|
33
34
|
"./dom": "./src/adapters/dom.js",
|
|
34
35
|
"./data": "./src/data.js",
|
|
35
|
-
"./upgrade": "./src/upgrade.js"
|
|
36
|
+
"./upgrade": "./src/upgrade.js",
|
|
37
|
+
"./write": "./src/write.js"
|
|
36
38
|
},
|
|
37
39
|
"scripts": {
|
|
38
40
|
"build": "npx esbuild src/hyper-html-api.js --bundle --minify --format=iife --global-name=HyperHtmlApi --outfile=dist/hyper-html-api.min.js",
|
|
@@ -61,7 +63,7 @@
|
|
|
61
63
|
"url": "git+https://github.com/panphora/hyper-html-api.git"
|
|
62
64
|
},
|
|
63
65
|
"dependencies": {
|
|
64
|
-
"hyper-morph": "^0.
|
|
66
|
+
"hyper-morph": "^1.0.0"
|
|
65
67
|
},
|
|
66
68
|
"devDependencies": {
|
|
67
69
|
"@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","hyper-html-api/write"]}
|
package/src/adapters/cheerio.js
CHANGED
|
@@ -1,3 +1,64 @@
|
|
|
1
|
+
import { capabilitySelector } from '../lib/region-capabilities.js'
|
|
2
|
+
|
|
3
|
+
const NO_DATA = capabilitySelector('data')
|
|
4
|
+
const NO_DATA_TOKENS = ['no-data', 'editor-ui']
|
|
5
|
+
|
|
6
|
+
function isElement(node) {
|
|
7
|
+
const t = node && node[0] && node[0].type
|
|
8
|
+
return t === 'tag' || t === 'script' || t === 'style'
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// The same test as the NO_DATA selector, without running css-select once per sibling:
|
|
12
|
+
// children() and insertAt() call it for every row of a list, and .is() made list writes quadratic
|
|
13
|
+
// with a large constant.
|
|
14
|
+
export function isNoDataEl(el) {
|
|
15
|
+
const attribs = el && el.attribs
|
|
16
|
+
if (!attribs) return false
|
|
17
|
+
if (NO_DATA_TOKENS.some((t) => Object.prototype.hasOwnProperty.call(attribs, t))) return true
|
|
18
|
+
const clay = attribs.clay
|
|
19
|
+
return typeof clay === 'string' && clay.split(/[\t\n\f\r ]+/).some((t) => NO_DATA_TOKENS.includes(t))
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function isNoData(node) {
|
|
23
|
+
return isElement(node) && isNoDataEl(node[0])
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function hasNoData(node) {
|
|
27
|
+
return !!node && node.length > 0 && isElement(node) && (node.is(NO_DATA) || node.find(NO_DATA).length > 0)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function inNoData(node) {
|
|
31
|
+
return !!node && !!node.closest && node.closest(NO_DATA).length > 0
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function projectedClone(node) {
|
|
35
|
+
const copy = node.clone()
|
|
36
|
+
copy.find(NO_DATA).remove()
|
|
37
|
+
return copy
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function escapeText(value) {
|
|
41
|
+
return String(value).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Mirrors dom.js replaceProjectedContent: remove only the children that are
|
|
45
|
+
// not no-data, then insert the new content where the first removed child was,
|
|
46
|
+
// so no-data children stay where they are.
|
|
47
|
+
function replaceProjected(node, html) {
|
|
48
|
+
const contents = node.contents()
|
|
49
|
+
const all = []
|
|
50
|
+
for (let i = 0; i < contents.length; i++) all.push(contents.eq(i))
|
|
51
|
+
const included = all.filter((k) => !isNoData(k))
|
|
52
|
+
const includedSet = new Set(included.map((k) => k[0]))
|
|
53
|
+
let anchorIdx = included.length ? all.findIndex((k) => k[0] === included[0][0]) : -1
|
|
54
|
+
while (anchorIdx !== -1 && anchorIdx < all.length && includedSet.has(all[anchorIdx][0])) anchorIdx++
|
|
55
|
+
const anchor = anchorIdx === -1 || anchorIdx >= all.length ? null : all[anchorIdx]
|
|
56
|
+
for (const k of included) k.remove()
|
|
57
|
+
if (html === '') return
|
|
58
|
+
if (anchor) anchor.before(html)
|
|
59
|
+
else node.append(html)
|
|
60
|
+
}
|
|
61
|
+
|
|
1
62
|
function isRulesTag(node) {
|
|
2
63
|
if (!node || !node.attr) return false
|
|
3
64
|
const tag = node.prop ? node.prop('tagName') : ''
|
|
@@ -12,10 +73,15 @@ function toWrappers(cheerioSet) {
|
|
|
12
73
|
}
|
|
13
74
|
|
|
14
75
|
const cheerioAdapter = {
|
|
76
|
+
semanticExclude: false,
|
|
15
77
|
find(ctx, selector, opts = {}) {
|
|
78
|
+
if (Object.prototype.hasOwnProperty.call(opts, 'exclude')) {
|
|
79
|
+
throw new Error('Cheerio does not support semantic exclude queries; omit exclude or use the DOM adapter.')
|
|
80
|
+
}
|
|
16
81
|
if (!ctx || !ctx.find) return []
|
|
17
82
|
let matches = toWrappers(ctx.find(selector))
|
|
18
83
|
if (!opts.includeRulesTag) matches = matches.filter((n) => !isRulesTag(n))
|
|
84
|
+
matches = matches.filter((n) => !inNoData(n))
|
|
19
85
|
const skipParts = []
|
|
20
86
|
if (opts.skip) skipParts.push(opts.skip)
|
|
21
87
|
// The cms-template seed marker means "not data" for EVERY consumer, so skip
|
|
@@ -39,12 +105,25 @@ const cheerioAdapter = {
|
|
|
39
105
|
|
|
40
106
|
children(node) {
|
|
41
107
|
if (!node || !node.children) return []
|
|
42
|
-
|
|
108
|
+
const kids = node.children()
|
|
109
|
+
const out = []
|
|
110
|
+
for (let i = 0; i < kids.length; i++) {
|
|
111
|
+
if (!isNoDataEl(kids[i])) out.push(kids.eq(i))
|
|
112
|
+
}
|
|
113
|
+
return out
|
|
43
114
|
},
|
|
44
115
|
|
|
45
116
|
text(node, value) {
|
|
46
|
-
if (value === undefined)
|
|
47
|
-
|
|
117
|
+
if (value === undefined) {
|
|
118
|
+
if (!hasNoData(node)) return node.text().trim()
|
|
119
|
+
if (isNoData(node)) return ''
|
|
120
|
+
return projectedClone(node).text().trim()
|
|
121
|
+
}
|
|
122
|
+
if (!hasNoData(node)) {
|
|
123
|
+
node.text(value)
|
|
124
|
+
return
|
|
125
|
+
}
|
|
126
|
+
replaceProjected(node, escapeText(value))
|
|
48
127
|
},
|
|
49
128
|
|
|
50
129
|
attr(node, name, value) {
|
|
@@ -64,12 +143,22 @@ const cheerioAdapter = {
|
|
|
64
143
|
// Cheerio's .prop() doesn't expose innerHTML/textContent/className as
|
|
65
144
|
// proper properties. Route reads through the matching cheerio API so
|
|
66
145
|
// they're symmetric with the writes below (and with the DOM adapter).
|
|
67
|
-
if (name === 'innerHTML')
|
|
68
|
-
|
|
146
|
+
if (name === 'innerHTML') {
|
|
147
|
+
if (!hasNoData(node)) return node.html()
|
|
148
|
+
return isNoData(node) ? '' : projectedClone(node).html()
|
|
149
|
+
}
|
|
150
|
+
if (name === 'textContent' || name === 'innerText') {
|
|
151
|
+
if (!hasNoData(node)) return node.text()
|
|
152
|
+
return isNoData(node) ? '' : projectedClone(node).text()
|
|
153
|
+
}
|
|
69
154
|
if (name === 'className') {
|
|
70
155
|
const v = node.attr('class')
|
|
71
156
|
return v !== undefined ? v : null
|
|
72
157
|
}
|
|
158
|
+
if (name === 'type') {
|
|
159
|
+
const v = node.attr('type')
|
|
160
|
+
return v !== undefined ? v : null
|
|
161
|
+
}
|
|
73
162
|
const v = node.prop(name)
|
|
74
163
|
return v !== undefined ? v : null
|
|
75
164
|
}
|
|
@@ -78,9 +167,10 @@ const cheerioAdapter = {
|
|
|
78
167
|
// For names that have semantic write meaning, route through the right
|
|
79
168
|
// cheerio API instead.
|
|
80
169
|
const v = value == null ? '' : String(value)
|
|
81
|
-
if (name === 'innerHTML') return node.html(v)
|
|
82
|
-
if (name === 'textContent' || name === 'innerText') return node.text(v)
|
|
170
|
+
if (name === 'innerHTML') return hasNoData(node) ? replaceProjected(node, v) : node.html(v)
|
|
171
|
+
if (name === 'textContent' || name === 'innerText') return hasNoData(node) ? replaceProjected(node, escapeText(v)) : node.text(v)
|
|
83
172
|
if (name === 'className') return node.attr('class', v)
|
|
173
|
+
if (name === 'type') return node.attr('type', v)
|
|
84
174
|
node.prop(name, value)
|
|
85
175
|
},
|
|
86
176
|
|
|
@@ -99,13 +189,22 @@ const cheerioAdapter = {
|
|
|
99
189
|
},
|
|
100
190
|
|
|
101
191
|
clone(node) {
|
|
102
|
-
return node.clone()
|
|
192
|
+
return hasNoData(node) ? projectedClone(node) : node.clone()
|
|
103
193
|
},
|
|
104
194
|
|
|
105
195
|
insertAt(parent, node, index) {
|
|
106
196
|
const siblings = parent.children()
|
|
107
|
-
|
|
108
|
-
|
|
197
|
+
const all = toWrappers(siblings)
|
|
198
|
+
const content = all.filter((k) => !isNoDataEl(k[0]))
|
|
199
|
+
if (content.length === all.length) {
|
|
200
|
+
if (index >= siblings.length) parent.append(node)
|
|
201
|
+
else siblings.eq(index).before(node)
|
|
202
|
+
return
|
|
203
|
+
}
|
|
204
|
+
if (index < content.length) content[index].before(node)
|
|
205
|
+
else if (content.length) content[content.length - 1].after(node)
|
|
206
|
+
else if (all.length) all[0].before(node)
|
|
207
|
+
else parent.append(node)
|
|
109
208
|
},
|
|
110
209
|
|
|
111
210
|
remove(node) {
|
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)
|
|
@@ -103,17 +106,28 @@ function writeText(adapter, node, value) {
|
|
|
103
106
|
// For every other write, returns the original node unchanged.
|
|
104
107
|
function writePropOrAttr(adapter, node, name, value) {
|
|
105
108
|
if (DOM_PROPERTIES_READ_ONLY_SET.has(name)) {
|
|
109
|
+
const current = adapter.prop(node, name)
|
|
110
|
+
if (current === value || (current != null && value != null && String(current) === String(value))) return node
|
|
106
111
|
throw new RuleTargetReadOnly(name)
|
|
107
112
|
}
|
|
108
113
|
if (name === 'outerHTML') {
|
|
109
114
|
const html = value == null ? '' : String(value)
|
|
110
115
|
return adapter.replaceWith(node, html)
|
|
111
116
|
}
|
|
117
|
+
// Compare before writing, exactly as writeText does. A property write of an
|
|
118
|
+
// identical value is not a no-op: assigning innerHTML destroys and rebuilds
|
|
119
|
+
// every child, and setting an attribute to the value it already has still
|
|
120
|
+
// emits a mutation record. The CMS re-applies the whole page on each
|
|
121
|
+
// keystroke, so without this every rich-text region on the page was torn
|
|
122
|
+
// down per keystroke (losing the caret, restarting an embedded video or
|
|
123
|
+
// iframe) and every attribute rule emitted a record to undo and live sync.
|
|
112
124
|
if (DOM_PROPERTIES_WRITE_SET.has(name)) {
|
|
113
|
-
|
|
125
|
+
const next = coercePropValue(name, value)
|
|
126
|
+
if (adapter.prop(node, name) !== next) adapter.prop(node, name, next)
|
|
114
127
|
return node
|
|
115
128
|
}
|
|
116
|
-
|
|
129
|
+
const next = value == null ? '' : String(value)
|
|
130
|
+
if (adapter.attr(node, name) !== next) adapter.attr(node, name, next)
|
|
117
131
|
return node
|
|
118
132
|
}
|
|
119
133
|
|