@panphora/clayjs 1.16.0 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (283) hide show
  1. package/dist/all.js +1 -1
  2. package/dist/clay-dom.js +1 -1
  3. package/dist/clay-events.js +1 -1
  4. package/dist/clay-internals.js +1 -1
  5. package/dist/clay-options.js +1 -1
  6. package/dist/clay-router.js +1 -1
  7. package/dist/clay-ui.js +1 -1
  8. package/dist/clay-utils.js +1 -1
  9. package/dist/clay.js +1 -1
  10. package/dist/clay.standalone.js +7917 -5621
  11. package/dist/m/attrs/refetch-on-save-ZUE7PSCI.js +1 -0
  12. package/dist/m/attrs/save-freeze-MYNVXREN.js +1 -0
  13. package/dist/m/c-2YYDMLNZ.js +1 -0
  14. package/dist/m/c-336SGU5W.js +1 -0
  15. package/dist/m/c-3H6BZDNJ.js +6 -0
  16. package/dist/m/{c-LR4CGEPT.js → c-3RUU4TPX.js} +1 -1
  17. package/dist/m/c-3XIRD4NU.js +1 -0
  18. package/dist/m/c-4DFEJ2PO.js +3 -0
  19. package/dist/m/c-56QRZTZH.js +1 -0
  20. package/dist/m/c-5J4E7O4Y.js +4 -0
  21. package/dist/m/c-5LKDWQTL.js +19 -0
  22. package/dist/m/c-5QWQ7A5L.js +1 -0
  23. package/dist/m/c-5RJFTLSF.js +1 -0
  24. package/dist/m/c-6AZOGAPE.js +1 -0
  25. package/dist/m/{c-Y6USGTS5.js → c-6CRUUXOX.js} +5 -5
  26. package/dist/m/{c-54RCDCBU.js → c-6KEVEQ7L.js} +1 -1
  27. package/dist/m/{c-LTGMXXKO.js → c-6NC5I2TV.js} +1 -1
  28. package/dist/m/{c-YDH7Q3NY.js → c-74MGYWZF.js} +1 -1
  29. package/dist/m/{c-Z36J63PP.js → c-7OLLJPWP.js} +1 -1
  30. package/dist/m/c-A3E3NIMC.js +1 -0
  31. package/dist/m/{c-5R4PTRG2.js → c-AMSNPOCX.js} +1 -1
  32. package/dist/m/c-B3JM5ZXC.js +1 -0
  33. package/dist/m/c-BPF2NSPV.js +1 -0
  34. package/dist/m/c-BQ6LOBEE.js +1 -0
  35. package/dist/m/c-CJ3A7ZKE.js +1 -0
  36. package/dist/m/c-CQHPGKX2.js +1 -0
  37. package/dist/m/c-DCXOXBF3.js +1 -0
  38. package/dist/m/c-DFS4XZJV.js +2 -0
  39. package/dist/m/{c-F3CKJTJS.js → c-DNENWY4O.js} +1 -1
  40. package/dist/m/c-E4LIR5X5.js +1 -0
  41. package/dist/m/c-EVCQ3BKA.js +1 -0
  42. package/dist/m/{c-5Y6TNX5W.js → c-EZU56NQV.js} +2 -2
  43. package/dist/m/c-FDNHHZY5.js +1 -0
  44. package/dist/m/{c-SWRJFCNN.js → c-FRLHSY7E.js} +1 -1
  45. package/dist/m/c-FROJUZMV.js +1 -0
  46. package/dist/m/c-G2JPKCTP.js +1 -0
  47. package/dist/m/c-GB6TU7WV.js +1 -0
  48. package/dist/m/{c-GB3JTV6E.js → c-GFJJEBTU.js} +1 -1
  49. package/dist/m/{c-J7CA54IP.js → c-GSFIGKOP.js} +1 -1
  50. package/dist/m/{c-OYTFP5QN.js → c-GY422N3Q.js} +1 -1
  51. package/dist/m/c-HAWFNBYG.js +1 -0
  52. package/dist/m/{c-33HUYEDI.js → c-HDDEEL77.js} +1 -1
  53. package/dist/m/c-HFKUVACH.js +1 -0
  54. package/dist/m/c-HHDFCNHV.js +1 -0
  55. package/dist/m/c-I2ZATQCD.js +2 -0
  56. package/dist/m/c-IEM4NTCS.js +1 -0
  57. package/dist/m/c-IW6GGOU2.js +1 -0
  58. package/dist/m/{c-SGCCC4FW.js → c-JDCX26UP.js} +2 -2
  59. package/dist/m/c-JRKY44DK.js +1 -0
  60. package/dist/m/c-JU3NK25H.js +1 -0
  61. package/dist/m/{c-VFX45IZQ.js → c-KAU6E43D.js} +1 -1
  62. package/dist/m/c-KBS3UV6B.js +1 -0
  63. package/dist/m/c-KGVGROZT.js +1 -0
  64. package/dist/m/{c-YG2NJYS6.js → c-KQ6TYJAP.js} +2 -2
  65. package/dist/m/{c-2JL6E75N.js → c-KU3ZFADW.js} +1 -1
  66. package/dist/m/c-LWLBHLVC.js +3 -0
  67. package/dist/m/c-M2L47S2X.js +7 -0
  68. package/dist/m/c-MFP2ZWD4.js +1 -0
  69. package/dist/m/{c-4YSCRICO.js → c-MKSQ4Y57.js} +1 -1
  70. package/dist/m/{c-2M73252O.js → c-NUFFJVVJ.js} +1 -1
  71. package/dist/m/c-NUHSPT5P.js +1 -0
  72. package/dist/m/c-O72HVYSA.js +1 -0
  73. package/dist/m/c-OW5QIGG3.js +1 -0
  74. package/dist/m/c-PGRCK73F.js +1 -0
  75. package/dist/m/{c-4DRMS4QG.js → c-PS5ARVWR.js} +1 -1
  76. package/dist/m/c-Q622NS2Y.js +1 -0
  77. package/dist/m/c-Q7NQD65V.js +1 -0
  78. package/dist/m/c-QH63LQOS.js +1 -0
  79. package/dist/m/{c-TQZ2JYHD.js → c-QICP2YR5.js} +1 -1
  80. package/dist/m/{c-7VGZ7RU5.js → c-QJ4OM3G6.js} +1 -1
  81. package/dist/m/{c-MMUIUUZG.js → c-R3L7ZJGB.js} +1 -1
  82. package/dist/m/c-R7IWVINQ.js +1 -0
  83. package/dist/m/{c-HVYXIS72.js → c-RSMOODDU.js} +1 -1
  84. package/dist/m/{c-KKWLDOPM.js → c-RYUXUUBX.js} +1 -1
  85. package/dist/m/c-S4ZEH46B.js +9 -0
  86. package/dist/m/c-SDAXDM2D.js +1 -0
  87. package/dist/m/c-SMBZG5X4.js +1 -0
  88. package/dist/m/{c-UXBMRDZB.js → c-SMGU7RT3.js} +1 -1
  89. package/dist/m/c-SPIORRYS.js +1 -0
  90. package/dist/m/c-SWLRT66R.js +1 -0
  91. package/dist/m/c-SZGYW5HT.js +1 -0
  92. package/dist/m/c-TCJTVAFN.js +1 -0
  93. package/dist/m/{c-HRDCD3WN.js → c-TJ6WOJL3.js} +1 -1
  94. package/dist/m/c-TYLXX4NF.js +21 -0
  95. package/dist/m/c-U62OB4BT.js +1 -0
  96. package/dist/m/{c-NMJRXKPC.js → c-U6YWUAR3.js} +1 -1
  97. package/dist/m/c-UDCSU5G5.js +2 -0
  98. package/dist/m/{c-NZMNXVF6.js → c-UDUUJPFZ.js} +1 -1
  99. package/dist/m/c-VE6ZMYMC.js +1 -0
  100. package/dist/m/c-VG5XIN4T.js +1 -0
  101. package/dist/m/c-VHM5XQHK.js +1 -0
  102. package/dist/m/c-VI5RMSVY.js +1 -0
  103. package/dist/m/c-VRZN56XY.js +1 -0
  104. package/dist/m/c-W5MCHEGA.js +1 -0
  105. package/dist/m/c-WDC5GVKU.js +1 -0
  106. package/dist/m/c-WWXIDH4O.js +28 -0
  107. package/dist/m/{c-QIX5BJYN.js → c-XCNTK76U.js} +1 -1
  108. package/dist/m/c-XMS6DPBR.js +1 -0
  109. package/dist/m/c-Y5HBBIQ4.js +1 -0
  110. package/dist/m/{c-5M4YEKCX.js → c-ZVPVXTJF.js} +1 -1
  111. package/dist/m/c-ZVRKXKM7.js +1 -0
  112. package/dist/m/{c-HT33EQRN.js → c-ZWIOJGMT.js} +1 -1
  113. package/dist/m/core/admin-attrs-QHOKPJ7W.js +1 -0
  114. package/dist/m/core/autosave-HRYGUWV6.js +1 -0
  115. package/dist/m/core/conflict-notice-6MROJN2L.js +1 -0
  116. package/dist/m/core/host-permission-FNXVEFNE.js +1 -0
  117. package/dist/m/core/is-edit-mode-KTWA3O5N.js +1 -0
  118. package/dist/m/core/{persist-HKHA66IY.js → persist-JFYRHMRJ.js} +1 -1
  119. package/dist/m/core/recovery-FLTCC2OC.js +1 -0
  120. package/dist/m/core/save-HQZ4S667.js +1 -0
  121. package/dist/m/core/save-core-KGQWFUNH.js +1 -0
  122. package/dist/m/core/snapshot-EGQZNT45.js +1 -0
  123. package/dist/m/core/unsaved-warning-IDJLD66H.js +1 -0
  124. package/dist/m/events/index-RN2JNGBV.js +1 -0
  125. package/dist/m/internals/index-PVXGPUDA.js +1 -0
  126. package/dist/m/lib/cache-bust-MUMFXZK6.js +1 -0
  127. package/dist/m/loader-S4I7GKXR.js +1 -0
  128. package/dist/m/manifest-4C419D67.js +1 -0
  129. package/dist/m/manifest-edit-B077F288.js +1 -0
  130. package/dist/m/manifest.json +1555 -1058
  131. package/dist/m/options/options-EJMS3K24.js +1 -0
  132. package/dist/m/page/{editor-XUTB2HB2.js → editor-NNJA4OKD.js} +21 -8
  133. package/dist/m/plugins/{ai-edit-ZQ4CGWIP.js → ai-edit-QN4PMMNL.js} +1 -1
  134. package/dist/m/plugins/demo-RM5IR6AO.js +1 -0
  135. package/dist/m/plugins/indicator-URDBBOQO.js +1 -0
  136. package/dist/m/plugins/live-HFWD4OIH.js +1 -0
  137. package/dist/m/plugins/{menu-HCKO3DSP.js → menu-3HIEQSI6.js} +2 -2
  138. package/dist/m/plugins/page-JOKB6XPR.js +2 -0
  139. package/dist/m/plugins/page-view-NXOJHNW6.js +1 -0
  140. package/dist/m/plugins/people-SGPJKANK.js +1 -0
  141. package/dist/m/plugins/{richclay-RC3L2F6X.js → richclay-NRQDSWX6.js} +2 -2
  142. package/dist/m/plugins/sortable-GWT4PWDV.js +1 -0
  143. package/dist/m/plugins/source-4ZRSAIYM.js +1 -0
  144. package/dist/m/plugins/undo-VDA5P7FH.js +1 -0
  145. package/dist/m/plugins/{upgrade-ZNYODP5Y.js → upgrade-W7FG5VFG.js} +1 -1
  146. package/dist/m/plugins/upload-WLYKK6TL.js +1 -0
  147. package/dist/m/plugins/visitor-drafts-LIDY7NH6.js +21 -0
  148. package/dist/m/plugins/visitor-drafts-owner-ZXCKBZE7.js +1 -0
  149. package/dist/m/plugins/wire-4N6GYAF6.js +1 -0
  150. package/dist/m/{reader-core-ILWLXVMP.js → reader-core-DXYCURFF.js} +2 -2
  151. package/dist/m/sync/live-sync-J7VMYTKS.js +1 -0
  152. package/dist/m/ui/{index-EVHKMKBL.js → index-3JLVI27O.js} +1 -1
  153. package/dist/offline-manifest.json +857 -623
  154. package/dist/page/themes/light-1.css +25 -1
  155. package/dist/server/core.cjs +115 -24
  156. package/package.json +1 -1
  157. package/src/core/boot-phase.js +2 -1
  158. package/src/core/conflict-download.js +3 -29
  159. package/src/core/download.js +32 -0
  160. package/src/core/host-meta.js +18 -0
  161. package/src/core/save-core.js +8 -4
  162. package/src/core/save.js +4 -4
  163. package/src/core/snapshot.js +39 -1
  164. package/src/lib/autosave-scheduler.js +3 -4
  165. package/src/page/blocks.js +34 -1
  166. package/src/page/board-views.js +2 -16
  167. package/src/page/chart-tables.js +11 -0
  168. package/src/page/chart.js +6 -10
  169. package/src/page/checkpoint-proof.js +289 -0
  170. package/src/page/chrome.js +24 -6
  171. package/src/page/document-title-dom.js +12 -0
  172. package/src/page/document-title-runtime.js +15 -1
  173. package/src/page/document-title.js +4 -1
  174. package/src/page/editor.js +77 -12
  175. package/src/page/emoji-data.js +162 -0
  176. package/src/page/features/board.js +12 -3
  177. package/src/page/features/chart.js +11 -0
  178. package/src/page/features/dates.js +180 -0
  179. package/src/page/features/emoji.js +187 -0
  180. package/src/page/features/mentions.js +188 -0
  181. package/src/page/features/registry.js +6 -1
  182. package/src/page/features/table.js +2 -2
  183. package/src/page/format-command.js +9 -0
  184. package/src/page/format-host.js +54 -0
  185. package/src/page/format-native-commands.js +142 -0
  186. package/src/page/format-native.js +42 -0
  187. package/src/page/inline.js +32 -8
  188. package/src/page/items.js +15 -3
  189. package/src/page/markdown.js +26 -2
  190. package/src/page/mention-picker.js +99 -0
  191. package/src/page/merge.js +1 -1
  192. package/src/page/projection.js +58 -15
  193. package/src/page/save-projection.js +39 -0
  194. package/src/page/save-states.js +1 -1
  195. package/src/page/schema.js +33 -0
  196. package/src/page/themes/content.css +25 -1
  197. package/src/page/themes/light-1.css +25 -1
  198. package/src/page/view-hooks.js +32 -0
  199. package/src/page/ybind/binding.js +31 -4
  200. package/src/page/ybind/marks.js +2 -1
  201. package/src/page/ybind/provider.js +13 -2
  202. package/src/page/ybind/recovery-replay.js +362 -4
  203. package/src/plugins/live.js +37 -1
  204. package/src/plugins/page.js +117 -3
  205. package/src/plugins/visitor-drafts/intro.js +2 -1
  206. package/src/server/checkpoint/index.js +2 -2
  207. package/src/sync/saved-stream.js +17 -8
  208. package/dist/m/attrs/refetch-on-save-NWPPXOCZ.js +0 -1
  209. package/dist/m/attrs/save-freeze-FUP4Q4X3.js +0 -1
  210. package/dist/m/c-35NBGMZB.js +0 -1
  211. package/dist/m/c-3IQRECYS.js +0 -1
  212. package/dist/m/c-4B6H4G5V.js +0 -1
  213. package/dist/m/c-4FFHZM32.js +0 -1
  214. package/dist/m/c-66O32MV3.js +0 -28
  215. package/dist/m/c-7O6AFR65.js +0 -1
  216. package/dist/m/c-ANQTJ3B5.js +0 -2
  217. package/dist/m/c-AYVOREBE.js +0 -1
  218. package/dist/m/c-B2ZXPOS3.js +0 -3
  219. package/dist/m/c-BMIZKMPV.js +0 -1
  220. package/dist/m/c-CJZSLMVQ.js +0 -1
  221. package/dist/m/c-DBE6ORSI.js +0 -1
  222. package/dist/m/c-EDHUR4MX.js +0 -1
  223. package/dist/m/c-EY6UOM54.js +0 -1
  224. package/dist/m/c-F7Y6FLPY.js +0 -1
  225. package/dist/m/c-FA4DZVTC.js +0 -1
  226. package/dist/m/c-G2BUZITR.js +0 -1
  227. package/dist/m/c-GBGWXTX4.js +0 -1
  228. package/dist/m/c-GHBCCVG4.js +0 -1
  229. package/dist/m/c-IB52R237.js +0 -1
  230. package/dist/m/c-IKWNE4R4.js +0 -1
  231. package/dist/m/c-IU3IYEU6.js +0 -1
  232. package/dist/m/c-IZ2EBRAJ.js +0 -1
  233. package/dist/m/c-KR4UW4KW.js +0 -1
  234. package/dist/m/c-KY3VJGUA.js +0 -8
  235. package/dist/m/c-LXENEBV7.js +0 -1
  236. package/dist/m/c-PPOSCAQD.js +0 -1
  237. package/dist/m/c-QQHEX6HA.js +0 -1
  238. package/dist/m/c-R7RMANJI.js +0 -9
  239. package/dist/m/c-RI4NT75Y.js +0 -1
  240. package/dist/m/c-RUJKSUQW.js +0 -1
  241. package/dist/m/c-T4VO4OCB.js +0 -1
  242. package/dist/m/c-TR6RMDQ7.js +0 -3
  243. package/dist/m/c-UKHTLWUW.js +0 -1
  244. package/dist/m/c-UNN7LWCT.js +0 -1
  245. package/dist/m/c-V7PZZRG7.js +0 -1
  246. package/dist/m/c-VL52ADDR.js +0 -1
  247. package/dist/m/c-WWDBYXLK.js +0 -1
  248. package/dist/m/c-XNNW2CWK.js +0 -1
  249. package/dist/m/c-Z4VRC7GU.js +0 -7
  250. package/dist/m/c-Z6K52OLP.js +0 -19
  251. package/dist/m/c-ZDY2MDAA.js +0 -21
  252. package/dist/m/core/admin-attrs-VGNLAUDK.js +0 -1
  253. package/dist/m/core/autosave-E4PEFPZ6.js +0 -1
  254. package/dist/m/core/conflict-notice-VQ6Y64PH.js +0 -1
  255. package/dist/m/core/host-permission-XN3K2IW3.js +0 -1
  256. package/dist/m/core/is-edit-mode-JXHDVGUL.js +0 -1
  257. package/dist/m/core/recovery-TBBSICE2.js +0 -1
  258. package/dist/m/core/save-WUCHTQBE.js +0 -1
  259. package/dist/m/core/save-core-FJVHT5M3.js +0 -1
  260. package/dist/m/core/snapshot-F3SWDZMM.js +0 -1
  261. package/dist/m/core/unsaved-warning-STKBHE6G.js +0 -1
  262. package/dist/m/events/index-23DPTUT4.js +0 -1
  263. package/dist/m/internals/index-WOVAP3RU.js +0 -1
  264. package/dist/m/lib/cache-bust-CGWT6ZJI.js +0 -1
  265. package/dist/m/loader-HXX6YNH5.js +0 -1
  266. package/dist/m/manifest-F22DEDAC.js +0 -1
  267. package/dist/m/manifest-edit-C3C7376B.js +0 -1
  268. package/dist/m/options/options-2LH76JQ3.js +0 -1
  269. package/dist/m/plugins/demo-ZIBFAA3R.js +0 -1
  270. package/dist/m/plugins/indicator-PV4YW2ID.js +0 -1
  271. package/dist/m/plugins/live-NUTTXSBS.js +0 -1
  272. package/dist/m/plugins/page-KSUH7G6J.js +0 -2
  273. package/dist/m/plugins/page-view-W73OW7WI.js +0 -1
  274. package/dist/m/plugins/people-AJJ32YCG.js +0 -1
  275. package/dist/m/plugins/sortable-YRMQX3ZU.js +0 -1
  276. package/dist/m/plugins/source-KHK5UUSK.js +0 -1
  277. package/dist/m/plugins/undo-OF2L3CXU.js +0 -1
  278. package/dist/m/plugins/upload-XSGNILUY.js +0 -1
  279. package/dist/m/plugins/visitor-drafts-XK5GW55Q.js +0 -21
  280. package/dist/m/plugins/visitor-drafts-owner-KSSH75EV.js +0 -1
  281. package/dist/m/plugins/wire-ZWVWKF76.js +0 -1
  282. package/dist/m/sync/live-sync-4AUVXVJU.js +0 -1
  283. /package/dist/m/plugins/{richclay-RC3L2F6X.js.LEGAL.txt → richclay-NRQDSWX6.js.LEGAL.txt} +0 -0
@@ -6,7 +6,7 @@ import { savePageForce, holdAllSaves, releaseAllSaves, suspendAutosave, resumeAu
6
6
  import { setSaveHeader } from "../core/save-core.js";
7
7
  import { lastSeenEtag, representedEtag, recordEtag } from "../core/etag.js";
8
8
  import { captureForSaveAndComparison } from "../core/snapshot.js";
9
- import { storeOf, stageStore, closeStore, checkpointWithin, requestCheckpoint, fastLane, pageLaneReady, pageWriterReady } from "./live.js";
9
+ import { storeOf, stageStore, closeStore, checkpointWithin, requestCheckpoint, fastLane, pageLaneReady, pageWriterReady, registerPageCheckpoints } from "./live.js";
10
10
  import { serializeLive } from "../live/ops.js";
11
11
  import { parseJsonRelaxed } from "../vendor/hyper-morph-json.vendor.js";
12
12
  import { saveStateFor, BLOCKED_TEXT, RETRY_TEXT, downloadPageCopy, downloadSnapshot, copyPageText } from "../page/save-states.js";
@@ -410,6 +410,7 @@ function dispose() {
410
410
  const inst = active;
411
411
  active = null;
412
412
  setSaveHeader("Page-Write", null);
413
+ registerPageCheckpoints(null);
413
414
  if (!inst) return;
414
415
  disposeInstall(inst);
415
416
  if (inst.retryTimer) {
@@ -438,6 +439,82 @@ function dispose() {
438
439
  restoreArticle(inst);
439
440
  }
440
441
 
442
+ // The page's journal, its replay and the proof that retires it, all imported the first
443
+ // time a page can actually journal: a reader, a page without a pinned identity and a host
444
+ // with no recovery service pay for none of it.
445
+ let recoveryModules = null;
446
+
447
+ function pageRecovery() {
448
+ if (!recoveryModules) {
449
+ recoveryModules = Promise.all([import("../page/ybind/recovery-replay.js"), import("../page/checkpoint-proof.js")])
450
+ .then(([replay, proof]) => ({ replay, proof }))
451
+ .catch((error) => {
452
+ console.warn("clayjs: page journal could not load", error);
453
+ return null;
454
+ });
455
+ }
456
+ return recoveryModules;
457
+ }
458
+
459
+ // What this session journals under, or null when this page cannot pin an identity or this
460
+ // host has no recovery service: the document is then edited with no local copy, as before.
461
+ async function openJournal(meta, store) {
462
+ const service = globalThis.window?.clay?.recovery ?? null;
463
+ if (!service || !store) return null;
464
+ const modules = await pageRecovery();
465
+ if (!modules) return null;
466
+ try {
467
+ return modules.replay.openPageJournal({
468
+ meta,
469
+ service,
470
+ base: modules.replay.journalBase(store.value),
471
+ });
472
+ } catch (error) {
473
+ console.warn("clayjs: page journal could not open", error);
474
+ return null;
475
+ }
476
+ }
477
+
478
+ // Replay once, after the authority snapshot is adopted and before input starts. A capsule
479
+ // this page may not replay is kept and named for review; nothing of it is applied.
480
+ async function replayJournal(inst) {
481
+ const journal = inst.binding?.journal;
482
+ if (!journal || !inst.store) return { replayed: [], review: [] };
483
+ const modules = await pageRecovery();
484
+ if (!modules) return { replayed: [], review: [] };
485
+ const outcome = await modules.replay.replayInto({ journal, state: inst.store.value, into: inst.binding.ydoc });
486
+ // The recovered page is this tab's page now: it is offered to the room exactly as an
487
+ // edit would be, and it is not one more journal and not one giant undo step.
488
+ if (outcome.replayed.length) inst.binding.provider.settle();
489
+ if (outcome.review.length) inst.recoveryReview = outcome.review;
490
+ return outcome;
491
+ }
492
+
493
+ // One accepted save retires the records a proof covers, and no others.
494
+ function installCheckpointProof(inst) {
495
+ registerPageCheckpoints(async ({ capture, state, article, etag }) => {
496
+ const journal = inst.binding?.journal;
497
+ if (!journal) return;
498
+ const modules = await pageRecovery();
499
+ const context = modules ? await journal.context() : null;
500
+ if (!context) return;
501
+ // Where this host serves the page state, if it serves one at all: asked here, because
502
+ // a page that journals nothing never needs the answer.
503
+ const { hostPageStateHref } = await import("../core/host-meta.js");
504
+ const answer = await modules.proof.checkpointAccepted({
505
+ channel: journal.channel,
506
+ records: journal.records(),
507
+ capture,
508
+ accepted: context,
509
+ article,
510
+ state,
511
+ etag,
512
+ href: await hostPageStateHref(),
513
+ });
514
+ if (answer.ok) journal.retire(answer.retired);
515
+ });
516
+ }
517
+
441
518
  export function createSteps(inst, options) {
442
519
  let meta = null;
443
520
  let binding = null;
@@ -460,6 +537,31 @@ export function createSteps(inst, options) {
460
537
  addDisposer(inst, () => editorReadyResolve?.());
461
538
  addDisposer(inst, () => clearLoadingStatus(inst));
462
539
 
540
+ // The format gate, fetched when a newer-format command first asks for it: neither
541
+ // the gate nor its host adapter is on the editor's ready path. One gate per session,
542
+ // built against this editor installation, and disposed with the editor.
543
+ let formatGate = null;
544
+ let formatGateLoading = null;
545
+ inst.loadFormatGate = () => {
546
+ if (formatGate) return Promise.resolve(formatGate);
547
+ formatGateLoading ??= Promise.all([import("../page/format-gate.js"), import("../page/format-host.js")])
548
+ .then(([{ createFormatGate }, { createFormatHost }]) => {
549
+ const host = createFormatHost();
550
+ formatGate = createFormatGate({
551
+ host,
552
+ supported: host.supported,
553
+ installed: () => identity?.token ?? null,
554
+ revision: () => null,
555
+ });
556
+ return formatGate;
557
+ })
558
+ .catch((error) => {
559
+ formatGateLoading = null;
560
+ throw error;
561
+ });
562
+ return formatGateLoading;
563
+ };
564
+
463
565
  // A document with a tool block, at boot or when one arrives, opens the store its
464
566
  // tools keep state in and the host that mounts them. A document with no tool
465
567
  // never waits for either.
@@ -762,6 +864,11 @@ function mergeRepresentedPage(store, value) {
762
864
  return result;
763
865
  };
764
866
  identity = authorIdentity();
867
+ // The journal is installed before the editor is enabled, and whether or not this tab
868
+ // can reach the room: a refused offer, a lost room and an oversize update all leave
869
+ // the work in a document that a crash must still be able to recover.
870
+ const journal = await openJournal(meta, store);
871
+ if (!isCurrent(inst)) return { ok: false, cancelled: true };
765
872
  binding = code.createYPageBinding({
766
873
  store,
767
874
  onStopped: (reason) => {
@@ -777,6 +884,7 @@ function mergeRepresentedPage(store, value) {
777
884
  ownedTokens: identity.owned,
778
885
  checkpointWithin,
779
886
  requestCheckpoint,
887
+ journal,
780
888
  registerUnsavedState: (def) => {
781
889
  registered = registerUnsavedState({
782
890
  id: def.id,
@@ -787,6 +895,7 @@ function mergeRepresentedPage(store, value) {
787
895
  },
788
896
  });
789
897
  inst.binding = binding;
898
+ if (journal) installCheckpointProof(inst);
790
899
  inst.flush = (options) => trackFlush(() => binding.flush(options));
791
900
  listenForSaves(inst);
792
901
  return { ok: true, store, handle };
@@ -851,6 +960,7 @@ function mountAndAttach(inst, source, loaded) {
851
960
  features,
852
961
  onAiTool: aiRequested() ? (_view, remove) => { openAi({ remove }); } : null,
853
962
  reviseTool: aiRequested() ? (toolId, rev) => { openAi({ target: { toolId, rev } }); } : null,
963
+ formatGate: inst.loadFormatGate,
854
964
  });
855
965
  } catch (error) {
856
966
  console.error("clayjs: page plugin could not mount the editor", error);
@@ -999,7 +1109,10 @@ function mountAndAttach(inst, source, loaded) {
999
1109
  inst.adoption = adoption;
1000
1110
 
1001
1111
  let outcome = await adoption.idle();
1002
- if (!outcome) return { ok: true, outcome: "unchanged" };
1112
+ if (!outcome) {
1113
+ await replayJournal(inst);
1114
+ return { ok: true, outcome: "unchanged" };
1115
+ }
1003
1116
  // Another tab is the room's writer, so this tab's adoption is the one that tab
1004
1117
  // lands: the wait ends when it reaches this tab, or as the timeout a refusal is.
1005
1118
  if (outcome.outcome === "writer-adopts") outcome = await awaitWriterAdoption(inst, found);
@@ -1008,6 +1121,7 @@ function mountAndAttach(inst, source, loaded) {
1008
1121
  // comes back from what the room accepted. A disposed install restores nothing:
1009
1122
  // dispose already did.
1010
1123
  if (!outcome.ok && isCurrent(inst)) abandonEditor(inst);
1124
+ else if (isCurrent(inst)) await replayJournal(inst);
1011
1125
  return outcome;
1012
1126
  }
1013
1127
 
@@ -1123,7 +1237,7 @@ function begin(options = {}, { activate = true, context = null } = {}) {
1123
1237
  options.onPhase?.(result);
1124
1238
  },
1125
1239
  }),
1126
- article: null, view: null, binding: null, adoption: null, source: null, store: null, toolHost: null, aiTool: null, bootHtml: "", bootRev: null, savedRev: null, staged: null, pageStore: null, releaseArticle: null, replaced: false, savesHeld: false, flush: null, listeners: [], retryTimer: null, retryShown: false, statusTimer: null, statusNote: null, notices: null, editorReadyResolve: null, context, inputOpen: false, sessionHeld: false, autosaveSuspended: false, staleRetry: false,
1240
+ article: null, view: null, binding: null, adoption: null, source: null, store: null, toolHost: null, aiTool: null, bootHtml: "", bootRev: null, savedRev: null, staged: null, pageStore: null, releaseArticle: null, replaced: false, savesHeld: false, flush: null, loadFormatGate: null, listeners: [], retryTimer: null, retryShown: false, statusTimer: null, statusNote: null, notices: null, editorReadyResolve: null, context, inputOpen: false, sessionHeld: false, autosaveSuspended: false, staleRetry: false,
1127
1241
  };
1128
1242
  active = inst;
1129
1243
  const boot = run(inst, options, { activate }).catch((error) => {
@@ -1,5 +1,6 @@
1
1
  import { INTRO_CSS } from "./intro-style.js";
2
2
  import { announceBottomUi } from "./bottom-ui.js";
3
+ import { bootPhase } from "../../core/boot-phase.js";
3
4
 
4
5
  export const COPY = {
5
6
  close: "Hide this introduction",
@@ -45,7 +46,7 @@ export function mountIntro({ memory, template, appName, hadDraft }) {
45
46
  if (!template || !template.content.textContent.trim() && !template.content.querySelector("img, svg, video, canvas")) return null;
46
47
  if (!forced()) {
47
48
  if (memory.get().intro.done || hadDraft) return null;
48
- if (window.location.hash) return null;
49
+ if (bootPhase.servedHash) return null;
49
50
  if (window.matchMedia && window.matchMedia("print").matches) return null;
50
51
  }
51
52
  return mount({ memory, template, appName });
@@ -256,7 +256,7 @@ export function renderCheckpoint(currentHtml, capture, { createDocument, recover
256
256
  edits.push({ start: articleLoc.startTag.startOffset, end: articleLoc.startTag.endOffset, text: articleStart.slice(0, -1) + rev + '>' });
257
257
  edits.push({ start: articleLoc.startTag.endOffset, end: articleLoc.endTag.startOffset, text: rendered.html });
258
258
  if (!customTitleOf(placement.titleModes)) {
259
- const edit = titleEdit(placement, documentTitle(rendered.model));
259
+ const edit = titleEdit(placement, documentTitle(rendered.model, { currentTitle: titleTextOf(placement.title), keepWithoutHeading: true }));
260
260
  if (edit) edits.push(edit);
261
261
  }
262
262
  return { kind: 'ok', html: replace(currentHtml, edits), revision: rendered.rev };
@@ -271,7 +271,7 @@ export function isCheckpointCurrent(currentHtml, capture) {
271
271
  const articleLoc = placement.article.sourceCodeLocation;
272
272
  if (attr(placement.article, 'data-rev') !== rendered.rev ||
273
273
  currentHtml.slice(articleLoc.startTag.endOffset, articleLoc.endTag.startOffset) !== rendered.html) return false;
274
- if (!customTitleOf(placement.titleModes) && titleTextOf(placement.title) !== documentTitle(rendered.model)) return false;
274
+ if (!customTitleOf(placement.titleModes) && titleTextOf(placement.title) !== documentTitle(rendered.model, { currentTitle: titleTextOf(placement.title), keepWithoutHeading: true })) return false;
275
275
  return capture.stores.every((store) => {
276
276
  const node = placement.tags.get(store.name);
277
277
  const loc = node.sourceCodeLocation;
@@ -177,6 +177,10 @@ export function createSavedStream({ documentURL, servedEtag = null, represented
177
177
  let presenceStore = null;
178
178
  let presenceLease = null;
179
179
  let presenceLoad = null;
180
+ // The corner the roster is drawn in, downloaded beside the store on the same first
181
+ // frame. It is the chrome alone: the block marks an editor draws are edit-only and
182
+ // a reader never imports them.
183
+ let presenceRoster = null;
180
184
  const presenceQueue = [];
181
185
 
182
186
  const active = (gen) => !stopped && gen === generation;
@@ -188,29 +192,34 @@ export function createSavedStream({ documentURL, servedEtag = null, represented
188
192
 
189
193
  function leavePresence() {
190
194
  presenceQueue.length = 0;
195
+ // A roster a newer owner has taken over is that owner's to clear: giving this
196
+ // lease back must not remove the squares it is drawing.
197
+ if (presenceRoster && (!presenceLease || presenceLease.active)) presenceRoster.clear();
191
198
  if (presenceLease) {
192
199
  presenceLease.detach();
193
200
  presenceLease = null;
194
201
  }
195
202
  presenceStore = null;
203
+ presenceRoster = null;
196
204
  presenceLoad = null;
197
205
  }
198
206
 
199
207
  // A frame that lands while the download is in flight waits in order, and a
200
208
  // download that failed keeps the queue so the next frame asks again.
201
209
  function takePresence(data) {
202
- if (presenceStore) {
203
- presenceStore.receive(data);
210
+ if (presenceRoster) {
211
+ presenceRoster.update(data);
204
212
  return;
205
213
  }
206
214
  presenceQueue.push(data);
207
215
  if (presenceLoad) return;
208
- presenceLoad = import('./presence-store.js')
209
- .then(({ presence }) => {
210
- presenceStore = presence;
211
- presenceLease = presence.attachTransport({ send: () => Promise.resolve(false) });
212
- for (const frame of presenceQueue.splice(0)) presence.receive(frame);
213
- return presence;
216
+ presenceLoad = Promise.all([import('./presence-store.js'), import('./presence.js')])
217
+ .then(([storeMod, rosterMod]) => {
218
+ presenceStore = storeMod.presence;
219
+ presenceRoster = rosterMod.presence;
220
+ presenceLease = presenceStore.attachTransport({ send: () => Promise.resolve(false) });
221
+ for (const frame of presenceQueue.splice(0)) presenceRoster.update(frame);
222
+ return presenceRoster;
214
223
  })
215
224
  .catch(() => {
216
225
  presenceLoad = null;
@@ -1 +0,0 @@
1
- import{a as r}from"../c-HT33EQRN.js";import"../c-IJUK2GPW.js";import{a as o,b as i,c as u,d as s}from"../c-S7LK4KUE.js";import"../c-GHBCCVG4.js";import"../c-HA6INT6J.js";import"../c-DCFSEJZG.js";import"../c-WRBKEJD4.js";import"../c-VHNSBD2M.js";function m(e){if(e.parentNode){r.pause();try{e.remove()}finally{r.resume()}}}function p(e){let a=o(e);if(!a||s(e))return;let t=new URL(e.getAttribute(a),location.href);t.searchParams.set("v",Date.now());let f=t.origin===location.origin?t.pathname+t.search:t.href;r.pause();try{let n=document.createElement(e.tagName);for(let{name:d,value:l}of e.attributes)n.setAttribute(d,l);i(n,a,f),u(e),e.insertAdjacentElement("afterend",n),n.onload=()=>m(e),setTimeout(()=>m(e),2e3)}finally{r.resume()}}function c(){document.addEventListener("clay:save-saved",()=>{document.querySelectorAll("[refetch-on-save]").forEach(p)})}c();var g=c;export{g as default};
@@ -1 +0,0 @@
1
- import{a}from"../c-LTGMXXKO.js";import"../c-QIX5BJYN.js";import"../c-HT33EQRN.js";import"../c-IJUK2GPW.js";import"../c-35NBGMZB.js";import"../c-XQXZAO7N.js";import"../c-S7LK4KUE.js";import"../c-GHBCCVG4.js";import"../c-HA6INT6J.js";import"../c-DCFSEJZG.js";import"../c-WRBKEJD4.js";import"../c-VHNSBD2M.js";export{a as default};
@@ -1 +0,0 @@
1
- import{a as I}from"./c-XQXZAO7N.js";import{e as L}from"./c-S7LK4KUE.js";import{d as D}from"./c-GHBCCVG4.js";import{b as q,i as N,o as H}from"./c-HA6INT6J.js";import{c as F,h as A,j as T,k as E,n as S,o as P}from"./c-DCFSEJZG.js";var z=[],f=[],Y=new WeakMap,R=null,g=0;function te(){return g}function U(e){return Y.get(e)||null}var _=new WeakMap,h=null;function re(){return h}function ne(e){h&&e&&(h.artifact=e)}function ce(e){return e&&_.get(e)||null}function se(e){e&&_.delete(e)}function V(e){let o=t=>{if(t.hasAttribute("onbeforesave")||t.hasAttribute("onbeforesnapshot"))return!0;let n=t.localName==="template"&&t.content?t.content:t;for(let i of n.children)if(o(i))return!0;return!1};return e.nodeType===1?o(e):!1}function s(e){for(let o of e.querySelectorAll(P))o.remove()}function d(e,o){for(let t of e.querySelectorAll(`[${o}]`))if(s(e),!(t!==e&&!e.contains(t)))try{new Function(t.getAttribute(o)).call(t)}catch(n){console.error(`[${o}] handler failed:`,n)}}var b=null;function le(e){b=e}function ie(e){return b?.(e),e}function ae(e){z.push(e)}function ue(e){R=e}var j="http://www.w3.org/1999/xhtml";function $(e){let o=[],t=r=>{for(let c of r.childNodes)if(c.nodeType===1){if(c.localName==="noscript"&&c.namespaceURI===j){let a=Array.from(c.childNodes);a.length&&a.every(m=>m.nodeType===3)&&o.push([c,a]);continue}t(c.localName==="template"&&c.content?c.content:c)}};if(t(e),!o.length)return"<!DOCTYPE html>"+e.outerHTML;let n=Math.random().toString(36).slice(2),i=o.map(([r,c],a)=>{let m=`\uE000clay-noscript-${n}-${a}\uE000`;return r.replaceChildren(r.ownerDocument.createTextNode(m)),[m,c.map(C=>C.data).join("")]}),l;try{l="<!DOCTYPE html>"+e.outerHTML}finally{for(let[r,c]of o)r.replaceChildren(...c)}for(let[r,c]of i)l=l.split(r).join(c);return l}function w(e,o=null){let t=$(e);if(!R)return t;let n=h;h=o;try{return R(e,t)}catch(i){return console.error("clayjs: save renderer failed, sending the full serialization",i),t}finally{h=n}}function fe(e){f.push(e)}function y(e,o=!0){let t=window.__preventOnclone;window.__preventOnclone=!0;try{return e.cloneNode(o)}finally{window.__preventOnclone=t}}function p({flushUndo:e=!0,authored:o=!0,forSave:t=!1,requestRefresh:n=!1,context:i=null}={}){e&&typeof window<"u"&&window.clay?.undo?.flush&&window.clay.undo.flush();let r=I(document.documentElement,{capability:"snapshot",provenance:Y}).root;for(let c of z)s(r),c(r,{original:U,forSave:t,requestRefresh:n});return L(r),b?.(r),s(r),i&&(i.authoredHandlers=V(r)),o&&d(r,"onbeforesnapshot"),s(r),F(r),H(r),q(r),r}function x(e,{authored:o=!0}={}){s(e),o&&d(e,"onbeforesave");for(let t of f)s(e),t(e);s(e);for(let t of e.querySelectorAll(A))t.remove();return k(e),e}function k(e){for(let o of e.querySelectorAll("[sap-error]"))o.removeAttribute("sap-error")}function B({flushUndo:e=!0,authored:o=!0}={}){return x(p({flushUndo:e,authored:o}),{authored:o})}var K=["style","class"];function v(e){D(e);for(let o of K){e.getAttribute(o)===""&&e.removeAttribute(o);for(let t of e.querySelectorAll(`[${o}=""]`))t.removeAttribute(o)}return"<!DOCTYPE html>"+e.outerHTML}function pe({flushUndo:e=!0}={}){let o=p({flushUndo:e});d(o,"onbeforesave");for(let t of o.querySelectorAll(T))t.remove();for(let t of f)s(o),t(o);return s(o),v(o)}function de({flushUndo:e=!0}={}){let o=p({flushUndo:e});d(o,"onbeforesave");for(let t of o.querySelectorAll(S))t.remove();for(let t of f)s(o),t(o);return s(o),v(o)}function me({flushUndo:e=!0}={}){let o=p({flushUndo:e});d(o,"onbeforesave");let t=o.querySelector(E)?y(o):null;for(let l of o.querySelectorAll(T))l.remove();for(let l of f)s(o),l(o);s(o);let n=v(o),i=n;if(t){for(let l of t.querySelectorAll(S))l.remove();for(let l of f)s(t),l(t);s(t),i=v(t)}return{forComparison:n,forDirty:i}}function he({emitForSync:e=!0,flushUndo:o=!0,requestRefresh:t=!1,forRequest:n=!1}={}){if(!Number.isSafeInteger(g+1))throw new Error("Save capture identity exhausted");let i=++g,l=n?{captureId:i,authoredHandlers:!1,artifact:null}:null,r=p({flushUndo:o,forSave:e,requestRefresh:t,context:l});e&&document.dispatchEvent(new CustomEvent("clay:snapshot-ready",{detail:{documentElement:r,forSave:!0,captureId:i}})),d(r,"onbeforesave");let c=y(r),a=r.querySelector(E)?y(r):null;for(let u of f)s(r),u(r);s(r);for(let u of r.querySelectorAll(A))u.remove();k(r);let m=w(r,l);for(let u of c.querySelectorAll(T))u.remove();for(let u of f)s(c),u(c);s(c);let C=v(c),O=C;if(a){for(let u of a.querySelectorAll(S))u.remove();for(let u of f)s(a),u(a);s(a),O=v(a)}let M={forSave:m,forComparison:C,forDirty:O,captureId:i};return l&&l.artifact&&_.set(M,l.artifact),M}function ye(){let e=p({flushUndo:!1});d(e,"onbeforesave");let o=y(e),t=new WeakMap;(function n(i,l){t.set(i,l);let r=i.children,c=l.children;for(let a=0;a<r.length;a++)n(r[a],c[a])})(o,e);for(let n of f)s(e),n(e);s(e);for(let n of e.querySelectorAll(A))n.remove();k(e);for(let n of o.querySelectorAll(S))n.remove();for(let n of f)s(o),n(o);return s(o),{saveClone:e,compareClone:o,pairMap:t}}function W({emitForSync:e=!0}={}){let o=p();return e&&document.dispatchEvent(new CustomEvent("clay:snapshot-ready",{detail:{documentElement:o}})),w(x(o))}function ve(e){let o=y(e,!1);for(let i of N)o.removeAttribute(i);let t=o.outerHTML,n=`</${o.localName}>`;return"<!DOCTYPE html>"+t.slice(0,t.length-n.length)+e.innerHTML+n}function Se(){return p().querySelector("body").innerHTML}function Ce({transform:e=null,flushUndo:o=!0}={}){if(!e&&o)return W({emitForSync:!1});let t=p({flushUndo:o});if(e){let n=e(t);if(n&&typeof n.then=="function")throw new TypeError("getHTML: the transform must be synchronous")}return w(x(t))}function Ae(e,{prepared:o=!1}={}){let t=y(e);return $(o?t:x(t,{authored:!1}))}function Te(){return w(B({flushUndo:!1,authored:!1}))}export{te as a,U as b,re as c,ne as d,ce as e,se as f,le as g,ie as h,ae as i,ue as j,fe as k,p as l,B as m,pe as n,de as o,me as p,he as q,ye as r,W as s,ve as t,Se as u,Ce as v,Ae as w,Te as x};
@@ -1 +0,0 @@
1
- import{d as i}from"./c-AYVOREBE.js";import{a as r,i as l}from"./c-7O6AFR65.js";var e=r,a=r,s=!1,n=0;function k(){return e}function w(){return s}function p(t){e=typeof t=="string"&&t!==""?t:null,n++,a=e}function L(){return a}function g(){a=null}function m(){p(null)}function c(t){typeof t.spec=="number"&&(s=t.extensions.includes("conditional"))}async function b(){return c(await i()),s}async function y({fresh:t=!1,clearIfMissing:d=t}={}){let f=n,u=await i({fresh:t});if(c(u),n!==f||r&&!(t&&d))return e;let o=u.document?.etag;return typeof o=="string"&&o!==""?(e=o,n++):d&&(e=null,n++),e}document.addEventListener("clay:sync-applied",t=>{t.detail?.source==="disk"&&(typeof t.detail.etag=="string"&&t.detail.etag||g())});document.addEventListener("clay:sync-applied",t=>{l&&t.detail?.source==="disk"&&(typeof t.detail.etag=="string"&&t.detail.etag||(m(),y({fresh:!0})))});export{k as a,w as b,p as c,L as d,g as e,m as f,b as g,y as h};
@@ -1 +0,0 @@
1
- import{d as A,e as I}from"./c-AYVOREBE.js";import{b as M,i as b,m as T}from"./c-7O6AFR65.js";var B=15e3,P=12e4,K=15e3,V=4e3,W=5e3,U=50,y=new Set(["sent","acked"]),R=new Set(["done","error","cancelled"]),j="wire",i=new Map,k=new Set,f=null,g=null,D=0,h=null;function Q(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`page-${Date.now()}-${Math.random().toString(16).slice(2)}`}function H(e){return new URL(e,window.location.origin).href}function N(){let e=M();return typeof e=="string"&&e!==""?e:null}function w(e){return{id:e.id,type:e.type,state:e.state,helper:e.helper,text:e.text,result:e.result,error:e.error,errorCode:e.errorCode,errorDetails:e.errorDetails,errorSource:e.errorSource,startedAt:e.startedAt}}function m(e,t){let n=w(e);for(let r of k)try{r(n,t||null)}catch(s){console.error("clay.wire: a listener threw",s)}document.dispatchEvent(new CustomEvent("clay:wire-state",{detail:n}))}function Y(e,t){e.state!==t&&(e.state=t,m(e))}function v(e,t,n,{cancelFirst:r=!1,errorCode:s=null}={}){clearTimeout(e.timer),e.timer=setTimeout(()=>{e.timer=null,r&&z(e),l(e,"error",n,{errorCode:s,errorSource:"client"})},t)}function q(e){clearTimeout(e.timer),e.timer=null}function Z(){if(!(i.size<=U))for(let[e,t]of i){if(i.size<=U)break;!y.has(t.state)&&t.state!=="landing"&&i.delete(e)}}function ee(){if(g)return g;let e=N(),t=`/_/wire/subscribe?page-url=${encodeURIComponent(window.location.href)}`+(e?`&token=${encodeURIComponent(e)}`:"");return f=new EventSource(H(t)),f.onmessage=n=>{let r;try{r=JSON.parse(n.data)}catch{return}te(r)},f.onerror=()=>{},g=new Promise(n=>{let r=!1,s=()=>{r||(r=!0,n())};f.onopen=s,setTimeout(s,2e3)}),g}function L(){for(let e of i.values())if(y.has(e.state))return;f&&(f.close(),f=null,g=null)}function te(e){if(!e||typeof e.id!="string")return;let t=i.get(e.id);if(!(!t||!y.has(t.state)))switch(e.type){case"wire/ack":e.payload?.mode==="jsonl"&&Number.isFinite(e.payload.budgetMs)&&e.payload.budgetMs>0?(t.structured=!0,v(t,e.payload.budgetMs+K,"the helper did not finish within its execution budget",{cancelFirst:!0,errorCode:"helper_timeout"})):v(t,P,"the agent stopped responding"),Y(t,"acked");break;case"wire/status":t.structured||v(t,P,"the agent stopped responding"),t.text=typeof e.text=="string"?e.text:"",t.state="acked",ne(t,e),m(t,e);break;case"wire/done":t.result=Object.prototype.hasOwnProperty.call(e,"payload")?e.payload:null,t.document==="edit"?ae(t):l(t,"done",null);break;case"wire/error":re(t,e);break;default:break}}function ne(e,t){if(!e.onStatus||typeof t.text!="string")return;let n={text:t.text};t.payload&&typeof t.payload=="object"&&Object.prototype.hasOwnProperty.call(t.payload,"progress")&&(n.progress=t.payload.progress);try{e.onStatus(n)}catch(r){console.error("clay.wire: an onStatus listener threw",r)}}function re(e,t){let n=t.payload,r=n&&typeof n=="object"&&!Array.isArray(n)&&(n.source==="application"||n.source==="host")&&typeof n.code=="string"&&n.code,s=typeof t.text=="string"&&t.text?t.text:"the handler reported an error";if(!r){l(e,"error",s);return}let a=n.source==="host"&&n.code==="helper_cancelled"?"cancelled":"error";l(e,a,s,{errorCode:n.code,errorDetails:Object.prototype.hasOwnProperty.call(n,"details")?n.details:null,errorSource:n.source})}function oe(){h||(h=e=>{if(e.detail?.source!=="peer"){for(let t of i.values())if(t.state==="landing"){l(t,"done",null);return}}},document.addEventListener("clay:sync-applied",h))}function se(){D>0||!h||(document.removeEventListener("clay:sync-applied",h),h=null)}function ae(e){R.has(e.state)||e.state==="landing"||(q(e),e.state="landing",D++,oe(),e.landingTimer=setTimeout(()=>{l(e,"done",null)},V),m(e),L())}function l(e,t,n,r={}){if(R.has(e.state))return;let s=e.state==="landing";if(q(e),clearTimeout(e.landingTimer),e.landingTimer=null,e.abort?.abort(),s&&(D--,se()),e.error=n,Object.prototype.hasOwnProperty.call(r,"errorCode")&&(e.errorCode=r.errorCode),Object.prototype.hasOwnProperty.call(r,"errorDetails")&&(e.errorDetails=r.errorDetails),Object.prototype.hasOwnProperty.call(r,"errorSource")&&(e.errorSource=r.errorSource),e.state=t,e.signal&&e.signalHandler&&(e.signal.removeEventListener("abort",e.signalHandler),e.signalHandler=null),ue(e),m(e),L(),Z(),e.settle){let a=e.settle;e.settle=null,a(w(e))}}var C=0,$=null,E=null;function ie(){return E||(E=import("./core/save-WUCHTQBE.js")),E}async function le(e){if(!b||e.holdsSave)return;let t=await ie();e.state==="sent"&&($=t,e.holdsSave=!0,!(C++>0)&&t.suspendAutosave())}function ue(e){e.holdsSave&&(e.holdsSave=!1,!(--C>0)&&(C=0,$?.resumeAutosave()))}var c=null,de=()=>!c||c.admitted,ce=(e,t,n)=>Object.assign(new Error(`clay.wire: ${e}`),{code:t,pending:n});function O(e){return e.document!=="edit"||e.generation===T().generation&&de()?!0:(l(e,"error","the page changed mode before this request went out",{errorCode:"stale-document",errorSource:"client"}),!1)}function _e(){return{id:"clay:wire",order:900,prepare(e={}){let t={admitted:e.initial===!0};return c=t,{enable(){c===t&&(t.admitted=!0)},quiesce(){if(c!==t)return;t.admitted=!1;let n=[...i.values()].filter(r=>r.document==="edit"&&(r.holdsSave||y.has(r.state))).map(r=>r.id);if(n.length)throw ce("a request on this page has not settled","pending-input",n)},resume(){c===t&&(t.admitted=!0)},dispose(){c===t&&(c=null)}}}}}function fe(e,t){return new Promise(n=>{let r=!1,s=()=>{r||(r=!0,document.removeEventListener(e,s),n())};document.addEventListener(e,s),setTimeout(s,t)})}async function pe(){if(!b)return;let e=window.clay;if(!e||typeof e.save!="function")return;let{isSaveInProgress:t}=await import("./core/save-core-FJVHT5M3.js"),{savesHeld:n,saveHoldReason:r}=await import("./core/save-WUCHTQBE.js");if(n())throw new Error(r());let s=Date.now()+W;for(let a=0;a<3;a++){t()&&await fe("clay:save-saved",Math.max(0,s-Date.now()));let u=await e.save();if(u?.ok||u?.msgType==="skipped"&&!t())return;if(u?.msgType==="error"||u?.msgType==="unknown")throw new Error(`could not save this page first: ${u.msg||u.msgType}`);if(Date.now()>=s)break}throw new Error("could not save this page before sending")}async function F(e,t){let n={"Content-Type":"application/json","Page-URL":window.location.href},r=N();r&&(n["Save-Token"]=r);let s=await fetch(H("/_/wire/send"),{method:"POST",headers:n,body:JSON.stringify(e),signal:t}),a=null;try{a=await s.json()}catch{a=null}return{ok:s.ok,status:s.status,reply:a}}function he(e,t={}){let n=typeof t.id=="string"&&t.id?t.id:Q(),r=typeof t.type=="string"&&t.type?t.type:"wire/request",s=Object.prototype.hasOwnProperty.call(t,"helper"),a=s&&typeof t.helper=="string"&&t.helper?t.helper:null,u=t.document===void 0?a?"none":"edit":t.document;if(s&&!a)return _(n,r,null,"helper must be a nonempty string","invalid_helper");if(u!=="edit"&&u!=="none")return _(n,r,a,'document must be "edit" or "none"',"invalid_document");if(i.has(n))return _(n,r,a,"a request with this id is already on the wire","duplicate_request");let o={id:n,type:r,state:"sent",helper:a,document:u,structured:!1,onStatus:typeof t.onStatus=="function"?t.onStatus:null,text:"",result:null,error:null,errorCode:null,errorDetails:null,errorSource:null,startedAt:Date.now(),timer:null,landingTimer:null,abort:typeof AbortController=="function"?new AbortController:null,holdsSave:!1,generation:T().generation,settle:null,signal:t.signal&&typeof t.signal.addEventListener=="function"?t.signal:null,signalHandler:null};return o.done=new Promise(d=>{o.settle=d}),i.set(n,o),m(o),o.signal&&(o.signalHandler=()=>x(n),o.signal.addEventListener("abort",o.signalHandler,{once:!0}),o.signal.aborted&&o.signalHandler()),(async()=>{if(o.state!=="sent")return;if(o.helper){let X=await I(j);if(o.state!=="sent")return;if(!X){l(o,"error","this host does not support named wire helpers",{errorCode:"helper_protocol_unsupported",errorSource:"client"});return}}if(!O(o)||o.document==="edit"&&(await le(o),o.state!=="sent"||!O(o)||(await pe(),o.state!=="sent")||!O(o)))return;if(await ee(),o.state!=="sent"){L();return}v(o,B,"the agent never answered",o.helper?{cancelFirst:!0,errorCode:"ack_timeout"}:void 0);let d={type:o.type,id:o.id,text:t.text,payload:e};o.helper&&(d.helper=o.helper),(o.helper||t.document!==void 0)&&(d.document=o.document);let{ok:G,status:J,reply:S}=await F(d,o.abort?.signal);if(o.state!=="sent")return;if(!G){l(o,"error",`the wire refused this request (${J})`);return}let p=S&&S.refused;if(p&&typeof p.code=="string"&&p.code){l(o,"error",p.message||"the handler refused this request",{errorCode:p.code,errorSource:p.source==="application"?"application":"host",errorDetails:null});return}(!S||S.delivered===0)&&l(o,"error","no agent is attached to this file")})().catch(d=>{l(o,"error",d&&d.message?d.message:String(d))}),{id:n,get state(){return o.state},done:o.done,cancel:()=>x(n)}}function _(e,t,n,r,s){let a={id:e,type:t,state:"error",helper:n,text:"",result:null,error:r,errorCode:s,errorDetails:null,errorSource:"client",startedAt:Date.now()};return{id:e,get state(){return a.state},done:Promise.resolve(w(a)),cancel:()=>!1}}function x(e){let t=i.get(e);return!t||!y.has(t.state)?!1:(z(t),l(t,"cancelled",null),!0)}function z(e){F({type:"wire/cancel",id:e.id}).catch(()=>{})}function ye(e){let t=i.get(e);return t?w(t):void 0}function ge(){return[...i.values()].map(w)}function we(){for(let e of i.values())if(y.has(e.state))return!0;return!1}function me(e){return typeof e!="function"?()=>{}:(k.add(e),()=>k.delete(e))}async function Se(){let e=await A({fresh:!0});if(!e.extensions.includes(j))return[];let t=e.document?.helpers;return Array.isArray(t)?t.filter(n=>n&&typeof n.name=="string"&&["ready","denied","unavailable"].includes(n.state)).map(({name:n,state:r})=>({name:n,state:r})):[]}var ve={send:he,cancel:x,get:ye,list:ge,isBusy:we,on:me,helpers:Se},ke=ve;export{_e as a,ve as b,ke as c};
@@ -1 +0,0 @@
1
- import{b as u}from"./c-PZ4XEPUP.js";import{w as p,x as i}from"./c-35NBGMZB.js";function y(e=new Date){let o=n=>String(n).padStart(2,"0");return`${e.getFullYear()}${o(e.getMonth()+1)}${o(e.getDate())}-${o(e.getHours())}${o(e.getMinutes())}${o(e.getSeconds())}`}function m(e=location.pathname){let o=e.split("/").filter(Boolean).pop();if(!o)return e.endsWith("/")||e===""?"index":"page";let n=o;try{n=decodeURIComponent(o)}catch{}return n.replace(/\.(html?|htmlclay)$/i,"")||"page"}function f(e,o){let t=`<script type="application/json" id="clay-lost-edits" clay="no-save">${JSON.stringify(o).replace(/</g,"\\u003c")}<\/script>`,a=e.lastIndexOf("</body>");return a>=0?e.slice(0,a)+t+e.slice(a):e+t}function O(e,{refused:o=!1}={}){let n=window.clay?.conflicts||null,t=[],a=new Set;for(let r of e){let l=n?.recoveryOf(r.id);l&&!a.has(l.id)&&(a.add(l.id),t.push(l))}t.sort((r,l)=>(r.ticket||0)-(l.ticket||0));let d=r=>p(r.recoveryRoot??r.root,{prepared:r.domain==="save"}),c,s;o||!t.length?(c=i(),s=t):(c=d(t[t.length-1]),s=t.slice(0,-1));let g=e.map(r=>{if(r.kind==="apply-incomplete")return{id:r.id,kind:"apply-incomplete",name:"Sync update that did not finish",error:r.error??null};let{id:l,name:w,kind:b,yours:$,now:R,sentence:S}=u(r);return{id:l,name:w,kind:b,yours:$,now:R,sentence:S}}),v={format:"clay-lost-edits",version:1,savedAt:new Date().toISOString(),page:location.href,refused:!!o,edits:g,earlierPages:s.map(r=>({applyId:r.id,source:r.source,html:d(r)}))};return{html:f(c,v),name:`${m()}-${o?"my-version":"my-copy"}-${y()}.html`}}function h({html:e,name:o}){let n=null;try{n=URL.createObjectURL(new Blob([e],{type:"text/html"}));let t=document.createElement("a");return t.setAttribute("clay","no-save no-watch no-snapshot"),t.href=n,t.download=o,t.style.setProperty("display","none","important"),document.body.appendChild(t),t.click(),t.remove(),setTimeout(()=>URL.revokeObjectURL(n),4e4),!0}catch(t){return console.error("clayjs: could not build the download",t),n&&URL.revokeObjectURL(n),!1}}function x({html:e=null,edits:o=[]}={}){try{let n=typeof e=="string"?e:i(),t={format:"clay-lost-edits",version:1,savedAt:new Date().toISOString(),page:location.href,refused:!1,edits:Array.isArray(o)?o:[],earlierPages:[]};return h({html:f(n,t),name:`${m()}-my-copy-${y()}.html`})}catch(n){return console.error("clayjs: could not build the download",n),!1}}function U(e,{refused:o=!1}={}){try{let{html:n,name:t}=O(e,{refused:o});return h({html:n,name:t})}catch(n){return console.error("clayjs: could not build the download",n),!1}}export{m as a,h as b,x as c,U as d};