@heycys/gallery 0.2.3 → 0.2.4

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 (220) hide show
  1. package/README.md +1 -1
  2. package/THIRD-PARTY-NOTICES.md +1 -1
  3. package/assets/preview/runtime.js +156 -0
  4. package/assets/preview/shell.html +107 -0
  5. package/assets/writing-preferences.md +1 -1
  6. package/browser/editor/components/divider/index.mjs +1 -1
  7. package/browser/editor/page/annotate/card.mjs +6 -0
  8. package/browser/editor/page/annotate/index.mjs +22 -2
  9. package/browser/editor/page/columns/index.mjs +1 -1
  10. package/browser/editor/page/conflicts.mjs +1 -1
  11. package/browser/editor/page/drag/index.mjs +1 -1
  12. package/browser/editor/page/editor.mjs +39 -3
  13. package/browser/editor/page/focus.mjs +104 -0
  14. package/browser/editor/page/handle/index.mjs +14 -2
  15. package/browser/editor/page/links/index.mjs +2 -2
  16. package/browser/editor/page/quiet.mjs +3 -3
  17. package/browser/editor/page/resize/index.mjs +1 -1
  18. package/browser/editor/page/session.mjs +4 -1
  19. package/browser/editor/page/ui.mjs +1 -1
  20. package/browser/shared/annotations.mjs +22 -3
  21. package/browser/shared/block-packs.mjs +13 -4
  22. package/browser/shared/document-look.mjs +14 -0
  23. package/browser/shared/drafts.mjs +1 -1
  24. package/browser/shared/extension-manifest.mjs +40 -12
  25. package/browser/shared/favorite-merge.mjs +17 -0
  26. package/browser/shared/favorites.mjs +77 -0
  27. package/browser/shared/i18n/en.mjs +123 -24
  28. package/browser/shared/outline-ops.mjs +109 -0
  29. package/browser/shared/outline.mjs +6 -0
  30. package/browser/shared/pages.mjs +20 -8
  31. package/browser/shared/paths.mjs +5 -2
  32. package/browser/shared/preference-documents.mjs +137 -0
  33. package/browser/shared/presence.mjs +94 -0
  34. package/browser/shared/preview-server.mjs +8 -5
  35. package/browser/shared/qa-levels.mjs +9 -1
  36. package/browser/shared/session.mjs +4 -0
  37. package/browser/shared/shipped-blocks.mjs +22 -4
  38. package/browser/shared/startup.mjs +101 -0
  39. package/browser/shared/workspace-columns.mjs +1 -1
  40. package/browser/shared/workspace-look.mjs +21 -8
  41. package/browser/shared/workspace-registry.mjs +6 -3
  42. package/browser/shared/workspace.mjs +37 -10
  43. package/browser/shared/writing-preferences.mjs +2 -42
  44. package/dist/chunk-25LYSMAE.mjs +2 -0
  45. package/dist/chunk-2I6ZVC5O.mjs +2 -0
  46. package/dist/{chunk-M4NRDYI5.mjs → chunk-2MYTOOP6.mjs} +1 -1
  47. package/dist/chunk-2VNENLER.mjs +2 -0
  48. package/dist/chunk-3FERXZF5.mjs +4 -0
  49. package/dist/chunk-3M6SBBGU.mjs +2 -0
  50. package/dist/chunk-3VCAAF34.mjs +2 -0
  51. package/dist/{chunk-WD4U6XXT.mjs → chunk-3ZTRLGSA.mjs} +1 -1
  52. package/dist/chunk-4FRA5AUE.mjs +2 -0
  53. package/dist/chunk-4LR2QEC2.mjs +4 -0
  54. package/dist/chunk-56SVJENP.mjs +966 -0
  55. package/dist/chunk-5CQISL2G.mjs +4 -0
  56. package/dist/{chunk-RRKJMHNX.mjs → chunk-5I5ZDDWC.mjs} +5 -5
  57. package/dist/chunk-5IHDLEB4.mjs +10 -0
  58. package/dist/chunk-5LRDMV7O.mjs +2 -0
  59. package/dist/chunk-5MVUYRKG.mjs +5 -0
  60. package/dist/chunk-5TLLIZT7.mjs +2 -0
  61. package/dist/chunk-6ILJWFYW.mjs +4 -0
  62. package/dist/chunk-6N25CJ6Y.mjs +3 -0
  63. package/dist/{chunk-SQ6Y2ZMA.mjs → chunk-7DTINW6U.mjs} +2 -2
  64. package/dist/chunk-7KWAGKIK.mjs +2 -0
  65. package/dist/chunk-7WNUOAFK.mjs +2 -0
  66. package/dist/chunk-7XCRW5RC.mjs +2 -0
  67. package/dist/{chunk-BYNPEUDS.mjs → chunk-7XSDTILF.mjs} +1 -1
  68. package/dist/chunk-ABKYFOVR.mjs +2 -0
  69. package/dist/chunk-AMUF7PUN.mjs +2 -0
  70. package/dist/{chunk-FJLM7YE7.mjs → chunk-B2EIMERT.mjs} +2 -2
  71. package/dist/{chunk-QNECWMGR.mjs → chunk-B45IAAU6.mjs} +1 -1
  72. package/dist/chunk-B6RAGF4R.mjs +2 -0
  73. package/dist/chunk-BSJKFE7I.mjs +4 -0
  74. package/dist/chunk-C72EEVLK.mjs +2 -0
  75. package/dist/chunk-CRAUKZ23.mjs +4 -0
  76. package/dist/chunk-F4CT35KL.mjs +2 -0
  77. package/dist/chunk-F63BNJLG.mjs +2 -0
  78. package/dist/chunk-FBKUPS44.mjs +2 -0
  79. package/dist/chunk-FL52ZL5Z.mjs +15 -0
  80. package/dist/chunk-FOZCU4VW.mjs +2 -0
  81. package/dist/chunk-G5HV7BC3.mjs +2 -0
  82. package/dist/{chunk-ERLAIBOA.mjs → chunk-GB5SOYQJ.mjs} +2 -2
  83. package/dist/chunk-GN3SG3IF.mjs +2 -0
  84. package/dist/{chunk-6QWQXHAV.mjs → chunk-HFTBVEZK.mjs} +1 -1
  85. package/dist/chunk-IOW5HLRK.mjs +2 -0
  86. package/dist/chunk-IQ3GJNTI.mjs +6 -0
  87. package/dist/chunk-K6SPFBUJ.mjs +2 -0
  88. package/dist/chunk-K7Y7SPTS.mjs +2 -0
  89. package/dist/chunk-L2IJCEUH.mjs +2 -0
  90. package/dist/{chunk-GPIWQ4X4.mjs → chunk-L3VT6LM4.mjs} +1 -1
  91. package/dist/chunk-L4WLQYFC.mjs +5 -0
  92. package/dist/{chunk-NLDF35P5.mjs → chunk-LAMCAGK6.mjs} +1 -1
  93. package/dist/chunk-LHGKPMTI.mjs +2 -0
  94. package/dist/chunk-LJZIYVNA.mjs +3 -0
  95. package/dist/chunk-LSVCTLS2.mjs +2 -0
  96. package/dist/chunk-LZY74XTP.mjs +2 -0
  97. package/dist/chunk-MC4LRSVH.mjs +2 -0
  98. package/dist/chunk-MCEXN4G5.mjs +2 -0
  99. package/dist/chunk-MTLAOCFF.mjs +181 -0
  100. package/dist/chunk-MZ66LN3B.mjs +2 -0
  101. package/dist/chunk-N5QWJRRI.mjs +2 -0
  102. package/dist/chunk-NF4MMOUB.mjs +2 -0
  103. package/dist/chunk-NHJYAJ73.mjs +3 -0
  104. package/dist/chunk-NRSD7SVY.mjs +2 -0
  105. package/dist/chunk-NT23I4XW.mjs +2 -0
  106. package/dist/chunk-NUALABIS.mjs +3 -0
  107. package/dist/chunk-NW6LAU22.mjs +2 -0
  108. package/dist/chunk-NWWHDGKF.mjs +5 -0
  109. package/dist/chunk-OFRCVMSJ.mjs +2 -0
  110. package/dist/chunk-OKVQQ3CX.mjs +4 -0
  111. package/dist/chunk-OM24O4KR.mjs +8 -0
  112. package/dist/{chunk-4B2TB5K2.mjs → chunk-PBMOC7KA.mjs} +2 -2
  113. package/dist/chunk-PVTCP43W.mjs +2 -0
  114. package/dist/chunk-Q62HZAJS.mjs +2 -0
  115. package/dist/chunk-QBJWIR3Q.mjs +2 -0
  116. package/dist/chunk-QDSEZX7Z.mjs +6 -0
  117. package/dist/chunk-QR4V4A2Z.mjs +15 -0
  118. package/dist/{chunk-QVGOPHOF.mjs → chunk-QRLVVZ3R.mjs} +1 -1
  119. package/dist/chunk-QW3QG67J.mjs +2 -0
  120. package/dist/chunk-R2T2EVWY.mjs +8 -0
  121. package/dist/{chunk-JJNHKGTD.mjs → chunk-R5RERE6G.mjs} +1 -1
  122. package/dist/chunk-RFHEWT3Y.mjs +5 -0
  123. package/dist/chunk-RS2Z2JQP.mjs +2 -0
  124. package/dist/chunk-S6YEC4GE.mjs +16 -0
  125. package/dist/chunk-SHZLMGGW.mjs +2 -0
  126. package/dist/chunk-TALJQM2O.mjs +2 -0
  127. package/dist/chunk-TLNJWEFY.mjs +22 -0
  128. package/dist/{chunk-ZLS2FRS6.mjs → chunk-TQZU7D7C.mjs} +1 -1
  129. package/dist/chunk-UTKNWYBA.mjs +2 -0
  130. package/dist/chunk-V3TM3TEN.mjs +2 -0
  131. package/dist/chunk-V3XROSP5.mjs +7 -0
  132. package/dist/{chunk-6QBHU4DF.mjs → chunk-V5JTW2LH.mjs} +1 -1
  133. package/dist/chunk-VAXLSISW.mjs +4 -0
  134. package/dist/chunk-VBHI3RG6.mjs +2 -0
  135. package/dist/{chunk-CRDG6EF2.mjs → chunk-VKZJRGDR.mjs} +1 -1
  136. package/dist/chunk-VZXZM7NS.mjs +2 -0
  137. package/dist/chunk-WDS6HEPE.mjs +2 -0
  138. package/dist/chunk-WHGANNEY.mjs +13 -0
  139. package/dist/chunk-WMJWC4QY.mjs +56 -0
  140. package/dist/{chunk-UTMAY3WK.mjs → chunk-WWONJJQS.mjs} +1 -1
  141. package/dist/chunk-X4WNLFIK.mjs +2 -0
  142. package/dist/chunk-XNNCQROX.mjs +11 -0
  143. package/dist/chunk-XRYECF23.mjs +170 -0
  144. package/dist/{chunk-225ALKYI.mjs → chunk-Z4NEXXFK.mjs} +1 -1
  145. package/dist/{chunk-PKVK6WFC.mjs → chunk-ZFVF2YPV.mjs} +2 -2
  146. package/dist/chunk-ZM2IX3R2.mjs +2 -0
  147. package/dist/chunk-ZNGGDUZI.mjs +2 -0
  148. package/dist/chunk-ZOEJQOKT.mjs +2 -0
  149. package/dist/cli.mjs +1 -1
  150. package/dist/server.mjs +1 -1
  151. package/dist/update-fetch.mjs +1 -1
  152. package/dist/worker.mjs +1 -1
  153. package/package.json +1 -1
  154. package/release.json +3 -3
  155. package/skill/SKILL.md +54 -148
  156. package/skill/references/building-blocks.md +4 -4
  157. package/skill/references/charts-and-figures.md +73 -0
  158. package/skill/references/extensions.md +47 -4
  159. package/skill/references/pages-and-data.md +22 -3
  160. package/skill/references/preference-files.md +7 -0
  161. package/skill/references/previews.md +17 -0
  162. package/skill/references/writing-html.md +21 -82
  163. package/web/assets/index-B4uUluLM.js +15 -0
  164. package/web/assets/index-C3vHT8sH.css +1 -0
  165. package/web/index.html +2 -2
  166. package/dist/chunk-2HS7ZBPU.mjs +0 -2
  167. package/dist/chunk-3F57LEN5.mjs +0 -2
  168. package/dist/chunk-4OZWXZE5.mjs +0 -5
  169. package/dist/chunk-5GK7HS62.mjs +0 -2
  170. package/dist/chunk-6GV3CBB2.mjs +0 -2
  171. package/dist/chunk-6NLXUKAY.mjs +0 -4
  172. package/dist/chunk-6XD6U3QA.mjs +0 -5
  173. package/dist/chunk-6Y3HYOBM.mjs +0 -2
  174. package/dist/chunk-7EFHNQ5B.mjs +0 -3
  175. package/dist/chunk-7M2BQQGZ.mjs +0 -2
  176. package/dist/chunk-7UZUQQ7Q.mjs +0 -554
  177. package/dist/chunk-ALZ6ZENZ.mjs +0 -3
  178. package/dist/chunk-BX5AKINW.mjs +0 -15
  179. package/dist/chunk-DR73Y2UJ.mjs +0 -3
  180. package/dist/chunk-EURLTOTZ.mjs +0 -4
  181. package/dist/chunk-F4ZA6JRZ.mjs +0 -3
  182. package/dist/chunk-FNCCVGKX.mjs +0 -2
  183. package/dist/chunk-FOJ3K5Z3.mjs +0 -6
  184. package/dist/chunk-FQ72LZHB.mjs +0 -2
  185. package/dist/chunk-G7N7YFVD.mjs +0 -2
  186. package/dist/chunk-GIRXJBGC.mjs +0 -2
  187. package/dist/chunk-GKOBB6DH.mjs +0 -2
  188. package/dist/chunk-GMJD7ID3.mjs +0 -2
  189. package/dist/chunk-GQJMVSSN.mjs +0 -2
  190. package/dist/chunk-HX4DLE3J.mjs +0 -10
  191. package/dist/chunk-IS7N3N6Q.mjs +0 -168
  192. package/dist/chunk-JEUK3ZO7.mjs +0 -2
  193. package/dist/chunk-JPG2LBQM.mjs +0 -11
  194. package/dist/chunk-JYK5WJPM.mjs +0 -2
  195. package/dist/chunk-KLQP46Y3.mjs +0 -4
  196. package/dist/chunk-L55NOXBE.mjs +0 -4
  197. package/dist/chunk-LCB6MARS.mjs +0 -5
  198. package/dist/chunk-LJLVCU6W.mjs +0 -16
  199. package/dist/chunk-LMUZQK5O.mjs +0 -2
  200. package/dist/chunk-NMF3IPYA.mjs +0 -13
  201. package/dist/chunk-ONKC4BCC.mjs +0 -2
  202. package/dist/chunk-OU6ZZVBX.mjs +0 -5
  203. package/dist/chunk-PUOQ65NC.mjs +0 -2
  204. package/dist/chunk-QJAVCTY7.mjs +0 -2
  205. package/dist/chunk-QP7BOHE4.mjs +0 -2
  206. package/dist/chunk-S3SX3COT.mjs +0 -20
  207. package/dist/chunk-SQ3FQCCN.mjs +0 -8
  208. package/dist/chunk-T4Y2ZSVX.mjs +0 -4
  209. package/dist/chunk-TANZRINB.mjs +0 -2
  210. package/dist/chunk-UGWMMEJ5.mjs +0 -15
  211. package/dist/chunk-UTF7GBQU.mjs +0 -4
  212. package/dist/chunk-V4ZHRALW.mjs +0 -170
  213. package/dist/chunk-XBNFXWAW.mjs +0 -6
  214. package/dist/chunk-XZV72SQ4.mjs +0 -2
  215. package/dist/chunk-YFJB534W.mjs +0 -2
  216. package/dist/chunk-Z6OKLRHC.mjs +0 -2
  217. package/dist/chunk-ZMHUDYLV.mjs +0 -2
  218. package/web/assets/index-D8P8uhDW.js +0 -15
  219. package/web/assets/index-FLb9jCfl.css +0 -1
  220. /package/dist/{chunk-PAREWQGB.mjs → chunk-NOGQX56R.mjs} +0 -0
@@ -1,16 +0,0 @@
1
- import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
2
- import{a as Te}from"./chunk-JEUK3ZO7.mjs";import{a as Ne,b as Oe,c as Xe,d as Ze,g as Ae,h as et}from"./chunk-PUOQ65NC.mjs";import{g as Qe}from"./chunk-6NLXUKAY.mjs";import{b as je}from"./chunk-VRPVVMRB.mjs";import{p as Se}from"./chunk-BX5AKINW.mjs";import{a as ce}from"./chunk-HYMEEXKN.mjs";import{a as Ee,f as le,p as ze}from"./chunk-TKWEX4FD.mjs";import T from"node:fs/promises";import pe from"node:os";import x from"node:path";import{pathToFileURL as De}from"node:url";import{instancesOf as ot,isInstance as bt}from"../browser/shared/components/index.mjs";import{ATTRIBUTE as $t,FALLBACK as xt,INSTANCE as he,SLOT as vt,SLOT_PART as tt}from"../browser/shared/components/installed.mjs";import{jsonIn as Et}from"../browser/shared/json-layout.mjs";import{QUERY_ROUTE as St}from"../browser/shared/workspace-query.mjs";import{documentDirectory as jt,documentFiles as Tt,layoutOf as it,listDocumentSlugs as Nt,PACKAGE_MANIFEST as Ot}from"../browser/shared/workspace.mjs";var At="in a browser, under the export's policy",de=(e=null)=>e?`the instances in ${e}, in a browser under the export's policy`:"the workspace's documents",q="component-check",ae=[360,736,1024],Le=["light","dark"],Lt=[1024,360],nt=1e4,rt=6e4,se=3e4,Dn=12e4,lt=2e3,Rt=3e3,Dt=60,Mn=15e3,Mt=2,Pt=8,Ct=se/2,_t=/^(?:wasm-)?eval$/,It=new Set(["TargetCloseError","ConnectionClosedError"]),Pn=e=>e.evaluateOnNewDocument(Ft,St);function Ft(e){let t=globalThis.fetch;if(typeof t!="function"||globalThis.__galleryQueries)return;let i={pending:new Map,count:0};globalThis.__galleryQueries=i,globalThis.fetch=function(r,n){let a=t.apply(this,arguments);try{let p=new URL(typeof r=="string"?r:r?.url??String(r),location.href);if(p.pathname===e){let u=++i.count,w=/\/__gallery\/components\/([a-z0-9-]+\/[a-z0-9-]+)\/kit\.js/.exec(new Error().stack??"");i.pending.set(u,{kind:p.searchParams.get("kind"),block:w?w[1]:null,at:Date.now()});let l=()=>{i.pending.delete(u)};Promise.resolve(a).then(l,l)}}catch{}return a}}var oe=e=>String(e?.message??e).split(`
3
- `)[0],ct=(e,t)=>`<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>${e}</title></head><body><main class="doc-page" data-doc-id="${e}">${t}
4
- </main></body></html>
5
- `,Bt=({example:e,template:t})=>`<p>example.html</p>${e}
6
- <hr><p>template.html</p>${t}`,Ht=e=>{for(let t=e.parentNode;t;t=t.parentNode)if(bt(t))return!0;return!1},dt=(e,t)=>ot(e,t).filter(i=>!Ht(i)),Me=(e,t)=>dt(ce(e),t).map(({sourceCodeLocation:{startLine:i,startOffset:r,endOffset:n}})=>({line:i,markup:e.slice(r,n)}));async function ht(e,t){let i=x.join(t,"components",...e.id.split("/"));for(let r of[Ot,"template.html",...e.files]){let n=ze(e,r);if(!n)continue;let a=await T.readFile(n);await T.mkdir(x.dirname(x.join(i,r)),{recursive:!0}),await T.writeFile(x.join(i,r),r==="kit.js"?`${a}
7
- //# sourceURL=kit.js
8
- `:a)}}async function Wt(e,{example:t,template:i},r){await ht(e,r);let n=x.join(r,q);await T.mkdir(n);let a=`${t}
9
- `,p=je(ct(q,Bt({example:t,template:i}))).text;await T.writeFile(x.join(n,"doc.html"),p),await T.writeFile(x.join(n,"doc.json"),JSON.stringify({title:q,description:q,type:"component"}));let w=await(await Se({directory:r,catalog:le(r)}))(q),l=x.join(r,"export.html");await T.writeFile(l,w);let f=a.split(`
10
- `).length-1,s=Me(p,e).map(({line:c})=>c>f?{file:"template.html",line:c-f}:{file:"example.html",line:c});return{html:w,file:l,places:s,source:p}}function qt({match:e,instance:t,slot:i,parts:r,boards:n}){if(!Object.entries(r).some(([l,{edit:f}])=>f==="data"&&!n.includes(l)))return[];let a=[...document.querySelectorAll(e)].filter(l=>!l.parentElement.closest(t)),p=l=>l.parentElement?.closest(`${t}, ${i}`)??null,u=l=>`<${l.localName}${l.classList.length?` class="${l.getAttribute("class")}"`:""}>`,w=l=>{let f=(l.textContent||l.getAttribute("aria-label")||l.getAttribute("placeholder")||l.getAttribute("title")||"").replace(/\s+/g," ").trim().slice(0,24);return`${u(l)}${f?` "${f}"`:""}`};return a.flatMap((l,f)=>{let s=[...l.querySelectorAll("button, input, select, textarea")].filter(c=>p(c)===l).filter(c=>{if(c.disabled||c.readOnly||c.type==="hidden")return!1;let h=c.getBoundingClientRect(),b=getComputedStyle(c);return h.width>0&&h.height>0&&b.visibility!=="hidden"&&b.display!=="none"});return s.length?[{at:f,what:s.slice(0,3).map(w).join(", "),counts:[s.length]}]:[]})}async function Gt({match:e,instance:t,slotPart:i,slotName:r,fallback:n,parts:a,boards:p,at:u,source:w,still:l,step:f,times:s,typed:c,typing:h}){let b=()=>[...document.querySelectorAll(e)].filter(o=>!o.parentElement.closest(t)),k=o=>new Promise(d=>setTimeout(d,o)),g=()=>new Promise(o=>{requestAnimationFrame(o),setTimeout(o,100)}),m=async o=>{await g(),await g();let d=o.outerHTML;for(let y=0,v=Date.now()+l;y<3;){if(Date.now()>v)return null;await k(f);let E=o.outerHTML;y=E===d?y+1:0,d=E}return d},_=o=>{let d=document.createElement("template");return d.innerHTML=o,d.content.firstElementChild},$=o=>`<${o.localName}${o.classList.length?` class="${o.getAttribute("class")}"`:""}>`,S=o=>o.nodeType===1?$(o):`the words "${o.data.trim().slice(0,40)}"`,B=o=>[...o.childNodes].filter(d=>d.nodeType===1||d.nodeType===3&&d.data.trim()),H=(o,d)=>["style","class"].includes(d)&&!o.getAttribute(d)?.trim()?null:o.getAttribute(d),D=(o,d)=>{for(let E of new Set([...o.getAttributeNames(),...d.getAttributeNames()]))if(H(o,E)!==H(d,E))return`${E} on ${$(d)}, ${JSON.stringify(H(o,E))} then ${JSON.stringify(H(d,E))}`;let[y,v]=[B(o),B(d)];for(let E=0;E<Math.max(y.length,v.length);E++){let[N,M]=[y[E],v[E]];if(!N||!M)return`${$(d)} ${N?`without ${S(N)}`:`with ${S(M)} more`}`;if(N.nodeType!==M.nodeType||N.localName!==M.localName||N.nodeType===3&&N.data.trim()!==M.data.trim())return`in ${$(d)}, ${S(N)} then ${S(M)}`;let I=N.nodeType===1?D(N,M):null;if(I)return I}return null},ue=o=>{let d=new Map;for(let y of o)d.set($(y),(d.get($(y))??0)+1);return d},_e=()=>[...document.querySelectorAll("*")].filter(o=>!o.closest(t)),Ie=o=>[...o.at(-1).keys()].filter(d=>o.length>2&&o.every((y,v)=>v===0||(y.get(d)??0)>(o[v-1].get(d)??0))),Fe=o=>o.parentElement?.closest(`${t}, ${i}`)??null,Be=o=>[...o.querySelectorAll(i)].filter(d=>Fe(d)===o),G=o=>{let d=o.cloneNode(!0);return Be(d).forEach(y=>y.replaceChildren()),d},Z=o=>Be(o).map(d=>{let y=[];for(let v=d.parentElement;v&&v!==o;v=v.parentElement)y.unshift($(v));return{name:d.getAttribute(r),place:y.join(" > "),blocks:[...DocKit.dehydrate(d.cloneNode(!0)).children].map(v=>v.localName).join(" "),html:DocKit.dehydrate(d.cloneNode(!0)).outerHTML}}),we=(o,d,y,{markup:v=!0}={})=>o.flatMap(({name:E,place:N,blocks:M,html:I})=>{let A=d.find(W=>W.name===E),X=A?A.place!==N?`moved the slot ${E} (${A.place?`in ${A.place}`:"straight in the instance"}, where the file has it ${N?`in ${N}`:"straight in the instance"})`:A.blocks!==M?`changed the blocks the slot ${E} holds (${M||"none"}, then ${A.blocks||"none"})`:v&&A.html!==I?`changed what the slot ${E} holds`:null:`took the slot ${E} off the instance`;return X?[{kind:"written-in",part:E,how:`${X}, ${y}`}]:[]}),He=o=>d=>Fe(d)===o,fe=(o,d=()=>!0)=>Object.entries(a).filter(([,{edit:y}])=>d(y)).flatMap(([y,v])=>[...o.querySelectorAll(v.at)].filter(He(o)).map(E=>({name:y,node:E}))),ee=o=>fe(o,d=>d==="text"),K=o=>Object.entries(a).filter(([,{edit:d}])=>d==="data").map(([d,y])=>({name:d,node:[...o.querySelectorAll(y.at)].find(He(o))})).filter(({node:d})=>d),C=[],V=b()[u];if(!V)return[{kind:"gone"}];if(V.hasAttribute(n))return[{kind:"fallback"}];let me=await m(V);if(me===null)return[{kind:"moving"}];let ie=_(w),We=Z(V);C.push(...we(Z(ie),We,"as it mounts",{markup:!1}));let ge=ee(ie);ee(V).forEach(({name:o,node:d},y)=>{ge[y]&&ge[y].node.innerHTML!==d.innerHTML&&C.push({kind:"redrawn",part:o,how:`the file says ${JSON.stringify(ge[y].node.textContent.trim())}, the page ${JSON.stringify(d.textContent.trim())}`})});let ke=DocKit.dehydrate(V.cloneNode(!0)),[qe,Ge]=[G(ie),G(ke)],ye=D(qe,Ge);if(ye){let o=fe(Ge),d=fe(qe).find(({node:y},v)=>o[v]&&D(y,o[v].node))?.name;C.push({kind:"left",what:ye,...d?{part:d}:{}})}let ft=K(ke);for(let[o,{name:d,node:y}]of K(ie).entries())!ye&&ft[o]?.node.innerHTML!==y.innerHTML&&C.push({kind:"data",part:d});let Q=[],be=new MutationObserver(o=>Q.push(...o));be.observe(document.documentElement,{subtree:!0,childList:!0,characterData:!0});let Ue=new Set,Je=o=>{Q.push(...be.takeRecords());for(let{name:d,node:y}of o)(!y.isConnected||Q.some(({target:v})=>y.contains(v)))&&Ue.add(d);Q.length=0},$e=[me],xe=[ue(_e())],Ke=o=>{$e.push(o),xe.push(ue(_e())),C.push(...we(We,Z(j),"as it mounts again"))},j=ke,ve=ee(j);Q.length=0,V.replaceWith(j);let U=await m(j);if(Je(ve),U!==null){Ke(U);for(let o=0;o<s&&U!==null;o++){let d=j.cloneNode(!0);ve=ee(d),Q.length=0,j.replaceWith(d),j=d,U=await m(j),Je(ve),U!==null&&Ke(U)}}be.disconnect(),U===null&&C.push({kind:"moving"});for(let o of Ue)C.push({kind:"redrawn",part:o,how:"a mount changes it"});let Ve=$e.map(o=>ue(G(_(o)).querySelectorAll("*"))),Ye=Ie(Ve);for(let o of Ye)C.push({kind:"piles",what:o,counts:Ve.map(d=>d.get(o)??0)});for(let o of Ie(xe))C.push({kind:"piles",what:o,outside:!0,counts:xe.map(d=>d.get(o)??0)});if(!Ye.length){let o=$e.slice(1).map(d=>D(G(_(me)),G(_(d)))).find(Boolean);o&&C.push({kind:"changed",what:o})}let re=U===null?[]:ee(j).filter(({node:o})=>o.textContent.trim()),mt=[...new Set([...new Map(re.map(o=>[o.name,o])).values(),...re])].slice(0,c),gt=Date.now()+h;for(let{node:o}of mt){if(Date.now()>gt)break;let d=document.createTreeWalker(o,NodeFilter.SHOW_TEXT).nextNode(),y=d.data;d.data=`${y}\u2026`;let v=re.map(({node:N})=>N.textContent);await m(j);let E=re.find(({node:N},M)=>!N.isConnected||N.textContent!==v[M]);if(E){C.push({kind:"redrawn",part:E.name,how:"a change of its words does not stand"});break}d.data=y,await m(j)}return U!==null&&K(j).length>0&&C.push(...await kt()),C;async function kt(){let o=[],d=null,y=!1,v="as it hears that it can write (the editable signal)",E=[],N=I=>{if(I.target!==j)return;let{parts:A,run:X}=I.detail,W=A.map(({part:O})=>O.innerHTML),P=A.map(({part:O})=>O.cloneNode(!0)),te=X(Object.fromEntries(A.map(({name:O},R)=>[O,P[R]]))),J=A.find(({part:O},R)=>O.innerHTML!==W[R]),Y=A.find(({part:O},R)=>P[R].cloneNode(!1).outerHTML!==O.cloneNode(!1).outerHTML);if(J&&A.forEach(({part:O},R)=>{O.innerHTML=W[R]}),!y){let O=J??Y??A.find((R,ne)=>P[ne].innerHTML!==W[ne]);O&&!E.some(R=>R.when===v)?E.push({kind:"unasked",part:O.name,when:v}):te&&!O&&I.preventDefault();return}J?d??=`it writes the part ${J.name} on the page, not the draft context.edit hands it, so the editor refuses the edit`:te&&Y&&(d??=`it changes the part ${Y.name}'s own tag or attributes, which are the file's: a change writes what a part holds, so the editor refuses the edit`),!(J||!te||Y)&&(A.forEach(({part:O},R)=>{o.push({part:O,before:W[R]}),O.replaceChildren(...P[R].childNodes)}),I.preventDefault())};document.addEventListener("doc-component-edit",N);try{return[...await M(),...E]}finally{document.removeEventListener("doc-component-edit",N)}async function M(){dispatchEvent(new Event("doc-editable")),await m(j),v="as it mounts";let I=j.cloneNode(!0);j.replaceWith(I),j=I;let A=await m(j);v="as it hears its part changed (the source signal)";let X=Z(j),W=DocKit.dehydrate(j.cloneNode(!0)),P=[];y=!0;try{if(!DocKit.example(j))return K(j).every(({name:F})=>p.includes(F))?[]:[{kind:"no-example"}]}catch(F){return[{kind:"example",what:`it throws: ${F?.message??F}`}]}finally{y=!1}let te=await m(j),J=DocKit.dehydrate(j.cloneNode(!0)),Y=Object.fromEntries(K(J).map(({name:F,node:z},yt)=>[F,z.innerHTML,K(W)[yt]?.node.innerHTML]).filter(([,F,z])=>F!==z));d?P.push({kind:"example",what:d}):o.length===0?P.push({kind:"example",what:"context.edit was not taken: it was not called, or it answered false, and the console says why"}):Object.keys(Y).length===0?P.push({kind:"example",what:"it changes nothing a part holds"}):P.push({kind:"wrote",parts:Y});for(let F of[W,J])for(let{node:z}of K(F))z.textContent="";let O=D(G(W),G(J));O&&P.push({kind:"example",what:`it changes what is no data part: ${O}`}),P.push(...we(X,Z(j),"as its example makes its edit"));for(let{part:F,before:z}of o.reverse())F.innerHTML=z;let R=await m(j),ne=A!==null&&R!==null?D(G(_(A)),G(_(R))):null;return te===null||R===null?P.push({kind:"moving"}):ne&&!O&&P.push({kind:"undo",what:ne}),P}}}var Ut=e=>e.map(({name:t,removed:i,added:r,lines:n})=>`${t} (-${i} +${r} of its ${n} line${n===1?"":"s"})`).join(" and "),Jt="a write changes the lines it means and no others: a row moved by context.rows, which takes the blank before it along, JSON written back by context.editJSON and laid out in template.html and example.html as it writes it (block-script.md, Two examples)";function Re(e,t){try{return JSON.parse(e),Et(e,JSON.parse(t))===t}catch{return!1}}var Kt="it changes nothing a part holds";function Vt({kind:e,what:t,part:i,how:r,when:n,counts:a,outside:p,parts:u,back:w,line:l,json:f},s,{script:c}){let h=k=>({...s,what:k}),b=k=>({...s,what:k,note:!0});switch(e){case"wrote":return{...s,told:!0,what:`its example wrote ${Ut(u)}; the server took it${w?"; put back as an undo does, it shows what it showed":""}`};case"laid":return b(`its example's write lays the part ${i} out anew (${r}): ${Jt}${f?`; this write is context.editJSON's, and what the file held is laid out otherwise: lay ${i} out as it writes it`:""}`);case"drops":return{...b(`${t} listens for dragover and not for dragenter: a drop goes where both are cancelled, and the move that enters it asks dragenter alone, so that a release then (on a card's words, its padding) drops nothing: cancel dragenter as dragover is cancelled (preventDefault)`),file:"kit.js",line:l};case"controls":return{...b(`where nothing is written (this look is an export: context.canEdit() is false) the instance of ${s.file}${s.line?`:${s.line}`:""} still shows ${t}${a[0]>3?` and ${a[0]-3} more`:""}, enabled, and the block has a data part: a reader presses a control that writes to no effect, and the export says the block can be edited. Draw a control that writes only while context.canEdit(), and hide it by the hidden attribute (the kit holds [hidden] over any display the style gives it) or disable it; ignore this for a control that only changes what a reader looks at, a filter or a tab, which an export keeps. Compare 1024-light.png with edit-1024-light.png: the second is what a reader who can edit sees`),file:"kit.js",line:void 0};case"gone":return h("the page does not hold this instance");case"fallback":return h(c?"its component failed or never started: the instance shows what it holds, read-only":"the instance shows as one of no custom block");case"moving":return b("what it shows never holds still (an animation?), so its mounts could not be compared");case"redrawn":return h(`the component redraws its text part ${i}: ${r}. A text part is the file's, what the user types in: read it, and draw in what is the component's`);case"left":return h(`dehydrate does not leave it as the file has it, so a copy of the view would hold what the kit made of it: ${t}. ${i?`That stands in its part ${i}, which is the file's: read a part, and draw in what is the component's`:"Name what it draws in the manifest's runtime, or take it off in dehydrate"}`);case"data":return h(`a mount changes its data part ${i}, so that a page would write what the component left there, with nothing edited: read a data part, and change it by context.edit alone`);case"no-example":return b("it has a data part and its component offers no example of an edit, so nothing has tried the way back to the file: give DocKit.component an example(host, context) that makes a small context.edit");case"example":return t===Kt?{...s,file:"kit.js",line:void 0,what:`its example(host, context) changes nothing a part holds on the instance of ${s.file}${s.line?`:${s.line}`:""}: the check runs it on every instance of example.html and of template.html, and template.html's is empty, with nothing to change a value of (the first entry of a list it does not hold yet). Make example() make a change that works on an empty instance too (add an entry, set a field), and have it call the function a reader's control calls, so that it tries the code a reader runs`}:h(`its example: ${t}`);case"refused":return h("what its example wrote cannot go in the file: a script, a handler, an address of code, data-block-id or data-ge-*, what does not read back as itself, or what is no JSON in a script of data");case"undo":return h(`with what its example wrote put back, as an undo does, it does not show what it showed: ${t}: draw from the part, and on the source signal`);case"unasked":return h(`it writes its data part ${i} with no reader's gesture, ${n}, once the page takes edits: a page would write it each time it opened. Call context.edit on a gesture alone, a press, a drop or a key, and draw what the part holds as it is`);case"written-in":return h(`kit.js ${r}: a slot is the document's, its blocks the reader's: read it with context.part, never write in it or move it, and draw outside it`);case"piles":return h(p?`${t} piles up outside the instance on each put-back (${a.join(", then ")} of them), so an undo adds another: a component draws in its instance, and what it has to put elsewhere it takes away again in destroy`:`${t} piles up on each put-back (${a.join(", then ")} of them): it is declared in neither the manifest's runtime nor dehydrate, so an undo adds another`);default:return h(`a mount does not give the same DOM again: ${t}`)}}var Yt=e=>[...new Map(e.toReversed().map(t=>[`${t.finding.kind}|${t.finding.part??""}|${["piles","example"].includes(t.finding.kind)?t.finding.what:""}|${t.finding.when??""}|${t.finding.line??""}`,t])).values()].toReversed(),zt=4e6;function Pe(e,t,i=(r,n)=>r===n){let[r,n]=[e.split(`
11
- `),t.split(`
12
- `)],a=0;for(;a<r.length&&a<n.length&&i(r[a],n[a]);)a++;let p=0;for(;p<r.length-a&&p<n.length-a&&i(r[r.length-1-p],n[n.length-1-p]);)p++;let[u,w]=[r.slice(a,r.length-p),n.slice(a,n.length-p)];if(u.length===0&&w.length===0)return[];if(u.length*w.length>zt)return[{removed:u,added:w}];let l=Array.from({length:u.length+1},()=>new Uint32Array(w.length+1));for(let c=u.length-1;c>=0;c--)for(let h=w.length-1;h>=0;h--)l[c][h]=i(u[c],w[h])?l[c+1][h+1]+1:Math.max(l[c+1][h],l[c][h+1]);let f=[],s=null;for(let c=0,h=0;c<u.length||h<w.length;)c<u.length&&h<w.length&&i(u[c],w[h])?(s=null,c++,h++):(s||f.push(s={removed:[],added:[]}),h<w.length&&(c===u.length||l[c][h+1]>=l[c+1][h])?s.added.push(w[h++]):s.removed.push(u[c++]));return f}function Qt(e,t){let i=n=>n.filter(a=>a.trim()).length,r=Pe(e,t);return{removed:r.reduce((n,a)=>n+i(a.removed),0),added:r.reduce((n,a)=>n+i(a.added),0),lines:i(e.split(`
13
- `))}}function Cn(e,t){let i=r=>r.map(n=>n.trim()).filter(Boolean);return Pe(e,t).map(({removed:r,added:n})=>({removed:i(r),added:i(n)})).filter(({removed:r,added:n})=>r.length+n.length>0)}function at(e,t){let i=0,r=0;for(let[n,a]of e.entries())if(n>0&&i>0&&i<t&&r++,i+=a.replace(/\s+/g,"").length,i>=t)break;return r}function Xt(e,t){let i=r=>r.filter(n=>!n.trim()).length;for(let{removed:r,added:n}of Pe(e,t,(a,p)=>a.trim()===p.trim())){if(i(n)>i(r))return"a line left blank";let[a,p]=[r.join("").replace(/\s+/g,""),n.join("").replace(/\s+/g,"")],u=0;for(;u<a.length&&u<p.length&&a[u]===p[u];)u++;let w=0;for(;w<a.length-u&&w<p.length-u&&a[a.length-1-w]===p[p.length-1-w];)w++;for(let[l,f,s]of[[u,r,n],[w,r.toReversed(),n.toReversed()]]){let[c,h]=[at(f,l)+1,at(s,l)+1];if(c!==h)return`${c} line${c===1?"":"s"} became ${h}`}}return null}function Zt(e,t){let i=Xt(e,t);return i&&!(Re(e,t)&&Re(e,e))?i:null}function en(e,{source:t,found:i,at:r,findings:n}){let a=Qe(t,dt(ce(t),i)[r],e.parts,new Map([[i.id,i]]));if(!a)return[{kind:"refused"}];let p=Object.keys(e.parts),u=a.map(({start:l,end:f,text:s},c)=>({name:p[c],before:t.slice(l,f),after:s}));return[{kind:"wrote",back:!n.some(({kind:l})=>l==="undo"||l==="moving"),parts:u.map(({name:l,before:f,after:s})=>({name:l,...Qt(f,s)}))},...u.flatMap(({name:l,before:f,after:s})=>{let c=Zt(f,s);return c?[{kind:"laid",part:l,how:c,json:Re(f,s)}]:[]})]}var tn=2e3;function nn({match:e,instance:t,at:i,most:r}){let n=[...document.querySelectorAll(e)].filter(a=>!a.parentElement.closest(t))[i];return n?[window,document,n,...n.querySelectorAll("*")].slice(0,r):[]}function an(e){return e.map((t,i)=>i<2?{parent:i-1,named:""}:{parent:i===2?1:e.indexOf(t.parentElement),named:`<${t.localName}${t.classList.length?` class="${t.getAttribute("class")}"`:""}>`})}function sn(){let e=new DragEvent("dragenter",{bubbles:!0,cancelable:!0,composed:!0,dataTransfer:new DataTransfer});return this.dispatchEvent(e),e.defaultPrevented}async function on(e,{match:t,at:i}){let r=new Map,n=({scriptId:a,url:p})=>r.set(a,p);e.on("Debugger.scriptParsed",n);try{await e.send("Debugger.enable"),await e.send("Debugger.setSkipAllPauses",{skip:!0});let{result:a}=await e.send("Runtime.evaluate",{expression:`(${nn})(${JSON.stringify({match:t,instance:he,at:i,most:tn})})`,objectGroup:"drops"}),{result:p}=await e.send("Runtime.callFunctionOn",{objectId:a.objectId,functionDeclaration:String(an),arguments:[{objectId:a.objectId}],returnByValue:!0}),{result:u}=await e.send("Runtime.getProperties",{objectId:a.objectId,ownProperties:!0}),w=u.filter(({name:c,value:h})=>/^\d+$/.test(c)&&h?.objectId).sort((c,h)=>Number(c.name)-Number(h.name)),l=[];for(let{value:c}of w)l.push((await e.send("DOMDebugger.getEventListeners",{objectId:c.objectId})).listeners);let f=(c,h)=>l[c]?.some(b=>b.type===h),s=[];for(let c=2;c<l.length;c++){let h=l[c].find(k=>k.type==="dragover"&&r.get(k.scriptId)==="kit.js");if(!h)continue;let b=!1;for(let k=c;k>=2&&!b;k=p.value[k].parent)b=f(k,"dragenter");if(!b&&(f(0,"dragenter")||f(1,"dragenter"))){let{result:k}=await e.send("Runtime.callFunctionOn",{objectId:w[c].value.objectId,functionDeclaration:String(sn),returnByValue:!0});b=k.value===!0}b||s.push({kind:"drops",what:p.value[c].named,line:h.lineNumber+1})}return s}finally{e.off("Debugger.scriptParsed",n),await e.send("Runtime.releaseObjectGroup",{objectGroup:"drops"}).catch(()=>{}),await e.send("Debugger.disable").catch(()=>{})}}function rn(e,t){let i={errors:new Map,notes:new Set,failed:new Set,dialogs:new Set,windows:0,opened:[],asked:1,pending:[]},r=n=>{let[a]=n.split(`
14
- `);i.errors.has(a)||i.errors.set(a,Number(/\bkit\.js:(\d+)/.exec(n)?.[1])||null)};return e.on("pageerror",n=>r(n.stack??n.message)),e.on("console",n=>{let a=n.type();!["error","warn","warning"].includes(a)||!Xe(n,t,["kit.js"])||i.pending.push(Promise.all(n.args().map(p=>p.evaluate(u=>u instanceof Error?u.stack:String(u)).catch(()=>""))).then(p=>{let u=p.join(" ")||n.text();a==="error"?r(u):i.notes.add(u.split(`
15
- `)[0])}))}),e.on("requestfailed",n=>{n.frame()===e.mainFrame()&&!n.isNavigationRequest()&&i.failed.add(n.url())}),e.on("request",n=>{n.isNavigationRequest()&&n.frame()===e.mainFrame()&&i.opened.push(n.url())}),i}async function ln(e,t){let i=await e.createCDPSession();return await i.send("Page.enable"),i.on("Page.javascriptDialogOpening",({type:r})=>{t.add(r),i.send("Page.handleJavaScriptDialog",{accept:!1}).catch(()=>{})}),i}function L(e,t,i=se){let r=0,n=()=>Object.assign(new Error(t),{stuck:!0,doing:t,limit:i}),a=new Promise((u,w)=>{r=setTimeout(()=>w(n()),i)}),p=e.catch(u=>{throw It.has(u.name)?n():Object.assign(u,{doing:t})});return Promise.race([p,a]).finally(()=>clearTimeout(r))}var cn=e=>`${Number((e/1e3).toFixed(1))} s`,pt=e=>`the browser did not answer within ${cn(e.limit)}, waiting until ${e.doing}`,Ce=e=>new Promise(t=>{if(!e.connected)return t(!0);e.once("disconnected",()=>t(!0)),setTimeout(()=>t(!1),lt)});function dn({match:e,instance:t}){let{clientWidth:i,scrollWidth:r}=document.documentElement;if(r<=i+1)return null;let n=[...document.querySelectorAll(e)].filter(a=>!a.parentElement.closest(t));return{wide:r,at:n.findIndex(a=>[a,...a.querySelectorAll("*")].some(p=>p.getBoundingClientRect().right>i+1))}}var st=16,hn="#8f8f8f";async function pn(e,t,i){let r=await Promise.all(t.map(async n=>`data:image/png;base64,${(await T.readFile(n)).toString("base64")}`));await e.setViewport({width:ae.reduce((n,a)=>n+a,0)+st*(ae.length-1),height:900}),await e.setContent(`<!doctype html><body style="margin: 0; display: flex; align-items: flex-start; gap: ${st}px; background: ${hn}">${r.map((n,a)=>`<img src="${n}" width="${ae[a]}" alt="" style="display: block">`).join("")}</body>`,{waitUntil:"load"}),await e.screenshot({path:i,fullPage:!0})}async function ut(e,{file:t,html:i,source:r,places:n,found:a,out:p,loading:u,answer:w=se}){let l=(m,_)=>L(m,_,w),f=await l(e.createBrowserContext(),"a browser context opened"),s=await l(f.newPage(),"a tab opened"),c=De(t).href,h=rn(s,c),b=await l(ln(s,h.dialogs),"the tab was set to refuse dialogs");f.on("targetcreated",m=>{m.type()==="page"&&(h.windows+=1,m.page().then(_=>_?.close()).then(()=>s.bringToFront()).catch(()=>{}))});let k={heard:h,blocked:[],late:[],taken:[],overviews:[],edited:[],asExport:[],answers:[],wide:[],stuck:null,stopped:null,gone:null},g=async m=>k.late.push(...await L(et(s,{timeout:nt}),m,3*nt+se));await l(Ze(s),"the tab was set to keep what the policy blocks"),await l(s.setViewport({width:736,height:900}),"the window went to 736px"),await l(s.emulateMediaFeatures([{name:"prefers-color-scheme",value:"light"}]),"the light theme came");try{await L(s.goto(c,{waitUntil:"load",timeout:0}),"the page opened",u),await g("the page opened");for(let $ of Le){await L(s.emulateMediaFeatures([{name:"prefers-color-scheme",value:$}]),`the ${$} theme came`);for(let S of ae){if(await L(s.setViewport({width:S,height:900}),`the window went to ${S}px`),await g(`it was drawn at ${S}px`),$===Le[0]){let H=await L(s.evaluate(dn,{match:a.match,instance:he}),`it was measured at ${S}px`);H&&k.wide.push({width:S,...H})}let B=x.join(p,`${S}-${$}.png`);await L(s.screenshot({path:B,fullPage:!0}),`it was pictured at ${S}px`),k.taken.push(B)}}await L(s.emulateMediaFeatures([{name:"prefers-color-scheme",value:"light"}]),"the light theme came"),await L(s.setViewport({width:736,height:900}),"the window went to 736px");let m=Me(i,a);for(let{at:$,...S}of await L(s.evaluate(qt,{match:a.match,instance:he,slot:tt,parts:a.parts,boards:a.settings?.length?[Ee]:[]}),"the page was asked what each instance still shows"))k.answers.push({finding:{kind:"controls",...S},place:n[$]});let _=a.files.includes("kit.js")&&Object.values(a.parts).some(({edit:$})=>$==="data");for(let $=0;$<m.length;$++){let S=await L(s.evaluate(Gt,{match:a.match,instance:he,slotPart:tt,slotName:vt,fallback:xt,parts:a.parts,boards:a.settings?.length?[Ee]:[],at:$,source:m[$].markup,still:Rt,step:Dt,times:Mt,typed:Pt,typing:Ct}),"an instance was put back"),B=S.find(({kind:D})=>D==="wrote"),H=[...S.filter(D=>D!==B),...B?en(B,{source:r,found:a,at:$,findings:S}):[]];_&&!S.some(({kind:D})=>D==="gone"||D==="fallback")&&H.push(...await L(on(b,{match:a.match,at:$}),"the page was asked what an instance listens to")),k.answers.push(...H.map(D=>({finding:D,place:n[$]})))}k.blocked=await L(s.evaluate(()=>globalThis.__qaViolations),"the page was asked what it blocked"),h.asked+=1,await L(s.goto(c,{waitUntil:"load",timeout:0}),"the page opened again",u),await g("the page opened again"),await L(s.evaluate(()=>dispatchEvent(new Event("doc-editable"))),"the page was told it takes edits"),await g("it was drawn as the editing page draws it");for(let $ of Lt){await L(s.setViewport({width:$,height:900}),`the window went to ${$}px`),await g(`it was drawn at ${$}px as the editing page draws it`);let S=x.join(p,`edit-${$}-light.png`);await L(s.screenshot({path:S,fullPage:!0}),`it was pictured at ${$}px as the editing page draws it`),k.edited.push(S),(await T.readFile(S)).equals(await T.readFile(x.join(p,`${$}-light.png`)))&&k.asExport.push(S)}k.blocked.push(...await L(s.evaluate(()=>globalThis.__qaViolations),"the page was asked what it blocked"));for(let $ of Le){let S=x.join(p,`overview-${$}.png`);await L(pn(s,ae.map(B=>x.join(p,`${B}-${$}.png`)),S),`the ${$} pictures were put side by side`),k.overviews.push(S)}}catch(m){if(m.syscall)throw m;await Ce(e)?k.gone=m.doing??"the page answered":m.stuck?k.stuck=m.doing:k.stopped=oe(m)}return await Promise.race([Promise.all(h.pending),new Promise(m=>setTimeout(m,lt).unref())]),k}var un=(e,t)=>e.startsWith(t)?e.slice(t.length):e;function wn(e,t,i){let r=new Map;for(let{url:n,directive:a,source:p,line:u}of e){if(_t.test(n)){let l=!p&&u>0;r.set(`${n}|${p}|${u}`,{file:l?"kit.js":"the page",...l?{line:u}:{},what:"the export's policy blocks code made from words (eval, new Function, a string given to setTimeout): an export runs none"});continue}let w=/^[a-z][a-z0-9+.-]*$/.test(n)?t.filter(l=>l.startsWith(`${n}:`)):[];for(let l of w.length?w:[n])r.set(`${l}|${a}`,{file:"the page",what:`the export's policy blocks ${un(l,i)||"something"} (${a}): ${a==="img-src"?"a picture of an instance is a data: address, or a file its style names":"an export holds all it needs"}`})}return[...r.values()]}function wt({heard:e,blocked:t,late:i,answers:r,wide:n,stuck:a,stopped:p},{places:u,script:w,folder:l}){let f=Yt(r).map(({finding:g,place:m})=>Vt(g,m,{script:w})),s=[...e.failed],c=s.filter(g=>!t.some(m=>m.url&&g.startsWith(m.url))),h=e.opened.length>e.asked?"it loads itself again (location.reload(), a new location.href), so a reader's page would not stay":a?`it stopped answering while waiting until ${a}${w?": a script that never ends, or a component that changes what it hears (a text part, on its source signal)":""}`:p&&`the look at it stopped: ${p}`,b=n.map(({width:g,wide:m})=>`${m}px wide in a ${g}px window`).join(", "),k=u[n.find(({at:g})=>g>=0)?.at]??{file:"the page"};return{problems:[...[...e.errors].map(([g,m])=>({file:m?"kit.js":"the page",line:m,what:`the console says ${g}`})),...wn(t,s,l),...c.map(g=>({file:"the page",what:`it could not load ${g.slice(0,120)}`})),...[...e.dialogs].map(g=>({file:"the page",what:`it opens a dialog (${g}), which stops a reader's page until it is answered: show what it says in the instance`})),...e.windows?[{file:"the page",what:"it opens a window, which takes a reader away from the page: show it in the instance, or link to it"}]:[],...h?[{file:"the page",what:h}]:[],...n.length?[{...k,what:`the page is ${b}: a reader scrolls the whole page sideways, and gallery qa fails it: let it fit the window (max-width: 100%), or put what is wider in a frame of its own that scrolls`}]:[],...f.filter(({note:g,told:m})=>!g&&!m)],notes:[...[...e.notes].map(g=>({file:"the page",what:`the console says ${g}`})),...f.filter(({note:g})=>g),...i.map(g=>({file:"the page",what:`waited for ${g}`}))],told:f.filter(({told:g})=>g)}}async function _n(e,t,{example:i,template:r},{find:n=Ne,start:a=Ae,loading:p=rt,answer:u=se}={}){let w=At,l=null,f=null;try{l=await T.mkdtemp(x.join(pe.tmpdir(),"gallery-component-check-"));let s=await Wt(t,{example:i,template:r},l),c=n();if(!c)return{title:w,unverified:"no Chrome, Edge or Chromium found (GALLERY_BROWSER=<its executable> picks one)"};try{f=await a({executablePath:c,args:Oe()})}catch(g){return{title:w,unverified:`the browser ${c} did not start, twice, each time with a fresh profile (${oe(g)}; GALLERY_BROWSER=<its executable> picks another)`}}let h=x.join(it(e).qa,"components",...t.id.split("/"));await T.rm(h,{recursive:!0,force:!0}),await T.mkdir(h,{recursive:!0});let b=await ut(f.browser,{...s,found:t,out:h,loading:p,answer:u}),k=wt(b,{places:s.places,script:t.files.includes("kit.js"),folder:De(`${l}${x.sep}`).href});return b.gone?{title:w,...k,unverified:`the browser went while waiting until ${b.gone}, so it says nothing of the block`}:{title:w,...k,...b.taken.length?{pictures:{folder:h,overviews:b.overviews.map(g=>x.basename(g)),each:b.taken.map(g=>x.basename(g)),edited:b.edited.map(g=>x.basename(g)),asExport:b.asExport.map(g=>x.basename(g))}}:{}}}catch(s){return s.reason==="check"?{title:w,problems:s.failures.map(c=>({file:"the export",what:c}))}:s.syscall?{title:w,unverified:`cannot write ${Te(s.syscall==="mkdtemp"?pe.tmpdir():s.path)} (${s.code})`}:f&&await Ce(f.browser)?{title:w,unverified:"the browser went before the page opened"}:s.stuck?{title:w,problems:[{file:"the page",what:`${pt(s)}, so the look stopped and the browser was closed`}]}:{title:w,problems:[{file:"the page",what:`the look at it stopped: ${oe(s)}`}]}}finally{await f?.close(),l&&await T.rm(l,{recursive:!0,force:!0,maxRetries:5,retryDelay:200}).catch(()=>{})}}async function fn(e,t){let i=[];for(let r of await Nt(e)){let n=jt(r,e),a=Tt(n).html,p=await T.readFile(a,"utf8").catch(()=>null);if(p===null)continue;let u=ot(ce(p),t),w=f=>{for(let s=f.parentNode;s;s=s.parentNode)if(u.includes(s))return!0;return!1},l=u.filter(f=>!w(f)).map(({sourceCodeLocation:{startLine:f,startOffset:s,endOffset:c}})=>({line:f,markup:p.slice(s,c)}));l.length&&i.push({slug:r,place:`${r}/${x.basename(a)}`,directory:n,instances:l})}return i}async function mn(e,t,i,r){let n=t.instances.map(({line:s,markup:c})=>`<p>${t.place}:${s}</p>${c}`).join(`
16
- `);for(let s of new Set([e.id,...[...n.matchAll(new RegExp(`${$t}="([^"]+)"`,"g"))].map(([,c])=>c)])){let c=s===e.id?e:i.get(s);c&&await ht(c,r)}let a=x.join(r,q);await T.mkdir(a),await T.cp(x.join(t.directory,"assets"),x.join(a,"assets"),{recursive:!0}).catch(s=>{if(s.code!=="ENOENT")throw s});let p=je(ct(q,n)).text;await T.writeFile(x.join(a,"doc.html"),p),await T.writeFile(x.join(a,"doc.json"),JSON.stringify({title:q,description:q,type:"component"}));let w=await(await Se({directory:r,catalog:le(r)}))(q),l=x.join(r,"export.html");await T.writeFile(l,w);let f=Me(p,e).map((s,c)=>({file:t.place,line:t.instances[c]?.line??null}));return{html:w,file:l,places:f,source:p}}async function In(e,t,{find:i=Ne,start:r=Ae,loading:n=rt}={}){let a=await fn(e,t);if(a.length===0)return[{title:de(),none:`none holds an instance of ${t.id}`}];let p=i();if(!p)return[{title:de(),unverified:"no Chrome, Edge or Chromium found (GALLERY_BROWSER=<its executable> picks one)"}];let u;try{u=await r({executablePath:p,args:Oe()})}catch(f){return[{title:de(),unverified:`the browser ${p} did not start, twice, each time with a fresh profile (${oe(f)}; GALLERY_BROWSER=<its executable> picks another)`}]}let{packages:w}=le(e),l=[];try{for(let f of a){let s=de(f.place),c=null;try{c=await T.mkdtemp(x.join(pe.tmpdir(),"gallery-component-check-"));let h=await mn(t,f,w,c),b=x.join(it(e).qa,"components",...t.id.split("/"),"documents",f.slug);await T.rm(b,{recursive:!0,force:!0}),await T.mkdir(b,{recursive:!0});let k=await ut(u.browser,{...h,found:t,out:b,loading:n}),g=wt(k,{places:h.places,script:t.files.includes("kit.js"),folder:De(`${c}${x.sep}`).href});if(k.gone){l.push({title:s,...g,unverified:`the browser went while waiting until ${k.gone}, so it says nothing of these instances`});break}l.push({title:s,...g,...k.taken.length?{pictures:{folder:b,overviews:k.overviews.map(m=>x.basename(m)),each:k.taken.map(m=>x.basename(m)),edited:k.edited.map(m=>x.basename(m)),asExport:k.asExport.map(m=>x.basename(m)),documents:!0}}:{}})}catch(h){if(h.reason==="check")l.push({title:s,problems:h.failures.map(b=>({file:f.place,what:`its instances, exported alone: ${b}`}))});else if(h.syscall)l.push({title:s,unverified:`cannot write ${Te(h.syscall==="mkdtemp"?pe.tmpdir():h.path)} (${h.code})`});else if(await Ce(u.browser)){l.push({title:s,unverified:"the browser went before the page opened"});break}else if(h.stuck){l.push({title:s,problems:[{file:"the page",what:`${pt(h)}, so the look at them stopped, the browser was closed, and no document after them was looked at`}]});break}else l.push({title:s,problems:[{file:"the page",what:`the look at them stopped: ${oe(h)}`}]})}finally{c&&await T.rm(c,{recursive:!0,force:!0,maxRetries:5,retryDelay:200}).catch(()=>{})}}}finally{await u.close()}return l}export{At as a,de as b,rt as c,se as d,Dn as e,Rt as f,Dt as g,Mn as h,Pn as i,oe as j,ct as k,Ut as l,Jt as m,Qt as n,Cn as o,Zt as p,ln as q,L as r,cn as s,pt as t,Ce as u,_n as v,In as w};
@@ -1,2 +0,0 @@
1
- import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
2
- import{a as h,b as v,d as p,e as S,h as j,j as I}from"./chunk-GMJD7ID3.mjs";import{a as A}from"./chunk-JEUK3ZO7.mjs";import{a as C}from"./chunk-JPG2LBQM.mjs";import"./chunk-ALZ6ZENZ.mjs";import"./chunk-IA4PSIMD.mjs";import{g as O}from"./chunk-7M2BQQGZ.mjs";import{b as i,f as g,i as y}from"./chunk-4OZWXZE5.mjs";import"./chunk-ZTHICSSF.mjs";import"./chunk-UMHUSOPJ.mjs";import"./chunk-TKWEX4FD.mjs";import"./chunk-A55HN5OK.mjs";import"./chunk-5L7RYZCL.mjs";import D from"node:path";import{pageLinks as F,pageOfLink as J}from"../browser/shared/page-links.mjs";import{reportsDirectory as E}from"../browser/shared/paths.mjs";import{findPreviewServer as K}from"../browser/shared/preview-server.mjs";import{topOf as M}from"../browser/shared/outline-shape.mjs";import{LINK_FILE as U,linkAddress as P,linkIcon as T}from"../browser/shared/web-links.mjs";var $=t=>t.replace(/\s+/g," ").trim(),k=t=>t==null?"none":JSON.stringify(t);async function x(t,e){let n=await K(),o=n?await j(n,e,t):null;if(o)return o;let[,s]=await C({edits:{},reports:{},reportsDirectory:E,web:{icon:a=>O(a)}}).run(t,e);return s}function _(t,e){let n=[...t.documents.values()].filter(({url:a})=>a!==void 0),o=J(F(n),e.replace(/^.*#/,""));return o?{slug:o,link:t.documents.get(o)}:{refused:t.documents.get(e)?`${p(t,e)} is a document, not a web link: gallery set changes a document.`:`No web link "${e}": gallery list --tree shows the sidebar's entries.`}}var W=(t,e)=>t.groups.find(n=>[v(n),n.id].some(o=>o.toLowerCase()===$(e).toLowerCase()))??null;async function B(t,e,n){if(t.length!==2)throw new i('Name the address and the name: gallery link add <url> "<name>".');let[o,s]=t,a=P(o);if(a.refused)throw new i(`Not an address a web link takes: ${o} (${{url:"no address",scheme:"http or https only",long:"2048 characters at most"}[a.refused]}).`);if(!$(s))throw new i("The name is never empty.");let d=n.get("--column"),u=n.get("--under"),l=n.get("--after"),c=n.get("--icon");if(d!==void 0&&u!==void 0)throw new i("--column and --under are two places: give one.");if(l!==void 0&&e.has("--first"))throw new i("--after and --first are two places: give one.");if(c!==void 0&&!T(c))throw new i(`Not an icon a web link takes: ${c} (an emoji, or an icon of the \u56FE\u6807 tab as /icons/<name>_<color>.svg).`);let f=await h(),w;if(d!==void 0){let L=W(f,d);L||(console.error(`No column "${d}" in the sidebar (${f.groups.map(v).join(", ")}): nothing added.`),process.exit(1)),w=M(L.id)}u!==void 0&&(w=(await y(u)).slug);let r=l===void 0?null:(await y(l)).slug,q=e.has("--first")||u===void 0&&r===null,m=await x("link",{url:a.url,title:$(s),...c?{icon:c}:{},...w!==void 0?{parent:w}:{},after:r,first:q});m?.ok||(console.error(`Not added: ${m?.message??m?.reason??"no answer"}.`),process.exit(1));let b=await h(),{slug:N,url:z}=m.link;console.log(`Added the web link ${p(b,N)}: ${z}`),console.log(`Placed it ${I(b,{parent:m.parent,index:m.index})}.`),console.log(S(b,N)),console.log(`It is ${A(D.join(E,N,U))}; the workbench shows the page beside the sidebar (a site that refuses frames: \u5728\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00).`)}async function G(t,e){if(t.length!==1)throw new i("Name one web link, then what to set: --url, --title, --icon.");if(!["--url","--title","--icon"].some(r=>e.has(r)))throw new i('Say what to set: --url <address>, --title "<name>", --icon <emoji|none>.');let n=e.has("--title")?$(e.get("--title")):void 0;if(n==="")throw new i("--title takes the words of the name: a web link's name is never empty.");let o;if(e.has("--url")){let r=P(e.get("--url"));if(r.refused)throw new i(`Not an address a web link takes: ${e.get("--url")}.`);o=r.url}let s;if(e.has("--icon")){let r=e.get("--icon").trim();if(r!=="none"&&!T(r))throw new i(`Not an icon a web link takes: ${r} (an emoji, none, or an icon of the \u56FE\u6807 tab).`);s=r==="none"?null:r}let a=await h(),d=_(a,t[0]);d.refused&&(console.error(d.refused),process.exit(1));let{slug:u,link:l}=d,c=await x("link-set",{slug:u,...o!==void 0?{url:o}:{},...n!==void 0?{title:n}:{},...s!==void 0?{icon:s}:{}});c?.ok||(console.error(`Not set: ${c?.message??c?.reason??"no answer"}.`),process.exit(1));let f=c.link,w=[...n!==void 0&&n!==l.title?[` title: ${k(l.title)} \u2192 ${k(f.title)}`]:[],...o!==void 0&&f.url!==l.url?[` url: ${l.url} \u2192 ${f.url}`]:[],...s!==void 0&&(f.icon??null)!==(l.icon??null)?[` icon: ${k(l.icon)} \u2192 ${k(f.icon??null)}`]:[]];if(!w.length)return void console.log(`Nothing to change: ${u} has ${e.size===1?"that already":"those already"}.`);console.log(`Set the web link ${u}:`);for(let r of w)console.log(r)}async function H(t){if(t.length!==1)throw new i("Name one web link to move to the trash.");let e=await h(),n=_(e,t[0]);n.refused&&(console.error(n.refused),process.exit(1));let o=await x("trash",{slug:n.slug,kind:"link"});o?.ok||(console.error(`Not moved to the trash: ${o?.message??o?.reason??"no answer"}.`),process.exit(1)),console.log(`Moved the web link ${p(e,n.slug)} to the trash: the workbench's \u8BBE\u7F6E \u203A \u56DE\u6536\u533A restores it where it was.`)}async function se(t){let[e,...n]=t;if(e==="add"){let{positional:o,options:s,values:a}=g({options:["--first"],values:["--column","--under","--after","--icon"],argv:n});return B(o,s,a)}if(e==="set"){let{positional:o,values:s}=g({values:["--url","--title","--icon"],argv:n});return G(o,s)}if(e==="remove"){let{positional:o}=g({argv:n});return H(o)}throw new i(e?`No such action: link ${e} (add, set, remove).`:"Say what to do: gallery link add, set or remove.")}export{se as run};
@@ -1,13 +0,0 @@
1
- import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
2
- import{c as Oe,f as we,g as ge,h as $e,i as We,j as ne,l as Y,m as Ge,n as Ae,o as Ke,p as Ve,q as ze,r as g,t as Qe,u as Ye}from"./chunk-LJLVCU6W.mjs";import{M as Xe}from"./chunk-XBNFXWAW.mjs";import{f as Te,i as Je}from"./chunk-SQ3FQCCN.mjs";import{a as K}from"./chunk-JEUK3ZO7.mjs";import{a as me}from"./chunk-M4NRDYI5.mjs";import{a as Ue,b as Ze,f as pe,g as qe}from"./chunk-PUOQ65NC.mjs";import{e as Ne,g as te}from"./chunk-S3SX3COT.mjs";import{b as Se}from"./chunk-VRPVVMRB.mjs";import{b as T,i as Pe}from"./chunk-4OZWXZE5.mjs";import{a as Be}from"./chunk-HYMEEXKN.mjs";import{f as Ee,j as He}from"./chunk-TKWEX4FD.mjs";import{randomBytes as Ct}from"node:crypto";import{existsSync as It}from"node:fs";import N from"node:fs/promises";import A from"node:path";import{isInstance as Re,isSlot as jt,partOf as Mt}from"../browser/shared/components/index.mjs";import{ATTRIBUTE as ke,FALLBACK as Rt,FIELDS as Dt,INSTANCE as ft,PACKAGE_ID as _t,SLOT as Ft}from"../browser/shared/components/installed.mjs";import{attr as ce,walk as Ht}from"../browser/shared/html-tree.mjs";import{documentDirectory as Pt,documentFiles as Bt,layoutOf as se,packageFolders as Jt,slugTaken as Ut}from"../browser/shared/workspace.mjs";var et=10,Ce=6,Zt=3,qt=100,De=1024,_e=900,Wt=4e3,le=3e4,Gt=1500,Ie=3e4,je=500,Kt=5e3,Vt=200,tt=20,nt=160,ye=12,zt=3600*1e3,Qt=["p","pi","pin"],he=e=>new Promise(t=>setTimeout(t,e));async function at(e){let{_keyDefinitions:t}=await import("./chunk-43B75J5T.mjs"),n=Object.hasOwn(t,e)?[e]:e.split("+"),a=new Set(["Control","Shift","Alt","Meta"]);if(n.some(s=>!Object.hasOwn(t,s))||n.slice(0,-1).some(s=>!a.has(s)))throw new T(`Not a key: ${e} (a key as a browser names it, Enter, Space, Escape, Tab, ArrowRight, a letter or a digit, after modifiers joined by "+": Shift+Tab, Control+Enter).`);return n}var ie={press:"<selector>",drag:'<selector>, with "to": <selector>',key:"[<selector>, <key>]",type:"[<selector>, <words>]",select:"[<selector>, <value>]"};async function ut(e,t=null){let n=d=>new T(t?`${t[0].toUpperCase()}${t.slice(1)}: ${d}`:`${d[0].toUpperCase()}${d.slice(1)}`);if(!e||typeof e!="object"||Array.isArray(e))throw n(`a step is an object naming one gesture: ${Object.entries(ie).map(([d,h])=>`"${d}": ${h}`).join(", ")}, and "then": <key> after it.`);let a=Object.keys(e).filter(d=>!Object.hasOwn(ie,d)&&!["to","then","replace"].includes(d));if(a.length)throw n(`no such field: ${a.join(", ")} (a step names one of ${Object.keys(ie).join(", ")}, "to" with a drag, "replace": true with typing and "then" after any).`);let s=Object.keys(ie).filter(d=>e[d]!==void 0),o=d=>t?`"${d}"`:`--${d}`;if(s.length!==1)throw n(s.length?`one gesture at a time: ${s.map(o).join(" or ")}.`:t?`name the gesture: ${Object.keys(ie).map(o).join(", ")}.`:"Say the gesture: --press <selector>, --drag <selector> --to <selector>, --key <selector> <key>, --type <selector> <words> or --select <selector> <value>; or --steps <file>.");let[i]=s;if(e.to!==void 0&&i!=="drag")throw n(`${o("to")} goes with ${o("drag")}: ${t?'"drag": <selector>, "to": <selector>':"--drag <selector> --to <selector>"}.`);if(i==="drag"&&e.to===void 0)throw n(`${o("drag")} takes ${o("to")}: ${t?'"drag": <selector>, "to": <selector>':"--drag <selector> --to <selector>"}, where it is dropped.`);if(e.replace!==void 0&&i!=="type")throw n(`${o("replace")} goes with ${o("type")}: it selects what the field holds before the words go in.`);if(e.replace!==void 0&&e.replace!==!0)throw n(`${o("replace")} is true: ${t?'"replace": true':"--replace"} selects what the field holds before the words go in.`);let l=(d,h)=>{if(typeof d!="string"||!d)throw n(`${h} is words: ${JSON.stringify(d)}.`);return d},c=(d,h)=>{if(!Array.isArray(d)||d.length!==2)throw n(`${o(i)} takes ${t?`[<selector>, ${h}]`:`<selector> ${h}`}.`);return[l(d[0],"a selector"),l(d[1],h)]},r={kind:i};if(i==="press"&&(r.at=l(e.press,"a selector")),i==="drag"&&Object.assign(r,{at:l(e.drag,"a selector"),to:l(e.to,"a selector")}),i==="key"){let[d,h]=c(e.key,"<key>");Object.assign(r,{at:d,key:h,keys:await at(h)})}return i==="type"&&([r.at,r.text]=c(e.type,"<words>"),e.replace&&(r.replace=!0)),i==="select"&&([r.at,r.value]=c(e.select,"<value>")),e.then!==void 0&&(r.then={key:l(e.then,"a key"),keys:await at(l(e.then,"a key"))}),r}async function Yt(e,t={},n=!1){if(n&&e.has("--steps"))throw new T('--steps <file> holds every gesture: --replace goes in a step of it, as { "type": [".name", "\u65B0\u540D\u5B57"], "replace": true }, not beside it.');if(e.has("--steps")){let s=["--press","--drag","--to","--key","--type","--select","--then"].filter(o=>e.has(o));if(s.length)throw new T(`--steps <file> holds every gesture: ${s.join(", ")} goes in it, not beside it.`);return null}let a={};for(let s of["press","drag","to","then"])e.has(`--${s}`)&&(a[s]=e.get(`--${s}`));for(let s of["key","type","select"])e.has(`--${s}`)&&(a[s]=[e.get(`--${s}`),t[`--${s}`]]);return n&&(a.replace=!0),ut(a)}async function Xt(e){let t=A.basename(e),n;try{n=await N.readFile(e,"utf8")}catch(o){throw new T(`No steps file: ${K(e)} (${o.code??ne(o)}).`)}let a;try{a=JSON.parse(n.replace(/^/,""))}catch(o){throw new T(`${t} is no JSON: ${ne(o)}. A steps file is a list of steps, as [{ "press": ".add" }, { "type": [".name", "\u65B0\u540D\u5B57"], "then": "Enter" }].`)}if(!Array.isArray(a)||a.length===0)throw new T(`${t} holds no list of steps: write [{ "press": ".add" }, { "type": [".name", "\u65B0\u540D\u5B57"], "then": "Enter" }].`);if(a.length>tt)throw new T(`${t} holds ${a.length} steps, and a trial makes ${tt} at most: try fewer at a time.`);let s=[];for(let[o,i]of a.entries())s.push(await ut(i,`step ${o+1} of ${t}`));return s}var pt=e=>{let t=e.parentNode;for(;t&&!Re(t);)t=t.parentNode;return t??null},en=(e,t)=>{for(let n=e.parentNode;n&&n!==t;n=n.parentNode)if(jt(n))return ce(n,Ft);return null};function wt(e){let t=[];return Ht(Be(e),n=>{if(!Re(n))return;let a=pt(n);t.push({element:n,id:ce(n,ke),blockId:ce(n,"data-block-id")??null,line:n.sourceCodeLocation?.startLine,in:a?{id:ce(a,ke),line:a.sourceCodeLocation?.startLine,slot:en(n,a)}:null})},{inTemplates:!1}),t}var gt=({line:e,in:t},n)=>`${n}:${e}${t?`, in ${t.slot?`the slot ${t.slot} of `:""}${t.id} at ${n}:${t.line}`:""}`,tn=(e,{id:t,blockId:n})=>n??(e.filter(a=>a.id===t).length===1?t:null);function nn(e,t,{slug:n,name:a}){let s=()=>e.map(c=>` ${tn(e,c)??"(no id yet: gallery export gives it one)"} ${c.id} at ${gt(c,a)}`).join(`
3
- `);if(t===null){if(e.length===1)return 0;throw new T(`${n} holds ${e.length} instances: name one, gallery block try ${n} <instance id> \u2026
4
- ${s()}`)}let o=e.findIndex(({blockId:c})=>c===t);if(o>=0)return o;let i=t.includes("/")?t:`local/${t}`,l=_t.test(i)?e.flatMap((c,r)=>c.id===i?[r]:[]):[];if(l.length===1)return l[0];throw new T(l.length?`${n} holds ${l.length} instances of ${i}: name one by its id
5
- ${s()}`:`${n} holds no instance ${t}:
6
- ${s()}`)}var an=e=>e.replace(/\s+data-block-id="[^"]*"/g,""),st=e=>an(Se(e).text),sn=(e,t)=>(typeof t=="function"?t(e):wt(e)[t]?.element)??null;function ot(e,t,n){let a=sn(e,t);if(!a||ce(a,ke)!==n.id)return null;let s=[],o=Object.entries(n.parts).map(([r,{at:d}])=>{let h=Mt(a,d).filter(f=>f.sourceCodeLocation?.endTag&&!Re(f)&&pt(f)===a).map(({sourceCodeLocation:{startTag:f,endTag:u}})=>({start:f.endOffset,end:u.startOffset}));return s.push(...h),{name:r,text:h.map(({start:f,end:u})=>e.slice(f,u)).join(`
7
- `)}}),i=s.sort((r,d)=>r.start-d.start||d.end-r.end).filter((r,d)=>!s.slice(0,d).some(h=>h.start<=r.start&&r.end<=h.end)),l="",c=0;for(let{start:r,end:d}of i)l+=e.slice(c,r),c=d;return{parts:o,outside:l+e.slice(c)}}function on(e,t,n,a){let[s,o]=[ot(e,n,a),ot(t,n,a)];return!s||!o?{parts:[],outside:null,gone:!0}:{parts:s.parts.flatMap(({name:l,text:c},r)=>c===o.parts[r].text?[]:[{name:l,...Ae(c,o.parts[r].text),how:Ve(c,o.parts[r].text),runs:Ke(c,o.parts[r].text)}]),outside:s.outside===o.outside?null:Ae(s.outside,o.outside),gone:!1}}function rn(e){let t=n=>n.length>nt?`${n.slice(0,nt)}\u2026`:n;return e.flatMap(({name:n,runs:a=[]})=>{let s=a.flatMap(({removed:l,added:c})=>[...l.map(r=>`- ${t(r)}`),...c.map(r=>`+ ${t(r)}`)]),o=e.length>1?" ":" ",i=s.slice(0,ye).map(l=>`${o}${l}`);return s.length>ye&&i.push(`${o}\u2026 ${s.length-ye} more line${s.length-ye===1?"":"s"}`),e.length>1?[` ${n}:`,...i]:i})}async function cn(e,t=null){let{components:n,marker:a}=se(e);return await mt([t,a,n].filter(Boolean))+me+te+je}async function ln(e,{directory:t,files:n,text:a}){let{scratch:s}=se(e);await N.mkdir(s,{recursive:!0});let o;do o=`try-${Ct(4).toString("hex")}`;while(Ut(o,e)||It(A.join(s,o)));let i=A.join(s,o);await N.mkdir(i),await N.cp(A.join(t,"assets"),A.join(i,"assets"),{recursive:!0}).catch(c=>{if(c.code!=="ENOENT")throw c}),await N.copyFile(n.json,A.join(i,A.basename(n.json))).catch(c=>{if(c.code!=="ENOENT")throw c});let l=A.join(i,A.basename(n.html));return await N.writeFile(l,a),{slug:o,folder:i,file:l}}async function $t(e,t){let{scratch:n,state:a}=se(e);await N.rm(A.join(n,t),{recursive:!0,force:!0,maxRetries:5,retryDelay:200}).catch(()=>{});for(let s of await N.readdir(a).catch(()=>[]))await N.rm(A.join(a,s,t),{recursive:!0,force:!0,maxRetries:3,retryDelay:100}).catch(()=>{})}async function dn(e,t=Date.now()){let{scratch:n}=se(e);for(let a of await N.readdir(n,{withFileTypes:!0}).catch(()=>[])){if(!a.isDirectory()||!/^try-[a-f0-9]{8}$/.test(a.name))continue;let{mtimeMs:s}=await N.stat(A.join(n,a.name)).catch(()=>({mtimeMs:t}));t-s>=zt&&await $t(e,a.name)}}async function mt(e){let t=[...e];for(let a of e)for(let s of await N.readdir(a,{recursive:!0,withFileTypes:!0}).catch(()=>[]))t.push(A.join(s.parentPath,s.name));let n=await Promise.all(t.map(a=>N.stat(a).then(({mtimeMs:s})=>s,()=>0)));return Math.max(...n)}var hn=e=>fetch(`${e}/__gallery/workspace/components`,{signal:AbortSignal.timeout(2e3)}).then(t=>t.ok?t.json():null).then(t=>Array.isArray(t?.packages)?t.packages:null,()=>null);async function fn(e,t,n){let{components:a,marker:s}=se(e),o=Jt(e).find(m=>m.id.toLowerCase()===t)?.folder??A.join(a,...t.split("/")),[i,l]=await Promise.all([mt([s,o]),hn(n)]),{packages:c,problems:r,settings:d}=Ee(e),h=l?.find(m=>m.id===t)??null,f=l?h?.state??"none":null,u=f==="normal"||f==="hidden",w=d.disabled.includes(t),k=r.get(t),y=k&&!w&&u?He("en",k.problem):null,p=l!==null&&c.has(t)&&!u;return{by:i+(y?Ne:me+te),held:y,behind:p,off:w,stamp:(c.get(t)??k)?.stamp??null,state:f,reason:h?.reason?.en??null}}var yt=({state:e,reason:t})=>e==="none"?"no such custom block":t?`it as not loading (${t})`:"it turned off";function un(e,{said:t,unparsed:n=null,off:a,behind:s=!1,state:o,reason:i}){let l="the instance shows what it holds, read-only, so a reader can do nothing with it";return n?`${l}: its kit.js did not parse, so no component of it started, and the console says ${n}`:t.length?`${l}: its component failed as the page started it, and the console says ${t.join("; ")}`:a?`${l}: ${e} is turned off in \u8BBE\u7F6E \u203A \u7EC4\u4EF6\u5217\u8868`:s?`${l}: the server has not taken ${e} as components/ holds it, where it loads: its catalog in use has ${yt({state:o,reason:i})}`:o==="disabled"&&!i?`${l}: ${e} is turned off in \u8BBE\u7F6E \u203A \u7EC4\u4EF6\u5217\u8868`:o==="broken"||o==="disabled"?`${l}: the server has ${e} as not loading (${i}): gallery block check ${e} says why`:o==="none"?`${l}: the server has not taken ${e} as components/ holds it (its catalog in use has no such custom block)`:o?`${l}: the page was served before the server took ${e} as components/ holds it, and did not load itself again with it`:`${l}: its component failed or never started, and the console said nothing of it`}var pn=(e,t,n)=>t.held?`${e} does not load as components/ holds it (${t.held}), and the server keeps it as it was until components/ has not changed for ${Ne/1e3}s, as it keeps a custom block written file by file`:t.behind?`components/ holds ${e} as loading, and the server's catalog in use still has ${yt(t)}: it takes what components/ holds once that has not changed for ${te/1e3}s`:n?`${e} or gallery.json changed a moment ago, and the server takes the change once components/ has not changed for ${te/1e3}s, the page served before loading itself again for it`:`the server took ${e} as components/ holds it, and the page served before is to load itself again with it`,wn=(e,t,n)=>t.held?`the server still keeps ${e} as it was`:t.behind?`the server has still not taken ${e} as components/ holds it`:`the server took ${e} as components/ holds it, and the page did not load itself again with it in ${n/1e3}s`;async function gn({root:e,id:t,origin:n,loadedAt:a,loaded:s,told:o=Kt,say:i=l=>console.log(l)}){let l=Date.now(),c,r=0,d=0,h=!1;for(;;await he(Vt)){let f=await fn(e,t,n),u=Date.now();c!==void 0&&f.stamp!==c&&(r=u),c=f.stamp,f.behind&&!d&&(d=u);let w=Math.max(f.by,...[r,d].filter(Boolean).map(y=>y+me+te)),k=s()?"the page loaded itself again":f.off?`gallery.json turns ${t} off now`:a>=w?`the page was asked for after the server took ${t} as components/ holds it`:u>w+o?wn(t,f,o):null;if(k)return h&&i(`Waited ${((u-l)/1e3).toFixed(1)}s: ${k}`),f;h||w-u<=je&&u-l<=je||(h=!0,i(`Waiting: ${pn(t,f,w>u)}, ${Math.ceil((w+o-u)/1e3)}s more at most`))}}function $n({instance:e,at:t,card:n}){return typeof n=="string"?[...[...document.querySelectorAll(".gallery-board > .gallery-card")].find(s=>s.getAttribute("data-card-id")===n)?.children??[]].find(s=>s.matches(e))??null:[...document.querySelectorAll(e)][t]??null}function mn(e,t){let n=u=>`<${u.localName}${u.classList.length?` class="${u.getAttribute("class")}"`:""}>`,a;try{a=e.querySelector(t)}catch{return{invalid:!0}}if(!a)return{none:!0,held:[...new Set([...e.querySelectorAll("[class]")].filter(u=>u.getClientRects().length>0).flatMap(u=>[...u.classList].map(w=>`.${w}`)))].slice(0,16)};let s=((a instanceof HTMLElement?a.innerText:a.textContent)??"").replace(/\s+/g," ").trim(),o={named:n(a),words:s.length>40?`${s.slice(0,40)}\u2026`:s},i=[...a.getClientRects()].filter(({width:u,height:w})=>u>0&&w>0);if(!i.length)return{...o,hidden:!0};let{left:l,top:c,right:r,bottom:d,width:h,height:f}=i.reduce((u,w)=>u.width*u.height>=w.width*w.height?u:w);return{...o,box:{left:l,top:c,right:r,bottom:d,x:l+h/2,y:c+f/2}}}function yn(e,{selector:t,x:n,y:a}){let s=e.querySelector(t),o=document.elementFromPoint(n,a);return!o||s.contains(o)?null:`<${o.localName}${o.classList.length?` class="${o.getAttribute("class")}"`:""}>`}function kn(e,{at:t,to:n}){let[a,s]=[e.querySelector(t),e.querySelector(n)];return a===s?"same":a.contains(s)?"inside":null}function kt(e){let t=a=>a instanceof Element?`<${a.localName}${a.classList.length?` class="${a.getAttribute("class")}"`:""}>`:"the page",n={edits:[],taken:0,states:[],started:null,dropped:null,effect:null};addEventListener("doc-component-edit",a=>{a.target===e&&(n.edits.push({taken:a.defaultPrevented,parts:(a.detail?.parts??[]).map(({name:s})=>s)}),a.defaultPrevented&&(n.taken+=1))}),new MutationObserver(a=>{for(let{oldValue:s}of a)n.states.push(s);n.states.push(document.documentElement.getAttribute("data-ge-save"))}).observe(document.documentElement,{attributes:!0,attributeFilter:["data-ge-save"],attributeOldValue:!0}),document.addEventListener("dragstart",a=>{n.started=t(a.target)},!0),document.addEventListener("drop",a=>{n.dropped=t(a.target)},!0),document.addEventListener("dragend",a=>{n.effect=a.dataTransfer?.dropEffect??null},!0),globalThis.__galleryTry=n}function bn(){return Object.assign(globalThis.__galleryTry,{edits:[],started:null,dropped:null,effect:null}),{taken:globalThis.__galleryTry.taken}}function bt(e){let t=[...e.querySelectorAll("input, select, textarea")].map(n=>n instanceof HTMLInputElement&&["checkbox","radio"].includes(n.type)?n.checked?"ticked":"not ticked":n.value);return{words:(e.innerText??"").replace(/\s+/g," ").trim(),fields:t}}function vn(e){let n=(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement?e.value:e.textContent??"").replace(/\s+/g," ").trim();return n.length>40?`${n.slice(0,40)}\u2026`:n}function xn(e){let t=document.activeElement,n="";if(t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement)try{n=t.value.slice(t.selectionStart??0,t.selectionEnd??0)}catch{}else{let s=getSelection();s&&!s.isCollapsed&&e.contains(s.anchorNode)&&(n=s.toString())}let a=n.replace(/\s+/g," ").trim();return a.length>40?`${a.slice(0,40)}\u2026`:a}function En(e){let t=document.activeElement;if(t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement)try{return t.selectionStart===null?null:t.selectionEnd===t.value.length}catch{return null}let n=getSelection();if(!n?.rangeCount||!e.contains(n.focusNode))return null;let a=document.createRange();return a.selectNodeContents(e),a.setStart(n.focusNode,n.focusOffset),a.toString().trim()===""}function Sn(e){let t=document.activeElement;if(t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement){t.select();return}let n=document.createRange();n.selectNodeContents(e),getSelection()?.removeAllRanges(),getSelection()?.addRange(n)}function it(e){let t=document.activeElement;return t&&(t===e||e.contains(t)||t instanceof HTMLElement&&t.isContentEditable&&t.contains(e))?null:`<${t?.localName??"body"}>`}function Tn(e){let t=document.activeElement;if(t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement){try{t.setSelectionRange(t.value.length,t.value.length)}catch{}return}let n=document.createRange();n.selectNodeContents(e),n.collapse(!1),getSelection()?.removeAllRanges(),getSelection()?.addRange(n)}function Nn(e,{selector:t,value:n}){let a=e.querySelector(t);if(!(a instanceof HTMLSelectElement))return{notSelect:`<${a.localName}${a.classList.length?` class="${a.getAttribute("class")}"`:""}>`};let s=[...a.options],o=s.find(i=>i.value===n)??s.find(i=>i.textContent.trim()===n);return o?a.disabled||o.disabled?{disabled:!0}:(a.focus(),o.selected=!0,a.dispatchEvent(new Event("input",{bubbles:!0})),a.dispatchEvent(new Event("change",{bubbles:!0})),{chosen:o.textContent.trim()}):{options:s.map(i=>i.value===i.textContent.trim()?i.value:`${i.value} (${i.textContent.trim()})`)}}async function Fe(e,{still:t,step:n,wait:a=0}){let s=globalThis.__galleryQueries??null,o=Date.now()+a,i=()=>s!==null&&s.pending.size>0&&Date.now()<o,l=()=>new Promise(r=>{requestAnimationFrame(r),setTimeout(r,100)});await l(),await l();let c=e.outerHTML;for(let r=0,d=Date.now()+t;r<3;){if(Date.now()>d)return null;await new Promise(f=>setTimeout(f,n));let h=e.outerHTML;i()?(r=0,d=Date.now()+t):r=h===c?r+1:0,c=h}return c}function On(e,t,{left:n,top:a,right:s,bottom:o}){let i=0;for(let[l,c,r,d]of[[e.x,t.x,n,s],[e.y,t.y,a,o]]){if(c===l)continue;let[h,f]=[(r-l)/(c-l),(d-l)/(c-l)];i=Math.max(i,Math.min(h,f))}return i*Math.hypot(t.x-e.x,t.y-e.y)}function An(e,t){let n=Math.hypot(t.x-e.x,t.y-e.y),a=c=>n===0?{x:e.x,y:e.y}:{x:e.x+(t.x-e.x)*c/n,y:e.y+(t.y-e.y)*c/n},s=Math.min(Ce,n),o=On(e,t,t)-Zt,i=o>s?o:n,l=[a(s/2),a(s)];for(let c=1;c<=et;c++)l.push(a(s+(i-s)*c/et));return i!==n&&l.push({x:t.x,y:t.y}),l}var de={press:"press",drag:"drag",key:"key",type:"typing",select:"choice"},ae=(e,{named:t,words:n})=>`${e} (${t}${n?` "${n}"`:""})`,rt=e=>Object.assign(new T(e),{unfound:!0});async function vt(e,t){let n=t.slice(0,-1);for(let a of n)await e.keyboard.down(a);await e.keyboard.press(t.at(-1));for(let a of n.toReversed())await e.keyboard.up(a)}async function Ln(e,t,n){let a=!1;for(let[s]of n.matchAll(/[\x00-\x7f]+|[^\x00-\x7f]+/gu)){if(/^[\x00-\x7f]/.test(s)){await e.keyboard.type(s);continue}a=!0;for(let o of Qt)await t.send("Input.imeSetComposition",{text:o,selectionStart:o.length,selectionEnd:o.length});await t.send("Input.insertText",{text:s})}return a?/[\x00-\x7f]/.test(n)?"its ASCII key by key and the rest through an input method":"through an input method, composed then committed":"key by key"}async function Cn(e,t,n,a){let s=await In(e,t,n,a);return n.then?(await vt(e,n.then.keys),{...s,said:`${s.said}, then ${n.then.key} pressed where the focus was`}):s}async function In(e,t,n,a){let s=async c=>{let r=await g(t.evaluate(mn,c),"the page was asked what the selector finds");if(r.invalid)throw new T(`Not a selector: ${c}.`);if(r.none)throw rt(`Nothing in the instance is ${c}${r.held.length?`: what it shows has ${r.held.join(", ")}`:": it shows nothing with a class"}.`);if(r.hidden)throw rt(`${c} finds ${r.named} in the instance, which is not shown (it has no box on the page), so a reader cannot reach it: name what it shows.`);return r},o=await s(n.at);if(n.kind==="press"){let{x:c,y:r}=o.box,d=await g(t.evaluate(yn,{selector:n.at,x:c,y:r}),"the page was asked what stands at the press");return await e.mouse.move(c,r),await e.mouse.down(),await e.mouse.up(),{said:`a press on ${ae(n.at,o)}, with the pointer at its middle`,over:d}}if(n.kind==="drag"){let c=await s(n.to),r=await g(t.evaluate(kn,{at:n.at,to:n.to}),"the page was asked where the drag ends");if(r)throw new T(`${r==="same"?`--drag and --to find the same element, ${o.named}`:`--to ${n.to} finds ${c.named}, which stands in what --drag ${n.at} finds, ${o.named}`}: a drag ends where it is dropped, on another element of the instance (another column, another row), which --to names.`);if(Math.hypot(c.box.x-o.box.x,c.box.y-o.box.y)<Ce)throw new T(`The middles of what --drag ${n.at} and --to ${n.to} find stand less than ${Ce}px apart, too near for a drag to start: name with --to where it is dropped, further off.`);let d=An(o.box,c.box);await e.mouse.move(o.box.x,o.box.y),await e.mouse.down();for(let{x:h,y:f}of d)await e.mouse.move(h,f);return await he(qt),await e.mouse.up(),{said:`a drag of ${ae(n.at,o)} to ${ae(n.to,c)}, with the pointer in ${d.length} moves, released as it comes onto it`}}if(n.kind==="select"){let c=await g(t.evaluate(Nn,{selector:n.at,value:n.value}),"the page was asked to choose the option");if(c.notSelect)throw new T(`${n.at} finds ${c.notSelect} in the instance, which is no <select>: --select names a <select> the instance draws, and the option by its value or its words.`);if(c.options)throw new T(`${n.at} has no option ${JSON.stringify(n.value)}: ${c.options.length?`its options are ${c.options.join(", ")}`:"it has no option"}.`);if(c.disabled)throw new T(`${n.at} or its option ${JSON.stringify(n.value)} is disabled, so a reader cannot choose it.`);return{said:`${JSON.stringify(c.chosen)} chosen in ${ae(n.at,o)}, as a reader picks an option`}}let i=await t.$(n.at);if(n.kind==="type"){let c=!1,r=await g(e.evaluate(vn,i),"the page was asked what the field holds");await g(e.evaluate(it,i),"the page was asked where the focus is")&&(await e.mouse.click(o.box.x,o.box.y),await g(e.evaluate(Tn,i),"the caret went to the end"),c=!0),n.replace&&await g(e.evaluate(Sn,i),"all the field holds was selected");let d=await g(e.evaluate(it,i),"the page was asked where the focus is"),h=await g(e.evaluate(xn,i),"the page was asked what is selected"),f=c||!r||n.replace||h?!0:await g(e.evaluate(En,i),"the page was asked where the caret is"),u=await Ln(e,a,n.text),w=c?", pressed first":", where the focus was",k='(--replace, or "replace": true in a step, puts them in its place)',y=n.replace?`${w}, ${r?`all it held (${JSON.stringify(r)}) selected first (--replace), so that the words took its place`:"nothing in it to replace"}`:h?`${w}, ${h===r?"all it held":"part of it"} (${JSON.stringify(h)}) selected already (a step before), so that the words took its place`:c?`, pressed first and the caret at its end${r?`: it held ${JSON.stringify(r)}, and the words went after it ${k}`:""}`:r?f===!1?`, where the focus was, the caret inside what it held (${JSON.stringify(r)}), where a step before left it (a press puts it where the pointer lands, an arrow key moves it), so that the words went in there, not after it ${k}`:f?`, where the focus was, the caret at its end: it held ${JSON.stringify(r)}, and the words went after it ${k}`:`, where the focus was: it held ${JSON.stringify(r)}, and the words went in at the caret, where a step before left it ${k}`:", where the focus was";return{said:`${JSON.stringify(n.text)} typed in ${ae(n.at,o)}${y}, ${u}`,unfocused:d,typed:!0}}await g(i.focus(),"the focus went to the element");let l=await g(e.evaluate(c=>document.activeElement===c||c.contains(document.activeElement)?null:`<${document.activeElement?.localName??"body"}>`,i),"the page was asked where the focus is");return await vt(e,n.keys),{said:`${n.key} pressed with the focus given to ${ae(n.at,o)}, as Tab gives it`,unfocused:l}}var xt=e=>fetch(`${e}/__gallery/workspace/info`,{signal:AbortSignal.timeout(2e3)}).then(t=>t.ok,()=>!1);async function jn(e,t,n){let a=Date.now();for(let s=0,o=0;;await he(100)){let{seen:i,now:l}=await g(e.evaluate(r=>({seen:globalThis.__galleryTry.states.slice(r),now:document.documentElement.getAttribute("data-ge-save")}),t),"the page was asked where saving stands"),c=l!=="saved"||i.some(r=>r!=="saved");if(c&&l==="saved")return"saved";if(l==="stopped"||l==="reloading")return l;if(s=l==="held"?s+1:0,s>=3)return"held";if(o=l==="offline"?o+1:0,o>0&&o%10===0&&!await xt(n))return"offline";if(!c&&Date.now()-a>Gt)return"unchanged";if(Date.now()-a>Ie)return l}}var Mn=e=>({held:"a card waits for a reader: someone else changed the part meanwhile, and the page held its write for the reader there, which closing the page dropped",offline:"the page could not reach the server (offline)",stopped:"the page stopped saving (stopped): the server refused its write",reloading:"the page loaded itself again (doc.html or a custom block it holds changed meanwhile)",waiting:`it waited ${Ie/1e3}s to be saved and never was`,syncing:`its save took more than ${Ie/1e3}s`})[e];function Rn(e,{parts:t,outside:n,gone:a},{gesture:s,name:o,held:i=!1,scratch:l=!1,aside:c="data-block-id aside"}){if(l)return{unverified:`${e}${!a&&t.length?`, the copy holding what the ${s} wrote, ${Y(t)}`:""}: the trial was made on a scratch copy, gone now, and ${o} holds nothing of it`};let r=n?`; outside the instance's parts -${n.removed} +${n.added} lines someone else wrote meanwhile, which stay`:"";return a?{unverified:`${e}, and ${o} holds the instance no more where it stood: someone else wrote the file meanwhile`}:t.length===0?{unverified:`${e}: ${o} is as it was${n?" in the instance's parts":""} (${c})${r}`}:i?{unverified:`${e}: what ${o} holds of ${Y(t)} is someone else's, which stays${r}`}:{unverified:`${e}: ${o} holds what the ${s} wrote, ${Y(t)}, kept (--keep)${r}`}}function Dn(e,t,{over:n,unfocused:a,refusals:s,name:o}){let i=[];return n&&i.push(`the press landed on ${n}, which stands over it there`),a&&i.push(e==="type"?`the element takes no typing (a field or an editable element), so the words went to ${a}`:`the element takes no focus (a button, a field or a tabindex), so the key went to ${a}`),t.started&&!t.dropped?i.push(`an HTML5 drag started (dragstart on ${t.started}) and nothing took its drop where it was released (dragend's dropEffect ${t.effect??"none"}): a list a card is dropped on cancels dragenter as well as dragover (preventDefault), or a release as the pointer comes onto it drops nothing`):t.dropped&&t.edits.length===0&&i.push(`it was dropped on ${t.dropped}, and no context.edit came of it`),t.edits.some(({taken:l})=>l)?i.push("context.edit was taken, and its change left what the parts hold as it was"):t.edits.length?i.push(`context.edit was called and the page refused it${s.length?`: the console says ${s.join("; ")}`:""}`):t.started||i.push(e==="type"?"no context.edit came of it: the component answers no typing there, or writes what was typed only on a key or as the field loses the focus (then Enter, --then Enter), or asked while context.canEdit() was false":`no context.edit came of it: the component answers no ${de[e]} there, or asked while context.canEdit() was false`),`the ${de[e]} wrote nothing to ${o}: ${i.join("; ")}`}async function Et(e,t){await We(e);let n={own:new Map,others:new Map,dialogs:new Map,pending:[],page:0,from:0},a=new RegExp(`/__gallery/components/${t}/kit\\.js[^:\\s)]*:(\\d+)`),s=(i,l,{at:c="",unparsed:r=!1}={})=>{if(l<n.from)return;let d=i.split(`
8
- `)[0],h=a.exec(i)??a.exec(c);i.includes(t)||h?n.own.set(d,{line:Number(h?.[1])||null,page:l,unparsed:r&&a.test(c)}):n.others.set(d,{page:l})};e.on("request",i=>{i.isNavigationRequest()&&i.frame()===e.mainFrame()&&(n.page+=1)}),e.on("console",i=>{if(!["error","warn","warning"].includes(i.type())||/^Failed to load resource/.test(i.text()))return;let{page:l}=n;n.pending.push(Promise.all(i.args().map(c=>c.evaluate(r=>r instanceof Error?r.stack:String(r)).catch(()=>""))).then(c=>s(c.join(" ")||i.text(),l)))});let o=await ze(e,{add:i=>n.dialogs.set(i,{page:n.page})});return o.on("Runtime.exceptionThrown",({exceptionDetails:{exception:i,text:l,url:c,lineNumber:r,stackTrace:d}})=>{s(i?.description??String(i?.value??l),n.page,{at:c?`${c}:${r+1}`:"",unparsed:!d&&i?.className==="SyntaxError"})}),await o.send("Runtime.enable"),n}function _n(e){e.from=e.page;for(let t of[e.own,e.others,e.dialogs])for(let[n,{page:a}]of t)a<e.from&&t.delete(n)}var re=e=>Promise.race([Promise.all(e.pending),he(2e3)]);async function Fn(e){let t=n=>e.waitForSelector(n,{timeout:le}).catch(a=>{if(a.name==="TimeoutError")throw a;return e.waitForSelector(n,{timeout:le})});try{return await t("[data-doc-ready]"),await t("html[data-ge-editing][data-ge-save]"),await e.waitForFunction(()=>globalThis.__galleryTryEditable===!0&&document.documentElement.getAttribute("data-ge-save")==="saved",{timeout:le}),!0}catch(n){if(n.name!=="TimeoutError")throw n;return!1}}async function St(e,{where:t,id:n}){let a=await g(e.evaluateHandle($n,{instance:ft,...t}),"the page was asked for the instance"),s=await g(a.evaluate((o,{fallback:i,id:l})=>!(o instanceof Element)||o.getAttribute("data-doc-component")!==l?null:(DocKit.reveal?.(o),{fallback:o.hasAttribute(i),height:o.getBoundingClientRect().height}),{fallback:Rt,id:n}),"the page was asked for the instance");return s?(await e.setViewport({width:De,height:Math.min(Wt,Math.max(_e,Math.ceil(s.height)+240))}),await g(a.evaluate(o=>o.scrollIntoView({block:"center",behavior:"instant"})),"the instance was brought into view"),await g(a.evaluate(Fe,{still:we,step:ge,wait:$e}),"the instance held still"),{host:a,fallback:s.fallback}):null}function Hn({at:e,found:t}){return{where:{at:e},ready:Fn,saves:n=>({mark:()=>g(n.evaluate(()=>globalThis.__galleryTry.states.length),"the page was asked where saving stands"),until:(a,s)=>jn(n,a,s)}),changes:(n,a)=>on(st(n),st(a),e,t),plain:(n,a,s)=>a===n&&Se(n).changes.length>0&&s.parts.length>0,stayed:Mn,outside:"others",aside:"data-block-id aside",inside:Tt}}async function Pn(e){return g(e.evaluate(({instance:t,fields:n})=>{let a=document.activeElement;return a instanceof HTMLElement&&a.closest(t)&&a.matches(n)?(a.blur(),!0):!1},{instance:ft,fields:Dt}),"the focus left the instance's field")}async function Bn(e){await e.keyboard.down("Control"),await e.keyboard.press("z"),await e.keyboard.up("Control")}var Jn=e=>`${e}${[11,12,13].includes(e%100)?"th":["th","st","nd","rd"][e%10]??"th"}`,Un=3,Le=(e,t)=>e.length===1?`the ${de[e[0].kind]}`:`step ${t+1}`,V=e=>e.length===1?`the ${de[e[0].kind]}`:"the steps";function Zn(e,t){if(e.words!==t.words){let a=0;for(;a<e.words.length&&e.words[a]===t.words[a];)a++;let s=o=>JSON.stringify(`${a>20?"\u2026":""}${o.slice(Math.max(0,a-20),a+30)}${o.length>a+30?"\u2026":""}`);return`its words read ${s(e.words)} there and ${s(t.words)} here`}let n=e.fields.findIndex((a,s)=>a!==t.fields[s]);if(n>=0||e.fields.length!==t.fields.length){let a=n>=0?n:Math.min(e.fields.length,t.fields.length);return`its field ${a+1} (of ${e.fields.length}) holds ${JSON.stringify(e.fields[a]??null)} there and ${JSON.stringify(t.fields[a]??null)} here`}return null}var ct=["ticked","not ticked"],qn=["true","false","checked","done"],Wn={amp:"&",lt:"<",gt:">",quot:'"',apos:"'",nbsp:" "},Me=e=>new Set(e.normalize("NFKC").toLowerCase().match(/[\p{L}\p{N}]+/gu)??[]),lt=e=>e.replace(/<[^>]*>/g," ").replace(/"(?:[^"\\]|\\.)*"\s*:/g," ").replace(/&(?:#(\d+)|#x([\da-f]+)|([a-z]+));/gi,(t,n,a,s)=>{let o=n?Number(n):a?Number.parseInt(a,16):null;return o!==null?o<=1114111?String.fromCodePoint(o):t:Wn[s.toLowerCase()]??t}),dt=e=>qn.map(t=>(e.join(`
9
- `).toLowerCase().match(new RegExp(`\\b${t}\\b`,"g"))??[]).length).join();function Gn(e){let t=new Set,n=!1;for(let{parts:a}of e)for(let{runs:s=[]}of a)for(let{removed:o,added:i}of s){let[l,c]=[Me(o.map(lt).join(`
10
- `)),Me(i.map(lt).join(`
11
- `))];for(let r of c)l.has(r)||t.add(r);for(let r of l)c.has(r)||t.add(r);dt(o)!==dt(i)&&(n=!0)}return{words:t,ticks:n}}function Kn(e,t,n){let a=({words:h,fields:f})=>Me([h,...f.filter(u=>!ct.includes(u))].join(" ")),[s,o]=[a(e),a(t)],i=[...[...s].filter(h=>!o.has(h)),...[...o].filter(h=>!s.has(h))],l=h=>/[^\x00-\x7f]/.test(h),c=h=>[...n.words].some(f=>f===h||[h,f].every(u=>[...u].length>=2)&&[f,h].some(u=>l(u))&&(h.includes(f)||f.includes(h))),r=i.filter(c),d=h=>JSON.stringify(h.fields.filter(f=>ct.includes(f)));return n.ticks&&d(e)!==d(t)&&r.push("a box ticked"),r}async function Vn(e,{root:t,address:n,fresh:a,steps:s,keep:o,file:i,name:l,line:c,found:r,out:d,host:h}){let f=await g(e.createBrowserContext(),"a browser context opened"),u=await g(f.newPage(),"a tab opened"),w=await g(Et(u,r.id),"the tab was set to listen"),k=h.saves(u),y=[w],p={problems:[],notes:[],steps:[]},m=($,O=`${l}:${c}`)=>p.problems.push({where:O,what:$}),L=!o,D=L?`the copy of ${l}`:l,_=new URL(n).origin,C=0,F=0;u.on("request",$=>{!$.isNavigationRequest()||$.frame()!==u.mainFrame()||(C+=1,F=Date.now())});let M=null,H=null,S=async()=>h.changes(H,await N.readFile(i,"utf8").catch(()=>"")),b=($,O,v=!1)=>({...p,unverified:Rn($,O,{gesture:s.length===1?de[s[0].kind]:"steps",name:l,held:v,scratch:L,aside:h.aside}).unverified}),j=h.stayed,Z=await g(u.createCDPSession(),"the tab opened a session");await g(u.evaluateOnNewDocument(()=>addEventListener("doc-editable",()=>{globalThis.__galleryTryEditable=!0})),"the tab was set to tell when the page takes edits"),await g(u.setViewport({width:De,height:_e}),"the window was sized"),await g(u.emulateMediaFeatures([{name:"prefers-color-scheme",value:"light"}]),"the light theme came");try{await g(u.goto(n,{waitUntil:"load",timeout:0}),"the page opened",Oe);let $=null,O=null;for(let x=1;!$;x++){let E=C;try{if(!await h.ready(u))return{...p,unverified:`the page did not come to edit in ${le/1e3}s, so nothing was tried`};if($=await St(u,{where:h.where,id:r.id}),!$)return{...p,unverified:`the page does not hold the instance where ${l} has it (${l} changed meanwhile?), so nothing was tried`};if(await he(Math.max(0,await cn(t,L?null:i)-Date.now())),$.fallback&&(O=await gn({root:t,id:r.id,origin:_,loadedAt:F,loaded:()=>C!==E})),C!==E)throw new Error("the page loaded itself again");if($.fallback)break;if(H=await N.readFile(i,"utf8"),await g($.host.evaluate(kt),"the page was asked to listen"),C!==E)throw new Error("the page loaded itself again")}catch(I){if(C===E||x===Un)throw I;$=null,_n(w)}}let{host:v}=$;if($.fallback){await re(w);let x=[...w.own].map(([E,{line:I,unparsed:z}])=>({words:`${E}${I?` (kit.js:${I})`:""}`,unparsed:z}));return w.own.clear(),m(un(r.id,{said:x.map(({words:E})=>E),unparsed:x.find(({unparsed:E})=>E)?.words??null,...O})),await ht(v,p,d,h.framed)}M=C;let P=H,X=null;for(let[x,E]of s.entries()){let I=Le(s,x),{taken:z}=await g(u.evaluate(bn),"the page was asked to listen"),fe=await k.mark(),W=await Cn(u,v,E,Z),Q=await k.until(fe,_),G=await N.readFile(i,"utf8").catch(()=>""),J=h.changes(P,G);if(p.steps.push({said:W.said,parts:J.parts,outside:J.outside,plain:h.plain(H,P,J),taken:z}),C>M)return b(`after ${I}, ${j("reloading")}`,await S());if(j(Q))return b(`after ${I}, ${j(Q)}`,await S(),Q==="held");if(J.gone)return b(`after ${I}`,await S());X={step:E,gestured:W,heard:await g(u.evaluate(()=>globalThis.__galleryTry),"the page was asked what it heard")};for(let{name:ve,how:R}of J.parts)R&&p.notes.push({where:`${l}:${c}`,what:`${I}'s write lays the part ${ve} out anew (${R}): ${Ge}`});J.parts.length&&(p.steps.at(-1).before=P),P=G}await ht(v,p,d,h.framed);let B=await g(v.evaluate(Fe,{still:we,step:ge,wait:$e}).then(()=>v.evaluate(bt)),"the instance held still"),q=p.steps.filter(({parts:x})=>x.length),be=p.steps.map(x=>x.outside).filter(Boolean);if(h.outside==="problem"?p.steps.forEach((x,E)=>{x.outside&&m(`${Le(s,E)} changed ${l} outside ${h.outsideSaid(x.outside)}`)}):be.length&&(p.others={removed:be.reduce((x,{removed:E})=>x+E,0),added:be.reduce((x,{added:E})=>x+E,0)}),q.length===0){await re(w);let x=[...w.own.keys()].filter(I=>I.includes("context.edit"));for(let I of x)w.own.delete(I);let E=Dn(X.step.kind,X.heard,{...X.gestured,refusals:x,name:D});return m(s.length===1?E:`none of the ${s.length} steps wrote anything to ${D}; of the last, step ${s.length}, ${E}`),p}if(!o){let x=await k.mark();if(await Pn(u)){let W=await k.until(x,_);if(C>M)return b(`as the focus left the instance's field, ${j("reloading")}`,await S());if(j(W))return b(`as the focus left the instance's field, ${j(W)}`,await S(),W==="held")}let E=await g(u.evaluate(()=>globalThis.__galleryTry.taken),"the page was asked what it took"),I=s.length===1,z=0,fe=0;e:for(let[W,Q]of[...q.entries()].toReversed()){let G=Le(s,p.steps.indexOf(Q)),J=Math.max(1,(q[W+1]?.taken??E)-Q.taken),ve=R=>I?R===1?"one Ctrl+Z":`${R} Ctrl+Z`:`${R===1?"the Ctrl+Z":`${R} Ctrl+Z`} for ${G}`;for(let R=1;;R++){let oe=R===1?`the Ctrl+Z for ${G}`:`the ${Jn(R)} Ctrl+Z for ${G}`,At=await k.mark();await Bn(u);let ue=await k.until(At,_),Lt=await N.readFile(i,"utf8").catch(()=>""),xe=h.changes(Q.before,Lt);if(C>M)return b(`after ${oe}, ${j("reloading")}`,await S());if(j(ue))return b(`after ${oe}, ${j(ue)}`,await S(),ue==="held");if(xe.gone)return b(`after ${oe}`,await S());if(ue==="unchanged"){m(`${R===1&&I?"one Ctrl+Z":oe} wrote nothing, so ${D} keeps what ${G} wrote: a reader's undo does not take it back (the component keeps Ctrl+Z from the page where the focus is, or wrote by no context.edit)`);break e}if(xe.parts.length===0){fe+=R;break}if(R>=J){m(`after ${ve(R)}${J>1?", one for each write the page took of it,":""} ${D} is not as it was${I?"":` before ${G}`}, ${Y(xe.parts)} still differing: a reader's undo does not give it back (the component writes again as it hears the part change)`);break e}}z+=1}z===q.length&&Object.assign(p,{undone:z,presses:fe})}if(p.problems.length)return p;await pe(u.close());let Ot=x=>p.notes.push({where:`${l}:${c}`,what:x}),ee=await Qn(f,{...await a(P),host:h,found:r,after:B,written:Gn(q),out:d,hearings:y,problem:m,note:Ot,called:V(s)});return p.readBack=ee.back,p.aside=ee.aside??!1,ee.picture&&(p.fresh=ee.picture),ee.unverified?p.unverified=`${ee.unverified}, so it was not read back`:p.others&&(p.unverified=`someone else wrote ${l} meanwhile, outside the instance's parts (the user's page, an Agent), which stays: try it again once the file holds still`),p}catch($){if($ instanceof T){if(p.steps.length&&($.made=p),!$.unfound||(await re(w),w.own.size===0&&w.dialogs.size===0))throw $;return m(`${$.message[0].toLowerCase()}${$.message.slice(1).replace(/\.$/,"")}; its component did not draw it, and the console says why`),p}let O=M===null?null:await S();if(O&&C>M)return b(`after a gesture, ${j("reloading")}`,O);if(await Ye(e)){let v=`the browser went while waiting until ${$.doing??"the page answered"}`;return O?b(v,O):{...p,unverified:`${v}, so nothing was tried`}}return $.stuck?m(`the page stopped answering while waiting until ${$.doing}: a script that never ends, or a component that changes what it hears`,"the page"):m(`the trial stopped: ${ne($)}`,"the page"),p}finally{let $=new Set;for(let O of y){await re(O);for(let[v,{line:P}]of O.own)!$.has(v)&&$.add(v)&&p.problems.push({where:P?`kit.js:${P}`:"the page",what:`the console says ${v}`});for(let v of O.others.keys())!$.has(v)&&$.add(v)&&p.notes.push({where:"the page",what:`the console says ${v}`});for(let v of O.dialogs.keys())!$.has(v)&&$.add(v)&&p.problems.push({where:"the page",what:`it opened a dialog (${v}), which stops a reader's page until it is answered: show what it says in the instance`})}await pe(f.close())}}function zn(e,t,n,a){console.log(`FAIL ${e}: ${Qe(t)}, so nothing was tried and the browser was closed${a?"":`; the copy of ${n} was taken away`}. A script that never ends does this, and so may a browser that stalled: run the command once more`),process.exitCode=1}async function Qn(e,{address:t,file:n,host:a,found:s,after:o,written:i,out:l,hearings:c,problem:r,note:d,called:h}){let f=await g(e.newPage(),"a tab opened");c.push(await g(Et(f,s.id),"the fresh tab was set to listen"));let u=a.saves(f),w=c.at(-1),k=new URL(t).origin;await g(f.evaluateOnNewDocument(()=>addEventListener("doc-editable",()=>{globalThis.__galleryTryEditable=!0})),"the fresh tab was set to tell when the page takes edits"),await g(f.setViewport({width:De,height:_e}),"the window was sized"),await g(f.emulateMediaFeatures([{name:"prefers-color-scheme",value:"light"}]),"the light theme came");let y=`a fresh page of what ${h} wrote`,p={back:!1};try{let m=await N.readFile(n,"utf8");if(await g(f.goto(t,{waitUntil:"load",timeout:0}),"the fresh page opened",Oe),!await a.ready(f))return{back:!1,unverified:`${y} did not come to edit in ${le/1e3}s`};let L=await St(f,{where:a.where,id:s.id});if(!L)return r(`${y} does not hold the instance where the file has it: what the steps wrote is no instance of ${s.id} as the page reads it`),p;if(L.fallback){await re(w);let b=[...w.own].map(([j,{line:Z}])=>`${j}${Z?` (kit.js:${Z})`:""}`);return w.own.clear(),r(`${y} shows the instance in its fallback, what it holds read-only: its component failed as the page started it, ${b.length?`and the console says ${b.join("; ")}`:"and the console said nothing of it"}: what ${h} wrote is what its mount cannot read`),p}await g(L.host.evaluate(kt),"the fresh page was asked to listen");let D=await u.until(await u.mark(),k);if(D==="offline")return{back:!1,unverified:`${y}: ${a.stayed(D)}`};if(D!=="unchanged"&&D!=="saved")return r(`${y}: ${a.stayed(D)??D}`),p;let _=a.changes(m,await N.readFile(n,"utf8").catch(()=>""));if(_.gone)return{back:!1,unverified:`${y}: its file holds the instance no more where it stood (someone else wrote it meanwhile)`};if(D==="saved"||_.parts.length)return r(`${y} writes ${_.parts.length?Y(_.parts):"it again"} with no gesture as it opens, so that a page would write each time it opened: draw what the parts hold as they are, and write on a gesture alone`),p;let C=await g(L.host.evaluate(Fe,{still:we,step:ge,wait:$e}).then(()=>L.host.evaluate(bt)),"the fresh page's instance held still"),F=Zn(o,C);if(!F)return{back:!0};let M=A.join(l,"fresh.png");await g(L.host.screenshot({path:M}),"the fresh page's instance was pictured").catch(()=>{});let H=`${y} shows the instance otherwise than the page did after ${h.replace(/^the steps$/,"the last step")}: ${F}`,S=Kn(o,C,i);return S.length?(r(`${H} (the fresh page's picture: ${K(M)}), and what differs is of what ${h} wrote (${S.slice(0,3).map(b=>b==="a box ticked"?b:JSON.stringify(b)).join(", ")}). What it draws of what it wrote is to come from its parts alone, read as it wrote them: a value kept in memory, or written in a form its mount does not read, is gone on the next page`),{...p,picture:M}):(d(`${H}; none of it is of what ${h} wrote, and a fresh page keeps no filter or tab chosen, no editor left open, no words typed and not committed (--then Enter commits them), and need not. Its picture: ${K(M)}. What a reader keeps belongs in a part`),{back:!0,aside:!0,picture:M})}catch(m){return await xt(k)?(m.stuck?r(`${y} stopped answering while waiting until ${m.doing}: a script that never ends, or a component that changes what it hears`,"the page"):r(`${y} could not be read back: ${ne(m)}`,"the page"),p):{back:!1,unverified:`the server stopped answering as ${y} opened`}}finally{await pe(f.close())}}async function ht(e,t,n,a=null){let s=A.join(n,"after.png");try{let o=a?await g(e.evaluateHandle(a),"the instance's frame was found"):e;await g(o.screenshot({path:s}),"the instance was pictured"),t.picture=s}catch(o){if(o.stuck)throw o}return t}var U={gesture:"Gesture: ",step:"Step ",wrote:"Wrote: ",undone:"Undone: ",kept:"Kept (--keep): ",readBack:"Read back: ",picture:"Picture of the instance after "},Tt="nothing outside the instance changed (data-block-id aside)",Yn="open it: no one has looked at it for you";function Xn({slug:e,name:t,steps:n,keep:a,host:s=null},o){let i=n.length>1,l=a?t:`the copy of ${t}`,c=s?.aside??"data-block-id aside",r=Nt({name:t,several:i,keep:a,host:s},o.steps),d=o.steps.filter(({parts:p})=>p.length),h=a&&d.some(({plain:p})=>p)?", its plain HTML the kit's markup":"",f=o.presses??o.undone;if(a&&d.length)r.push(`${U.kept}${t} holds what ${V(n)} wrote`);else if(o.undone){let p=i?f===o.undone?`${f} Ctrl+Z, one for each step that wrote, the last first, each giving ${l} back as it was before its step`:`${f} Ctrl+Z for the ${o.undone} step${o.undone===1?"":"s"} that wrote, one for each write the page took, the last first, each step's giving ${l} back as it was before it`:f===1?`one Ctrl+Z, and ${l} is as it was`:`${f} Ctrl+Z, one for each write the page took of ${V(n)}, and ${l} is as it was`;r.push(`${U.undone}${p} (${c}${h})`)}o.readBack&&r.push(`${U.readBack}${a?`${t} opened again in a fresh page`:`a fresh page of what ${V(n)} wrote (a copy of it)`}: the instance mounts, writes nothing as it opens, and shows what the page showed after ${i?"the last step":V(n)}${o.aside?` of what ${i?"they":"it"} wrote; what else the page showed there, which nothing wrote, it does not (the note)`:""}`);for(let{where:p,what:m}of o.problems)r.push(` FAIL ${p}: ${m}`);for(let{where:p,what:m}of o.notes)r.push(` note ${p}: ${m}`);o.picture&&r.push(`${U.picture}${i?"the last step":V(n)}: ${K(o.picture)} (${Yn})`);let u=[o.picture,o.fresh].filter(Boolean);u.length&&r.push(Xe([{folder:A.dirname(u[0]),files:u}]));let w=o.problems.length;if(w)return{lines:[...r,`FAIL ${e}: ${w} problem${w===1?"":"s"}`],code:1};if(o.unverified)return{lines:[...r,`UNVERIFIED ${e}: ${o.unverified}`],code:3};let k=[...new Set(d.flatMap(({parts:p})=>p.map(({name:m})=>m)))].join(" and "),y=a?", kept (--keep)":`, ${f===1?"one Ctrl+Z":`${f} Ctrl+Z`} took ${i?"them":"it"} back`;return{lines:[...r,`OK ${e}: ${V(n)} wrote ${k}${y}, and a fresh page read ${i?"them":"it"} back${a?"":`; ${t} not written (a scratch copy)`}`],code:0}}function Nt({several:e,keep:t,host:n=null},a){let s=[];for(let[o,i]of a.entries()){if(s.push(e?`${U.step}${o+1}: ${i.said}`:`${U.gesture}${i.said}`),i.parts.length===0){e&&s.push(`${U.wrote}nothing`);continue}let l=t&&i.plain?"; and the page wrote the document's plain HTML as the kit's markup, as its first save of an edit does (gallery check and gallery export say what, by line, once), which stays":"",c=i.outside?n?.outside==="problem"?`; and outside ${n.outsideSaid(i.outside)}`:`; outside the instance's parts -${i.outside.removed} +${i.outside.added} lines someone else wrote meanwhile (the user's page, an Agent), which stay`:`; ${n?.inside??Tt}`;s.push(`${U.wrote}${Y(i.parts)}${c}${l}`,...rn(i.parts))}return s}function ea({name:e,steps:t,keep:n,host:a=null},s){let o=s.steps.length,i=o===1?"step 1":`steps 1 to ${o}`,l=s.steps.some(({parts:d})=>d.length),c=Nt({name:e,several:t.length>1,keep:n,host:a},s.steps),r=`step ${o+1} was not made, for the mistake below`;return n?c.push(l?`${U.kept}${e} holds what ${i} wrote, which stays; ${r}`:`Not made: ${r}; ${i} wrote nothing to ${e}`):c.push(`Not made: ${r}; ${i} ${l?"wrote to":"made"} a scratch copy, gone now, and ${e} holds nothing of ${o===1?"it":"them"}`),c}async function ka(e,{named:t,values:n,seconds:a={},keep:s,replace:o=!1}){let i=await Yt(n,a,o),l=i?[i]:null;if(t.length===0)throw new T("Name the document: gallery block try <slug> [<instance id>] and the gesture.");if(t.length>2)throw new T("gallery block try takes a document and an instance's id at most.");let c=n.has("--steps")?A.resolve(n.get("--steps")):null,r=l??await Xt(c),{slug:d,block:h}=await Pe(t[0]),f=Pt(d,e),u=Bt(f),w=u.html,k=await N.readFile(w,"utf8").catch(()=>null);k===null&&(console.error(`No document "${d}": ${K(w)} does not exist (gallery list lists those there are).`),process.exit(1));let y=wt(k);y.length===0&&(console.error(`${d} holds no instance of a custom block (an element with ${ke}): gallery block list says which there are, and gallery block show <id> how to write one.`),process.exit(1));let p=A.basename(w),m=nn(y,t[1]??h,{slug:d,name:p}),{id:L,line:D}=y[m],_=Ee(e),C=_.packages.get(L);if(!C){let S=_.problems.get(L);console.error(S?.off?`${L} is turned off in \u8BBE\u7F6E \u203A \u7EC4\u4EF6\u5217\u8868: its instances show what they hold, read-only, so a reader can do nothing with them.`:S?`${L} does not load, so its instances show what they hold, read-only: gallery block check ${L} says why.`:`No component ${L} in this workspace, so its instance shows what it holds, read-only: gallery block list says which there are.`),process.exit(1)}console.log(`${L} in ${d}, ${gt(y[m],p)}: ${K(w)}`),c&&console.log(`Steps: ${r.length} from ${K(c)}, made one after another in one page`);let F=await Je({slug:d,command:`gallery block try ${d}`});if(!F.ok){console.log(`UNVERIFIED ${d}: ${F.message}`),process.exitCode=3;return}await dn(e);let M=[],H=async S=>{let b=await ln(e,{directory:f,files:u,text:S});return M.push(b.slug),b};try{let S=s?{slug:d,file:w}:await H(k),b=Te(F.port,S.slug);console.log(s?`Page: ${b} (the document's page alone, editable: the Agent's own; --keep: what ${V(r)} write stays in ${p}; the server runs on after this command)`:`Page: ${b} (a scratch copy of ${d}, its page alone, editable, made for this trial and gone at its end: ${p} is not written, and no page of the user's shows the trial; the server runs on after this command)`);let j=Ue();if(!j){console.log(`UNVERIFIED ${d}: no Chrome, Edge or Chromium found (GALLERY_BROWSER=<its executable> picks one), so nothing was tried`),process.exitCode=3;return}let Z;try{Z=await qe({executablePath:j,args:Ze()})}catch(O){console.log(`UNVERIFIED ${d}: the browser ${j} did not start, twice, each time with a fresh profile (${ne(O)}; GALLERY_BROWSER=<its executable> picks another), so nothing was tried`),process.exitCode=3;return}let $=A.join(se(e).qa,d,"try");try{await N.rm($,{recursive:!0,force:!0}),await N.mkdir($,{recursive:!0});let O=async B=>{if(s)return{address:b,file:S.file};let q=await H(B);return{address:Te(F.port,q.slug),file:q.file}},v;try{v=await Vn(Z.browser,{root:e,address:b,fresh:O,steps:r,keep:s,file:S.file,name:p,line:D,found:C,out:$,host:Hn({at:m,found:C})})}catch(B){if(B instanceof T&&B.made&&console.log(ea({name:p,steps:r,keep:s},B.made).join(`
12
- `)),B.stuck)return zn(d,B,p,s);throw B}let{lines:P,code:X}=Xn({slug:d,name:p,steps:r,keep:s},v);console.log(P.join(`
13
- `)),process.exitCode=X}finally{await Z.close()}}finally{for(let S of M)await $t(e,S)}}export{le as a,Gt as b,Ie as c,at as d,ie as e,ut as f,Yt as g,Xt as h,wt as i,gt as j,nn as k,an as l,st as m,ot as n,on as o,rn as p,cn as q,ln as r,$t as s,dn as t,fn as u,un as v,gn as w,Fe as x,An as y,Rn as z,Dn as A,Et as B,_n as C,Hn as D,V as E,Zn as F,Me as G,Gn as H,Kn as I,Vn as J,zn as K,U as L,Tt as M,Yn as N,Xn as O,ea as P,ka as Q};
@@ -1,2 +0,0 @@
1
- import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
2
- import{a,b,c,d,e,f,g,h}from"./chunk-XZV72SQ4.mjs";import"./chunk-V4ZHRALW.mjs";import"./chunk-SQ3FQCCN.mjs";import"./chunk-JEUK3ZO7.mjs";import"./chunk-6QWQXHAV.mjs";import"./chunk-2OHANJ6Q.mjs";import"./chunk-7UZUQQ7Q.mjs";import"./chunk-4B2TB5K2.mjs";import"./chunk-KLQP46Y3.mjs";import"./chunk-4OZWXZE5.mjs";import"./chunk-HX4DLE3J.mjs";import"./chunk-FJLM7YE7.mjs";import"./chunk-HYMEEXKN.mjs";import"./chunk-E7656LR7.mjs";import"./chunk-TKWEX4FD.mjs";import"./chunk-A55HN5OK.mjs";import"./chunk-5L7RYZCL.mjs";export{c as HOME_NOT_MADE,g as emptyRequiredOf,d as missingPageSaid,a as pageAddressOf,b as pageAloneOf,h as run,e as setsOf,f as settingsGiven};
@@ -1,5 +0,0 @@
1
- import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
2
- import{c as _}from"./chunk-PKVK6WFC.mjs";import{n as G,p as Le,r as Ee,s as Ne,t as Ie,x as Oe}from"./chunk-NMF3IPYA.mjs";import{c as he,d as pe,e as ue,f as fe,g as we,h as ge,i as me,j as z,l as $e,n as Y,o as ke,q as be,r as ye,s as xe,t as ve,u as Se}from"./chunk-LJLVCU6W.mjs";import{M as Ae}from"./chunk-XBNFXWAW.mjs";import"./chunk-342HXE3Q.mjs";import"./chunk-T4Y2ZSVX.mjs";import{d as Ce,g as je}from"./chunk-XZV72SQ4.mjs";import"./chunk-V4ZHRALW.mjs";import"./chunk-5GK7HS62.mjs";import{i as ie}from"./chunk-SQ3FQCCN.mjs";import{a as W}from"./chunk-JEUK3ZO7.mjs";import"./chunk-M4NRDYI5.mjs";import{a as re,b as le,e as de,f as K,g as ce}from"./chunk-PUOQ65NC.mjs";import"./chunk-6QWQXHAV.mjs";import"./chunk-ZLS2FRS6.mjs";import"./chunk-S3SX3COT.mjs";import"./chunk-IA4PSIMD.mjs";import"./chunk-2OHANJ6Q.mjs";import"./chunk-F4ZA6JRZ.mjs";import"./chunk-7M2BQQGZ.mjs";import"./chunk-6NLXUKAY.mjs";import"./chunk-VRPVVMRB.mjs";import"./chunk-7UZUQQ7Q.mjs";import{a as H,b as j,c as P,d as D,f as oe}from"./chunk-4B2TB5K2.mjs";import{a as te,e as B,f as ae}from"./chunk-KLQP46Y3.mjs";import{b as se}from"./chunk-4OZWXZE5.mjs";import"./chunk-BX5AKINW.mjs";import"./chunk-HX4DLE3J.mjs";import"./chunk-ZTHICSSF.mjs";import"./chunk-FJLM7YE7.mjs";import"./chunk-PAREWQGB.mjs";import{j as ne}from"./chunk-BFJGHSQN.mjs";import"./chunk-U5XL7D6A.mjs";import"./chunk-HYMEEXKN.mjs";import"./chunk-UMHUSOPJ.mjs";import"./chunk-W5NPH5UA.mjs";import"./chunk-ECZBLQKK.mjs";import"./chunk-E7656LR7.mjs";import{f as Z,j as ee}from"./chunk-TKWEX4FD.mjs";import{b as X,e as _e}from"./chunk-A55HN5OK.mjs";import"./chunk-5L7RYZCL.mjs";_e();import{existsSync as Ue}from"node:fs";import R from"node:fs/promises";import O from"node:path";import{isInstance as Ke}from"../browser/shared/components/index.mjs";import{ATTRIBUTE as He,INSTANCE as Ye}from"../browser/shared/components/installed.mjs";import{attr as M,hasClass as q,walk as Re}from"../browser/shared/html-tree.mjs";import{assetFile as Qe,imageFile as Te,referencedFile as Me}from"../browser/shared/media.mjs";import{pageAssetAddress as Ve,pageExists as Je,pageFiles as Xe}from"../browser/shared/pages.mjs";import{layoutOf as U}from"../browser/shared/workspace.mjs";var Q=[1280,1920,600],De=["light","dark"],Ze=900,et=3e4,tt=new Set(["iframe","frame","object","embed"]),at=/^\d+$/,ot={x:[0,11],y:[0,1/0],w:[1,12],h:[1,24]};function st(e,{catalog:g,folder:o,slug:h}){let i=[],s=d=>d?.sourceCodeLocation?.startLine??1,n=(d,a)=>i.push({line:typeof d=="number"?d:s(d),what:a}),t=X(e.replace(/^/," "),{sourceCodeLocationInfo:!0}),c=[],f=[];Re(t,d=>{d.tagName&&(d.tagName==="main"&&q(d,"gallery-page")&&c.push(d),q(d,"gallery-board")&&f.push(d),q(d,"gallery-card")&&!q(d.parentNode,"gallery-board")&&n(d,`a card (class gallery-card) that is no board's child: each card stands right in a <div class="gallery-board" data-board-id="\u2026">, which lays it out, and this one is laid out by none`))},{inTemplates:!1}),c.length===0&&(f.length>0||j(e).cards.length>0)&&n(1,`no <main class="gallery-page">: a page's boards stand in one (it is how a block knows it is on a page: context.place "page", and how the page follows the theme)`);let y=new Map;for(let d of f){let a=d.parentNode;for(;a&&!(a.tagName==="main"&&q(a,"gallery-page"));)a=a.parentNode;c.length&&!a&&n(d,`a board outside <main class="gallery-page">: its cards' blocks would not know they are on a page`);let r=M(d,"data-board-id");r===void 0||r===""?n(d,"a board with no data-board-id: write one (main, side\u2026), of lowercase letters, digits and hyphens, once in the page"):H.test(r)?y.has(r)?n(d,`data-board-id="${r}" again (line ${y.get(r)} has it): each board's id is its own`):y.set(r,s(d)):n(d,`data-board-id="${r}": a board's id is lowercase letters, digits and single hyphens (main, side-2)`)}let S=new Map,N=new Map;for(let d of j(e).cards){let{node:a}=d,r=M(a,"data-card-id"),k=r&&H.test(r)?`card ${r}`:"this card";r===void 0||r===""?n(a,"a card with no data-card-id: write one (c<n>, the lowest none holds, or a name of your own), of lowercase letters, digits and hyphens: its place, its writes and the reader's state go by it"):H.test(r)?S.has(r)?n(a,`data-card-id="${r}" again (line ${S.get(r)} has it): each card's id is its own, and the page's writes go by it`):S.set(r,s(a)):n(a,`data-card-id="${r}": a card's id is lowercase letters, digits and single hyphens (c3, water)`);let u=0;Re(a,x=>{x!==a&&Ke(x)&&(u+=1)},{inTemplates:!1}),u===0?n(a,`${k} holds no instance of a custom block (an element with ${He}): a card is one block's instance, gallery/static's for what only shows`):u>1?n(a,`${k} holds ${u} instances: a card holds one (put each on a card of its own)`):d.instance&&d.instance.parentNode!==a&&n(d.instance,`${k}'s instance stands inside another element of the card: write it right in the card's <section>`);let b={};for(let x of["x","y","w","h"]){let A=M(a,`data-${x}`),[L,E]=ot[x];A===void 0?n(a,`${k} has no data-${x}: a card says its place and size in whole cells, data-x data-y data-w data-h`):at.test(A.trim())?Number(A)<L||Number(A)>E?n(a,`${k}'s data-${x}="${A}": ${x} is ${E===1/0?`${L} or more`:`${L} to ${E}`}${x==="w"?" (a row is 12 cells)":""}`):b[x]=Number(A):n(a,`${k}'s data-${x}="${A}" is no whole number`)}b.x!==void 0&&b.w!==void 0&&b.x+b.w>12?n(a,`${k} reaches past the row's end: data-x ${b.x} and data-w ${b.w} make ${b.x+b.w}, and a row is 12 cells (x + w is 12 at most)`):Object.keys(b).length===4&&N.set(d.board,[...N.get(d.board)??[],{id:r??null,...b,line:s(a)}]),d.block&&nt(d.block,g,x=>n(d.instance,`${k}'s block ${d.block}: ${x}`))}for(let d of N.values())for(let a=0;a<d.length;a++)for(let r=a+1;r<d.length;r++){let[k,u]=[d[a],d[r]];k.x<u.x+u.w&&u.x<k.x+k.w&&k.y<u.y+u.h&&u.y<k.y+k.h&&n(u.line,`card ${u.id??"here"} (x ${u.x}, y ${u.y}, ${u.w} \xD7 ${u.h}) shares cells with card ${k.id??`at line ${k.line}`} (x ${k.x}, y ${k.y}, ${k.w} \xD7 ${k.h}): no two cards of a board overlap; move one to a free spot (gallery page add finds one for a new card)`)}return i.push(...it(e,{folder:o,slug:h})),i.sort((d,a)=>d.line-a.line)}function nt(e,g,o){let h=g.packages.get(e);if(h){h.places.includes("page")||o(`a block of documents (its manifest's places has no "page"): on a custom page its card says so and runs nothing`);return}let i=g.problems.get(e);g.settings.disabled.includes(e)?o("turned off in \u8BBE\u7F6E \u203A \u7EC4\u4EF6\u5217\u8868: its card says so and runs nothing (the user turns it on again)"):i?o(`it does not load (${ee("en",i.problem)}): gallery block check ${e} says why`):ae(e)&&B(e)?o(`one of Gallery's own blocks, not yet in this workspace: gallery block add ${B(e).pack===te?B(e).name:e} puts it in`):o("no custom block of that id in this workspace: gallery block list lists them")}function it(e,{folder:g,slug:o}){let h=[],i=`${Ve(o,"assets/")}`;for(let s of ne(e,()=>!0)){let n=s.value.trim(),t=["a","area"].includes(s.node.tagName)&&s.how==="href",c=Me(n)??(n.startsWith(i)?Me(n.slice(i.length-7)):null),f=`"${n.length>60?`${n.slice(0,60)}\u2026`:n}"`,y=s.how==="css"?`<style>'s url() ${f}`:`<${s.node.tagName}>'s ${s.how==="style"?"style url()":s.how} ${f}`;if(c!==null){Qe(c)?tt.has(s.node.tagName)&&!Te(c)?h.push({line:s.line,what:`${y}: a frame of a file of the page's assets/ downloads it and shows nothing, as the server hands out a page's own file that is no picture, stylesheet or script for saving only: write what it shows in the page itself, frame a site by its https address, or offer the file with a link, <a href="${c}" download>`}):Ue(O.join(g,c))||h.push({line:s.line,what:`${y}: ${c} is not in the page's folder (${W(O.join(g,"assets"))}): put the file there${Te(c)?"":", or link to it"}`}):h.push({line:s.line,what:`${y} names a file the server serves none by: the page's own files go right in pages/${o}/assets/, each named with letters, digits, dots, dashes and underscores (assets/cover.png)`});continue}t||!n||/^(?:[a-z][a-z0-9+.-]*:|\/|#|\?)/i.test(n)||h.push({line:s.line,what:`${y} is relative to /pages/${o}, where nothing is served: put the file in pages/${o}/assets/ and write assets/<file>`})}return h}function rt(e,g){let o=P(e).text,h=[];for(let i of j(o).cards){let s=i.block?g.packages.get(i.block):null;if(!s?.settings?.some(f=>f.required)||!s.parts.settings)continue;let n=G(D(o,i),_,{...s,parts:{settings:s.parts.settings}})?.parts.find(({name:f})=>f==="settings"),t={};try{t=n?.text.trim()?JSON.parse(n.text):{}}catch{continue}let c=je(s,t);c.length&&h.push({id:i.id,block:i.block,line:i.node.sourceCodeLocation?.startLine??1,empty:c})}return h}var lt=({id:e,block:g,empty:o})=>`card ${e} (${g}) holds no ${o.map(({key:h,label:i,zh:s})=>`${h} (${s&&s!==i?`${i}, ${s}`:i})`).join(" and no ")} in its settings, which it cannot show anything without: it shows its ask for one (the grip at its top right \u203A \u8BBE\u7F6E\u2026), and no picture of the page shows what it is for. Ask the user for it, or take it from what the workspace says (\u5199\u4F5C\u504F\u597D, the documents), write it in the card's settings part, and tell them in the handoff which you did`,dt=(e,g=!1)=>{let o=h=>M(e.node,`data-${h}`)??"-";return`x ${o("x")}, y ${o("y")}, ${o("w")} \xD7 ${o("h")}${g?` on ${e.board??"-"}`:""}`},Fe=e=>`${e.board},${M(e.node,"data-x")},${M(e.node,"data-y")}`,Pe=e=>`${M(e.node,"data-w")},${M(e.node,"data-h")}`;function ct(e,g,o){let[h,i]=[P(e).text,P(g).text],[s,n]=[j(h).cards,j(i).cards],t=new Set([...s,...n].map(a=>a.board)).size>1,c=a=>dt(a,t),f={added:[],removed:[],moved:[],resized:[],data:[],markup:[],page:null,kept:0};for(let a of s)n.some(r=>r.id===a.id)||f.removed.push({id:a.id,block:a.block,cells:c(a)});for(let a of n)s.some(r=>r.id===a.id)||f.added.push({id:a.id,block:a.block,cells:c(a)});for(let a of n){let r=s.find($=>$.id===a.id);if(!r)continue;let[k,u]=[Fe(r)!==Fe(a),Pe(r)!==Pe(a)];k&&f.moved.push({id:a.id,block:a.block,was:c(r),now:c(a)}),u&&f.resized.push({id:a.id,block:a.block,was:c(r),now:c(a)});let[b,x]=[D(h,r),D(i,a)];if(b===x){!k&&!u&&(f.kept+=1);continue}let A=r.block===a.block?o.packages.get(a.block):null,L=A?{...A,parts:Object.fromEntries(Object.entries(A.parts).filter(([,$])=>$.edit==="data"))}:null,[E,l]=L?[G(b,_,L),G(x,_,L)]:[null,null];if(!E||!l){f.markup.push({id:a.id,block:A?a.block:null});continue}let v=E.parts.flatMap(({name:$,text:m},I)=>m===l.parts[I].text?[]:[{name:$,...Y(m,l.parts[I].text),runs:ke(m,l.parts[I].text)}]);v.length&&f.data.push({id:a.id,block:a.block,parts:v}),E.outside!==l.outside&&f.markup.push({id:a.id,block:a.block})}let y=(a,r)=>{let k="",u=0;for(let b of[...r].sort((x,A)=>x.start-A.start))k+=a.slice(u,b.start),u=b.end;return k+a.slice(u)},[S,N]=[y(h,s),y(i,n)],d=a=>a.replace(/\s+/g," ");return d(S)!==d(N)&&(f.page=Y(S.replace(/^\s*\n/gm,""),N.replace(/^\s*\n/gm,""))),f}var ze="(the user's, on the page)",We="(put there by Gallery)";function ht(e,g){let o=n=>{let t=new Map;for(let c of g)if(c.by===n)for(let[f,y]of Object.entries(c.cards??{}))t.set(f,new Set([...t.get(f)??[],...Array.isArray(y)?y:[]]));return t},h=o("page"),i=o("gallery"),s=n=>t=>{let c=!!h.get(t.id)?.has(n);return{...t,user:c,...!c&&i.get(t.id)?.has(n)?{gallery:!0}:{}}};return{...e,added:e.added.map(s("added")),removed:e.removed.map(s("removed")),moved:e.moved.map(s("cells")),resized:e.resized.map(s("cells")),data:e.data.map(s("content")),markup:e.markup.map(s("content"))}}function pt(e,g){let o=({id:t,block:c})=>`${t}${c?` (${c})`:""}`,h=t=>t.user?` ${ze}`:t.gallery?` ${We}`:"",i=[];for(let t of e.added)i.push(` added ${o(t)} at ${t.cells}${h(t)}`);for(let t of e.removed)i.push(` removed ${o(t)}, which stood at ${t.cells}${h(t)}`);for(let t of e.moved)i.push(` moved ${o(t)}: ${t.was} then ${t.now}${h(t)}`);for(let t of e.resized)e.moved.some(c=>c.id===t.id)||i.push(` resized ${o(t)}: ${t.was} then ${t.now}${h(t)}`);for(let t of e.data)i.push(` data ${o(t)}: ${$e(t.parts)}${h(t)}`,...Le(t.parts).map(c=>` ${c}`));for(let t of e.markup)i.push(` markup ${o(t)}: its markup outside its place and its data parts${t.block?"":" (a block the workspace has not: its markup whole)"}${h(t)}`);if(e.page&&i.push(` page its own HTML outside the cards: -${e.page.removed} +${e.page.added} of its ${e.page.lines} line${e.page.lines===1?"":"s"}`),i.length===0)return[`No change since ${g}: every card where it was, with the data it had.`];let s=["added","removed","moved","resized","data","markup"].some(t=>e[t].some(c=>c.user)),n=["added","removed","moved","resized","data","markup"].some(t=>e[t].some(c=>c.gallery));return[`Changes since ${g}:`,...i,...e.kept?[e.kept===1?" The other card as it was.":` The other ${e.kept} cards as they were.`]:[],...s?[` Each change marked ${ze} is the user's own gesture on the page since then (a move, a resize, a card added or deleted there, what they typed in it), which the page wrote: leave it as it is, never put it back.`]:[],...n?[` Each change marked ${We} is Gallery's own doing, not the user's and not yours: the cards it put on the home page when it made it (\u95EE\u5019\u4E0E\u65E5\u671F, \u4FBF\u7B7E): leave it as it is.`]:[]]}async function ut(e,g){let{qa:o,state:h}=U(e),i=O.join(o,g,"checked.html"),s=await R.readFile(i,"utf8").catch(()=>null);if(s!==null){let{mtime:y}=await R.stat(i);return{text:s,since:`the last check that found nothing (${qe(y)}, local time, ${W(i)})`,at:y.getTime()}}let n=O.join(h,"pages",g),t=(await R.readdir(n).catch(()=>[])).filter(y=>/^\d{15}-\d{4}\.html$/.test(y)).sort();if(t.length===0)return null;let c=O.join(n,t.at(-1)),f=Number(t.at(-1).slice(0,15));return{text:await R.readFile(c,"utf8"),since:`the page as it was before its last write (${qe(new Date(f))}, local time; used because no check has passed yet)`,at:f}}var qe=e=>`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")} ${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`;function ft(e,g){let o=t=>`<${t.localName}${t.getAttribute("src")?` src="${t.getAttribute("src").slice(0,80)}"`:""}>`,h=[...document.querySelectorAll(".gallery-board > .gallery-card")].map(t=>{let c=t.parentElement.getBoundingClientRect(),f=t.getBoundingClientRect(),y=[...t.children].find(S=>S.matches(e));return{id:t.getAttribute("data-card-id"),block:y?.getAttribute(g)??null,out:f.width>0&&(f.left<c.left-1||f.right>c.right+1),tall:t.scrollHeight>t.clientHeight+1?{needs:t.scrollHeight,has:t.clientHeight}:null,wide:t.scrollWidth>t.clientWidth+1?{needs:t.scrollWidth,has:t.clientWidth}:null,fallback:!!y?.hasAttribute("data-doc-fallback"),error:(t.querySelector(".doc-kit-error")?.textContent??"").trim()||null,broken:[...t.querySelectorAll("img")].filter(S=>S.complete&&S.naturalWidth===0).map(o)}}),i=[...document.querySelectorAll("img")].filter(t=>!t.closest(".gallery-card")&&t.complete&&t.naturalWidth===0).map(o),s=document.documentElement.scrollWidth,n=[...globalThis.__galleryQueries?.pending.values()??[]].map(({kind:t,block:c,at:f})=>({kind:t,block:c,waited:Date.now()-f}));return{cards:h,broken:i,stuck:n,wide:s>innerWidth+1?s:0,columns:document.querySelector(".gallery-board")?.getAttribute("data-columns")??null}}async function wt(e,{address:g,out:o,readers:h=new Set,wait:i=ge,limits:s={}}){let{loading:n=he,ready:t=et,answer:c=pe,closing:f=de,looking:y=ue}=s,S=new Map,N=new Map,d=[],a=!1,r=(l,v,$,m,I=S)=>{if(a)return;let w=I.get(l)??{card:v,what:$,looks:[]};w.looks.push(m),I.set(l,w)},k="a browser context opened",u=(l,v,$=c)=>(k=v,ye(l,v,$)),b=Q.flatMap(l=>De.map(v=>({width:l,theme:v,view:`${l} ${v}`}))),x=null,A=async({width:l,theme:v,view:$})=>{let m=await u(x.newPage(),"a tab opened");try{m.on("pageerror",p=>r(`error ${z(p)}`,null,`the page threw: ${z(p)}`,$)),m.on("console",p=>{p.type()==="error"&&!/^Failed to load resource/.test(p.text())&&r(`console ${p.text().split(`
3
- `)[0]}`,null,`the console says ${p.text().split(`
4
- `)[0]}`,$)}),m.on("response",p=>{let C=new URL(p.url());p.status()>=400&&C.origin===new URL(g).origin&&C.pathname!=="/favicon.ico"&&r(`request ${C.pathname}`,null,`${C.pathname} answered ${p.status()}`,$)}),await u(be(m,{add:p=>r(`dialog ${p}`,null,`it opened a dialog (${p}), which stops a reader's page until it is answered`,$)}),"the tab was set to refuse dialogs"),await u(me(m),"the tab was set to watch the page's reads of the workspace"),await u(m.setViewport({width:l,height:Ze}),`the window went to ${l}px`),await u(m.emulateMediaFeatures([{name:"prefers-color-scheme",value:v}]),`the ${v} theme came`),await u(m.goto(g,{waitUntil:"load",timeout:0}),"the page opened",n),await u(m.waitForSelector("html[data-doc-ready][data-doc-drawn]",{timeout:0}),"the page was drawn (its html got data-doc-drawn)",t),await u(m.evaluate(()=>document.fonts?.ready.then(()=>!0)),"the page's fonts loaded");let I=await u(m.$("main"),"the page's main was found")??await u(m.$("body"),"the page's body was found");await u(I.evaluate(Oe,{still:fe,step:we,wait:i}),"the page held still");let w=await u(m.evaluate(ft,Ye,He),"the page was looked at");for(let{kind:p,block:C,waited:Ge}of w.stuck){let V=w.cards.filter(F=>C?F.block===C:h.has(F.block)),J=F=>`the workspace had not answered ${F} read of "${p}" ${Math.round(Ge/1e3)} s after it asked, so its picture shows it before it drew what it reads, which the picture then does not tell (open the page in Gallery to see it)`;if(V.length)for(let F of V)r(`unanswered ${F.id} ${p}`,F.id,J("its"),$,N);else r(`unanswered ${p}`,null,J("a card's"),$,N)}w.wide&&r("wide",null,`the page is ${w.wide}px wide in a window ${l}px wide: something of its own reaches past the window (a width of its own, a long word), and a reader scrolls it sideways`,$);for(let p of w.broken)r(`broken ${p}`,null,`a picture that does not load: ${p}`,$);for(let p of w.cards){p.fallback&&r(`fallback ${p.id}`,p.id,`its block failed: the card shows what its instance holds, read-only${p.error?` (${p.error.slice(0,200)})`:""}`,$),p.out&&r(`out ${p.id}`,p.id,"it is drawn out of its board",$),p.tall&&r(`tall ${p.id}`,p.id,`what it holds does not fit it: ${p.tall.needs}px high in a card that shows ${p.tall.has}px, the rest scrolling inside the card (give the card more cells, data-h, or a size its block lists; a block whose content grows says card.fit "content")`,$),p.wide&&r(`wide ${p.id}`,p.id,`what it holds is wider than the card: ${p.wide.needs}px in a card ${p.wide.has}px wide`,$);for(let C of p.broken)r(`broken ${p.id} ${C}`,p.id,`a picture that does not load: ${C}`,$)}let T=O.join(o,`${l}-${v}.png`);await u(m.screenshot({path:T,fullPage:!0}),"the page was pictured"),a||d.push(T)}finally{await K(m.close(),f)}},L=l=>({problems:[...S.values()],notes:[...N.values()],pictures:d,unverified:null,stuck:!1,...l}),E=null;try{x=await u(e.createBrowserContext(),"a browser context opened");for(let l of b)E=l,await gt(A(l),y,()=>k);return L({})}catch(l){return await Se(e)?L({unverified:`the browser went while it looked (${z(l)})`}):l.stuck?(r("stopped",null,mt(l,b.indexOf(E??b[0])<b.length-1),(E??b[0]).view),L({stuck:!0})):L({unverified:`the look stopped: ${z(l)}`})}finally{a=!0,await K(x?.close(),f)}}function gt(e,g,o){let h=0,i=new Promise((s,n)=>{h=setTimeout(()=>n(Object.assign(new Error(o()),{stuck:!0,doing:o(),limit:g,whole:!0})),g)});return Promise.race([e,i]).finally(()=>clearTimeout(h))}function mt(e,g){return`${e.whole?`the look was not done in ${xe(e.limit)}, waiting until ${e.doing}`:ve(e)}; the look stopped here and the browser was closed${g?", so the looks after it were not made":""}. A script of the page that never ends does this, and so may a browser that stalled: run the check once more, and if it stops at the same place again, the page holds it up`}function Be(e){let g=[...new Set(e.map(i=>i.split(" ")[0]))],o=[...new Set(e.map(i=>i.split(" ")[1]))],h=i=>i.length<2?i.join(""):`${i.slice(0,-1).join(", ")} and ${i.at(-1)}`;return`at ${h(g)}px${o.length===De.length?"":`, ${h(o)}`}`}async function Ht(e,g){if(g.length!==1)throw new se("gallery page check takes one page's slug.");let[o]=g,h=Xe(o,e);Je(o,e)||(console.error(await Ce(o,e)),process.exit(1));let i=new Date,s=await R.readFile(h.html,"utf8"),n=O.basename(h.html),t=Z(e),{boards:c,cards:f}=j(s);console.log(`${o}: ${W(h.html)}, ${c.length} board${c.length===1?"":"s"} and ${f.length} card${f.length===1?"":"s"}`);let y=[],S=st(s,{catalog:t,folder:h.folder,slug:o});for(let{line:l,what:v}of S)y.push(` FAIL ${n}:${l}: ${v}`);console.log(S.length?`Structure: ${S.length} problem${S.length===1?"":"s"}`:"Structure: nothing wrong (the page's own HTML, scripts and frames its own; every board's and card's id once, one instance a card, the cells on the board and none shared, every block one a page runs, every file of assets/ there)");for(let l of y)console.log(l);for(let l of j(P(s).text).cards)console.log(` ${l.id} ${l.block??"(no instance)"} x ${l.x}, y ${l.y}, ${l.w} \xD7 ${l.h}${c.length>1?` on ${l.board}`:""} ${n}:${l.node.sourceCodeLocation?.startLine}`);let N=rt(s,t);for(let l of N)console.log(` note ${n}:${l.line}: ${lt(l)}`);let d=await ut(e,o),a=d?await oe(U(e).state,o,d.at):[];console.log((d?pt(ht(ct(d.text,s,t),a),d.since):["No earlier version to tell changes against: the next check that finds nothing keeps this one, and says what changed since."]).join(`
5
- `));let r=new Map(j(P(s).text).cards.map(l=>[l.id,l.node.sourceCodeLocation?.startLine??1])),k=(l,v=null,$=0)=>{if(l)return{line:`FAIL ${o}: ${l} problem${l===1?"":"s"}`,code:1};if(v)return{line:`UNVERIFIED ${o}: ${v}; its structure was checked, and nothing is wrong with it`,code:3};let m=N.length?`; and ${N.length===1?"one card asks":`${N.length} cards ask`} for a setting no one gave (see "note" above): ${N.map(({id:I,empty:w})=>`${I} (${w.map(({key:T})=>T).join(", ")})`).join(", ")}`:"";return{line:`OK ${o}: its structure, and its ${f.length} card${f.length===1?"":"s"} at ${Q.join(", ")}px in light and dark${$?`; but ${$===1?"one card was":`${$} cards were`} pictured before the workspace answered it (see "note" above), so ${$===1?"its picture does":"their pictures do"} not show what ${$===1?"it reads":"they read"}`:""}${m}`,code:0}},u=await ie({command:`gallery page check ${o}`}),b=async(l,v,$=0)=>{let{line:m,code:I}=k(l,v,$);if(console.log(m),I===0){let w=O.join(U(e).qa,o,"checked.html");await R.mkdir(O.dirname(w),{recursive:!0}),await R.writeFile(w,s),await R.utimes(w,i,i)}process.exitCode=I};if(!u.ok)return b(S.length,`${u.message}, so the page was not looked at`);let x=re();if(!x)return b(S.length,"no Chrome, Edge or Chromium found (GALLERY_BROWSER=<its executable> picks one), so the page was not looked at");await Ie(e);let A=await Ee(e,{directory:h.folder,files:h,text:s}),L=O.join(U(e).qa,o,"check"),E=null;try{let{pageAloneOf:l}=await import("./chunk-ONKC4BCC.mjs"),v=l(u.port,A.slug);console.log(`Looked at: ${v} (a scratch copy of ${o}, gone at the end: nothing a block does as it opens writes ${n}), at ${Q.join(", ")}px, light and dark`);try{E=await ce({executablePath:x,args:le()})}catch(w){return b(S.length,`the browser ${x} did not start, twice (${z(w)}), so the page was not looked at`)}await R.rm(L,{recursive:!0,force:!0}),await R.mkdir(L,{recursive:!0});let $=new Set([...t.packages.values()].filter(({needs:w})=>w?.includes("workspace")).map(({id:w})=>w)),m=await wt(E.browser,{address:v,out:L,readers:$});m.stuck&&(await E.close(),E=null);for(let{card:w,what:T,looks:p}of m.problems)console.log(` FAIL ${n}:${w?r.get(w)??1:1}: ${w?`card ${w}: `:""}${T} (${Be(p)})`);let I=new Map(j(s).cards.map(w=>[w.id,w.block]));for(let{card:w,what:T,looks:p}of m.notes)console.log(` note ${n}:${w?r.get(w)??1:1}: ${w?`card ${w}${I.get(w)?` (${I.get(w)})`:""}: `:""}${T} (${Be(p)})`);return m.pictures.length&&(console.log(`Pictures of the page in ${W(L)}: ${m.pictures.map(w=>O.basename(w)).join(", ")}`),console.log(Ae([{folder:O.dirname(L),files:m.pictures}]))),b(S.length+m.problems.length,m.unverified,new Set(m.notes.map(({card:w})=>w??"")).size)}finally{await E?.close(),await Ne(e,A.slug)}}export{We as GALLERYS_MARK,Q as LOOK_WIDTHS,De as THEMES,ze as USERS_MARK,ut as baselineOf,pt as changesSaid,rt as emptyRequired,lt as emptyRequiredSaid,wt as look,ht as markedTheUsers,ct as pageChanges,Ht as pageCheckCommand,st as structureProblems};
@@ -1,2 +0,0 @@
1
- import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
2
- import{spawn as O}from"node:child_process";import{existsSync as I}from"node:fs";import C from"node:fs/promises";import _ from"node:os";import q from"node:path";import{APART as S}from"../browser/editor/components/registry.mjs";var N=6e4,x=600,B=["A4","A3","Letter","Legal","Tabloid"];function F(){if(process.env.GALLERY_BROWSER)return process.env.GALLERY_BROWSER;let{PROGRAMFILES:o="","PROGRAMFILES(X86)":e="",LOCALAPPDATA:r="",HOME:i=""}=process.env;return({win32:[`${o}\\Google\\Chrome\\Application\\chrome.exe`,`${e}\\Google\\Chrome\\Application\\chrome.exe`,`${r}\\Google\\Chrome\\Application\\chrome.exe`,`${e}\\Microsoft\\Edge\\Application\\msedge.exe`,`${o}\\Microsoft\\Edge\\Application\\msedge.exe`],darwin:["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge","/Applications/Chromium.app/Contents/MacOS/Chromium",...i?[`${i}/Applications/Google Chrome.app/Contents/MacOS/Google Chrome`,`${i}/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge`,`${i}/Applications/Chromium.app/Contents/MacOS/Chromium`]:[]],linux:["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/opt/google/chrome/chrome","/usr/bin/microsoft-edge","/usr/bin/microsoft-edge-stable","/opt/microsoft/msedge/msedge","/usr/bin/chromium","/usr/bin/chromium-browser","/snap/bin/chromium"]}[process.platform]??[]).find(s=>s&&I(s))??null}var $=()=>process.getuid?.()===0?["--no-sandbox"]:[],te=()=>["--no-first-run","--no-default-browser-check","--disable-extensions","--hide-scrollbars","--lang=zh-CN",...$()];function oe(o,e,r=[]){let i=o.location()?.url??"";return!/^Failed to load resource|^Refused to |Content Security Policy/.test(o.text())&&(!i||i.startsWith(e)||r.includes(i))}var re=o=>o.evaluateOnNewDocument(()=>{globalThis.__qaViolations=[],document.addEventListener("securitypolicyviolation",e=>{globalThis.__qaViolations.push({url:e.blockedURI,directive:e.effectiveDirective||e.violatedDirective,source:e.sourceFile,line:e.lineNumber})})}),V=3e4,W=5e3;function ie(o,e=W){let r=0,i=new Promise(c=>{r=setTimeout(c,e)});return Promise.race([Promise.resolve(o).catch(()=>{}),i]).finally(()=>clearTimeout(r))}var E=o=>new Promise(e=>setTimeout(e,o).unref()),D=o=>String(o??"").replace(/\s+/g," ").trim(),M=o=>{let e=o.split(/\r?\n/).map(D).filter(Boolean).at(-1);return e?`: ${e.slice(0,200)}`:""};async function se({executablePath:o,args:e=[],attempts:r=2,start:i=H}){let c=[];for(let s=0;s<r;s+=1){let n=await C.mkdtemp(q.join(_.tmpdir(),"gallery-browser-")),t=()=>C.rm(n,{recursive:!0,force:!0,maxRetries:5,retryDelay:200}).catch(()=>{});try{let{browser:a,stop:l}=await i({executablePath:o,args:e,profile:n});return{browser:a,failures:c,close:async()=>{await l().catch(()=>{}),await t()}}}catch(a){c.push(D(a?.message??a)),await t()}}throw Object.assign(new Error(c.at(-1)??"the browser did not start"),{failures:c})}async function H({executablePath:o,args:e,profile:r,starting:i=V}){let{default:c}=await import("./chunk-ERLAIBOA.mjs"),s=await c.defaultArgs({headless:!0,userDataDir:r,args:[...e,"--remote-debugging-port=0"]}),n=process.platform!=="win32",t=O(o,s,{stdio:["ignore","ignore","pipe"],windowsHide:!0,detached:n}),a=!1;t.on("error",()=>a||=t.pid===void 0);let l=()=>a||t.exitCode!==null||t.signalCode!==null,u=new Promise(f=>t.once("exit",f)),m=()=>{if(!l())try{n?process.kill(-t.pid,"SIGKILL"):t.kill()}catch{try{t.kill("SIGKILL")}catch{}}};process.once("exit",m);let p="",d=new Promise((f,w)=>{let g=setTimeout(()=>w(new Error(`it said nothing of its DevTools port in ${i/1e3}s${M(p)}`)),i);t.stderr.setEncoding("utf8"),t.stderr.on("data",h=>{p=`${p}${h}`.slice(-4e3);let y=/DevTools listening on (ws:\/\/\S+)/.exec(p);y&&(clearTimeout(g),f(y[1]))}),t.once("error",h=>(clearTimeout(g),w(h))),t.once("exit",(h,y)=>(clearTimeout(g),w(new Error(`it stopped (${y??`exit ${h}`}) before it opened its DevTools port${M(p)}`))))}),A=async()=>{try{l()||await Promise.race([u,E(5e3)]),m(),l()||await Promise.race([u,E(3e3)])}finally{process.off("exit",m)}},v;try{let f=await d,w=0,g=new Promise((y,G)=>{w=setTimeout(()=>G(new Error(`it opened its DevTools port and did not answer in ${i/1e3}s`)),i)}),h=c.connect({browserWSEndpoint:f,defaultViewport:{width:800,height:600}});h.catch(()=>{}),v=await Promise.race([h,g]).finally(()=>clearTimeout(w))}catch(f){throw m(),await A(),f}return{browser:v,stop:async()=>{await Promise.race([v.close().catch(()=>{}),E(5e3)]),await A()}}}var b=null,L=0,T=0;async function K(){let o=F();if(!o)throw Object.assign(new Error("\u6CA1\u6709\u627E\u5230 Chrome \u6216 Edge\uFF1A\u5BFC\u51FA PDF \u9700\u8981\u7535\u8111\u4E0A\u88C5\u6709\u5176\u4E2D\u4E00\u4E2A\u6D4F\u89C8\u5668"),{reason:"browser"});let{default:e}=await import("./chunk-ERLAIBOA.mjs");return e.launch({executablePath:o,headless:!0,args:["--no-first-run","--no-default-browser-check","--disable-extensions",...$()]})}async function R(o,e){clearTimeout(L),T+=1,b??=K().catch(i=>{throw b=null,i});let r=await(await b).newPage();try{return await r.emulateMediaFeatures([{name:"prefers-reduced-motion",value:"reduce"},{name:"prefers-color-scheme",value:"light"}]),await r.setViewport({width:1200,height:900}),await r.setContent(o,{waitUntil:"load",timeout:6e4}),await P(r,{changing:x}),await e(r)}finally{await r.close().catch(()=>{}),T-=1,T===0&&(L=setTimeout(async()=>{let i=b;b=null,(await i?.catch(()=>null))?.close().catch(()=>{})},N))}}async function P(o,{timeout:e=15e3,changing:r=e}={}){let i=[],c=(n,t,a=e)=>{t!==!0&&i.push(`${n} (${t===!1?`not in ${a/1e3}s`:t})`)},s=(n,t=e)=>o.evaluate(n,t).catch(a=>a.message);return c("the fonts loaded",await s(n=>Promise.race([Promise.resolve(document.fonts?.ready).then(()=>!0),new Promise(t=>setTimeout(()=>t(!1),n))]))),c("the kit's first drawing done (data-doc-drawn)",await s(n=>new Promise(t=>{let a=Date.now(),l=()=>{!globalThis.DocKit||document.documentElement.hasAttribute("data-doc-drawn")?(globalThis.DocCode?.colorAll?.(),t(!0)):Date.now()-a>n?t(!1):setTimeout(l,50)};l()}))),c("the page done changing",await s(n=>new Promise(t=>{let a=()=>[document.documentElement.scrollHeight,...[...document.querySelectorAll("[style]")].map(d=>d.getAttribute("style")),...[...document.adoptedStyleSheets??[]].flatMap(d=>[...d.cssRules].map(A=>A.cssText)),...[...document.querySelectorAll("svg, canvas")].map(d=>d.outerHTML.length),[...document.images].filter(d=>d.complete).length].join("|"),l=Date.now(),u=a(),m=0,p=()=>{let d=a();m=d===u?m+1:0,u=d,m>=3?t(!0):Date.now()-l>n?t(!1):setTimeout(p,100)};setTimeout(p,100)}),r),r),i}async function k(o){await o.evaluate(()=>{document.documentElement.setAttribute("data-doc-theme","light");for(let e of document.querySelectorAll("[data-doc-sheets]")){let r=e.querySelector(":scope > .doc-sheet-tabs");if(r){for(let i of r.querySelectorAll(":scope > .doc-sheet-tab")){let c=i.getAttribute("data-sheet-tab"),s=[...e.querySelectorAll(":scope > [data-doc-sheet]")].find(a=>a.getAttribute("data-doc-sheet")===c);if(!s)continue;s.hidden=!1,s.removeAttribute("aria-hidden"),s.style.setProperty("display","block","important");let n=r.cloneNode(!1);n.removeAttribute("id"),n.removeAttribute("role"),n.style.setProperty("break-after","avoid");let t=i.cloneNode(!0);t.removeAttribute("id"),t.setAttribute("aria-selected","true"),t.classList.add("is-active"),n.append(t),s.before(n)}r.style.setProperty("display","none","important")}}for(let e of document.querySelectorAll("details"))e.open=!0;window.dispatchEvent(new Event("resize"))}),await P(o,{changing:x})}var j={A4:793.7,A3:1122.5,Letter:816,Legal:816,Tabloid:1056},z=96;async function U(o,e){await o.emulateMediaType("print");let r=await o.evaluate(()=>Math.max(0,innerWidth-document.documentElement.clientWidth));await o.setViewport({width:Math.floor(e)+r,height:900}),await P(o,{changing:x})}function ne(o,{paper:e="A4",scale:r=1}={}){let i=B.includes(e)?e:"A4",c=Math.min(2,Math.max(.1,r));return R(o,async s=>(await k(s),await U(s,(j[i]-2*z)/c),Buffer.from(await s.pdf({format:i,scale:c,printBackground:!0,margin:{top:"1in",right:"1in",bottom:"1in",left:"1in"}}))))}function ae(o){return R(o,async e=>{await k(e);let r=e.viewport(),i=await e.$$("main figure.doc-figure"),c=[];for(let s of i){let n=0;try{n=await s.evaluate(async(t,a)=>{let l=[];for(let u=t.closest(a);u;u=u.parentElement.closest(a))l.unshift(u);for(let u of l)u.style.setProperty("height","auto"),u.style.setProperty("max-height","calc(100dvh - (2 * var(--doc-dialog-margin)))"),u.showModal();return await new Promise(u=>requestAnimationFrame(()=>requestAnimationFrame(u))),l.length?Math.ceil(t.getBoundingClientRect().height):0},S),n&&(await e.setViewport({...r,height:r.height+n}),await P(e,{changing:x})),await s.evaluate(t=>t.scrollIntoView({block:"center"})),c.push(Buffer.from(await s.screenshot({type:"png"})))}catch{c.push(null)}await s.evaluate((t,a)=>{for(let l=t.closest(a);l;l=l.parentElement.closest(a))l.close(),l.style.removeProperty("height"),l.style.removeProperty("max-height"),l.getAttribute("style")||l.removeAttribute("style")},S).catch(()=>{}),n&&await e.setViewport(r).catch(()=>{})}return c})}export{F as a,te as b,oe as c,re as d,W as e,ie as f,se as g,P as h,ne as i,ae as j};
@@ -1,2 +0,0 @@
1
- import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
2
- import{d as m,i as g,k as p}from"./chunk-SQ3FQCCN.mjs";import{b as a,f as l,i as c}from"./chunk-4OZWXZE5.mjs";import"./chunk-5L7RYZCL.mjs";import{reportsDirectory as i}from"../browser/shared/paths.mjs";import{joinDefaultTree as b,joinedLine as k}from"../browser/shared/drafts.mjs";var D=5e3;async function v(f){let{positional:s,options:u}=l({options:["--no-browser"],argv:f});if(s.length>1)throw new a("Name one document at most.");let{slug:o=null,block:w=null}=s.length?await c(s[0]):{};console.log(`\u5DE5\u4F5C\u533A\uFF1A${i}`);let e=await g({slug:o,baseline:o!==null});if(e.ok||console.error(e.message),e.reason==="missing"){let{HOME:n,pageExists:d}=await import("../browser/shared/pages.mjs"),{missingPageSaid:E,HOME_NOT_MADE:r}=await import("./chunk-ONKC4BCC.mjs");d(o,i)?console.error(`"${o}" is a custom page, not a document: gallery page open ${o} opens it and gives its address.`):o===n&&await E(o,i)===r&&console.error(r)}if(o!==null&&e.reason!=="missing"){let{roundBegins:n}=await import("./chunk-Z6OKLRHC.mjs");await n(o,e.ok?{}:{wait:D})}if(o!==null&&e.reason!=="missing"){let n=k(await b(i,o));n&&console.log(n)}e.ok||process.exit(1);let t=await p(o,e,w);for(let n of t)console.log(n);console.log(await m(t,u))}export{v as run};
@@ -1,2 +0,0 @@
1
- import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
2
- import{a as S,b as K,c as E,d as v,e as x,f as H}from"./chunk-GMJD7ID3.mjs";import{a as D,b as j}from"./chunk-JEUK3ZO7.mjs";import{b as M,f as R,h as T}from"./chunk-4OZWXZE5.mjs";import O from"node:fs/promises";import _ from"node:path";import{iconKind as ee}from"../browser/shared/emoji/icon-value.mjs";import{descendantsIn as J,parentIn as C}from"../browser/shared/outline.mjs";import{topOf as U}from"../browser/shared/outline-shape.mjs";import{fullAddress as z,namedPlace as te}from"../browser/shared/page-address.mjs";import{reportsDirectory as G}from"../browser/shared/paths.mjs";import{documentLinks as Q,listReportSlugs as oe,roleOf as ne}from"../browser/shared/reports.mjs";import{documentDirectory as se,documentFiles as le,isSlugName as ie}from"../browser/shared/workspace.mjs";import{isWorkspace as W,readRegistry as re,workspaceKey as Y}from"../browser/shared/workspace-registry.mjs";import{findIn as ce,rankReports as V,reportLines as ae}from"../browser/shared/search.mjs";async function X(i=G){let n=(await oe(i)).filter(ie);return(await Promise.all(n.map(async a=>{let r=se(a,i),{html:u,json:s}=le(r),g=await O.stat(u).catch(()=>null);if(!g?.isFile()||await ne(r)==="instructions")return null;let l=await O.readFile(s,"utf8").then(JSON.parse).catch(()=>({})),d=t=>typeof t=="string"?t.replace(/\s+/g," ").trim():"";return{slug:a,title:d(l.title)||a,description:d(l.description),edited:g.mtimeMs,file:u}}))).filter(Boolean)}var P=i=>{let n=new Date(i),o=a=>String(a).padStart(2,"0");return`${n.getFullYear()}-${o(n.getMonth()+1)}-${o(n.getDate())} ${o(n.getHours())}:${o(n.getMinutes())}`},k=i=>`${i} document${i===1?"":"s"}`;async function de(i,n,o){let a=[...new Set(o.toLowerCase().split(/\s+/).filter(Boolean))],r=new Set(n.map(({slug:s})=>s));return(await Promise.all(i.filter(({slug:s})=>!r.has(s)).map(async s=>{let g=ae(await O.readFile(s.file,"utf8").catch(()=>"")),l=a.map(d=>ce(g,d,{most:1})).filter(({count:d})=>d>0);return l.length?{...s,words:l.length,count:l.reduce((d,{count:t})=>d+t,0),hit:l[0].hits[0].text}:null}))).filter(Boolean).sort((s,g)=>g.words-s.words||g.count-s.count||g.edited-s.edited)}var q=i=>[...i.documents.values()].filter(n=>typeof n.url=="string"),F=i=>`${i} web link${i===1?"":"s"}`;async function ge(i,n){if(i.length>1)throw new M("--tree takes one document at most (its slug, link or address).");let o=await S(),a=new Map(n.map(e=>[e.slug,e])),r=new Map((o.extensions??[]).map(e=>[e.id,e])),u=o.columns.filter(e=>(!e.extension||r.has(e.extension))&&!e.hidden&&!e.away),s=u.length>1?u:null,g=o.children[""]??[],l=null;if(i.length===1){let e=await H(i[0],"--tree",o);if(e.refused){for(let h of await j({reading:!0}))console.log(h);console.error(e.refused),process.exit(1)}l=e.slug,g=[l]}for(let e of await j({reading:!0}))console.log(e);let d=e=>console.log(`${e.title}\u680F\uFF08\u6269\u5C55 ${e.id}\uFF1A${e.error?`\u6761\u76EE\u8BFB\u4E0D\u51FA\u6765\uFF1A${e.error.message}`:`${e.count} \u4E2A\u6761\u76EE`}\uFF1Bgallery extension check ${e.id} \u6253\u51FA\u5B83\u4EEC\uFF09`),t=()=>{for(let e of r.values())d(e)},p=u.filter(e=>!e.extension).flatMap(e=>J(o.children,U(e.id))),f=p.filter(e=>o.documents.get(e)?.url!==void 0).length,m=p.length-f;if(m+f===0){console.log('No documents yet: gallery new <slug> "<title>" makes one.'),l===null&&t();return}let w=f?`${k(m)} and ${F(f)}`:k(m);if(l===null)console.log(`${w}, as the sidebar shows them (one under another indented)${s?", column by column":""}:`);else{let e=J(o.children,l),h=e.some($=>o.documents.get($)?.url!==void 0)?`${e.length} ${e.length===1?"entry":"entries"}`:k(e.length);console.log(x(o,l)),console.log(e.length?`${v(o,l)} and the ${h} under it, as the sidebar shows them:`:`${v(o,l)}, with no document under it:`)}let c=(e,h)=>{let{title:$,description:y,icon:b,url:B,draft:N}=o.documents.get(e),A=a.get(e)?.edited,L=E(o,e),I=B!==void 0?[`\u7F51\u9875\u94FE\u63A5\uFF1A${B}`]:N?[N.missing?"\u522B\u5904\u7684\u5E95\u7A3F\uFF0C\u627E\u4E0D\u5230\u4E86":L?`\u300C${L}\u300D\u7684\u5E95\u7A3F\uFF1A${N.path}`:`\u522B\u5904\u7684\u5E95\u7A3F\uFF1A${N.path}`]:[...L?[`\u300C${L}\u300D\u7684\u6587\u6863`]:[],...y?[`\u8BF4\u660E\uFF1A${y}`]:[],...A?[`\u4E0A\u6B21\u7F16\u8F91\uFF1A${P(A)}`]:[]];console.log(`${" ".repeat(h)}${e} ${ee(b)==="emoji"?`${b} `:""}${$}${I.length?` \uFF08${I.join("\uFF1B")}\uFF09`:""}`);for(let Z of o.children[e]??[])c(Z,h+1)};if(l!==null||!s){for(let e of g)c(e,0);l===null&&t();return}for(let e of s){if(e.extension){d(r.get(e.extension)),r.delete(e.extension);continue}let h=o.children[U(e.id)]??[];console.log(`${K(e)}\u680F${h.length?"":"\uFF08\u7A7A\uFF09"}`);for(let $ of h)c($,1)}t()}async function fe(i){let n=_.resolve(G),o=(t,p)=>Y(t)===Y(p),a=[n,...re().workspaces.map(({root:t})=>t).filter(t=>!o(t,n))],r=a.filter(W),u=a.filter(t=>!W(t)),s=(await Promise.all(r.map(async t=>(await X(t)).map(p=>({...p,root:t}))))).flat(),g=i.join(" ").trim(),l=V(s,g),d=`${r.length} workspace${r.length===1?"":"s"}`;if(console.log(`Searched ${d} of this machine (gallery workspaces lists them; the current one: ${n}).`),s.length===0)console.log(`No documents in ${r.length===1?"it":"any of them"} yet.`);else if(l.length===0)console.log(`No document's title, description or slug in the ${d} holds ${g.split(/\s+/).map(t=>`"${t}"`).join(" or ")}: gallery list --all lists all ${s.length}.`);else{console.log(g?`${l.length} of ${k(s.length)}, the best match first:`:`${k(s.length)}, the one edited last first:`);let t=new Map,p=f=>(t.has(f)||t.set(f,Promise.all([Q(f),S(f)]).then(([{links:m},w])=>({links:m,tree:w}))),t.get(f));for(let{root:f,slug:m,title:w,description:c,edited:e,file:h}of l){let{links:$,tree:y}=await p(f);console.log(`\u5DE5\u4F5C\u533A\uFF1A${f}`),console.log(`${m} ${w}`),c&&console.log(` \u8BF4\u660E\uFF1A${c}`),C(y.children,m)&&console.log(` ${x(y,m)}`),console.log(` \u5730\u5740\uFF1A${z("",{slug:m},$)}`),console.log(` \u4E0A\u6B21\u7F16\u8F91\uFF1A${P(e)}`),console.log(` ${D(h)}`)}console.log('One in another workspace is worked on there: pass its \u5DE5\u4F5C\u533A as --workspace to every command (gallery open <slug> --workspace "<\u5DE5\u4F5C\u533A>" gives its address).')}u.length&&console.log(`Not searched, no longer there (gallery workspaces --forget <path> forgets one, nothing on disk changed): ${u.join(", ")}`)}async function Me(i){let{positional:n,options:o}=R({options:["--tree","--all"],argv:i});if(o.has("--all")){if(o.has("--tree"))throw new M("--all and --tree go apart: --tree is the current workspace's tree.");return fe(n)}let a=await X();if(o.has("--tree"))return ge(n,a);let r=n.join(" ").trim(),{links:u}=await Q(),s=n.length===1?te(n[0],u):null,g=s&&s.slug!==n[0],l=g?a.filter(({slug:c})=>c===s.slug):V(a,r),d=[...l,...r&&!g?await de(a,l,r):[]],t=await S(),p=r.toLowerCase().split(/\s+/).filter(Boolean),f=g?[]:q(t).filter(({slug:c,title:e,url:h})=>!p.length||p.some($=>`${e} ${h} ${c}`.toLowerCase().includes($))),m=n.length===1&&d.length===0&&f.length===0?await T(n[0]):null;for(let c of await j({reading:!0}))console.log(c);let w=()=>{if(!f.length)return;let c=q(t).length;console.log(r?`${f.length} of ${F(c)} in the sidebar:`:`${F(c)} in the sidebar:`);for(let{slug:e,title:h,url:$}of f)console.log(`${e} ${h}`),console.log(` \u7F51\u9875\u94FE\u63A5\uFF1A${$}`),C(t.children,e)&&console.log(` ${x(t,e)}`)};if(m)console.log(m);else if(a.length===0)console.log('No documents yet: gallery new <slug> "<title>" makes one.'),w();else if(d.length===0&&f.length===0)console.log(`No document's title, description, slug or text holds ${r.split(/\s+/).map(c=>`"${c}"`).join(" or ")}: gallery list lists all ${a.length}.`);else if(d.length===0)w();else{console.log(r?`${d.length} of ${k(a.length)}, the best match first:`:`${k(a.length)}, the one edited last first:`);for(let{slug:c,title:e,description:h,edited:$,file:y,hit:b}of d)console.log(`${c} ${e}`),h&&console.log(` \u8BF4\u660E\uFF1A${h}`),b&&console.log(` \u6B63\u6587\uFF1A${b}`),C(t.children,c)&&console.log(` ${x(t,c)}`),console.log(` \u5730\u5740\uFF1A${z("",{slug:c},u)}`),console.log(` \u4E0A\u6B21\u7F16\u8F91\uFF1A${P($)}`),console.log(` ${D(y)}`);w()}}export{X as a,P as b,Me as c};
@@ -1,20 +0,0 @@
1
- import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
2
- import{a as De,b as Fe}from"./chunk-IA4PSIMD.mjs";import{b as Ie}from"./chunk-F4ZA6JRZ.mjs";import{a as be,b as Ne,c as ht,d as Te,e as Ee,f as Re}from"./chunk-6NLXUKAY.mjs";import{b as je,c as Me,e as Ae,g as Gt}from"./chunk-VRPVVMRB.mjs";import{a as he}from"./chunk-UMHUSOPJ.mjs";import{a as $e,d as xe,e as Se,f as ve,g as Oe}from"./chunk-W5NPH5UA.mjs";import{e as ye,f as ge,g as ke,h as Kt}from"./chunk-ECZBLQKK.mjs";import{a as J,m as we}from"./chunk-E7656LR7.mjs";import{g as me,u as pe}from"./chunk-TKWEX4FD.mjs";var Mn=3e4,An=12e4,Nn=1500,Je=1e4,Pe=p=>p.reduce((u,{key:d,tag:f})=>u.set(`${d}
3
- ${f}`,(u.get(`${d}
4
- ${f}`)??0)+1),new Map);function Le({now:p=Date.now,hold:u=Mn,limit:d=An,quiet:f=Nn}={}){let b=new Map,h=new Map,x=new Map,l=new Map,c=new Map;return{wrote(g,k){l.set(g,J(k))},judge(g,{source:k,mtime:R}){if(k===null)return b.delete(g),x.delete(g),{held:!1,signs:[],wait:0,own:!1};let N=J(k),S=c.get(g)?.hash===N?c.get(g).signs:null;S||(S=Ne(k),c.set(g,{hash:N,signs:S}));let Q=p(),L=(U,D=!1)=>(b.delete(g),h.set(g,Pe(S)),x.set(g,k),{held:!1,signs:[],wait:U,own:D});if(l.get(g)===N)return L(0,!0);let _=h.get(g)??new Map,z=Pe(S);if([...z].some(([U,D])=>D>(_.get(U)??0))){let U=Math.min(R,Q),D=b.get(g)??U;b.set(g,D);let V=Math.min(u-(Q-U),d-(Q-D));if(V>0)return{held:!0,signs:S.filter(({key:s,tag:w})=>z.get(`${s}
5
- ${w}`)>(_.get(`${s}
6
- ${w}`)??0)),wait:V,own:!1,taken:x.get(g)}}return L(Math.min(f,Math.max(0,f-(Q-R))))}}}import{documentKey as nr}from"../browser/shared/workspace-address.mjs";import{serviceLocation as rr}from"../browser/shared/service-location.mjs";import{createHmac as or,randomBytes as ee}from"node:crypto";import{existsSync as ar,mkdirSync as sr,readFileSync as ir,writeFileSync as cr}from"node:fs";import H from"node:fs/promises";import P from"node:path";import{FILE as fr}from"../browser/shared/annotations.mjs";import{escapeTyped as lr}from"../browser/shared/escape.mjs";import{writeAtomic as Jt}from"../browser/shared/files.mjs";import{sendJson as Y}from"../browser/shared/http.mjs";import{REQUEST_ID as Xt}from"../browser/shared/ids.mjs";import{UPLOAD_REQUEST_LIMIT as ur}from"../browser/shared/media.mjs";import{reportsDirectory as dr}from"../browser/shared/paths.mjs";import{sameDirectory as mr}from"../browser/shared/preview-server.mjs";import{slugPattern as rt}from"../browser/shared/reports.mjs";import{TODO_MOST as pr}from"../browser/shared/workspace-query.mjs";import{documentDirectory as wr,documentFiles as Nt,isDocumentSource as hr}from"../browser/shared/workspace.mjs";import Qt from"node:fs/promises";import _e from"node:path";import{checkAnnotations as Tn,cleanAnchor as En,cleanItem as Ue,FILE as Rn,itemsText as In,readItems as Dn,treeText as We}from"../browser/shared/annotations.mjs";import{writeAtomic as Fn}from"../browser/shared/files.mjs";import{slugPattern as Pn}from"../browser/shared/reports.mjs";import{documentDirectory as Be,documentFiles as Jn}from"../browser/shared/workspace.mjs";var Ln=600*1e3,_n=600*1e3;function Un(p){let{units:u,boxes:d}=ke(p),f=[...u].sort((l,c)=>l.elStart-c.elStart),b=new Map(f.map((l,c)=>[l.id,c])),h=new Map(f.map(l=>[l.id,We(l.node)])),x={h2:null,h3:null,h4:null};return f.map(l=>{let c=[];for(let N=l;N;N=N.parent===null?null:u[N.parent]){let S=d[N.box];if(S?.kind==="panel"&&S.key!==null){let L=u.find(_=>_.kind==="tab"&&_.parent===S.unit&&_.key===S.key);L&&c.unshift({tab:h.get(L.id)})}let Q=S?.unit===null||S?.unit===void 0?null:u[S.unit];if(Q?.tag==="details"&&S.kind==="details"){let L=Q.node.childNodes.find(_=>_.tagName==="summary");L&&c.push({details:We(L)})}}let g=c.find(N=>N.tab)?.tab,k=c.find(N=>N.details)?.details,R=[g,x.h2,x.h3,x.h4,k].filter(Boolean);return l.tag==="h2"?Object.assign(x,{h2:h.get(l.id),h3:null,h4:null}):l.tag==="h3"?Object.assign(x,{h3:h.get(l.id),h4:null}):l.tag==="h4"&&(x.h4=h.get(l.id)),{id:l.blockId,text:h.get(l.id),parent:l.parent===null?null:b.get(l.parent)??null,where:R,heading:/^h[2-4]$/.test(l.tag)}})}function Ye({reportsDirectory:p,read:u,write:d=Fn,dropped:f=()=>{},now:b=Date.now}){let h=new Map,x=new Map,l=new Map,c=(s,w)=>{let r=l.get(s);if(r?.text===w)return r.units;let a=Un(w);return l.set(s,{text:w,units:a}),a},g=s=>_e.join(Be(s,p),Rn),k=s=>typeof s=="string"&&Pn.test(s);async function R(s){let w=await Qt.readFile(g(s),"utf8").catch(()=>null);return{text:w,items:w===null?[]:Dn(w)}}async function N(s,w,r){let a=In(w);return a===r||(a===null?await Qt.rm(g(s),{force:!0}):await d(g(s),a)),S(a)}let S=s=>s===null?"":J(s),Q=s=>{let w=h.get(s)??new Map;for(let[r,a]of w)b()-a>Ln&&w.delete(r);return[...w.keys()]},L=(s,w)=>w.forEach(r=>h.get(s)?.delete(r)),_=s=>{let w=x.get(s)??x.set(s,new Map).get(s);for(let[r,a]of w)b()-a>_n&&w.delete(r);return w};async function z(s,{keep:w=null,items:r=null,before:a=void 0}={}){let O=r?{items:r,text:a}:await R(s),v=await u(s).catch(()=>null);if(!v)return{items:O.items,units:[],places:new Map,version:S(O.text),missing:!0};let I=c(s,v.text),T=_(s),$=Tn(O.items,I,{keep:new Set([...T.keys(),w])});for(let A of T.keys())$.waiting.has(A)||T.delete(A);if($.dropped.length>0){let A=h.get(s)??h.set(s,new Map).get(s);for(let tt of $.dropped)A.set(tt.id,b())}let M=$.changed||r?await N(s,$.items,O.text):S(O.text);return $.dropped.length>0&&f(s,$.dropped),{items:$.items,units:I,places:$.places,version:M,missing:!1}}let Z=(s,{items:w,version:r})=>({ok:!0,version:r,items:w,dropped:Q(s)});async function U(s){if(!k(s))return[400,{ok:!1,reason:"body"}];let w=await z(s);return w.missing?[404,{ok:!1,reason:"missing"}]:[200,Z(s,w)]}async function D(s){if(!k(s))return[400,{ok:!1,reason:"body"}];let w=await z(s);if(w.missing)return[404,{ok:!1,reason:"missing"}];let r=null,a=Jn(Be(s,p));try{r=JSON.parse(await Qt.readFile(a.json,"utf8"))}catch{}let O=await u(s).catch(()=>null),v=/<h1\b[^>]*>([\s\S]*?)<\/h1>/i.exec(O?.text??"")?.[1]?.replace(/<[^>]*>/g,"").trim(),I=typeof r?.title=="string"&&r.title.trim()?r.title.trim():v||s,T=w.units.some(M=>M.heading),$=w.items.map(M=>{let A=w.units[w.places.get(M.id)?.at],tt=A?.where?.length?A.where:A?.heading?[A.text]:[];return{where:tt,top:T&&tt.length===0,blocks:M.anchor.blocks.filter(ot=>w.units.some($t=>$t.id===ot)),whole:M.anchor.kind==="blocks",quote:M.anchor.quote,text:M.text}});return[200,{ok:!0,title:I,path:_e.resolve(a.html),items:$}]}async function V(s){let{slug:w}=s??{};if(!k(w))return[400,{ok:!1,reason:"body"}];if(!await u(w).catch(()=>null))return[404,{ok:!1,reason:"missing"}];let r=await R(w);if(s.anchors&&typeof s.anchors=="object"&&!Array.isArray(s.anchors)){let T=r.items.map(M=>{let A=Object.hasOwn(s.anchors,M.id)?En(s.anchors[M.id]):null;return A&&A.kind===M.anchor.kind?{...M,anchor:A}:M}),$=await N(w,T,r.text);return[200,Z(w,{items:T,version:$})]}let a=r.items,O=null,v=null;if(s.put!==void 0){let T=a.find(M=>M.id===s.put?.id),$=Ue({...s.put,created:T?.created??s.put?.created});if(!$)return[400,{ok:!1,reason:"item"}];a=T?a.map(M=>M.id===$.id?$:M):[...a,$],O=$.id,T||_(w).set($.id,b()),L(w,[$.id])}else if(typeof s.remove=="string")a=a.filter(T=>T.id!==s.remove);else if(s.clear===!0)v=a,a=[];else if(Array.isArray(s.restore)){let T=new Map(a.map(A=>[A.id,A])),$=s.restore.map(A=>Ue(A,A?.updated)).filter(A=>A&&!(T.get(A.id)?.updated>A.updated)),M=new Set($.map(A=>A.id));for(let A of M)T.has(A)||_(w).set(A,b());a=[...a.filter(A=>!M.has(A.id)),...$],L(w,[...M])}else return[400,{ok:!1,reason:"body"}];let I=await z(w,{keep:O,items:a,before:r.text});return[200,{...Z(w,I),...v?{removed:v}:{}}]}async function st(s){if(!k(s))return;let{text:w}=await R(s);w!==null&&await z(s)}return{list:U,copy:D,change:V,afterWrite:st}}import yt from"node:fs/promises";import gt from"node:path";import{writeAtomic as Ze}from"../browser/shared/files.mjs";import{slugPattern as Vt}from"../browser/shared/reports.mjs";var Pt=1,Mt={seen:"seen.html",base:"base.html",state:"state.json"},Wn=4,Bn=1800*1e3;function Ce({stateDirectory:p=null,shown:u,folderOf:d,isPage:f=()=>!1,log:b=null,now:h=Date.now,quiet:x=Bn}){let l=new Map,c=r=>gt.join(p,"changes",r),g=Promise.resolve(),k=r=>{let a=g.then(r);return g=a.catch(O=>b?.(`changes: ${O.message}`)),a};async function R(r){if(!p)return l.get(r)?.state??null;try{let a=JSON.parse(await yt.readFile(gt.join(c(r),Mt.state),"utf8"));return a?.v===Pt&&typeof a.seen=="string"?a:null}catch{return null}}async function N(r,a){return p?yt.readFile(gt.join(c(r),Mt[a]),"utf8").catch(()=>null):l.get(r)?.[a]??null}async function S(r,a,O={}){if(!p){let v=l.get(r)??{};l.set(r,{...v,...O,state:a});return}await yt.mkdir(c(r),{recursive:!0});for(let[v,I]of Object.entries(O))I===null?await yt.rm(gt.join(c(r),Mt[v]),{force:!0}):await Ze(gt.join(c(r),Mt[v]),I);await Ze(gt.join(c(r),Mt.state),`${JSON.stringify(a)}
7
- `)}async function Q(r){l.delete(r),p&&await yt.rm(c(r),{recursive:!0,force:!0,maxRetries:3})}let L=async r=>Math.round((await yt.stat(d(r)).catch(()=>null))?.birthtimeMs??0),_=r=>r?.base?`${r.since}|${r.writes}`:null,z=r=>Number.isFinite(r?.draft)&&h()-r.draft<x?r.draft:null,Z=(r,a,O,v=z(r))=>[{v:Pt,born:r?.born??0,seen:a,...v===null?{}:{draft:v}},{seen:O,base:null}];async function U(r){let a=await R(r);if(!a)return null;let O=await L(r);return a.born&&O&&a.born!==O?(await Q(r),null):a}async function D(r,a){if(typeof a!="string"||!Vt.test(r)||f(r))return!1;let O=J(a),v=await U(r);if(!v)return await S(r,{v:Pt,born:await L(r),seen:O},{seen:a}),!1;if(v.seen===O)return!1;let I=await N(r,"seen"),T=new Date(h()).toISOString();if(I===null)return await S(r,...Z(v,O,a)),!1;let $=u(I),M=u(a);if(!v.base){if(!ht($,M))return await S(r,...Z(v,O,a)),!1;if(z(v)!==null||Te($))return await S(r,...Z(v,O,a,h())),!1;let{draft:ot,...$t}=v;return await S(r,{...$t,seen:O,base:J($),since:T,at:T,writes:1},{seen:a,base:$}),!0}let A=await N(r,"base");if(A===null||!ht(A,M))return await S(r,...Z(v,O,a)),!0;let tt=ht($,M)!==null;return await S(r,{...v,seen:O,...tt?{at:T,writes:v.writes+1}:{}},{seen:a}),tt}async function V(r,a,O,v){if(!Vt.test(r)||f(r))return!1;let I=await U(r),T=J(a);if(!I?.base)return await S(r,...Z(I??{born:await L(r)},T,a,v?null:z(I))),!1;let $=await N(r,"base");if($!==null&&O)try{$=O($)}catch(M){b?.(`changes: ${r}: the baseline did not take the edit (${M.message})`)}return $===null||!ht($,u(a))?(await S(r,...Z(I,T,a)),!0):(await S(r,{...I,seen:T,base:J($)},{seen:a,base:$}),!1)}async function st(r,a){if(!Vt.test(r)||f(r))return{ended:!1,moved:!1};let O=typeof a=="string"?await D(r,a):!1,v=await U(r);if(v?.draft===void 0)return{ended:!1,moved:O};let{draft:I,...T}=v;return await S(r,T),{ended:z(v)!==null,moved:O}}let s=new Map;async function w(r,a){await D(r,a);let O=u(a),v=J(O),I=await U(r);if(!I?.base)return{pending:!1,version:v};let T=`${r} ${I.base} ${v}`,$=s.get(T);if($===void 0){let M=await N(r,"base");for($=M===null?null:ht(M,O),s.set(T,$);s.size>Wn;)s.delete(s.keys().next().value)}return $?{pending:!0,version:v,stamp:_(I),since:I.since,writes:I.writes,...$}:{pending:!1,version:v}}return{look:(r,a)=>k(()=>D(r,a)),wrote:(r,a,O=null,{reader:v=!1}={})=>k(()=>V(r,a,O,v)),endDraft:(r,a=null)=>k(()=>st(r,a)),read:(r,a)=>k(()=>w(r,a)),stamp:r=>k(async()=>_(await U(r))),snapshot:r=>k(async()=>{let a=await U(r);return a?{state:a,seen:await N(r,"seen"),base:await N(r,"base")}:null}),clear:r=>k(async()=>{let a=await U(r);a?.base&&await S(r,{v:Pt,born:a.born,seen:a.seen},{base:null})}),restore:(r,a)=>k(async()=>{a?.state&&await S(r,a.state,{seen:a.seen,base:a.base})}),forget:r=>k(()=>Q(r)),idle:()=>k(async()=>{})}}import{randomBytes as Yn}from"node:crypto";import ct from"node:fs/promises";import kt from"node:path";import{FILE as Zn,readItems as Cn}from"../browser/shared/annotations.mjs";import{writeAtomic as Hn}from"../browser/shared/files.mjs";import{documentDirectory as zn}from"../browser/shared/workspace.mjs";var Kn=20,Ke=/^\d{8}T\d{6}Z-[a-f0-9]{8}\.json$/,He=80,Ge=({stateDirectory:p,slug:u})=>kt.join(p,"dropped-annotations",u),Qe=p=>({id:p.id,text:p.text,quote:p.anchor?.quote??"",kind:p.anchor?.kind??"text"});async function Ve({stateDirectory:p,reportsDirectory:u,slug:d,time:f,items:b}){let h=Ge({stateDirectory:p,reportsDirectory:u,slug:d});await ct.mkdir(h,{recursive:!0});let x=f.replace(/[-:]/g,"").replace(/\.\d+Z$/,"Z");await Hn(kt.join(h,`${x}-${Yn(4).toString("hex")}.json`),JSON.stringify({time:f,items:b}));let l=(await ct.readdir(h)).filter(c=>Ke.test(c)).sort();await Promise.all(l.slice(0,Math.max(0,l.length-Kn)).map(c=>ct.rm(kt.join(h,c),{force:!0})))}async function no({stateDirectory:p,reportsDirectory:u,slug:d}){let f=Ge({stateDirectory:p,reportsDirectory:u,slug:d}),b=(await ct.readdir(f).catch(()=>[])).filter(l=>Ke.test(l)).sort();if(b.length===0)return[];let h=new Set(Cn(await ct.readFile(kt.join(zn(d,u),Zn),"utf8").catch(()=>"")).map(l=>l.id)),x=[];for(let l of b){let c=kt.join(f,l);try{let g=JSON.parse(await ct.readFile(c,"utf8")),k=Array.isArray(g?.items)?g.items.filter(R=>typeof R?.id=="string"&&!h.has(R.id)):[];typeof g?.time=="string"&&k.length&&x.push({time:g.time,items:k})}catch{}await ct.rm(c,{force:!0}).catch(()=>{})}return x}var Gn=(p,u=new Date)=>{let d=new Date(p),f=h=>String(h).padStart(2,"0"),b=`${f(d.getHours())}:${f(d.getMinutes())}`;return d.toDateString()===u.toDateString()?b:`${d.getFullYear()}-${f(d.getMonth()+1)}-${f(d.getDate())} ${b}`},ze=p=>{let u=String(p??"").replace(/\s+/g," ").trim();return JSON.stringify(u.length>He?`${u.slice(0,He-1)}\u2026`:u)};function qt(p,{time:u=null,items:d},{today:f=new Date}={}){let b=kt.resolve(p),h=`${d.length} \u6279\u6CE8 (annotation${d.length===1?"":"s"})`;return[`annotations ${b}: ${u?`at ${Gn(u,f)}, `:""}Gallery deleted ${h} whose words are gone from the document (rewritten or deleted):`,...d.map(({id:x,text:l,quote:c,kind:g})=>` ${x} ${ze(l)} on ${g==="blocks"?"the blocks ":""}${ze(c)}`)]}function ro(p,u,{today:d=new Date}={}){return u.length?[...u.flatMap(f=>qt(p,f,{today:d}))," they were the reader's: say in your hand-off which your edit carried out and which you left, and never write them back"]:[]}import{randomBytes as Qn}from"node:crypto";import bt from"node:fs/promises";import At from"node:path";import{writeAtomic as Vn}from"../browser/shared/files.mjs";var qn=20,qe=/^\d{8}T\d{6}Z-[a-f0-9]{8}\.json$/,Xe=({stateDirectory:p,slug:u})=>At.join(p,"rewrites",u);async function tn({stateDirectory:p,reportsDirectory:u,slug:d,time:f,changes:b}){let h=Xe({stateDirectory:p,reportsDirectory:u,slug:d});await bt.mkdir(h,{recursive:!0});let x=f.replace(/[-:]/g,"").replace(/\.\d+Z$/,"Z");await Vn(At.join(h,`${x}-${Qn(4).toString("hex")}.json`),JSON.stringify({time:f,changes:b}));let l=(await bt.readdir(h)).filter(c=>qe.test(c)).sort();await Promise.all(l.slice(0,Math.max(0,l.length-qn)).map(c=>bt.rm(At.join(h,c),{force:!0})))}async function en({stateDirectory:p,reportsDirectory:u,slug:d}){let f=Xe({stateDirectory:p,reportsDirectory:u,slug:d}),b=(await bt.readdir(f).catch(()=>[])).filter(x=>qe.test(x)).sort(),h=[];for(let x of b){let l=At.join(f,x);try{let c=JSON.parse(await bt.readFile(l,"utf8"));typeof c?.time=="string"&&Array.isArray(c.changes)&&h.push(c)}catch{}await bt.rm(l,{force:!0}).catch(()=>{})}return h}var Xn=(p,u=new Date)=>{let d=new Date(p),f=h=>String(h).padStart(2,"0"),b=`${f(d.getHours())}:${f(d.getMinutes())}`;return d.toDateString()===u.toDateString()?b:`${d.getFullYear()}-${f(d.getMonth()+1)}-${f(d.getDate())} ${b}`};function fo(p,u,{today:d=new Date}={}){if(!u.length)return[];let f=At.resolve(p),b=[];for(let{time:h,changes:x}of u){let l=[];for(let{line:c,rule:g,key:k}of[...x].sort((R,N)=>R.line-N.line)){let R=`line ${c} ${g}${k?` ${k}`:""}`;l.includes(R)||l.push(R)}b.push(`preview ${f}: at ${Xn(h,d)}, when the reader edited the page, the preview wrote your natural HTML as the kit's markup: ${l.join(", ")}`),b.push(...x.filter(c=>c.note).map(({line:c,rule:g,note:k})=>` line ${c}, ${g}: ${k}`))}return b.push(" re-read the file before editing it (those lines are the file's as you had left it)"),b}import{todoRef as tr}from"../browser/shared/workspace-query.mjs";var er=(p,u)=>p.length===u.length&&p.every((d,f)=>d===u[f]);function nn(p,u,d,f){let b=Fe(u),h=De(d,{at:!0}),x=null,l=c=>(x??=ye(d).units).find(g=>g.elStart===c)??null;return f.map(c=>{let g=tr(c?.ref);if(!g||g.slug!==p||typeof c.done!="boolean")return{reason:"ref"};let k=g.block?h.find(N=>N.block===g.block)??null:null;if(k&&k.text!==g.text)return{reason:"changed"};if(!k){let N=h.filter(S=>S.text===g.text&&er(S.path,g.path));if(g.version===b)k=N.find(S=>S.nth===g.nth)??null;else{if(N.length>1)return{reason:"ambiguous"};k=N[0]??null}}if(!k)return{reason:"changed"};let R=l(k.at);return R?{unit:R,done:k.done,want:c.done}:{reason:"locked"}})}function rn(p,u){let d=new Map,f=u.map(c=>{if(!c.unit)return!1;let g=d.has(c.unit.id)?d.get(c.unit.id):c.done;return d.set(c.unit.id,c.want),g!==c.want}),b=new Map;for(let c of u)c.unit&&d.get(c.unit.id)!==c.done&&b.set(c.unit.id,c);if(b.size===0)return{commit:null,changed:f};let h=[],x=[],l=new Map;for(let[c,g]of b){let k=`todo${h.length}`,R=g.unit.blockId?{key:k,id:g.unit.blockId}:{key:k,open:c,hash:we(p,g.unit)};h.push({key:k,unit:R,attribute:"data-checked",value:d.get(c)?"":null}),x.push(R),l.set(c,k)}return{commit:{units:h,touch:x,keys:l},changed:f}}import{EMPTY_STYLE as yr,emptyWordsScript as gr,showEmpty as kr}from"../browser/editor/components/placeholder.mjs";import{TOKENS as br}from"../browser/editor/page/look.mjs";import{MARGIN_STYLE as $r,earlyMarginScript as xr}from"../browser/editor/page/margin.mjs";var te=/^[a-f0-9]{16}$/,ne=2*1024*1024,Sr=ur,on=50,an=/^\d{8}T\d{6}Z-[a-f0-9]{16}\.html$/,vr=30,sn=3,cn=200,ft="\u6587\u4EF6\u4E00\u518D\u88AB\u4FEE\u6539\uFF08\u4F8B\u5982 AI \u6B63\u5728\u5199\u5165\uFF09\uFF0C\u7A0D\u540E\u518D\u540C\u6B65",Or="\u8FD9\u6B21\u7684\u4FEE\u6539\u592A\u5927\uFF0C\u4E00\u6B21\u5B58\u4E0D\u4E0B",jr=250,lt=Symbol("again"),Mr="/__gallery/edit/src/editor/page/editor.mjs",Ar=p=>new Promise(u=>setTimeout(u,p));function Nr(p,u=ne){return new Promise((d,f)=>{let b=[],h=0;p.on("data",x=>{h+=x.length,h>u?b.length=0:b.push(x)}),p.on("end",()=>h>u?f(new Error("too-large")):d(Buffer.concat(b).toString("utf8"))),p.on("error",f)})}function Tr(p){if(!p)return ee(16).toString("hex");let u=P.join(p,"token");try{let f=ir(u,"utf8").trim();if(/^[a-f0-9]{32}$/.test(f))return f}catch{}let d=ee(16).toString("hex");try{sr(p,{recursive:!0,mode:448}),cr(u,d,{mode:384})}catch{}return d}function zo({base:p="",token:u=null,reportsDirectory:d=dr,stateDirectory:f=null,write:b=Jt,ids:h=!0,finish:x=R=>R,log:l=null,settling:c={},reviewing:g={},onChanges:k=()=>{}}={}){let R=u??Tr(rr().data),N=Le(c),S=c.wait??Je,Q=new Map,L=async(t,n,e,o="reader")=>{let i=await b(t,n,e);if(i!==!1&&hr(P.basename(t))){let y=P.basename(P.dirname(t));N.wrote(y,n),Q.set(y,{hash:J(n),by:o})}return i},_=t=>wr(t,d),z=t=>Nt(_(t)).html,Z=new Map,U=f&&P.join(f,"snapshots"),D=Promise.resolve(),V=Promise.resolve(),st=async(t,n,e,{by:o="time"}={})=>{let i=(await H.readdir(t)).filter(m=>n.test(m));if(i.length<=e)return;let y=o==="name"?i.sort():(await Promise.all(i.map(async m=>({name:m,time:(await H.stat(P.join(t,m))).mtimeMs})))).sort((m,j)=>m.time-j.time).map(({name:m})=>m);await Promise.all(y.slice(0,y.length-e).map(m=>H.rm(P.join(t,m),{force:!0})))},s=(t,n)=>{U&&(D=D.then(async()=>{let e=P.join(U,`${t}.html`),o=new Date;try{await H.utimes(e,o,o);return}catch{}await H.mkdir(U,{recursive:!0}),await Jt(e,n),await st(U,/^[a-f0-9]{16}\.html$/,on)}).catch(()=>{}))},w=(t,n)=>{f&&(D=D.then(async()=>{let e=P.join(f,"history",t),o=J(n);if(await H.mkdir(e,{recursive:!0}),(await H.readdir(e)).filter(m=>an.test(m)).sort().at(-1)?.endsWith(`-${o}.html`))return;let y=new Date().toISOString().replace(/[-:]/g,"").replace(/\.\d+Z$/,"Z");await Jt(P.join(e,`${y}-${o}.html`),n),await st(e,an,vr,{by:"name"})}).catch(()=>{}))},r=new Map,a=t=>f&&P.join(f,"receipts",t),O=(t,n,e,o)=>{for(r.set(`${t} ${n}`,{digest:e,answer:o});r.size>cn*4;)r.delete(r.keys().next().value);let i=a(t);i&&(D=D.then(async()=>{await H.mkdir(i,{recursive:!0}),await Jt(P.join(i,`${n}.json`),JSON.stringify({digest:e,answer:o})),await st(i,{test:y=>y.endsWith(".json")&&Xt.test(y.slice(0,-5))},cn)}).catch(()=>{}))},v=async(t,n)=>{let e=r.get(`${t} ${n}`);if(e)return e;let o=a(t);if(!o)return null;await D;try{let i=JSON.parse(await H.readFile(P.join(o,`${n}.json`),"utf8"));return typeof i?.digest=="string"&&i.answer?.ok?i:null}catch{return null}},I=new Map,T=(t,n)=>{let e=new Date().toISOString();if(!f)return void I.set(t,[...I.get(t)??[],{time:e,changes:n}].slice(-20));D=D.then(()=>tn({stateDirectory:f,reportsDirectory:d,slug:t,time:e,changes:n})).catch(()=>{})},$=async t=>{if(!f){let n=I.get(t)??[];return I.delete(t),n}return await D,en({stateDirectory:f,reportsDirectory:d,slug:t})},M=(t,n)=>{for(Z.delete(t),Z.set(t,n);Z.size>on;)Z.delete(Z.keys().next().value);s(t,n)},A=async t=>{if(Z.has(t))return Z.get(t);if(!U||!te.test(t))return null;await D;let n=await H.readFile(P.join(U,`${t}.html`),"utf8").catch(()=>null);return n===null||J(n)!==t?null:(M(t,n),n)},tt=new Map,ot=t=>{let n=tt.get(t);if(n)return n;let e=je(t,{finish:x});for(tt.set(t,e);tt.size>8;)tt.delete(tt.keys().next().value);return e},$t=P.join(P.resolve(d),".gallery","pages"),C=Ce({...g,stateDirectory:f,shown:t=>ot(t).text,folderOf:_,log:l,isPage:t=>P.resolve(_(t)).startsWith($t+P.sep)}),ut=(t,n)=>n.then(e=>{e&&k(t)},e=>l?.(`${t}: the Agent's changes not kept (${e.message})`));async function Lt(t,n=void 0){if(typeof t!="string"||!rt.test(t))return null;let e=z(t),o=n!==void 0?n:await H.readFile(e,"utf8").catch(()=>null);if(o===null)return null;let{text:i,changes:y}=ot(o);return{file:e,source:o,text:i,version:J(i),changes:y}}async function it(t){if(typeof t!="string"||!rt.test(t))return{source:null,held:!1,signs:[],wait:0,own:!1};let n=z(t),e=await H.readFile(n,"utf8").catch(()=>null),o=(await H.stat(n).catch(()=>null))?.mtimeMs??0;return{source:e,...N.judge(t,{source:e,mtime:o})}}async function xt(t,n=Date.now()+S){for(;;){let e=await it(t);if(!e.held||Date.now()>=n)return e;await Ar(Math.max(0,Math.min(jr,n-Date.now())))}}async function _t(t,{wait:n=S}={}){let e=await xt(t,Date.now()+n),o=await Lt(t,e.held&&e.taken!==void 0?e.taken:e.source);return o&&{...o,held:e.held===!0}}function fn(t,n,{editor:e=Mr,kitTags:o=()=>[]}={}){let{html:i,map:y}=be(n);M(y.version,n);let m=me(),j=pe(m).map(({assets:B,...X})=>({...X,kit:o(B)})),E=`<script type="application/json" id="doc-edit-map" data-doc-dev>${JSON.stringify({slug:t,token:R,...y,components:j,hidden:m.settings.hidden}).replace(/</g,"\\u003c")}</script>
8
- <script data-doc-dev>document.currentScript.remove(); import(${JSON.stringify(e)});</script>`,W=`<style data-doc-dev>.doc-display { display: none; }</style>
9
- <style data-doc-dev data-ge-palette>${br}</style>
10
- <style data-doc-dev>${yr}</style>
11
- <script data-doc-dev>${gr()}</script>
12
- <script data-doc-dev>document.currentScript.remove(); document.documentElement.setAttribute("data-ge-order", "file");</script>
13
- <style data-doc-dev data-ge-margin-style>${$r}</style>
14
- <script data-doc-dev>document.currentScript.remove(); ${xr(nr(t,p),{notes:ar(P.join(_(t),fr))})}</script>`;return{html:kr(i),snippet:E,head:W}}let ln=t=>M(J(t),t);function re(t){if(t.method!=="POST")return[405,{ok:!1,reason:"method"}];let n=t.headers.host??"",e=t.socket.localPort;return n!==`127.0.0.1:${e}`&&n!==`localhost:${e}`?[403,{ok:!1,reason:"host"}]:t.headers.origin!==`http://${n}`?[403,{ok:!1,reason:"origin"}]:t.headers["x-gallery-token"]!==R?[403,{ok:!1,reason:"token"}]:null}async function dt(t,n=ne){let e=re(t);if(e)return{error:e};if(!/^application\/json\b/i.test(t.headers["content-type"]??""))return{error:[415,{ok:!1,reason:"type"}]};try{return{body:JSON.parse(await Nr(t,n))}}catch(o){return{error:o.message==="too-large"?[413,{ok:!1,reason:"body",message:Or}]:[400,{ok:!1,reason:"body"}]}}}async function Ut(t,n){let{slug:e,opening:o,known:i=null,texts:y=[],units:m=[],touch:j=[],pageIds:F=null,request:E=null,agent:W=!1}=t;if(typeof e!="string"||!rt.test(e)||![y,m,j].every(Array.isArray))return[400,{ok:!1,reason:"body"}];if(E!==null&&(typeof E!="string"||!Xt.test(E)))return[400,{ok:!1,reason:"body"}];let B=E===null?null:J(JSON.stringify([o??null,y,m,j])),X=await oe(t);if(X)return X;let K=nt=>(E!==null&&O(e,E,B,nt),[200,nt]),G=z(e),et=typeof o=="string"&&te.test(o)?await A(o):null,q=nt=>or("sha256",R).update(`${e}
15
- ${nt}`).digest("hex").slice(0,32);for(let nt=1;;nt++){let{source:at,held:It}=await it(e);if(at===null)return[404,{ok:!1,reason:"missing"}];if(It)return Date.now()<n?lt:[409,{ok:!1,reason:"busy",message:ft}];ut(e,C.look(e,at));let{text:jt,changes:zt}=ot(at),ce=[],Dt=xe({current:jt,opening:et,texts:y,units:m,touch:j,ids:h?()=>{let Ft=typeof h=="function"?h():Kt();return ce.push(Ft),Ft}:!1,seal:q,pageIds:F}),{title:fe,icon:le,...ue}=Dt,wt=Dt.text===jt?jt:x(Dt.text);wt!==Dt.text&&(ue.version=J(wt));let de={...ue,foreign:typeof i=="string"&&J(jt)!==i};if(wt===jt)return K({ok:!0,...de,wrote:!1,notes:[]});if(w(e,at),!await L(G,wt,{expect:at},W===!0?"agent":"reader")){if(nt===sn)return[409,{ok:!1,reason:"busy",message:ft}];continue}w(e,wt),ut(e,C.wrote(e,wt,Ft=>{let jn=0;return Ee(Ft,{opening:et,texts:y,units:m,touch:j,pageIds:F,seal:q,ids:h?()=>ce[jn++]??(typeof h=="function"?h():Kt()):!1})},{reader:W!==!0})),zt.length&&(l&&l(Gt(G,zt).join(`
16
- `)),T(e,zt));let On=[...fe?await Tt(P.dirname(G),fe):[],...le!==void 0?await Wt(P.dirname(G),le):[]];return K({ok:!0,...de,wrote:!0,notes:On})}}async function un(t,n){return typeof t!="string"||!rt.test(t)?[404,{ok:!1,reason:"missing",message:"\u627E\u4E0D\u5230\u8FD9\u4EFD\u6587\u6863"}]:!Array.isArray(n)||n.length===0||n.length>pr?[400,{ok:!1,reason:"body"}]:Bt({slug:t},async(e,o)=>{let{source:i,held:y}=await it(t);if(i===null)return[404,{ok:!1,reason:"missing",message:"\u627E\u4E0D\u5230\u8FD9\u4EFD\u6587\u6863"}];if(y)return Date.now()<o?lt:[409,{ok:!1,reason:"busy",message:ft}];let{text:m}=ot(i),j=nn(t,i,m,n),{commit:F,changed:E}=rn(m,j),W=j.map((q,nt)=>q.reason?{ok:!1,reason:q.reason}:{ok:!0,changed:E[nt],block:q.unit.blockId??null});if(!F)return[200,{ok:!0,results:W,wrote:!1}];let B=J(m);M(B,m);let X=await Ut({slug:t,opening:B,units:F.units,touch:F.touch},o);if(X===lt)return lt;let[K,G]=X;if(!G.ok)return[K,G];let et=new Map((G.units??[]).map(q=>[q.key,q]));return[200,{ok:!0,wrote:G.wrote===!0,results:W.map((q,nt)=>{if(!q.ok)return q;let at=F.keys.get(j[nt].unit.id);if(at===void 0)return q;let It=et.get(at);return It?.status!=="applied"?{ok:!1,reason:It?.reason==="ambiguous"?"ambiguous":"changed"}:{...q,block:G.ids?.[at]??q.block}})}]})}async function oe({slug:t,opening:n,texts:e=[],units:o=[],touch:i=[],request:y=null}){if(typeof t!="string"||!rt.test(t)||typeof y!="string"||!Xt.test(y)||![e,o,i].every(Array.isArray))return null;let m=await v(t,y);return m?m.digest===J(JSON.stringify([n??null,e,o,i]))?[200,{...m.answer,again:!0}]:[409,{ok:!1,reason:"request",message:"\u540C\u4E00\u6B21\u4FDD\u5B58\u7684\u5185\u5BB9\u4E0D\u4E00\u81F4"}]:null}async function dn(t,n){let{slug:e,opening:o,texts:i=[],units:y=[],instances:m=[],pageIds:j=null}=t;if(typeof e!="string"||!rt.test(e)||!Array.isArray(i)||!Array.isArray(y)||!Array.isArray(m))return[400,{ok:!1,reason:"body"}];let{source:F,held:E}=await it(e);if(E)return Date.now()<n?lt:[409,{ok:!1,reason:"busy",message:ft}];let W=await Lt(e,F);if(W===null)return[404,{ok:!1,reason:"missing"}];let{text:B,version:X}=W,K=typeof o=="string"&&te.test(o)?await A(o):null;return[200,{ok:!0,version:X,reverted:Oe({current:B,opening:K,texts:i,pageIds:j}),units:Se({current:B,units:y}),parts:ve({current:B,instances:m,pageIds:j})}]}let mn=600*1e3,St=new Map;async function ae(t,n){let e=_(t),o=null;try{o=JSON.parse(await H.readFile(Nt(e).json,"utf8"))}catch{}let{title:i,icon:y}=Ae(n,o);i&&typeof o?.title=="string"&&o.title!==i.to&&await Tt(e,{from:o.title,to:i.to,synced:!0}),y&&!y.missing&&await Wt(e,y.to)}async function pn(t,n){let{slug:e,action:o,stamp:i=null,undo:y=null}=t;if(typeof e!="string"||!rt.test(e)||!["accept","revert","undo"].includes(o))return[400,{ok:!1,reason:"body"}];let m=z(e),{source:j,held:F}=await it(e);if(j===null)return[404,{ok:!1,reason:"missing"}];if(F)return Date.now()<n?lt:[409,{ok:!1,reason:"busy",message:ft}];if(o==="undo"){for(let[G,et]of St)Date.now()-et.at>mn&&St.delete(G);let K=typeof y=="string"?St.get(y):null;return!K||K.slug!==e?[404,{ok:!1,reason:"gone",message:"\u64A4\u9500\u5DF2\u7ECF\u8FC7\u671F"}]:j!==K.after?[409,{ok:!1,reason:"moved-on",message:"\u64A4\u56DE\u4E4B\u540E\u6587\u6863\u53C8\u6539\u8FC7\u4E86\uFF0C\u6CA1\u6CD5\u64A4\u9500"}]:(w(e,j),await L(m,K.before,{expect:j})?(w(e,K.before),St.delete(y),await ae(e,K.before),await C.restore(e,K.saved),await C.wrote(e,K.before),k(e),[200,{ok:!0,version:J(ot(K.before).text)}]):[409,{ok:!1,reason:"busy",message:ft}])}await C.look(e,j);let E=await C.snapshot(e),W=E?.state?.base?`${E.state.since}|${E.state.writes}`:null;if(W===null)return[200,{ok:!0,none:!0}];if(W!==i)return[409,{ok:!1,reason:"changed",message:"Agent \u521A\u521A\u53C8\u6539\u4E86\u6587\u6863\uFF0C\u518D\u770B\u4E00\u773C"}];if(o==="accept")return await C.clear(e),k(e),[200,{ok:!0}];let B=E.base;if(w(e,j),!await L(m,B,{expect:j}))return[409,{ok:!1,reason:"busy",message:ft}];w(e,B),await ae(e,B);let X=ee(8).toString("hex");return St.set(X,{slug:e,before:j,after:B,saved:E,at:Date.now()}),await C.clear(e),await C.wrote(e,B),k(e),[200,{ok:!0,version:J(ot(B).text),undo:X}]}async function wn(t,n){let e=await dt(t);if(e.error)return Y(n,...e.error);let o=e.body??{};try{if(o.action!=="read")return Y(n,...await Bt(o,pn));if(typeof o.slug!="string"||!rt.test(o.slug))return Y(n,400,{ok:!1,reason:"body"});let i=await _t(o.slug,{wait:0});return i===null?Y(n,404,{ok:!1,reason:"missing"}):Y(n,200,{ok:!0,...await C.read(o.slug,i.source)})}catch(i){return Y(n,500,{ok:!1,reason:"write",message:i.message})}}async function Tt(t,{from:n,to:e,synced:o}){let i=["\u6807\u9898\u5DF2\u66F4\u65B0",...o?[]:["\u5355\u72EC\u6253\u5F00\u6216\u5BFC\u51FA\u65F6\u7684\u9875\u9762\u540D\u79F0\u539F\u672C\u5C31\u548C\u6807\u9898\u4E0D\u540C\uFF0C\u6CA1\u6709\u8DDF\u7740\u6539"]],y=Nt(t).json,m=await H.readFile(y,"utf8").catch(()=>""),j=null;try{j=JSON.parse(m)}catch{}if(j?.title!==n)return[...i,"\u641C\u7D22\u548C\u4FA7\u680F\u91CC\uFF08\u6CA1\u6253\u5F00\u8FD9\u4EFD\u6587\u6863\u65F6\uFF09\u7684\u6587\u6863\u540D\u539F\u672C\u5C31\u548C\u6807\u9898\u4E0D\u540C\uFF0C\u6CA1\u6709\u8DDF\u7740\u6539"];let F=new RegExp(`("title"\\s*:\\s*)${JSON.stringify(n).replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}`),E=F.test(m)?m.replace(F,(W,B)=>B+JSON.stringify(e)):`${JSON.stringify({...j,title:e},null,2)}
17
- `;try{await L(y,E)}catch(W){return l?.(`${P.basename(y)}'s title was not written (${W.code??W.message}): ${y}`),[...i,"\u641C\u7D22\u548C\u4FA7\u680F\u91CC\uFF08\u6CA1\u6253\u5F00\u8FD9\u4EFD\u6587\u6863\u65F6\uFF09\u7684\u6587\u6863\u540D\u6CA1\u80FD\u8DDF\u7740\u6539"]}return i}async function Wt(t,n){let e=Nt(t).json,o=null;try{o=JSON.parse(await H.readFile(e,"utf8"))}catch{}if(!o||typeof o!="object")return l?.(`${P.basename(e)} could not be read, so its icon was not written: ${e}`),["\u9875\u9762\u56FE\u6807\u5DF2\u66F4\u6362\uFF0C\u4F46\u641C\u7D22\u548C\u4FA7\u680F\u91CC\uFF08\u6CA1\u6253\u5F00\u8FD9\u4EFD\u6587\u6863\u65F6\uFF09\u7684\u56FE\u6807\u6CA1\u80FD\u8DDF\u7740\u6362"];if((o.icon??null)===n)return[];let{icon:i,...y}=o,m=n===null?y:{...y,icon:n};try{await L(e,`${JSON.stringify(m,null,2)}
18
- `)}catch(j){return l?.(`${P.basename(e)}'s icon was not written (${j.code??j.message}): ${e}`),["\u9875\u9762\u56FE\u6807\u5DF2\u66F4\u6362\uFF0C\u4F46\u641C\u7D22\u548C\u4FA7\u680F\u91CC\uFF08\u6CA1\u6253\u5F00\u8FD9\u4EFD\u6587\u6863\u65F6\uFF09\u7684\u56FE\u6807\u6CA1\u80FD\u8DDF\u7740\u6362"]}return[]}async function hn(t,n){let e=typeof n=="string"?n.replace(/\s+/g," ").trim():"";if(!e)return{ok:!1,reason:"title",message:"\u6807\u9898\u4E0D\u80FD\u4E3A\u7A7A"};let o=z(t),i=await H.readFile(o,"utf8").catch(()=>null);if(i===null)return{ok:!1,reason:"missing"};ut(t,C.look(t,i));let y=he(i),m=ge(y).find(E=>E.kind==="title");if(!m)return{ok:!1,reason:"no-title",message:"\u8FD9\u4EFD\u6587\u6863\u6CA1\u6709\u6807\u9898"};let j=lr(e),F=$e({current:y,edits:[{id:m.id,parts:[{keep:!0,html:j}]}],ids:h});return F.ok?F.text!==i&&!await L(o,F.text,{expect:i})?{ok:!1,reason:"changed-again"}:(F.text!==i&&ut(t,C.wrote(t,F.text,E=>Re(E,j))),{ok:!0,title:e,notes:F.title?await Tt(P.dirname(o),F.title):[]}):{ok:!1,reason:"conflict"}}let vt=t=>(n,e)=>{let o=V.then(()=>t(n));return V=o.catch(()=>{}),o.then(([i,y])=>Y(e,i,y),i=>Y(e,500,{ok:!1,reason:"write",message:i.message}))},se=(t,{early:n=null}={})=>async(e,o)=>{let i=await dt(e);if(i.error)return Y(o,...i.error);let y=i.body??{};try{let m=n&&await n(y);return m?Y(o,...m):Y(o,...await Bt(y,t))}catch(m){return Y(o,500,{ok:!1,reason:"write",message:m.message})}};async function Bt(t,n){let e=Date.now()+S;for(;;){await xt(t.slug,e);let o=V.then(()=>n(t,e));V=o.catch(()=>{});let i=await o;if(i!==lt)return i}}async function Yt(t,{reader:n=!1}={}){if(typeof t!="string"||!rt.test(t))return{ok:!1,reason:"missing",message:"\u627E\u4E0D\u5230\u8FD9\u4EFD\u6587\u6863"};let e=_(t),{html:o,json:i}=Nt(e);for(let y=1;;y++){let{source:m,held:j}=n?await it(t):{source:await H.readFile(o,"utf8").catch(()=>null),held:!1};if(m===null)return{ok:!1,reason:"missing",message:"\u627E\u4E0D\u5230\u8FD9\u4EFD\u6587\u6863"};if(j)return{ok:!1,reason:"busy",message:"\u6587\u4EF6\u4E00\u518D\u88AB\u4FEE\u6539\uFF08\u4F8B\u5982 AI \u6B63\u5728\u5199\u5165\uFF09\uFF0C\u6CA1\u6709\u5199\u5165"};ut(t,C.look(t,m));let F=null;try{F=JSON.parse(await H.readFile(i,"utf8"))}catch{}let{text:E,changes:W,added:B,given:X,repeated:K,title:G,icon:et}=Me(m,{finish:x,next:typeof h=="function"?h:void 0,metadata:F});if(E!==m){if(w(t,m),!await L(o,E,{expect:m},n?"reader":"agent")){if(y===sn)return{ok:!1,reason:"busy",message:"\u6587\u4EF6\u4E00\u518D\u88AB\u4FEE\u6539\uFF08\u4F8B\u5982 AI \u6B63\u5728\u5199\u5165\uFF09\uFF0C\u6CA1\u6709\u5199\u5165"};continue}w(t,E),ut(t,C.wrote(t,E)),n&&W.length&&(l&&l(Gt(o,W).join(`
19
- `)),T(t,W))}return G&&typeof F?.title=="string"&&F.title!==G.to&&await Tt(e,{from:F.title,to:G.to,synced:G.page}),et&&!et.missing&&await Wt(e,et.to),{ok:!0,changes:E===m?[]:W,added:E===m?0:B,given:E===m?[]:X,repeated:K,written:E!==m,title:G,icon:et}}}let yn=async(t,{reader:n=!1}={})=>{n&&await xt(t);let e=V.then(()=>Yt(t,{reader:n}));return V=e.catch(()=>{}),e};async function Zt(t){let n=await dt(t);if(n.error)return{refused:n.error};let{slug:e,workspace:o}=n.body??{};return typeof e!="string"||!rt.test(e)||typeof o!="string"?{refused:[400,{ok:!1,reason:"body"}]}:mr(o,d)?{slug:e}:{refused:[409,{ok:!1,reason:"elsewhere",message:"\u8FD9\u4E2A\u9884\u89C8\u670D\u52A1\u5668\u7BA1\u7684\u662F\u53E6\u4E00\u4E2A\u76EE\u5F55\u7684\u6587\u6863"}]}}async function gn(t,n){try{let e=V.then(async()=>{let{slug:y,refused:m}=await Zt(t);if(m)return{answer:m};let j=await Yt(y);return{slug:j.ok?y:null,answer:[j.ok?200:j.reason==="missing"?404:409,j]}});V=e.catch(()=>{});let{slug:o,answer:i}=await e;return o&&await Et(o),Y(n,...i)}catch(e){return Y(n,500,{ok:!1,reason:"write",message:e.message})}}async function kn(t){let{slug:n,refused:e}=await Zt(t);return e||(await Et(n),[200,{ok:!0}])}async function ie(t){let{source:n}=await xt(t),{ended:e,moved:o}=await C.endDraft(t,n);return o&&k(t),e}async function bn(t){let{slug:n,refused:e}=await Zt(t);return e||[200,{ok:!0,ended:await ie(n)}]}let mt=Ie({reportsDirectory:d}),Ot=Ye({reportsDirectory:d,read:t=>_t(t,{wait:0}),write:L,dropped:(t,n)=>{let e=n.map(Qe);l&&l(qt(P.join(_(t),"annotations.json"),{items:e}).join(`
20
- `)),f&&(D=D.then(()=>Ve({stateDirectory:f,reportsDirectory:d,slug:t,time:new Date().toISOString(),items:e})).catch(()=>{}))}}),Ct=Promise.resolve(),Ht=t=>{let n=Ct.then(t);return Ct=n.catch(()=>{}),n},$n=t=>(n,e)=>Ht(()=>t(n)).then(([o,i])=>Y(e,o,i),o=>Y(e,500,{ok:!1,reason:"write",message:o.message})),xn=300,pt=new Map;async function Et(t){let n=pt.get(t);n&&(clearTimeout(n.timer),pt.delete(t));let e=Ht(()=>Ot.afterWrite(t));n&&e.then(n.resolve,n.reject),await e.catch(o=>l?.(`${t}: annotations not checked: ${o.message}`)),await D}let Sn=t=>{let n=t.headers.host??"",e=t.socket.localPort;return n!==`127.0.0.1:${e}`&&n!==`localhost:${e}`?[403,{ok:!1,reason:"host"}]:t.headers["x-gallery-token"]!==R?[403,{ok:!1,reason:"token"}]:null};async function vn(t){if(t.method==="GET"){let e=Sn(t);if(e)return e;let o=new URL(t.url??"/","http://localhost").searchParams;return o.get("as")==="copy"?Ot.copy(o.get("slug")):Ot.list(o.get("slug"))}let n=await dt(t);return n.error??Ot.change(n.body)}let Rt=(t,n=ne)=>async e=>{let o=await dt(e,n);return o.error??t(o.body)};return{token:R,preview:fn,opened:ln,check:dt,checkHeaders:re,upload:vt(Rt(mt.upload,Sr)),addEmoji:vt(Rt(mt.addEmoji)),unfurl:vt(Rt(mt.unfurl)),annotations:$n(vn),checkAnnotations(t){let n=pt.get(t);return n||(n={timer:0},n.done=new Promise((e,o)=>Object.assign(n,{resolve:e,reject:o})),pt.set(t,n)),clearTimeout(n.timer),n.timer=setTimeout(()=>{pt.delete(t),Ht(()=>Ot.afterWrite(t)).then(n.resolve,n.reject)},xn),n.done},frameable:vt(Rt(mt.frameable)),listEmojis:mt.listEmojis,readEmoji:mt.readEmoji,respond:vt,keepVersion:w,renameReport:hn,read:Lt,settled:it,writerOf:(t,n)=>typeof n=="string"&&Q.get(t)?.hash===J(n)?Q.get(t).by:null,whenTaken:xt,readTaken:_t,takeRewrites:$,handIn:yn,handInReport:Yt,handInRequest:gn,settleRequest:(t,n)=>kn(t).then(([e,o])=>Y(n,e,o),e=>Y(n,500,{ok:!1,reason:"write",message:e.message})),settleNotes:Et,roundRequest:(t,n)=>bn(t).then(([e,o])=>Y(n,e,o),e=>Y(n,500,{ok:!1,reason:"write",message:e.message})),beginRound:ie,commit:se(Ut,{early:oe}),handleCommit:Ut,setTodos:un,reverted:se(dn),changes:wn,noteTaken:(t,n)=>C.look(t,n),forgetChanges:t=>C.forget(t),drain:async()=>{await V,await Promise.all([...pt.keys()].map(Et)),await Ct,await C.idle(),await D},stored:async()=>{await C.idle(),await D}}}export{no as a,ro as b,en as c,fo as d,Mn as e,An as f,Nn as g,Tr as h,zo as i};
@@ -1,8 +0,0 @@
1
- import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
2
- import{spawn as J}from"node:child_process";import b from"node:fs";import m from"node:fs/promises";import Q from"node:os";import P from"node:path";import{escapeMarkup as X}from"../browser/shared/escape.mjs";import{spawn as C}from"node:child_process";import{existsSync as H,readFileSync as M}from"node:fs";import w from"node:path";var V=e=>!["","0",void 0].includes(e),z=(e,r)=>(r.PATH??"").split(w.delimiter).some(t=>t&&H(w.join(t,e))),U=()=>{try{return process.platform==="linux"&&/microsoft/i.test(M("/proc/version","utf8"))}catch{return!1}};function K(e,{platform:r=process.platform,env:t=process.env,wsl:o=U()}={}){let n=encodeURI(e);return V(t.GALLERY_NO_BROWSER)?{skip:"GALLERY_NO_BROWSER is set"}:r==="win32"?{command:w.join(t.SystemRoot||t.windir||"C:\\Windows","System32","rundll32.exe"),args:["url.dll,FileProtocolHandler",n]}:r==="darwin"?{command:"open",args:[n]}:o?{command:"cmd.exe",args:["/c","start",'""',n.replace(/[&^]/g,"^$&")]}:!t.DISPLAY&&!t.WAYLAND_DISPLAY?{skip:"no display here (neither DISPLAY nor WAYLAND_DISPLAY is set)"}:z("xdg-open",t)?{command:"xdg-open",args:[n]}:{skip:"xdg-open is not installed"}}var q="Opened it in the default browser (if that is not Chrome or Edge, open the address there to edit).",T=e=>e.opened?q:`Not opened in a browser: ${e.why}.`;async function I(e,r){let t=K(e,r);return t.skip?{opened:!1,why:t.skip}:new Promise(o=>{let n;try{n=C(t.command,t.args,{detached:!0,stdio:"ignore",windowsHide:!0})}catch(s){return o({opened:!1,why:`${w.basename(t.command)} did not start (${s.code??s.message})`})}n.once("error",s=>o({opened:!1,why:`${w.basename(t.command)} did not start (${s.code??s.message})`})),n.once("spawn",()=>{n.unref(),o({opened:!0})})})}import{packageRoot as Z,projectRoot as G,release as O,reportsDirectory as h}from"../browser/shared/paths.mjs";import{workspaceId as ee,registerQuietly as te}from"../browser/shared/workspace-registry.mjs";import{serviceLocation as re,workspaceBase as ne}from"../browser/shared/service-location.mjs";import{fullAddress as oe}from"../browser/shared/page-address.mjs";import{findPreviewServer as se,galleryVersion as F,portIsFree as ie,previewServerFor as ae,readAnnouncement as ce}from"../browser/shared/preview-server.mjs";import{documentLinks as le}from"../browser/shared/reports.mjs";import{defaultWorkspace as de,documentDirectory as pe,documentFiles as ue}from"../browser/shared/workspace.mjs";var $="\u4EA4\u7ED9\u7528\u6237\uFF08\u73B0\u5728\u5C31\u628A\u8FD9\u4E2A\u5730\u5740\u7ED9\u7528\u6237\uFF1B\u7528 Chrome \u6216 Edge \u6253\u5F00\uFF09\uFF1A",fe="Agent \u81EA\u7528\uFF08\u53EA\u6709\u6587\u6863\u9875\uFF0C\u4E0D\u4EA4\u7ED9\u7528\u6237\uFF09\uFF1A",me=e=>`send the user ${e} now, in a message of its own, before any other step; then `;function Xe(e,r){let t=e.at(-1)??"";return`Next: ${t.startsWith($)?me(t.slice($.length)):""}${r}`}async function Ze(e,r){let t=e.at(-1)??"";return t.startsWith($)?r.has("--no-browser")?"Not opened in a browser (--no-browser).":T(await I(t.slice($.length))):null}var D="GALLERY_NO_PREVIEW",he=e=>!["","0",void 0].includes(e),et=e=>e.has("--no-preview")||he(process.env[D]),we=4317,$e=20,ye=(e=process.env)=>{let r=Number(e.GALLERY_PORT);return Number.isInteger(r)&&r>0&&r<65536?r:we},ge=6e4,ve=5*1024*1024,xe=P.join(G,"node_modules","vite","bin","vite.js"),ke=P.join(Z,"dist","server.mjs"),Le=e=>new Promise(r=>setTimeout(r,e)),Se=de(),R=re(),f=R.serverLog,W=()=>ne(h),A=(e,r)=>`http://127.0.0.1:${e}${W()}/generated/${r}.html`,be=(e,r)=>`${A(e,r)}?agent`,Y=e=>`http://127.0.0.1:${e}/`,Ae=async(e,r)=>{let t=await le(h).then(n=>n.links,()=>null),o=oe(`http://127.0.0.1:${e}`,r,t);return W()?o.replace("/#",`/#~${ee(h)}/`):o};async function Pe({first:e=ye(),count:r=$e}={}){let t=Number((await m.readFile(R.lastPortFile,"utf8").catch(()=>"")).trim()),o=Array.from({length:Math.max(0,r)},(n,s)=>e+s);return Number.isInteger(t)&&t>0&&t<65536?[t,...o.filter(n=>n!==t)]:o}async function Re(){return await m.mkdir(P.dirname(f),{recursive:!0}),await m.stat(f).then(r=>r.size,()=>0)>ve&&await m.rename(f,`${f}.1`).catch(()=>{}),b.openSync(f,"a")}async function Ee(e,r){if(!O){let{writeSharedAssets:p}=await import("./chunk-CRDG6EF2.mjs");await p()}let t=await Re();b.writeSync(t,`
3
- [${new Date().toISOString()}] ${r}: Gallery ${F} on 127.0.0.1:${e} for ${h}
4
- `);let[o,n]=O?[[ke,"--port",String(e)],Q.homedir()]:[[xe,"--host","127.0.0.1","--port",String(e),"--strictPort"],G],s=J(process.execPath,o,{cwd:n,env:{...process.env,GALLERY_WORKSPACE:Se,GALLERY_SERVER_KIND:"cli"},detached:!0,stdio:["ignore",t,t],windowsHide:!0});return b.closeSync(t),s.unref(),s}async function Ne({slug:e=null,command:r=`gallery open${e?` ${e}`:""}`,ports:t=null,starting:o=ge,baseline:n=!1}={}){await te(h);let s=()=>!0;if(e){let a=ue(pe(e,h)),c=await m.readFile(a.html,"utf8").catch(()=>null);if(c===null)return{ok:!1,reason:"missing",message:`No document "${e}": ${a.html} does not exist (gallery new ${e} "<\u6807\u9898>" makes one; gallery list lists those there are).`};n&&await import("./chunk-225ALKYI.mjs").then(({previewBaseline:x})=>x(e,c));let i=await m.readFile(a.json,"utf8").then(JSON.parse).catch(()=>({})),v=[/<title>([^<]*)<\/title>/i.exec(c)?.[1]?.trim(),typeof i.title=="string"?i.title.trim():""].filter(Boolean);s=x=>v.length===0||v.some(_=>x.includes(_)||x.includes(X(_)))}let p=t??await Pe(),k=p.length?`${Math.min(...p)} to ${Math.max(...p)}`:"none",L=`gallery open${e?` ${e}`:""}`,E=async(a,c=[])=>{let i=await ae({ports:p.slice(a),start:v=>Ee(v,r)});return i.busy?.newer?{failed:{ok:!1,reason:"newer",message:`A newer Gallery (${i.busy.version}) serves this Gallery data directory (port ${i.busy.port}, pid ${i.busy.pid}) and gave no answer in 10s; this is Gallery ${F}. Update this one (npm i -g @heycys/gallery@latest), or run ${L} again in a while.`}}:i.busy?{failed:{ok:!1,reason:"busy",message:`The shared Gallery server (port ${i.busy.port}, pid ${i.busy.pid}) took the request and gave no answer in 10s: it is busy or stuck. Run ${L} again in a while, or stop that process first (gallery stop): a second server for this data directory is not started beside it.`}}:i.stuck?{failed:{ok:!1,reason:"stuck",message:`An older Gallery's server serves this Gallery data directory and did not stop: ${i.stuck.message}`}}:i.port===null?{failed:{ok:!1,reason:"ports",message:`No server for this data directory runs, and no port from ${k} is free to start one on: stop a server on one of them (or name another first port: GALLERY_PORT=<n>), then run ${L}.`}}:{...i,passed:[...c,...i.passed]}},u=await E(0);if(u.failed)return u.failed;let{port:l,started:d,passed:S,replaced:j}=u,y=u.running??null,N=Date.now()+o,g="",B=async()=>{if(e){let c=await fetch(`${A(l,e)}?present`,{signal:AbortSignal.timeout(5e3)}).catch(()=>null),i=c?.ok?await c.text():"";return g=c?i?`HTTP ${c.status} without the title`:`HTTP ${c.status}`:"no answer",!!(i&&s(i))}let a=await fetch(`http://127.0.0.1:${l}/__gallery/workspace/info`,{signal:AbortSignal.timeout(5e3)}).catch(()=>null);return g=a?`HTTP ${a.status}`:"no answer",!!a?.ok};for(;;await Le(300)){if(Date.now()>N)return{ok:!1,reason:"timeout",message:`${e?A(l,e):Y(l)} did not answer${e?" with the document's title":""} in ${o/1e3}s (${g})${d?`; the server's output is in ${f}`:""}.`};if(d){let a=await se({answering:!0});if(a&&a.pid!==d.pid){if(d.exitCode===null)try{process.kill(d.pid)}catch{}({port:l}=a),y={pid:a.pid,kind:(await ce())?.kind??"cli",version:null},d=null;continue}if(!a&&d.exitCode===null){g="the server started has not announced itself yet";continue}if(!a){if(!await ie(l)){if(u=await E(p.indexOf(l)+1,[...S,`${l} (taken by another program while the server started)`]),u.failed)return u.failed;({port:l,started:d,passed:S}=u),y=u.running??null,N=Date.now()+o;continue}let c=await m.readFile(f,"utf8").catch(()=>"");return{ok:!1,reason:"stopped",message:`The Gallery server on port ${l} stopped (exit ${d.exitCode}). Its last words (${f}):
5
- ${c.split(`
6
- `).slice(-15).join(`
7
- `)}`}}}if(await B())break}return await m.writeFile(R.lastPortFile,`${l}
8
- `).catch(()=>{}),{ok:!0,port:l,pid:d?.pid??y?.pid??null,kind:y?.kind??"cli",started:!!d,replaced:j??null,passed:S}}var _e=e=>e.length<2?e.join(""):`${e.slice(0,-1).join(", ")} and ${e.at(-1)}`;function Te({port:e,pid:r,kind:t,started:o,replaced:n,passed:s=[]}){let p=[`pid ${r}`,...t==="dev"?["npm run dev's"]:[],...o?[`started now${s.length?`, after passing over ${_e(s)}`:""}`]:[],...n?[`it replaced Gallery ${n.version??"an older version"}'s server, pid ${n.pid}`]:[]],k=o?`; its log: ${f}`:"";return`Gallery's shared server runs on port ${e} (${p.join(", ")}${k}). This command is done; the server runs on after it (nothing to wait for or keep running).`}async function Ie(e,r,t=null){return[Te(r),...e?[`${fe}${be(r.port,e)}`]:[],`${$}${e?await Ae(r.port,{slug:e,block:t}):Y(r.port)}`]}async function tt(e,{skipped:r,command:t,ports:o=null}){let n=`gallery open ${e} starts it and prints the address to give the user`;if(r)return[`Preview: not started (--no-preview or ${D}): ${n}.`];let s=await Ne({slug:e,command:t,ports:o});return s.ok?Ie(e,s):[`Preview: not started: ${s.message}`,`When that is fixed, ${n}.`]}export{$ as a,fe as b,Xe as c,Ze as d,et as e,be as f,Y as g,Pe as h,Ne as i,Te as j,Ie as k,tt as l};
@@ -1,4 +0,0 @@
1
- import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
2
- import{e as D,f as x}from"./chunk-5GK7HS62.mjs";import{a as d,b as u,c as w,d as y}from"./chunk-S3SX3COT.mjs";import{b as c,d as f,e as m,g as p,h as g,i as a,j as h}from"./chunk-VRPVVMRB.mjs";import{k as l}from"./chunk-FJLM7YE7.mjs";import{a as s}from"./chunk-UMHUSOPJ.mjs";import S from"node:path";import{FILE as j}from"../browser/shared/annotations.mjs";import{editStateDirectory as L,reportsDirectory as i}from"../browser/shared/paths.mjs";import{documentDirectory as $,documentFiles as k}from"../browser/shared/workspace.mjs";function O({say:e=!0}={}){return o=>{let{text:t,changes:n}=c(o.html,{finish:l});if(e&&n.length&&console.log(p(o.htmlPath,n,{pending:!0}).join(`
3
- `)),e){let r=f(o.html);r.length&&console.log(D(o.htmlPath,r,r.length,{pending:!0}).join(`
4
- `));for(let N of x(o.htmlPath,m(s(o.html),o.metadata),{pending:!0}))console.log(N)}return t}}function b(e){for(let o of e){for(let t of g(o.html))console.log(`note ${o.slug}: ${t} (read-only in the preview)`);for(let t of a(o.html))console.log(`note ${o.slug}: ${t}`);for(let t of h(o.html))console.log(`note ${o.slug}: ${t}`)}}async function q(e){for(let o of e){let t=await w({stateDirectory:L,reportsDirectory:i,slug:o});for(let n of y(k($(o,i)).html,t))console.log(n)}}async function z(e){for(let o of e){let t=await d({stateDirectory:L,reportsDirectory:i,slug:o});for(let n of u(S.join($(o,i),j),t))console.log(n)}}export{O as a,b,q as c,z as d};
@@ -1,2 +0,0 @@
1
- import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
2
- import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y}from"./chunk-EURLTOTZ.mjs";import"./chunk-Q4UEPUWF.mjs";import"./chunk-5L7RYZCL.mjs";export{d as CACHE_FILE,e as FRESH,c as NEWER_LINE,a as PACKAGE,f as RETRY,b as SKILL_LINE,g as TIMEOUT,j as cacheDirectory,h as checkOff,r as claimCheck,o as latestUrl,w as newerLine,l as npmSettings,k as parseNpmrc,p as readCache,s as refreshCache,n as refreshEnv,m as registryOf,u as skillFolders,v as skillLine,x as skillLines,q as stale,t as startRefresh,y as versionNotes,i as viaNpx};