hyper-html-api 0.8.1 → 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.
Files changed (217) hide show
  1. package/README.md +28 -0
  2. package/conformance/MANIFEST.json +2 -2
  3. package/conformance/cases/no-data-list-skipped.expected.json +6 -0
  4. package/conformance/cases/no-data-list-skipped.html +1 -0
  5. package/conformance/cases/no-data-list-skipped.meta +4 -0
  6. package/conformance/cases/no-data-list-skipped.parsed.json +3 -0
  7. package/conformance/cases/no-data-list-skipped.rules +1 -0
  8. package/conformance/cases/no-data-text-projected.expected.json +3 -0
  9. package/conformance/cases/no-data-text-projected.html +1 -0
  10. package/conformance/cases/no-data-text-projected.meta +4 -0
  11. package/conformance/cases/no-data-text-projected.parsed.json +3 -0
  12. package/conformance/cases/no-data-text-projected.rules +1 -0
  13. package/conformance/cases/props-type-is-attribute.expected.json +5 -0
  14. package/conformance/cases/props-type-is-attribute.meta +4 -0
  15. package/conformance/cases/write-attr-app-scheme.after.html +1 -0
  16. package/conformance/cases/write-attr-app-scheme.after.json +3 -0
  17. package/conformance/cases/write-attr-app-scheme.data.json +1 -0
  18. package/conformance/cases/write-attr-app-scheme.html +1 -0
  19. package/conformance/cases/write-attr-app-scheme.meta +4 -0
  20. package/conformance/cases/write-attr-app-scheme.write.json +4 -0
  21. package/conformance/cases/write-attr-href.after.html +1 -0
  22. package/conformance/cases/write-attr-href.after.json +3 -0
  23. package/conformance/cases/write-attr-href.data.json +1 -0
  24. package/conformance/cases/write-attr-href.html +1 -0
  25. package/conformance/cases/write-attr-href.meta +4 -0
  26. package/conformance/cases/write-attr-href.write.json +4 -0
  27. package/conformance/cases/write-checked-false.after.html +1 -0
  28. package/conformance/cases/write-checked-false.after.json +3 -0
  29. package/conformance/cases/write-checked-false.data.json +1 -0
  30. package/conformance/cases/write-checked-false.html +1 -0
  31. package/conformance/cases/write-checked-false.meta +4 -0
  32. package/conformance/cases/write-checked-false.write.json +4 -0
  33. package/conformance/cases/write-checked-true.after.html +1 -0
  34. package/conformance/cases/write-checked-true.after.json +3 -0
  35. package/conformance/cases/write-checked-true.data.json +1 -0
  36. package/conformance/cases/write-checked-true.html +1 -0
  37. package/conformance/cases/write-checked-true.meta +4 -0
  38. package/conformance/cases/write-checked-true.write.json +4 -0
  39. package/conformance/cases/write-crlf-multi.after.html +12 -0
  40. package/conformance/cases/write-crlf-multi.after.json +8 -0
  41. package/conformance/cases/write-crlf-multi.data.json +1 -0
  42. package/conformance/cases/write-crlf-multi.html +12 -0
  43. package/conformance/cases/write-crlf-multi.meta +4 -0
  44. package/conformance/cases/write-crlf-multi.write.json +4 -0
  45. package/conformance/cases/write-fallback-implied.after.html +1 -0
  46. package/conformance/cases/write-fallback-implied.after.json +3 -0
  47. package/conformance/cases/write-fallback-implied.data.json +1 -0
  48. package/conformance/cases/write-fallback-implied.html +1 -0
  49. package/conformance/cases/write-fallback-implied.meta +4 -0
  50. package/conformance/cases/write-fallback-implied.write.json +4 -0
  51. package/conformance/cases/write-flatten.after.html +1 -0
  52. package/conformance/cases/write-flatten.after.json +3 -0
  53. package/conformance/cases/write-flatten.data.json +1 -0
  54. package/conformance/cases/write-flatten.html +1 -0
  55. package/conformance/cases/write-flatten.meta +4 -0
  56. package/conformance/cases/write-flatten.write.json +4 -0
  57. package/conformance/cases/write-list-empty-no-seed.data.json +1 -0
  58. package/conformance/cases/write-list-empty-no-seed.error.json +8 -0
  59. package/conformance/cases/write-list-empty-no-seed.html +1 -0
  60. package/conformance/cases/write-list-empty-no-seed.meta +4 -0
  61. package/conformance/cases/write-list-grow-from-template.after.html +1 -0
  62. package/conformance/cases/write-list-grow-from-template.after.json +5 -0
  63. package/conformance/cases/write-list-grow-from-template.data.json +1 -0
  64. package/conformance/cases/write-list-grow-from-template.html +1 -0
  65. package/conformance/cases/write-list-grow-from-template.meta +4 -0
  66. package/conformance/cases/write-list-grow-from-template.write.json +4 -0
  67. package/conformance/cases/write-list-object-clone.after.html +1 -0
  68. package/conformance/cases/write-list-object-clone.after.json +12 -0
  69. package/conformance/cases/write-list-object-clone.data.json +1 -0
  70. package/conformance/cases/write-list-object-clone.html +1 -0
  71. package/conformance/cases/write-list-object-clone.meta +4 -0
  72. package/conformance/cases/write-list-object-clone.write.json +4 -0
  73. package/conformance/cases/write-list-scalar-grow.after.html +4 -0
  74. package/conformance/cases/write-list-scalar-grow.after.json +7 -0
  75. package/conformance/cases/write-list-scalar-grow.data.json +1 -0
  76. package/conformance/cases/write-list-scalar-grow.html +4 -0
  77. package/conformance/cases/write-list-scalar-grow.meta +4 -0
  78. package/conformance/cases/write-list-scalar-grow.write.json +4 -0
  79. package/conformance/cases/write-list-scalar-shrink.after.html +4 -0
  80. package/conformance/cases/write-list-scalar-shrink.after.json +5 -0
  81. package/conformance/cases/write-list-scalar-shrink.data.json +1 -0
  82. package/conformance/cases/write-list-scalar-shrink.html +4 -0
  83. package/conformance/cases/write-list-scalar-shrink.meta +4 -0
  84. package/conformance/cases/write-list-scalar-shrink.write.json +4 -0
  85. package/conformance/cases/write-list-shrink-zero.after.html +1 -0
  86. package/conformance/cases/write-list-shrink-zero.after.json +3 -0
  87. package/conformance/cases/write-list-shrink-zero.data.json +1 -0
  88. package/conformance/cases/write-list-shrink-zero.html +1 -0
  89. package/conformance/cases/write-list-shrink-zero.meta +4 -0
  90. package/conformance/cases/write-list-shrink-zero.write.json +4 -0
  91. package/conformance/cases/write-no-data-kept.after.html +1 -0
  92. package/conformance/cases/write-no-data-kept.after.json +3 -0
  93. package/conformance/cases/write-no-data-kept.data.json +1 -0
  94. package/conformance/cases/write-no-data-kept.html +1 -0
  95. package/conformance/cases/write-no-data-kept.meta +4 -0
  96. package/conformance/cases/write-no-data-kept.write.json +4 -0
  97. package/conformance/cases/write-no-rules-tag.data.json +1 -0
  98. package/conformance/cases/write-no-rules-tag.error.json +6 -0
  99. package/conformance/cases/write-no-rules-tag.html +1 -0
  100. package/conformance/cases/write-no-rules-tag.meta +4 -0
  101. package/conformance/cases/write-noop.after.html +3 -0
  102. package/conformance/cases/write-noop.after.json +3 -0
  103. package/conformance/cases/write-noop.data.json +1 -0
  104. package/conformance/cases/write-noop.html +3 -0
  105. package/conformance/cases/write-noop.meta +4 -0
  106. package/conformance/cases/write-noop.write.json +4 -0
  107. package/conformance/cases/write-outerhtml-unchanged.after.html +1 -0
  108. package/conformance/cases/write-outerhtml-unchanged.after.json +3 -0
  109. package/conformance/cases/write-outerhtml-unchanged.data.json +1 -0
  110. package/conformance/cases/write-outerhtml-unchanged.html +1 -0
  111. package/conformance/cases/write-outerhtml-unchanged.meta +4 -0
  112. package/conformance/cases/write-outerhtml-unchanged.write.json +4 -0
  113. package/conformance/cases/write-readonly-changed.data.json +1 -0
  114. package/conformance/cases/write-readonly-changed.error.json +6 -0
  115. package/conformance/cases/write-readonly-changed.html +1 -0
  116. package/conformance/cases/write-readonly-changed.meta +4 -0
  117. package/conformance/cases/write-readonly-unchanged.after.html +1 -0
  118. package/conformance/cases/write-readonly-unchanged.after.json +4 -0
  119. package/conformance/cases/write-readonly-unchanged.data.json +1 -0
  120. package/conformance/cases/write-readonly-unchanged.html +1 -0
  121. package/conformance/cases/write-readonly-unchanged.meta +4 -0
  122. package/conformance/cases/write-readonly-unchanged.write.json +4 -0
  123. package/conformance/cases/write-refused-animate.data.json +1 -0
  124. package/conformance/cases/write-refused-animate.error.json +11 -0
  125. package/conformance/cases/write-refused-animate.html +1 -0
  126. package/conformance/cases/write-refused-animate.meta +4 -0
  127. package/conformance/cases/write-refused-attr-name.data.json +1 -0
  128. package/conformance/cases/write-refused-attr-name.error.json +11 -0
  129. package/conformance/cases/write-refused-attr-name.html +1 -0
  130. package/conformance/cases/write-refused-attr-name.meta +4 -0
  131. package/conformance/cases/write-refused-data-url.data.json +1 -0
  132. package/conformance/cases/write-refused-data-url.error.json +11 -0
  133. package/conformance/cases/write-refused-data-url.html +1 -0
  134. package/conformance/cases/write-refused-data-url.meta +4 -0
  135. package/conformance/cases/write-refused-innerhtml.data.json +1 -0
  136. package/conformance/cases/write-refused-innerhtml.error.json +11 -0
  137. package/conformance/cases/write-refused-innerhtml.html +1 -0
  138. package/conformance/cases/write-refused-innerhtml.meta +4 -0
  139. package/conformance/cases/write-refused-javascript-url.data.json +1 -0
  140. package/conformance/cases/write-refused-javascript-url.error.json +11 -0
  141. package/conformance/cases/write-refused-javascript-url.html +1 -0
  142. package/conformance/cases/write-refused-javascript-url.meta +4 -0
  143. package/conformance/cases/write-refused-list-removes-rules-tag.data.json +1 -0
  144. package/conformance/cases/write-refused-list-removes-rules-tag.error.json +11 -0
  145. package/conformance/cases/write-refused-list-removes-rules-tag.html +1 -0
  146. package/conformance/cases/write-refused-list-removes-rules-tag.meta +4 -0
  147. package/conformance/cases/write-refused-multiple.data.json +1 -0
  148. package/conformance/cases/write-refused-multiple.error.json +15 -0
  149. package/conformance/cases/write-refused-multiple.html +1 -0
  150. package/conformance/cases/write-refused-multiple.meta +4 -0
  151. package/conformance/cases/write-refused-onclick.data.json +1 -0
  152. package/conformance/cases/write-refused-onclick.error.json +11 -0
  153. package/conformance/cases/write-refused-onclick.html +1 -0
  154. package/conformance/cases/write-refused-onclick.meta +4 -0
  155. package/conformance/cases/write-refused-rules-tag-ancestor.data.json +1 -0
  156. package/conformance/cases/write-refused-rules-tag-ancestor.error.json +11 -0
  157. package/conformance/cases/write-refused-rules-tag-ancestor.html +1 -0
  158. package/conformance/cases/write-refused-rules-tag-ancestor.meta +4 -0
  159. package/conformance/cases/write-refused-script.data.json +1 -0
  160. package/conformance/cases/write-refused-script.error.json +11 -0
  161. package/conformance/cases/write-refused-script.html +1 -0
  162. package/conformance/cases/write-refused-script.meta +4 -0
  163. package/conformance/cases/write-shape-mismatch.data.json +1 -0
  164. package/conformance/cases/write-shape-mismatch.error.json +12 -0
  165. package/conformance/cases/write-shape-mismatch.html +1 -0
  166. package/conformance/cases/write-shape-mismatch.meta +4 -0
  167. package/conformance/cases/write-text-basic.after.html +3 -0
  168. package/conformance/cases/write-text-basic.after.json +3 -0
  169. package/conformance/cases/write-text-basic.data.json +1 -0
  170. package/conformance/cases/write-text-basic.html +3 -0
  171. package/conformance/cases/write-text-basic.meta +4 -0
  172. package/conformance/cases/write-text-basic.write.json +4 -0
  173. package/conformance/cases/write-text-escape.after.html +1 -0
  174. package/conformance/cases/write-text-escape.after.json +3 -0
  175. package/conformance/cases/write-text-escape.data.json +1 -0
  176. package/conformance/cases/write-text-escape.html +1 -0
  177. package/conformance/cases/write-text-escape.meta +4 -0
  178. package/conformance/cases/write-text-escape.write.json +4 -0
  179. package/conformance/cases/write-text-null-clears.after.html +1 -0
  180. package/conformance/cases/write-text-null-clears.after.json +3 -0
  181. package/conformance/cases/write-text-null-clears.data.json +1 -0
  182. package/conformance/cases/write-text-null-clears.html +1 -0
  183. package/conformance/cases/write-text-null-clears.meta +4 -0
  184. package/conformance/cases/write-text-null-clears.write.json +4 -0
  185. package/conformance/cases/write-type-attribute.after.html +1 -0
  186. package/conformance/cases/write-type-attribute.after.json +3 -0
  187. package/conformance/cases/write-type-attribute.data.json +1 -0
  188. package/conformance/cases/write-type-attribute.html +1 -0
  189. package/conformance/cases/write-type-attribute.meta +4 -0
  190. package/conformance/cases/write-type-attribute.write.json +4 -0
  191. package/conformance/cases/write-unknown-key.data.json +1 -0
  192. package/conformance/cases/write-unknown-key.error.json +11 -0
  193. package/conformance/cases/write-unknown-key.html +3 -0
  194. package/conformance/cases/write-unknown-key.meta +4 -0
  195. package/conformance/cases/write-unmatched.data.json +1 -0
  196. package/conformance/cases/write-unmatched.error.json +14 -0
  197. package/conformance/cases/write-unmatched.html +1 -0
  198. package/conformance/cases/write-unmatched.meta +4 -0
  199. package/conformance/write-policy.json +78 -0
  200. package/dist/hyper-html-api.engine.min.js +1 -1
  201. package/dist/hyper-html-api.min.js +5 -4
  202. package/dist/hyper-html-api.upgrade.min.js +2 -2
  203. package/package.json +4 -3
  204. package/packed-contract.json +1 -1
  205. package/src/adapters/cheerio.js +105 -10
  206. package/src/engine/apply.js +2 -0
  207. package/src/engine/errors.js +25 -0
  208. package/src/engine/index.js +3 -0
  209. package/src/engine/splice.js +118 -0
  210. package/src/engine/write-plan.js +52 -0
  211. package/src/engine/write-policy.js +136 -0
  212. package/src/write.js +29 -0
  213. package/conformance/cases/props-type-is-node-type.expected.json +0 -5
  214. package/conformance/cases/props-type-is-node-type.meta +0 -11
  215. /package/conformance/cases/{props-type-is-node-type.html → props-type-is-attribute.html} +0 -0
  216. /package/conformance/cases/{props-type-is-node-type.parsed.json → props-type-is-attribute.parsed.json} +0 -0
  217. /package/conformance/cases/{props-type-is-node-type.rules → props-type-is-attribute.rules} +0 -0
@@ -1,2 +1,2 @@
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);})();
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,7 +9,7 @@
9
9
  "apply",
10
10
  "CMS"
11
11
  ],
12
- "version": "0.8.1",
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"
@@ -33,7 +33,8 @@
33
33
  "./cheerio": "./src/adapters/cheerio.js",
34
34
  "./dom": "./src/adapters/dom.js",
35
35
  "./data": "./src/data.js",
36
- "./upgrade": "./src/upgrade.js"
36
+ "./upgrade": "./src/upgrade.js",
37
+ "./write": "./src/write.js"
37
38
  },
38
39
  "scripts": {
39
40
  "build": "npx esbuild src/hyper-html-api.js --bundle --minify --format=iife --global-name=HyperHtmlApi --outfile=dist/hyper-html-api.min.js",
@@ -62,7 +63,7 @@
62
63
  "url": "git+https://github.com/panphora/hyper-html-api.git"
63
64
  },
64
65
  "dependencies": {
65
- "hyper-morph": "^0.5.3"
66
+ "hyper-morph": "^1.0.0"
66
67
  },
67
68
  "devDependencies": {
68
69
  "@web/test-runner": "^0.20.0",
@@ -1 +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"]}
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"]}
@@ -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, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
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') : ''
@@ -20,6 +81,7 @@ const cheerioAdapter = {
20
81
  if (!ctx || !ctx.find) return []
21
82
  let matches = toWrappers(ctx.find(selector))
22
83
  if (!opts.includeRulesTag) matches = matches.filter((n) => !isRulesTag(n))
84
+ matches = matches.filter((n) => !inNoData(n))
23
85
  const skipParts = []
24
86
  if (opts.skip) skipParts.push(opts.skip)
25
87
  // The cms-template seed marker means "not data" for EVERY consumer, so skip
@@ -43,12 +105,25 @@ const cheerioAdapter = {
43
105
 
44
106
  children(node) {
45
107
  if (!node || !node.children) return []
46
- return toWrappers(node.children())
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
47
114
  },
48
115
 
49
116
  text(node, value) {
50
- if (value === undefined) return node.text().trim()
51
- node.text(value)
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))
52
127
  },
53
128
 
54
129
  attr(node, name, value) {
@@ -68,12 +143,22 @@ const cheerioAdapter = {
68
143
  // Cheerio's .prop() doesn't expose innerHTML/textContent/className as
69
144
  // proper properties. Route reads through the matching cheerio API so
70
145
  // they're symmetric with the writes below (and with the DOM adapter).
71
- if (name === 'innerHTML') return node.html()
72
- if (name === 'textContent' || name === 'innerText') return node.text()
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
+ }
73
154
  if (name === 'className') {
74
155
  const v = node.attr('class')
75
156
  return v !== undefined ? v : null
76
157
  }
158
+ if (name === 'type') {
159
+ const v = node.attr('type')
160
+ return v !== undefined ? v : null
161
+ }
77
162
  const v = node.prop(name)
78
163
  return v !== undefined ? v : null
79
164
  }
@@ -82,9 +167,10 @@ const cheerioAdapter = {
82
167
  // For names that have semantic write meaning, route through the right
83
168
  // cheerio API instead.
84
169
  const v = value == null ? '' : String(value)
85
- if (name === 'innerHTML') return node.html(v)
86
- 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)
87
172
  if (name === 'className') return node.attr('class', v)
173
+ if (name === 'type') return node.attr('type', v)
88
174
  node.prop(name, value)
89
175
  },
90
176
 
@@ -103,13 +189,22 @@ const cheerioAdapter = {
103
189
  },
104
190
 
105
191
  clone(node) {
106
- return node.clone()
192
+ return hasNoData(node) ? projectedClone(node) : node.clone()
107
193
  },
108
194
 
109
195
  insertAt(parent, node, index) {
110
196
  const siblings = parent.children()
111
- if (index >= siblings.length) parent.append(node)
112
- else siblings.eq(index).before(node)
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)
113
208
  },
114
209
 
115
210
  remove(node) {
@@ -106,6 +106,8 @@ function writeText(adapter, node, value) {
106
106
  // For every other write, returns the original node unchanged.
107
107
  function writePropOrAttr(adapter, node, name, value) {
108
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
109
111
  throw new RuleTargetReadOnly(name)
110
112
  }
111
113
  if (name === 'outerHTML') {
@@ -49,3 +49,28 @@ export class RuleTargetReadOnly extends Error {
49
49
  this.target = name
50
50
  }
51
51
  }
52
+
53
+ export class WriteRefused extends Error {
54
+ constructor(refusals) {
55
+ super(`write refused: ${refusals.length} write(s) broke the content-only policy`)
56
+ this.name = 'WriteRefused'
57
+ this.refusals = refusals
58
+ }
59
+ }
60
+
61
+ export class NoRulesTag extends Error {
62
+ constructor(token) {
63
+ super(`no <script data-rules-name~="${token}"> rules tag in this document`)
64
+ this.name = 'NoRulesTag'
65
+ this.token = token
66
+ }
67
+ }
68
+
69
+ export class WriteRejected extends Error {
70
+ constructor(unknownKeys, unmatched) {
71
+ super(`write rejected: ${unknownKeys.length} unknown key(s), ${unmatched.length} rule(s) with no matching element`)
72
+ this.name = 'WriteRejected'
73
+ this.unknownKeys = unknownKeys
74
+ this.unmatched = unmatched
75
+ }
76
+ }
@@ -9,6 +9,9 @@ export { parseStrict, parseRelaxed } from './rules.js'
9
9
  export { ruleAttrIndex, splitRule } from './rule-syntax.js'
10
10
  export * as errors from './errors.js'
11
11
  export { DOM_PROPERTIES, DOM_PROPERTIES_SET, DOM_PROPERTIES_READ_ONLY_SET } from './dom-properties.js'
12
+ export { WRITE_POLICY, guardAdapter, checkAttribute, urlScheme } from './write-policy.js'
13
+ export { planWrite } from './write-plan.js'
14
+ export { trackAdapter, spliceDocument } from './splice.js'
12
15
 
13
16
  // source: object literal → use as-is (no tag); string → look up by token.
14
17
  // For an element root, search the whole document (root.ownerDocument) so a
@@ -0,0 +1,118 @@
1
+ function raw(node) {
2
+ return node && node[0] ? node[0] : node
3
+ }
4
+
5
+ // Records which nodes a write touched. Structural changes mark the parent,
6
+ // since the parent's children are what changed. Clones are recorded so their
7
+ // copied source locations are never trusted.
8
+ export function trackAdapter(adapter) {
9
+ const dirty = new Set()
10
+ const cloned = new WeakSet()
11
+ const mark = (node) => {
12
+ const r = raw(node)
13
+ if (r) dirty.add(r)
14
+ }
15
+ const markTree = (r) => {
16
+ if (!r) return
17
+ cloned.add(r)
18
+ for (const c of r.children || []) markTree(c)
19
+ }
20
+ return {
21
+ ...adapter,
22
+ text(node, value) {
23
+ if (value === undefined) return adapter.text(node)
24
+ mark(node)
25
+ return adapter.text(node, value)
26
+ },
27
+ attr(node, name, value) {
28
+ if (value === undefined) return adapter.attr(node, name)
29
+ mark(node)
30
+ return adapter.attr(node, name, value)
31
+ },
32
+ removeAttr(node, name) {
33
+ mark(node)
34
+ return adapter.removeAttr(node, name)
35
+ },
36
+ prop(node, name, value) {
37
+ if (value === undefined) return adapter.prop(node, name)
38
+ mark(node)
39
+ return adapter.prop(node, name, value)
40
+ },
41
+ replaceWith(node, html) {
42
+ const p = adapter.parent(node)
43
+ if (p) mark(p)
44
+ return adapter.replaceWith(node, html)
45
+ },
46
+ clone(node) {
47
+ const c = adapter.clone(node)
48
+ markTree(raw(c))
49
+ return c
50
+ },
51
+ insertAt(parent, node, index) {
52
+ mark(parent)
53
+ const from = adapter.parent(node)
54
+ if (from) mark(from)
55
+ return adapter.insertAt(parent, node, index)
56
+ },
57
+ remove(node) {
58
+ const p = adapter.parent(node)
59
+ if (p) mark(p)
60
+ return adapter.remove(node)
61
+ },
62
+ dirty,
63
+ cloned,
64
+ }
65
+ }
66
+
67
+ function attached(r, docRoot) {
68
+ let n = r
69
+ while (n && n.parent) n = n.parent
70
+ return n === docRoot
71
+ }
72
+
73
+ function located(r, cloned) {
74
+ let n = r
75
+ while (n && n.type !== 'root') {
76
+ const loc = n.sourceCodeLocation
77
+ if (!cloned.has(n) && loc && loc.startOffset != null && loc.endOffset != null) return n
78
+ n = n.parent
79
+ }
80
+ return null
81
+ }
82
+
83
+ function hasAncestorIn(r, set) {
84
+ let n = r.parent
85
+ while (n) {
86
+ if (set.has(n)) return true
87
+ n = n.parent
88
+ }
89
+ return false
90
+ }
91
+
92
+ // Replaces the source span of each topmost changed element with its fresh
93
+ // serialization, then proves the result by reparsing: the spliced text must
94
+ // render exactly like the mutated tree. Anything unprovable falls back to the
95
+ // whole-document render.
96
+ export function spliceDocument(load, src, $, tracker) {
97
+ const full = $.html()
98
+ const fallback = { html: full, spliced: false }
99
+ const docRoot = raw($.root())
100
+ const targets = new Set()
101
+ for (const r of tracker.dirty) {
102
+ if (!attached(r, docRoot)) continue
103
+ const at = located(r, tracker.cloned)
104
+ if (!at) return fallback
105
+ targets.add(at)
106
+ }
107
+ const top = [...targets].filter((r) => !hasAncestorIn(r, targets))
108
+ top.sort((a, b) => b.sourceCodeLocation.startOffset - a.sourceCodeLocation.startOffset)
109
+ let out = src
110
+ let prevStart = Infinity
111
+ for (const r of top) {
112
+ const { startOffset, endOffset } = r.sourceCodeLocation
113
+ if (endOffset > prevStart) return fallback
114
+ out = out.slice(0, startOffset) + $.html(r) + out.slice(endOffset)
115
+ prevStart = startOffset
116
+ }
117
+ return load(out).html() === full ? { html: out, spliced: true } : fallback
118
+ }
@@ -0,0 +1,52 @@
1
+ import { ruleAttrIndex } from './rule-syntax.js'
2
+
3
+ function isPlainObject(v) {
4
+ return v !== null && typeof v === 'object' && !Array.isArray(v)
5
+ }
6
+
7
+ function label(path) {
8
+ return path.reduce((out, part) => (typeof part === 'number' ? `${out}[${part}]` : out ? `${out}.${part}` : part), '')
9
+ }
10
+
11
+ // Walks rules against data without touching the document. Reports data keys
12
+ // the rules do not define, and scalar rules whose selector matches nothing.
13
+ // Shape problems are left to apply(), which already reports them. Inside list
14
+ // items only unknown keys are checked, because new rows do not exist yet.
15
+ export function planWrite(adapter, root, rules, data, opts = {}) {
16
+ const unknownKeys = []
17
+ const unmatched = []
18
+
19
+ function checkKeys(rule, value, path) {
20
+ if (Array.isArray(rule)) {
21
+ const [, shape] = rule
22
+ if (!Array.isArray(value) || !isPlainObject(shape)) return
23
+ value.forEach((item, i) => checkKeys(shape, item, [...path, i]))
24
+ return
25
+ }
26
+ if (!isPlainObject(rule) || !isPlainObject(value)) return
27
+ for (const key of Object.keys(value)) {
28
+ if (!Object.prototype.hasOwnProperty.call(rule, key)) unknownKeys.push(label([...path, key]))
29
+ else checkKeys(rule[key], value[key], [...path, key])
30
+ }
31
+ }
32
+
33
+ function checkTargets(ctx, rule, value, path) {
34
+ if (value === undefined) return
35
+ if (typeof rule === 'string') {
36
+ if (rule.endsWith('[]') || rule === '.' || rule.startsWith('@')) return
37
+ const at = ruleAttrIndex(rule)
38
+ const selector = at === -1 ? rule : rule.slice(0, at)
39
+ if (!selector) return
40
+ if (adapter.find(ctx, selector, opts).length === 0) unmatched.push({ path: label(path), selector })
41
+ return
42
+ }
43
+ if (Array.isArray(rule)) return
44
+ if (isPlainObject(rule) && isPlainObject(value)) {
45
+ for (const [key, sub] of Object.entries(rule)) checkTargets(ctx, sub, value[key], [...path, key])
46
+ }
47
+ }
48
+
49
+ checkKeys(rules, data, [])
50
+ checkTargets(root, rules, data, [])
51
+ return { unknownKeys, unmatched }
52
+ }