@panphora/clayjs 1.23.0 → 1.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/all.js +1 -1
- package/dist/blockeditor/themes/light-1.css +431 -0
- package/dist/clay-dom.js +1 -1
- package/dist/clay-events.js +1 -1
- package/dist/clay-internals.js +1 -1
- package/dist/clay-options.js +1 -1
- package/dist/clay-router.js +1 -1
- package/dist/clay-ui.js +1 -1
- package/dist/clay-utils.js +1 -1
- package/dist/clay.js +1 -1
- package/dist/clay.standalone.js +30285 -26613
- package/dist/m/c-277QP5ET.js +1 -0
- package/dist/m/c-2BLVA6IN.js +5 -0
- package/dist/m/c-2OJMOUPC.js +1 -0
- package/dist/m/c-2PVGJFI5.js +1 -0
- package/dist/m/{c-AYVGD6A6.js → c-3UW5EJ77.js} +1 -1
- package/dist/m/{c-T5NK2TVY.js → c-42ZNV7LI.js} +1 -1
- package/dist/m/{c-3TLG3OLG.js → c-46LJAZZJ.js} +1 -1
- package/dist/m/c-47IBJGPQ.js +1 -0
- package/dist/m/c-5FXEKU4Y.js +1 -0
- package/dist/m/c-5KXDKC5G.js +1 -0
- package/dist/m/{c-EUGJVHDD.js → c-5RZNFTWD.js} +1 -1
- package/dist/m/c-65LJU2H2.js +72 -0
- package/dist/m/{c-NQJRVJ56.js → c-6IJEVE6B.js} +1 -1
- package/dist/m/{c-NW54NHKE.js → c-6LEYVQJK.js} +1 -1
- package/dist/m/{c-GSRLXYWL.js → c-6Q6RGFBF.js} +1 -1
- package/dist/m/c-6RGEQNVV.js +1 -0
- package/dist/m/c-7CM4GMTS.js +6 -0
- package/dist/m/c-7NCWENHV.js +1 -0
- package/dist/m/c-7V6MGMX2.js +1 -0
- package/dist/m/{c-LKSL4AUJ.js → c-7WZSUTYP.js} +1 -1
- package/dist/m/c-A4L7APIU.js +1 -0
- package/dist/m/c-APGHGDZM.js +1 -0
- package/dist/m/c-AT7GLQGV.js +34 -0
- package/dist/m/{c-ZRXJD4G6.js → c-B7GOFGQR.js} +1 -1
- package/dist/m/{c-KDXIJEEF.js → c-BGN7RCTJ.js} +1 -1
- package/dist/m/c-BKM46LUJ.js +1 -0
- package/dist/m/c-BOMQIQ3V.js +1 -0
- package/dist/m/{c-62HZW5DH.js → c-C5AKJVRH.js} +1 -1
- package/dist/m/{c-BXYSDKAN.js → c-CJ7QYEWI.js} +1 -1
- package/dist/m/c-CTGRDT6E.js +1 -0
- package/dist/m/c-CV4T65JE.js +6 -0
- package/dist/m/c-CVSWLX3X.js +1 -0
- package/dist/m/c-CZHTXGJS.js +1 -0
- package/dist/m/c-D7NT5S4F.js +1 -0
- package/dist/m/c-DD26VXAP.js +1 -0
- package/dist/m/{c-ANNFZFLN.js → c-DDS23EY6.js} +1 -1
- package/dist/m/{c-ALDVFPWL.js → c-DFKBGSN2.js} +1 -1
- package/dist/m/c-DIKR7H57.js +147 -0
- package/dist/m/c-DXPOFLEJ.js +1 -0
- package/dist/m/c-EDE45NM7.js +1 -0
- package/dist/m/c-EILLN2H2.js +1 -0
- package/dist/m/c-EODTTNVA.js +1 -0
- package/dist/m/{c-G6COVIZB.js → c-ESK4S67I.js} +1 -1
- package/dist/m/c-FDWR3FL7.js +1 -0
- package/dist/m/{c-WQZTI5P2.js → c-FEC6LGFF.js} +1 -1
- package/dist/m/c-FLEIU6CG.js +1 -0
- package/dist/m/c-FQAQRXGK.js +1 -0
- package/dist/m/{c-W4JCVLAB.js → c-FSQXFG5T.js} +1 -1
- package/dist/m/c-FVPNX2GO.js +135 -0
- package/dist/m/c-FYDKYW6E.js +1 -0
- package/dist/m/c-GNI7WHKF.js +32 -0
- package/dist/m/c-GO635CRU.js +3 -0
- package/dist/m/c-H3FNLBHN.js +2 -0
- package/dist/m/c-HDVH3MVC.js +72 -0
- package/dist/m/c-HIX5H5L7.js +1 -0
- package/dist/m/c-HKSLOVU4.js +1 -0
- package/dist/m/{c-SGRIYOAJ.js → c-HL6BLJNA.js} +1 -1
- package/dist/m/c-HTLYXCUH.js +1 -0
- package/dist/m/{c-QIR5CAKM.js → c-IUL7PU4P.js} +1 -1
- package/dist/m/c-IXO7EI2Q.js +1 -0
- package/dist/m/{c-W5E5P2TZ.js → c-JQF2EUCG.js} +1 -1
- package/dist/m/{c-NEL7HQW3.js → c-JWDCQL6J.js} +1 -1
- package/dist/m/c-KQKKIVLW.js +20 -0
- package/dist/m/c-LATNQ6Q5.js +1 -0
- package/dist/m/c-LD6UVV5R.js +1 -0
- package/dist/m/c-LS7IVQVW.js +1 -0
- package/dist/m/{c-JCOQVZYS.js → c-LSVN3OLG.js} +1 -1
- package/dist/m/{c-JDZDF2QM.js → c-LTSPHVAK.js} +1 -1
- package/dist/m/c-MFOSMAVM.js +3 -0
- package/dist/m/c-MJ7GVE46.js +1 -0
- package/dist/m/c-MP6S4AZU.js +6 -0
- package/dist/m/c-MQKSKQHG.js +2 -0
- package/dist/m/{c-UHUNXWKN.js → c-MQYEDF3Q.js} +1 -1
- package/dist/m/{c-IHUWUKIU.js → c-MR75YPRT.js} +1 -1
- package/dist/m/c-ND3Q2G2I.js +1 -0
- package/dist/m/c-NEQRFC4O.js +1 -0
- package/dist/m/{c-5FKRZNJV.js → c-NFQFV7OP.js} +1 -1
- package/dist/m/c-NHXOBD6A.js +1 -0
- package/dist/m/{c-QIKT6SKM.js → c-NICICT4P.js} +1 -1
- package/dist/m/c-NQAPWM7O.js +1 -0
- package/dist/m/{c-QUGCKMWF.js → c-NVU3DORS.js} +1 -1
- package/dist/m/{c-LWIDDWAR.js → c-OCYG4NBQ.js} +22 -22
- package/dist/m/c-OH2FPYSY.js +19 -0
- package/dist/m/c-OYHI67B6.js +1 -0
- package/dist/m/{c-R2XUODVY.js → c-OYW5MFPZ.js} +1 -1
- package/dist/m/{c-5B4YBZXC.js → c-P2HKMJAW.js} +1 -1
- package/dist/m/{c-TSBVMWAH.js → c-PCNJETUA.js} +1 -1
- package/dist/m/c-PDBNCJCT.js +1 -0
- package/dist/m/c-PGSBXHUE.js +1 -0
- package/dist/m/{c-5TIZ2I64.js → c-PYG2NGWU.js} +1 -1
- package/dist/m/c-Q26XHBLQ.js +1 -0
- package/dist/m/c-Q6BG3ZLO.js +1 -0
- package/dist/m/c-QENKN7QI.js +1 -0
- package/dist/m/c-QQFHEODI.js +1 -0
- package/dist/m/c-QTEUO2K6.js +1 -0
- package/dist/m/c-R23UHMXG.js +1 -0
- package/dist/m/c-RETTCOWO.js +10 -0
- package/dist/m/c-SE3SIY7Y.js +7 -0
- package/dist/m/{c-XX75FFNL.js → c-SGGGCIVD.js} +1 -1
- package/dist/m/c-SGH3UTF3.js +1 -0
- package/dist/m/c-SIM7Z3U7.js +1 -0
- package/dist/m/{c-X5LNHET5.js → c-SKMIR5HQ.js} +1 -1
- package/dist/m/{c-R27DWQKX.js → c-STRI73GQ.js} +1 -1
- package/dist/m/c-SUXHUL7U.js +1 -0
- package/dist/m/c-SXGEWPFC.js +10 -0
- package/dist/m/c-SXNSSHPP.js +1 -0
- package/dist/m/c-T3P3AXEW.js +1 -0
- package/dist/m/{c-PXLTUYZC.js → c-TFLRT5JX.js} +1 -1
- package/dist/m/{c-YCLU4UNT.js → c-TGIMBAWE.js} +1 -1
- package/dist/m/c-TGSHHFO6.js +1 -0
- package/dist/m/c-U4NTUVDZ.js +1 -0
- package/dist/m/c-UOOIF2AL.js +1 -0
- package/dist/m/{c-6TYGD5AB.js → c-UOUUI265.js} +1 -1
- package/dist/m/c-V2U3F4QX.js +1 -0
- package/dist/m/c-V2V5FKXX.js +1 -0
- package/dist/m/c-VBXRXTVS.js +26 -0
- package/dist/m/c-VHSMPITY.js +1 -0
- package/dist/m/c-VPXCXBDT.js +1 -0
- package/dist/m/c-WCG6AKA7.js +1 -0
- package/dist/m/c-WNOLMHI2.js +1 -0
- package/dist/m/{c-CRPIDGXC.js → c-X6MOYATI.js} +1 -1
- package/dist/m/{c-FQGHR32O.js → c-X75G43SZ.js} +1 -1
- package/dist/m/c-XB6EAIAR.js +13 -0
- package/dist/m/c-XMIDHEKF.js +1 -0
- package/dist/m/c-XUZMRQ7O.js +4 -0
- package/dist/m/{c-2Z22FCFK.js → c-XW5TIYYB.js} +1 -1
- package/dist/m/c-YDW4VCHP.js +1 -0
- package/dist/m/{c-QGAPG7OM.js → c-YLHTD3KX.js} +1 -1
- package/dist/m/c-YNIEIPBS.js +1 -0
- package/dist/m/c-Z4G2UK6T.js +4 -0
- package/dist/m/c-Z6MROEQ4.js +1 -0
- package/dist/m/c-ZFO5RW6G.js +2 -0
- package/dist/m/c-ZGCO4J3H.js +8 -0
- package/dist/m/c-ZKKAF4UT.js +3 -0
- package/dist/m/c-ZRGEN6QQ.js +4 -0
- package/dist/m/core/{admin-attrs-U7IJNYBG.js → admin-attrs-ONRWVXPK.js} +1 -1
- package/dist/m/core/{autosave-F5YQCKVL.js → autosave-TBKAAAFB.js} +1 -1
- package/dist/m/core/conflict-notice-FOEE6I7E.js +1 -0
- package/dist/m/core/draft-mode-4MCL3LYI.js +1 -0
- package/dist/m/core/{host-permission-6EVJGNPL.js → host-permission-X4BENZEU.js} +1 -1
- package/dist/m/core/{is-edit-mode-GCX6767E.js → is-edit-mode-FFHCQ5DR.js} +1 -1
- package/dist/m/core/{persist-CJXIL7D4.js → persist-6ILUR34S.js} +1 -1
- package/dist/m/core/{recovery-DRFZRJED.js → recovery-APWADU4K.js} +1 -1
- package/dist/m/core/save-6HT2LABE.js +1 -0
- package/dist/m/core/save-core-EVMNZQ4V.js +1 -0
- package/dist/m/core/site-edits-G4BOZMV4.js +1 -0
- package/dist/m/core/{unsaved-warning-HNQVTA2D.js → unsaved-warning-ITZDIZ2I.js} +1 -1
- package/dist/m/internals/{index-NRPNDTSA.js → index-HS3CQDFW.js} +1 -1
- package/dist/m/loader-GLLVDUZA.js +1 -0
- package/dist/m/manifest-50FF1C45.js +1 -0
- package/dist/m/manifest-edit-BE1A621D.js +1 -0
- package/dist/m/manifest.json +2072 -1811
- package/dist/m/page/editor-KAZDJNND.js +307 -0
- package/dist/m/plugins/ai-edit-LABECCSN.js +6 -0
- package/dist/m/plugins/{cms-H7DTMUQX.js → cms-T2HLI7JG.js} +16 -16
- package/dist/m/plugins/{demo-42BSYQ7T.js → demo-T7B4RIKL.js} +1 -1
- package/dist/m/plugins/{derive-QVI3LI3A.js → derive-6LPJOCAV.js} +1 -1
- package/dist/m/plugins/indicator-J4ABFARX.js +1 -0
- package/dist/m/plugins/{live-DCUBKXY4.js → live-PGBIEMGB.js} +1 -1
- package/dist/m/plugins/menu-YZL3X2AJ.js +1 -0
- package/dist/m/plugins/page-WOCNX2IN.js +2 -0
- package/dist/m/plugins/page-view-SJODOOGE.js +1 -0
- package/dist/m/plugins/{people-5XRNRP5U.js → people-C4TCWFOQ.js} +1 -1
- package/dist/m/plugins/{quickcrop-WWF5I422.js → quickcrop-X5MRIBAP.js} +2 -2
- package/dist/m/plugins/richclay-Y2NV44NA.js +549 -0
- package/dist/m/plugins/sortable-XCHQG65Z.js +1 -0
- package/dist/m/plugins/{source-6BKMK4PO.js → source-YK7MO23W.js} +1 -1
- package/dist/m/plugins/{undo-3JEYK5QY.js → undo-VLRBQNPN.js} +1 -1
- package/dist/m/plugins/upgrade-NNTJBSK2.js +1 -0
- package/dist/m/plugins/{upload-TTCQRIM5.js → upload-ZKKJV76X.js} +1 -1
- package/dist/m/plugins/visitor-drafts-RTZNONHT.js +20 -0
- package/dist/m/plugins/{visitor-drafts-owner-Z5B2OQBR.js → visitor-drafts-owner-LHUHFU3L.js} +1 -1
- package/dist/m/plugins/{visitor-menu-4LQMKLPP.js → visitor-menu-FY4KM2SW.js} +1 -1
- package/dist/m/plugins/wire-M2NR354P.js +1 -0
- package/dist/m/{reader-core-POFQCKRV.js → reader-core-T2S3JC4E.js} +2 -2
- package/dist/m/sync/live-sync-Z64YREWQ.js +1 -0
- package/dist/m/ui/index-MGTWOW2C.js +1 -0
- package/dist/m/vendor/{sap-core.vendor-OA5SKL7Q.js → sap-core.vendor-QAEPMETX.js} +1 -1
- package/dist/offline-manifest.json +1250 -1082
- package/dist/server/core.cjs +132 -109
- package/dist/server/page-compaction-worker.cjs +5 -5
- package/dist/server/rooms.mjs +3 -1
- package/docs/guide.md +89 -44
- package/entries/clay-data.js +1 -1
- package/entries/sap.js +1 -1
- package/package.json +5 -3
- package/src/blockeditor/themes/content.css +70 -0
- package/src/blockeditor/themes/light-1.css +431 -0
- package/src/blockeditor/themes/light-1.source.css +270 -0
- package/src/blockeditor/themes/light-2.css +211 -0
- package/src/blockeditor/themes/light-3.css +130 -0
- package/src/blockeditor/themes/light-4.css +299 -0
- package/src/core/conflict-notice.js +28 -0
- package/src/core/draft-mode.js +6 -0
- package/src/core/host-meta.js +6 -6
- package/src/core/is-edit-mode.js +9 -3
- package/src/core/mode-support.js +3 -0
- package/src/core/mode-switch.js +4 -4
- package/src/core/mode-transition.js +3 -1
- package/src/core/page-format-wire.js +1 -1
- package/src/core/page-format.js +8 -8
- package/src/core/save-accepted.js +6 -7
- package/src/core/save-core.js +52 -23
- package/src/core/save-failure-notice.js +37 -0
- package/src/core/save-feedback.js +6 -0
- package/src/core/save-replace.js +1 -1
- package/src/core/save-size.js +2 -2
- package/src/core/save.js +78 -15
- package/src/core/site-edits.js +166 -0
- package/src/core/unsaved-warning.js +2 -2
- package/src/core/upgrade-run.js +4 -4
- package/src/lib/ai-comment.js +23 -0
- package/src/lib/effect.js +8 -0
- package/src/lib/idb-error-code.js +20 -0
- package/src/live/fast-lane.js +10 -10
- package/src/live/local-lane.js +10 -10
- package/src/live/page-compaction.js +8 -8
- package/src/live/server-lane.js +1 -1
- package/src/loader-logic.js +48 -18
- package/src/loader.js +11 -6
- package/src/page/adopt-boot.js +1 -1
- package/src/page/adopt.js +2 -2
- package/src/page/ai-area.js +182 -0
- package/src/page/ai-preview.js +80 -0
- package/src/page/ai-surface.js +257 -0
- package/src/page/ai-tool.js +308 -145
- package/src/page/announce.js +2 -2
- package/src/page/awareness.js +18 -18
- package/src/page/blocks.js +35 -34
- package/src/page/blocksel.js +2 -2
- package/src/page/board-drag.js +11 -11
- package/src/page/board-face.js +1 -1
- package/src/page/board-panel.js +26 -26
- package/src/page/board-style.js +127 -127
- package/src/page/board-view.js +48 -48
- package/src/page/chart.js +29 -29
- package/src/page/checkpoint-proof.js +19 -19
- package/src/page/chrome.js +74 -65
- package/src/page/clipboard-shape.js +1 -1
- package/src/page/csv-import.js +4 -4
- package/src/page/drag.js +5 -5
- package/src/page/editor.js +301 -296
- package/src/page/export-html.js +8 -8
- package/src/page/features/checklist.js +36 -36
- package/src/page/features/export-html.js +19 -19
- package/src/page/features/export-markdown.js +10 -10
- package/src/page/features/import-markdown.js +13 -13
- package/src/page/features/media.js +50 -50
- package/src/page/features/table.js +17 -17
- package/src/page/features/title-cover.js +17 -17
- package/src/page/features/title-icon.js +7 -7
- package/src/page/features/toc.js +1 -1
- package/src/page/features/tool.js +42 -18
- package/src/page/format-command.js +4 -4
- package/src/page/format-gate.js +6 -6
- package/src/page/format-host.js +6 -6
- package/src/page/format-level.js +3 -3
- package/src/page/format-native-commands.js +2 -2
- package/src/page/highlight-slot.js +1 -1
- package/src/page/highlight.js +4 -4
- package/src/page/history-intent.js +2 -2
- package/src/page/image-actions.js +4 -4
- package/src/page/link.js +10 -10
- package/src/page/media.js +3 -3
- package/src/page/mention-picker.js +7 -7
- package/src/page/merge.js +1 -1
- package/src/page/placeholder.js +3 -3
- package/src/page/projection.js +11 -11
- package/src/page/reader-patch.js +2 -2
- package/src/page/recover.js +26 -26
- package/src/page/recovery-ui.js +28 -28
- package/src/page/rich/chart.js +1 -1
- package/src/page/rich/page-tool.js +21 -6
- package/src/page/rich/tool-runtime.js +3 -2
- package/src/page/save-projection.js +2 -2
- package/src/page/save-states.js +9 -9
- package/src/page/schema.js +9 -9
- package/src/page/table-style.js +21 -21
- package/src/page/toc-link.js +1 -1
- package/src/page/tool-capability.js +8 -3
- package/src/page/tool-transport.js +52 -0
- package/src/page/tool-views.js +4 -0
- package/src/page/tools.js +6 -1
- package/src/page/view.js +6 -6
- package/src/page/ybind/binding.js +1 -1
- package/src/page/ybind/conversion.js +1 -1
- package/src/page/ybind/layout.js +4 -4
- package/src/page/ybind/migrate.js +1 -1
- package/src/page/ybind/origins.js +2 -2
- package/src/page/ybind/provider.js +2 -2
- package/src/page/ybind/recovery-proof.js +3 -3
- package/src/page/ybind/recovery-replay.js +2 -2
- package/src/plugins/ai-edit/picker.js +235 -0
- package/src/plugins/ai-edit.js +220 -34
- package/src/plugins/indicator-chip.js +39 -34
- package/src/plugins/indicator.js +13 -4
- package/src/plugins/live.js +21 -13
- package/src/plugins/menu/actions.js +89 -17
- package/src/plugins/menu/seo.js +32 -6
- package/src/plugins/menu/shell-style.js +26 -7
- package/src/plugins/menu/shell.js +12 -7
- package/src/plugins/menu/variants.js +6 -10
- package/src/plugins/menu/visitor.js +44 -34
- package/src/plugins/menu.js +3 -2
- package/src/plugins/page-view.js +2 -2
- package/src/plugins/page.js +257 -98
- package/src/plugins/sortable.js +7 -0
- package/src/plugins/upgrade.js +2 -1
- package/src/plugins/visitor-drafts/commit.js +303 -0
- package/src/plugins/visitor-drafts/idb.js +221 -0
- package/src/plugins/visitor-drafts/intro-style.js +1 -1
- package/src/plugins/visitor-drafts/intro.js +8 -25
- package/src/plugins/visitor-drafts/prompt.js +30 -4
- package/src/plugins/visitor-drafts/session.js +345 -0
- package/src/plugins/visitor-drafts/store.js +351 -32
- package/src/plugins/visitor-drafts.js +158 -27
- package/src/server/checkpoint/index.js +8 -8
- package/src/server/rooms/index.js +2 -2
- package/src/server/rooms/live-data-rooms.js +35 -35
- package/src/server/rooms/live-page-history.js +2 -2
- package/src/server/rooms/page-admission.js +34 -6
- package/src/server/rooms/page-conversion.js +1 -1
- package/src/server/rooms/page-lineage.js +4 -4
- package/src/server/rooms/page-rebase.js +4 -4
- package/src/server/rooms/page-room-conformance.js +14 -14
- package/src/server/rooms/page-state.js +2 -2
- package/src/server/rooms/page-write-admission.js +7 -7
- package/src/server/rooms/page-write-guard.js +3 -3
- package/src/sync/data-guard-notice.js +265 -0
- package/src/sync/live-sync.js +54 -11
- package/src/sync/page-relay.js +4 -4
- package/src/sync/presence-store.js +1 -1
- package/src/sync/presence-target.js +3 -3
- package/src/sync/presence.js +1 -1
- package/src/sync/stream.js +54 -13
- package/src/sync/wire-profile.js +8 -3
- package/src/ui/bevel.js +1 -1
- package/src/ui/index.js +9 -10
- package/src/ui/skins/cms.js +1 -1
- package/src/ui/skins/quickcrop.js +1 -1
- package/src/ui/skins/richclay.js +2 -2
- package/src/ui/toast-lazy.js +12 -3
- package/src/ui/toast.js +9 -3
- package/src/vendor/hyper-html-api-data.vendor.js +1 -1
- package/src/vendor/hyper-html-api-upgrade.vendor.js +2 -2
- package/src/vendor/hypercms.vendor.js +16 -16
- package/src/vendor/richclay.vendor.js +48 -20
- package/src/vendor/sap-core.vendor.js +1 -1
- package/tool-generation/context.md +44 -0
- package/tool-generation/system.md +23 -0
- package/dist/m/c-24PMUJIV.js +0 -2
- package/dist/m/c-2AYVYEI4.js +0 -1
- package/dist/m/c-2AZDZWCK.js +0 -1
- package/dist/m/c-2L6O5PDS.js +0 -6
- package/dist/m/c-2RYOGUQM.js +0 -2
- package/dist/m/c-2ZVOEU4M.js +0 -1
- package/dist/m/c-37NAONZA.js +0 -1
- package/dist/m/c-3GJ4SDE2.js +0 -1
- package/dist/m/c-3O7OBDCM.js +0 -1
- package/dist/m/c-5OJ7YF2N.js +0 -1
- package/dist/m/c-5WMXEKFH.js +0 -135
- package/dist/m/c-6RDOKLN7.js +0 -1
- package/dist/m/c-A4IP6MBC.js +0 -1
- package/dist/m/c-A6L3FMUS.js +0 -1
- package/dist/m/c-ATKAOH23.js +0 -1
- package/dist/m/c-B6O7AJYG.js +0 -32
- package/dist/m/c-BCGWJYXW.js +0 -1
- package/dist/m/c-BGKAT2FL.js +0 -7
- package/dist/m/c-BYTKL6UX.js +0 -1
- package/dist/m/c-DHBRA6DL.js +0 -1
- package/dist/m/c-DTMZ3ZHI.js +0 -1
- package/dist/m/c-E3ZXARWA.js +0 -1
- package/dist/m/c-EK63G3CG.js +0 -1
- package/dist/m/c-ELYIIYRS.js +0 -1
- package/dist/m/c-EXKHPOVC.js +0 -3
- package/dist/m/c-FCSZ3DC5.js +0 -20
- package/dist/m/c-FTWGYI5E.js +0 -1
- package/dist/m/c-G4PWUDD5.js +0 -1
- package/dist/m/c-GBKB5WDL.js +0 -2
- package/dist/m/c-GBTVCJXC.js +0 -1
- package/dist/m/c-GC2HICFJ.js +0 -1
- package/dist/m/c-GRWMD6O5.js +0 -1
- package/dist/m/c-HCNWJE4A.js +0 -4
- package/dist/m/c-HG2C77BM.js +0 -4
- package/dist/m/c-JGHEACGK.js +0 -1
- package/dist/m/c-JGLX6TBK.js +0 -1
- package/dist/m/c-JNRKHYWO.js +0 -1
- package/dist/m/c-KBS3UV6B.js +0 -1
- package/dist/m/c-KQ7E3PYY.js +0 -1
- package/dist/m/c-L3F5ZLIV.js +0 -1
- package/dist/m/c-L4KMT7FO.js +0 -6
- package/dist/m/c-L5VFATT6.js +0 -1
- package/dist/m/c-LCYPMULG.js +0 -1
- package/dist/m/c-LIGQYZ7M.js +0 -6
- package/dist/m/c-LKIWEPAV.js +0 -1
- package/dist/m/c-MPSKIU2I.js +0 -1
- package/dist/m/c-N7JPUPGC.js +0 -1
- package/dist/m/c-NK33MMYF.js +0 -1
- package/dist/m/c-NQLWOHLH.js +0 -10
- package/dist/m/c-NTHUTABN.js +0 -1
- package/dist/m/c-NWX3MFT4.js +0 -1
- package/dist/m/c-OKXI52N7.js +0 -1
- package/dist/m/c-OPONJ2UK.js +0 -128
- package/dist/m/c-OWQWOGYI.js +0 -1
- package/dist/m/c-P6Q2ZTFQ.js +0 -1
- package/dist/m/c-QEN6HZCA.js +0 -1
- package/dist/m/c-QIXT3Q7C.js +0 -28
- package/dist/m/c-QM5LXRDT.js +0 -9
- package/dist/m/c-QYYUVLVG.js +0 -1
- package/dist/m/c-RQRMPZXD.js +0 -1
- package/dist/m/c-SBCBXKOZ.js +0 -26
- package/dist/m/c-SKF5HL4I.js +0 -4
- package/dist/m/c-SRPC3VBE.js +0 -1
- package/dist/m/c-TANBH7FI.js +0 -1
- package/dist/m/c-THGQQDYY.js +0 -1
- package/dist/m/c-UD5JZTDL.js +0 -1
- package/dist/m/c-UDGEFWNU.js +0 -1
- package/dist/m/c-UGNV5MFB.js +0 -1
- package/dist/m/c-VIRFF5HG.js +0 -8
- package/dist/m/c-VJYEVRYK.js +0 -1
- package/dist/m/c-VQCEOGKH.js +0 -13
- package/dist/m/c-VYJ7O4RI.js +0 -34
- package/dist/m/c-W7IPVCAA.js +0 -1
- package/dist/m/c-WBGWGOM7.js +0 -1
- package/dist/m/c-WJ5DRBHT.js +0 -72
- package/dist/m/c-X5WC4PX5.js +0 -1
- package/dist/m/c-XCFQEWW6.js +0 -3
- package/dist/m/c-XGH4GS2T.js +0 -1
- package/dist/m/c-XLQ3BDMM.js +0 -1
- package/dist/m/c-ZQXNHZZT.js +0 -72
- package/dist/m/core/conflict-notice-42H4ASLA.js +0 -1
- package/dist/m/core/draft-mode-WSQAT67S.js +0 -1
- package/dist/m/core/save-ESPSQPLV.js +0 -1
- package/dist/m/core/save-core-6SQHOR6W.js +0 -1
- package/dist/m/loader-FBDE2UAB.js +0 -1
- package/dist/m/manifest-1D2F5CA5.js +0 -1
- package/dist/m/manifest-edit-F7CC5CFD.js +0 -1
- package/dist/m/page/editor-OSKOW6RS.js +0 -304
- package/dist/m/plugins/ai-edit-VV4QTINH.js +0 -6
- package/dist/m/plugins/indicator-WVPGMOZ7.js +0 -1
- package/dist/m/plugins/menu-Q4MFFQ6E.js +0 -1
- package/dist/m/plugins/page-OAWUJQEL.js +0 -2
- package/dist/m/plugins/page-view-DZ26ZDDQ.js +0 -1
- package/dist/m/plugins/richclay-PGOOJ4OK.js +0 -517
- package/dist/m/plugins/sortable-266HY6TR.js +0 -1
- package/dist/m/plugins/upgrade-BNZVFHMZ.js +0 -1
- package/dist/m/plugins/visitor-drafts-2AUYKAIJ.js +0 -20
- package/dist/m/plugins/wire-W2EV36KZ.js +0 -1
- package/dist/m/sync/live-sync-XGUPHI3I.js +0 -1
- package/dist/m/ui/index-VGYAKAKI.js +0 -1
- package/dist/page/themes/light-1.css +0 -431
- package/src/page/themes/content.css +0 -70
- package/src/page/themes/light-1.css +0 -431
- package/src/page/themes/light-1.source.css +0 -270
- package/src/page/themes/light-2.css +0 -211
- package/src/page/themes/light-3.css +0 -130
- package/src/page/themes/light-4.css +0 -299
- /package/dist/m/{c-FILLTJA7.js → c-QTTJYJMA.js} +0 -0
- /package/dist/m/plugins/{quickcrop-WWF5I422.js.LEGAL.txt → quickcrop-X5MRIBAP.js.LEGAL.txt} +0 -0
- /package/dist/m/plugins/{richclay-PGOOJ4OK.js.LEGAL.txt → richclay-Y2NV44NA.js.LEGAL.txt} +0 -0
package/src/page/recovery-ui.js
CHANGED
|
@@ -29,26 +29,26 @@ import {
|
|
|
29
29
|
export const REVIEW_TEXT = "Work from an earlier session could not be put back. Read it, download it, or recover it as a copy.";
|
|
30
30
|
|
|
31
31
|
// The control and its panel sit in one shadow root inside the page shell, so the page's
|
|
32
|
-
// CSS cannot restyle them. The page's --
|
|
32
|
+
// CSS cannot restyle them. The page's --blockeditor-* tokens still reach them, and they keep
|
|
33
33
|
// the page's font and colour.
|
|
34
34
|
const STYLES = `
|
|
35
35
|
:host { font: inherit !important; color: inherit !important; }
|
|
36
|
-
.
|
|
37
|
-
.
|
|
38
|
-
.
|
|
39
|
-
.
|
|
40
|
-
.
|
|
41
|
-
.
|
|
42
|
-
.
|
|
43
|
-
.
|
|
44
|
-
.
|
|
45
|
-
.
|
|
46
|
-
.
|
|
47
|
-
.
|
|
36
|
+
.blockeditor-recovery-root { display: contents; }
|
|
37
|
+
.blockeditor-recovery { position: fixed; right: 16px; bottom: 16px; z-index: 20; min-height: 36px; padding: 0 14px; font: inherit; font-size: 14px; color: var(--blockeditor-ink); background: var(--blockeditor-pop-bg); border: 1px solid var(--blockeditor-chrome-line-rest); border-radius: 999px; cursor: pointer; }
|
|
38
|
+
.blockeditor-recovery[hidden], .blockeditor-recovery-panel[hidden] { display: none; }
|
|
39
|
+
.blockeditor-recovery-panel { position: fixed; right: 16px; bottom: 64px; z-index: 21; width: min(420px, calc(100vw - 32px)); max-height: 60vh; overflow-y: auto; color: var(--blockeditor-ink); background: var(--blockeditor-pop-bg); border: 1px solid var(--blockeditor-chrome-line-rest); border-radius: var(--blockeditor-chrome-radius); padding: 8px; box-sizing: border-box; }
|
|
40
|
+
.blockeditor-recovery-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 4px 6px 8px; font-weight: 600; }
|
|
41
|
+
.blockeditor-recovery-note { margin: 0 6px 8px; font-size: 13px; opacity: .72; }
|
|
42
|
+
.blockeditor-recovery-failure { margin: 0 6px 8px; font-size: 13px; color: var(--blockeditor-warn, #b25b00); }
|
|
43
|
+
.blockeditor-recovery-row { display: grid; grid-template-columns: 1fr auto; gap: 4px 12px; align-items: center; min-height: 44px; padding: 8px 6px; border-top: 1px solid var(--blockeditor-chrome-line-rest); }
|
|
44
|
+
.blockeditor-recovery-meta { grid-column: 1; font-size: 12px; opacity: .72; }
|
|
45
|
+
.blockeditor-recovery-text { grid-column: 1; overflow-wrap: anywhere; white-space: pre-wrap; }
|
|
46
|
+
.blockeditor-recovery-row button, .blockeditor-recovery-head button { grid-column: 2; grid-row: 1 / span 2; min-height: 36px; padding: 0 12px; font: inherit; font-size: 14px; color: inherit; background: transparent; border: 1px solid var(--blockeditor-chrome-line-rest); border-radius: var(--blockeditor-chrome-radius); cursor: pointer; }
|
|
47
|
+
.blockeditor-recovery-row.is-busy button { opacity: .6; cursor: progress; }
|
|
48
48
|
@media (max-width: 560px) {
|
|
49
|
-
.
|
|
50
|
-
.
|
|
51
|
-
.
|
|
49
|
+
.blockeditor-recovery { top: 12px; bottom: auto; min-height: 44px; }
|
|
50
|
+
.blockeditor-recovery-panel { left: 0; right: 0; bottom: 0; width: 100%; max-height: 70vh; border-radius: var(--blockeditor-chrome-radius) var(--blockeditor-chrome-radius) 0 0; }
|
|
51
|
+
.blockeditor-recovery-row button, .blockeditor-recovery-head button { min-height: 44px; }
|
|
52
52
|
}
|
|
53
53
|
`;
|
|
54
54
|
|
|
@@ -136,7 +136,7 @@ export function insertCopy(view, blocks) {
|
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
const preview = (doc, text) => {
|
|
139
|
-
const box = el(doc, "div", "
|
|
139
|
+
const box = el(doc, "div", "blockeditor-recovery-text");
|
|
140
140
|
box.textContent = text.length > PREVIEW_LIMIT ? `${text.slice(0, PREVIEW_LIMIT)}…` : text;
|
|
141
141
|
return box;
|
|
142
142
|
};
|
|
@@ -184,13 +184,13 @@ export function createRecoveryReview({
|
|
|
184
184
|
onCovered = () => {},
|
|
185
185
|
} = {}) {
|
|
186
186
|
const doc = mount.ownerDocument;
|
|
187
|
-
const button = el(doc, "button", "
|
|
188
|
-
const panel = el(doc, "div", "
|
|
187
|
+
const button = el(doc, "button", "blockeditor-recovery", { type: "button", "aria-haspopup": "dialog", "aria-expanded": "false" });
|
|
188
|
+
const panel = el(doc, "div", "blockeditor-recovery-panel", { role: "dialog", "aria-label": "Recover work" });
|
|
189
189
|
button.hidden = true;
|
|
190
190
|
panel.hidden = true;
|
|
191
|
-
const content = el(doc, "div", "
|
|
191
|
+
const content = el(doc, "div", "blockeditor-recovery-root");
|
|
192
192
|
content.append(button, panel);
|
|
193
|
-
const ui = mountEditorUI({ name: "
|
|
193
|
+
const ui = mountEditorUI({ name: "blockeditor-recovery", content, css: [STYLES], parent: mount });
|
|
194
194
|
|
|
195
195
|
let rows = [];
|
|
196
196
|
let journaled = [];
|
|
@@ -312,23 +312,23 @@ export function createRecoveryReview({
|
|
|
312
312
|
|
|
313
313
|
function draw() {
|
|
314
314
|
panel.replaceChildren();
|
|
315
|
-
const head = el(doc, "div", "
|
|
315
|
+
const head = el(doc, "div", "blockeditor-recovery-head");
|
|
316
316
|
head.append(doc.createTextNode("Recover work"));
|
|
317
317
|
head.append(rowButton("Download", download));
|
|
318
318
|
const done = rowButton("Close", () => { close(); button.focus(); });
|
|
319
319
|
head.append(done);
|
|
320
|
-
const note = el(doc, "p", "
|
|
320
|
+
const note = el(doc, "p", "blockeditor-recovery-note");
|
|
321
321
|
note.textContent = REVIEW_TEXT;
|
|
322
322
|
panel.append(head, note);
|
|
323
323
|
if (failure) {
|
|
324
|
-
const line = el(doc, "p", "
|
|
324
|
+
const line = el(doc, "p", "blockeditor-recovery-failure");
|
|
325
325
|
line.textContent = failure;
|
|
326
326
|
panel.append(line);
|
|
327
327
|
}
|
|
328
328
|
for (const row of rows) {
|
|
329
|
-
const item = el(doc, "div", "
|
|
329
|
+
const item = el(doc, "div", "blockeditor-recovery-row", { "data-capsule": String(row.id) });
|
|
330
330
|
if (busy.has(row.id)) item.classList.add("is-busy");
|
|
331
|
-
const meta = el(doc, "div", "
|
|
331
|
+
const meta = el(doc, "div", "blockeditor-recovery-meta");
|
|
332
332
|
meta.textContent = `${row.message}${copied.has(row.id) ? " · Recovered as a copy" : ""}`;
|
|
333
333
|
const action = rowButton("Recover as a copy", () => recover(row));
|
|
334
334
|
action.disabled = busy.has(row.id) || copied.has(row.id);
|
|
@@ -336,8 +336,8 @@ export function createRecoveryReview({
|
|
|
336
336
|
panel.append(item);
|
|
337
337
|
}
|
|
338
338
|
for (const row of journaled) {
|
|
339
|
-
const item = el(doc, "div", "
|
|
340
|
-
const meta = el(doc, "div", "
|
|
339
|
+
const item = el(doc, "div", "blockeditor-recovery-row", { "data-composing": row.blockId });
|
|
340
|
+
const meta = el(doc, "div", "blockeditor-recovery-meta");
|
|
341
341
|
meta.textContent = "Text typed while composing. It never reached the page.";
|
|
342
342
|
item.append(meta, preview(doc, row.text));
|
|
343
343
|
const actions = el(doc, "div", "");
|
package/src/page/rich/chart.js
CHANGED
|
@@ -92,7 +92,7 @@ function renderPie(model, slices, width) {
|
|
|
92
92
|
const y1 = fmt(PIE.cy + PIE.radius * Math.sin(slice.from));
|
|
93
93
|
const x2 = fmt(PIE.cx + PIE.radius * Math.cos(slice.to));
|
|
94
94
|
const y2 = fmt(PIE.cy + PIE.radius * Math.sin(slice.to));
|
|
95
|
-
parts.push(`<path${point} d="M ${PIE.cx} ${PIE.cy} L ${x1} ${y1} A ${PIE.radius} ${PIE.radius} 0 ${slice.fraction > .5 ? 1 : 0} 1 ${x2} ${y2} Z" fill="${slice.color}" stroke="var(--
|
|
95
|
+
parts.push(`<path${point} d="M ${PIE.cx} ${PIE.cy} L ${x1} ${y1} A ${PIE.radius} ${PIE.radius} 0 ${slice.fraction > .5 ? 1 : 0} 1 ${x2} ${y2} Z" fill="${slice.color}" stroke="var(--blockeditor-bg)" stroke-width="2"/>`);
|
|
96
96
|
});
|
|
97
97
|
slices.forEach((slice, index) => {
|
|
98
98
|
const yy = fmt(54 + index * 36);
|
|
@@ -5,7 +5,12 @@ export { capabilityAdvertised } from "../tool-capability.js";
|
|
|
5
5
|
const CONTEXT_LIMIT = 16384;
|
|
6
6
|
const bytes = (value) => new TextEncoder().encode(JSON.stringify(value)).length;
|
|
7
7
|
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {{protocol: 'blockeditor-tool/1', requestId: string, prompt: string,
|
|
10
|
+
* context: {title: string, outline: unknown[], tables: unknown[]},
|
|
11
|
+
* target: null | {toolId: string, rev: string},
|
|
12
|
+
* current: null | {artifact: object, state: unknown}}} ToolRequest
|
|
13
|
+
*/
|
|
9
14
|
/** @typedef {{requestId: string, artifact: object, state: unknown}} ToolResult */
|
|
10
15
|
/** @typedef {{requestId: string, code: string, message: string}} ToolFailure */
|
|
11
16
|
|
|
@@ -31,7 +36,12 @@ function trimmedContext(context) {
|
|
|
31
36
|
return copy;
|
|
32
37
|
}
|
|
33
38
|
|
|
34
|
-
|
|
39
|
+
// The wire sees the request id as the host's own column, a UUID: a made-up string is
|
|
40
|
+
// refused before the model is asked.
|
|
41
|
+
const freshRequestId = () =>
|
|
42
|
+
globalThis.crypto?.randomUUID?.() ?? `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
43
|
+
|
|
44
|
+
export function createToolClient({ transport, newId = freshRequestId }) {
|
|
35
45
|
let active = null;
|
|
36
46
|
const discard = (candidate) => {
|
|
37
47
|
if (!candidate || candidate.discarded || candidate.done) return;
|
|
@@ -41,14 +51,14 @@ export function createToolClient({ transport, newId }) {
|
|
|
41
51
|
candidate.resolve({ requestId: candidate.requestId, code: "discarded", message: "Candidate discarded" });
|
|
42
52
|
};
|
|
43
53
|
return {
|
|
44
|
-
request(prompt, context, target = null) {
|
|
54
|
+
request(prompt, context, target = null, current = null) {
|
|
45
55
|
const trimmed = trimmedContext(context);
|
|
46
56
|
if (active) discard(active);
|
|
47
57
|
const requestId = newId();
|
|
48
58
|
const candidate = { requestId, discarded: false, done: false };
|
|
49
59
|
candidate.promise = new Promise((resolve) => { candidate.resolve = resolve; });
|
|
50
60
|
active = candidate;
|
|
51
|
-
const request = { protocol: "
|
|
61
|
+
const request = { protocol: "blockeditor-tool/1", requestId, prompt, context: trimmed, target, current };
|
|
52
62
|
candidate.request = request;
|
|
53
63
|
const finish = (reply) => {
|
|
54
64
|
if (candidate.discarded || candidate.done || reply?.requestId !== requestId) return;
|
|
@@ -62,9 +72,14 @@ export function createToolClient({ transport, newId }) {
|
|
|
62
72
|
} else candidate.resolve(typeof reply?.code === "string" ? reply : { requestId, code: "invalid-result", message: "invalid-result" });
|
|
63
73
|
};
|
|
64
74
|
try {
|
|
65
|
-
|
|
75
|
+
const failed = (error) => finish({
|
|
76
|
+
requestId,
|
|
77
|
+
code: typeof error?.code === "string" ? error.code : "transport-error",
|
|
78
|
+
message: String(error?.message ?? error),
|
|
79
|
+
});
|
|
80
|
+
Promise.resolve(transport.request(request)).then(finish, failed);
|
|
66
81
|
} catch (error) {
|
|
67
|
-
finish({ requestId, code: "transport-error", message: String(error?.message ?? error) });
|
|
82
|
+
finish({ requestId, code: typeof error?.code === "string" ? error.code : "transport-error", message: String(error?.message ?? error) });
|
|
68
83
|
}
|
|
69
84
|
return candidate;
|
|
70
85
|
},
|
|
@@ -138,7 +138,7 @@ export function scopeCss(css, blockSelector) {
|
|
|
138
138
|
export function mountTool({ root, artifact, mode, state, tables = () => [], onError = () => {}, setTimer = setTimeout, clearTimer = clearTimeout }) {
|
|
139
139
|
const listeners = { change: new Set(), tables: new Set() };
|
|
140
140
|
const timers = new Set();
|
|
141
|
-
let cleanup, disposed = false;
|
|
141
|
+
let cleanup, disposed = false, failed = false;
|
|
142
142
|
const dispose = () => {
|
|
143
143
|
if (disposed) return;
|
|
144
144
|
disposed = true;
|
|
@@ -181,11 +181,12 @@ export function mountTool({ root, artifact, mode, state, tables = () => [], onEr
|
|
|
181
181
|
if (typeof mount !== "function") throw new TypeError("tool script must define mount(tool)");
|
|
182
182
|
cleanup = mount(tool);
|
|
183
183
|
} catch (error) {
|
|
184
|
+
failed = true;
|
|
184
185
|
try { dispose(); } catch (cleanupError) { onError(cleanupError); }
|
|
185
186
|
onError(error);
|
|
186
187
|
root.innerHTML = `${artifact.fallbackHtml}<p data-tool-error>Tool could not start</p>`;
|
|
187
188
|
}
|
|
188
|
-
return { notifyState: () => notify("change"), notifyTables: () => notify("tables"), dispose };
|
|
189
|
+
return { notifyState: () => notify("change"), notifyTables: () => notify("tables"), dispose, failed };
|
|
189
190
|
}
|
|
190
191
|
|
|
191
192
|
function deepFreeze(value) {
|
|
@@ -12,8 +12,8 @@ import { customTitle, writeTitle } from "./document-title-dom.js";
|
|
|
12
12
|
import { blocksFromPageValues } from "./ybind/decode.js";
|
|
13
13
|
import { YDecodeError } from "./ybind/provider.js";
|
|
14
14
|
|
|
15
|
-
export const ARTICLE = "article[data-
|
|
16
|
-
const PAGE = /^
|
|
15
|
+
export const ARTICLE = "article[data-blockeditor]";
|
|
16
|
+
const PAGE = /^blockeditor(\.[0-9]+)?$/;
|
|
17
17
|
|
|
18
18
|
export function pageTags(root) {
|
|
19
19
|
return [...root.querySelectorAll('script[merge][clay~="live"]')].filter((el) => PAGE.test(el.getAttribute("merge")));
|
package/src/page/save-states.js
CHANGED
|
@@ -8,8 +8,8 @@ import { downloadHtml, documentName } from "../core/download.js";
|
|
|
8
8
|
// table does not know falls to `error`, which leaves the existing generic
|
|
9
9
|
// "Couldn't save" feedback exactly as it was.
|
|
10
10
|
const SAVE_STATE_BY_CODE = Object.freeze({
|
|
11
|
-
"
|
|
12
|
-
"
|
|
11
|
+
"blockeditor-converting": "retrying",
|
|
12
|
+
"blockeditor-capacity": "retrying",
|
|
13
13
|
busy: "retrying",
|
|
14
14
|
"rate-limited": "retrying",
|
|
15
15
|
offline: "retrying",
|
|
@@ -17,17 +17,17 @@ const SAVE_STATE_BY_CODE = Object.freeze({
|
|
|
17
17
|
"network-error": "retrying",
|
|
18
18
|
timeout: "retrying",
|
|
19
19
|
"save-history-pending": "retrying",
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
20
|
+
"blockeditor-condition-required": "blocked",
|
|
21
|
+
"blockeditor-conversion-refused": "blocked",
|
|
22
|
+
"blockeditor-conversion-required": "blocked",
|
|
23
|
+
"blockeditor-conversion-stale": "blocked",
|
|
24
24
|
"save-id-reused": "blocked",
|
|
25
25
|
"too-large": "blocked",
|
|
26
26
|
"unsupported-host": "blocked",
|
|
27
27
|
"save-history-refresh-required": "blocked",
|
|
28
28
|
"provenance-unsupported": "blocked",
|
|
29
29
|
"receipt-expired": "blocked",
|
|
30
|
-
"
|
|
30
|
+
"blockeditor-full": "blocked",
|
|
31
31
|
"compaction-failed": "blocked",
|
|
32
32
|
});
|
|
33
33
|
|
|
@@ -55,7 +55,7 @@ function saveStateFor({ ok = false, code = null, offline = false } = {}) {
|
|
|
55
55
|
function withoutPageTag(html) {
|
|
56
56
|
let doc;
|
|
57
57
|
try { doc = new DOMParser().parseFromString(html, "text/html"); } catch { return html; }
|
|
58
|
-
const tags = [...doc.querySelectorAll('script[type="application/json"][merge="
|
|
58
|
+
const tags = [...doc.querySelectorAll('script[type="application/json"][merge="blockeditor"][clay~="live"]')]
|
|
59
59
|
.filter((el) => !el.closest("template") && !el.closest("noscript"));
|
|
60
60
|
if (tags.length !== 1) return html;
|
|
61
61
|
const outer = tags[0].outerHTML;
|
|
@@ -83,7 +83,7 @@ async function copyPageText() {
|
|
|
83
83
|
try {
|
|
84
84
|
const { forSave } = captureForSaveAndComparison({ emitForSync: false });
|
|
85
85
|
const doc = new DOMParser().parseFromString(forSave, "text/html");
|
|
86
|
-
const articles = doc.querySelectorAll("article[data-
|
|
86
|
+
const articles = doc.querySelectorAll("article[data-blockeditor]");
|
|
87
87
|
if (articles.length !== 1) return false;
|
|
88
88
|
await navigator.clipboard.writeText(articles[0].textContent);
|
|
89
89
|
return true;
|
package/src/page/schema.js
CHANGED
|
@@ -52,7 +52,7 @@ export const schema = new model.Schema({
|
|
|
52
52
|
due: { default: null },
|
|
53
53
|
},
|
|
54
54
|
toDOM: (n) => ["div", ref(n, {
|
|
55
|
-
class: "
|
|
55
|
+
class: "blockeditor-li",
|
|
56
56
|
"data-kind": n.attrs.kind,
|
|
57
57
|
"data-indent": String(n.attrs.indent),
|
|
58
58
|
"data-checked": n.attrs.checked ? "true" : "false",
|
|
@@ -68,7 +68,7 @@ export const schema = new model.Schema({
|
|
|
68
68
|
group: "block",
|
|
69
69
|
content: "inline*",
|
|
70
70
|
attrs: block,
|
|
71
|
-
toDOM: (n) => ["aside", ref(n, { class: "
|
|
71
|
+
toDOM: (n) => ["aside", ref(n, { class: "blockeditor-callout" }), 0],
|
|
72
72
|
},
|
|
73
73
|
code_block: {
|
|
74
74
|
group: "block",
|
|
@@ -83,7 +83,7 @@ export const schema = new model.Schema({
|
|
|
83
83
|
group: "block",
|
|
84
84
|
content: "inline*",
|
|
85
85
|
attrs: { ...block, open: { default: false }, level: { default: null } },
|
|
86
|
-
toDOM: (n) => ["div", ref(n, { class: "
|
|
86
|
+
toDOM: (n) => ["div", ref(n, { class: "blockeditor-toggle", "data-open": n.attrs.open ? "true" : "false", ...(n.attrs.level ? { "data-level": String(n.attrs.level) } : {}) }), 0],
|
|
87
87
|
},
|
|
88
88
|
divider: {
|
|
89
89
|
group: "block",
|
|
@@ -97,7 +97,7 @@ export const schema = new model.Schema({
|
|
|
97
97
|
group: "block",
|
|
98
98
|
atom: true,
|
|
99
99
|
attrs: { ...block, maxLevel: { default: null } },
|
|
100
|
-
toDOM: (n) => ["div", ref(n, { class: "
|
|
100
|
+
toDOM: (n) => ["div", ref(n, { class: "blockeditor-toc", "data-type": "toc", ...(n.attrs.maxLevel ? { "data-max-level": String(n.attrs.maxLevel) } : {}) })],
|
|
101
101
|
},
|
|
102
102
|
image: {
|
|
103
103
|
group: "block",
|
|
@@ -110,7 +110,7 @@ export const schema = new model.Schema({
|
|
|
110
110
|
group: "block",
|
|
111
111
|
atom: true,
|
|
112
112
|
attrs: { ...block, src: { default: "" }, name: { default: "" }, size: { default: null }, mime: { default: null } },
|
|
113
|
-
toDOM: (n) => ["div", ref(n, { class: "
|
|
113
|
+
toDOM: (n) => ["div", ref(n, { class: "blockeditor-file", "data-type": "file", "data-src": safeFileHref(n.attrs.src) ?? "", "data-name": n.attrs.name, "data-size": n.attrs.size == null ? "" : String(n.attrs.size), "data-mime": n.attrs.mime ?? "" }),
|
|
114
114
|
["a", { href: safeFileHref(n.attrs.src), target: "_blank", rel: "noopener noreferrer" }, n.attrs.name || "file"]],
|
|
115
115
|
},
|
|
116
116
|
table: {
|
|
@@ -174,8 +174,8 @@ export const schema = new model.Schema({
|
|
|
174
174
|
selectable: true,
|
|
175
175
|
attrs: { ...block, raw: { default: null } },
|
|
176
176
|
toDOM: (n) => ["div", ref(n, { "data-type": "newer-format", "data-format": String(n.attrs.raw?.t ?? ""), contenteditable: "false" }),
|
|
177
|
-
["span", { class: "
|
|
178
|
-
["span", { class: "
|
|
177
|
+
["span", { class: "blockeditor-newer-format" }, `Newer format: ${String(n.attrs.raw?.t ?? "")}`],
|
|
178
|
+
["span", { class: "blockeditor-newer-format-text" }, n.textContent]],
|
|
179
179
|
},
|
|
180
180
|
|
|
181
181
|
text: { group: "inline" },
|
|
@@ -202,7 +202,7 @@ export const schema = new model.Schema({
|
|
|
202
202
|
attrs: { id: {} },
|
|
203
203
|
inclusive: false,
|
|
204
204
|
excludes: "mention date link",
|
|
205
|
-
toDOM: (m) => ["span", { "data-
|
|
205
|
+
toDOM: (m) => ["span", { "data-blockeditor-mention": m.attrs.id }, 0],
|
|
206
206
|
},
|
|
207
207
|
// A date mention is the calendar date as ordinary ISO text with this mark over it:
|
|
208
208
|
// `date` is YYYY-MM-DD, and no time, zone, reminder or relative word is stored.
|
|
@@ -210,7 +210,7 @@ export const schema = new model.Schema({
|
|
|
210
210
|
attrs: { date: {} },
|
|
211
211
|
inclusive: false,
|
|
212
212
|
excludes: "mention date link",
|
|
213
|
-
toDOM: (m) => ["time", { datetime: m.attrs.date, "data-
|
|
213
|
+
toDOM: (m) => ["time", { datetime: m.attrs.date, "data-blockeditor-date": "" }, 0],
|
|
214
214
|
},
|
|
215
215
|
// The floor-1 formats (format-native.js): written as named descriptors,
|
|
216
216
|
// drawn as the elements the saved article keeps for them.
|
package/src/page/table-style.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
export const TABLE_CSS = `
|
|
2
|
-
.
|
|
3
|
-
.
|
|
4
|
-
.
|
|
5
|
-
.
|
|
6
|
-
.
|
|
7
|
-
.
|
|
8
|
-
.
|
|
9
|
-
.
|
|
10
|
-
.
|
|
11
|
-
.
|
|
12
|
-
.
|
|
13
|
-
.
|
|
14
|
-
.
|
|
15
|
-
.
|
|
16
|
-
.
|
|
17
|
-
.
|
|
2
|
+
.blockeditor-editor .blockeditor-table { position: relative; }
|
|
3
|
+
.blockeditor-table td { position: relative; }
|
|
4
|
+
.blockeditor-table th { position: relative; }
|
|
5
|
+
.blockeditor-table td.is-cell-selected { background: var(--blockeditor-block-selected); }
|
|
6
|
+
.blockeditor-editor.has-cell-rect .blockeditor-table td ::selection, .blockeditor-editor.has-cell-rect .blockeditor-table td::selection { background: transparent; }
|
|
7
|
+
.blockeditor-editor.has-cell-rect .blockeditor-table td { caret-color: transparent; }
|
|
8
|
+
.blockeditor-table table.is-sized { table-layout: fixed; min-width: 0; }
|
|
9
|
+
.blockeditor-table table.is-sized th, .blockeditor-table table.is-sized td { min-width: 0; overflow-wrap: anywhere; }
|
|
10
|
+
.blockeditor-table-resize { position: absolute; top: 0; bottom: 0; inset-inline-end: -4px; width: 8px; z-index: 2; cursor: col-resize; touch-action: none; }
|
|
11
|
+
.blockeditor-table-resize:hover, .blockeditor-table-resize:active, .blockeditor-table-resize:focus-visible { background: var(--blockeditor-accent); opacity: 0.4; }
|
|
12
|
+
.blockeditor-table-add-row, .blockeditor-table-add-col { position: absolute; z-index: 1; padding: 0; background: var(--blockeditor-chrome-bg-moved); color: var(--blockeditor-ink-soft); display: flex; align-items: center; justify-content: center; font: inherit; font-size: 14px; line-height: 1; cursor: pointer; opacity: 0; transition: opacity 120ms; }
|
|
13
|
+
.blockeditor-table-add-row { left: 0; right: 0; top: 100%; height: 16px; border-radius: 0 0 6px 6px; border: 1px solid var(--blockeditor-chrome-line-moved); border-top: 0; padding-bottom: 2px; box-sizing: border-box; }
|
|
14
|
+
.blockeditor-table-add-col { top: 0; bottom: 0; left: 100%; width: 16px; border-radius: 0 6px 6px 0; border: 1px solid var(--blockeditor-chrome-line-moved); border-left: 0; box-sizing: border-box; }
|
|
15
|
+
.blockeditor-table:hover > .blockeditor-table-add-row, .blockeditor-table:hover > .blockeditor-table-add-col, .blockeditor-table-add-row:focus-visible, .blockeditor-table-add-col:focus-visible { opacity: 1; }
|
|
16
|
+
.blockeditor-table-add-row:hover, .blockeditor-table-add-col:hover { background: var(--blockeditor-pop-hover); color: var(--blockeditor-ink); }
|
|
17
|
+
.blockeditor-table-date { position: absolute; inset-inline-start: 0; top: 100%; z-index: 3; font: inherit; color: var(--blockeditor-pop-ink); background: var(--blockeditor-pop-bg); border: 1px solid var(--blockeditor-pop-line); border-radius: 6px; padding: 4px 6px; box-shadow: var(--blockeditor-pop-shadow); }
|
|
18
18
|
@media (max-width: 560px) {
|
|
19
|
-
.
|
|
20
|
-
.
|
|
21
|
-
.
|
|
22
|
-
.
|
|
23
|
-
.
|
|
19
|
+
.blockeditor-table-date { min-height: 44px; }
|
|
20
|
+
.blockeditor-table-resize { display: none; }
|
|
21
|
+
.blockeditor-table-add-row, .blockeditor-table-add-col { position: static; display: inline-block; width: 50%; height: 44px; border-radius: 0; opacity: 1; border-block-start: 1px solid var(--blockeditor-rule); }
|
|
22
|
+
.blockeditor-table-add-row::after { content: " Row"; }
|
|
23
|
+
.blockeditor-table-add-col::after { content: " Column"; }
|
|
24
24
|
}
|
|
25
25
|
`;
|
package/src/page/toc-link.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// The saved table of contents' links: decode the anchor a link names, and reveal
|
|
2
2
|
// the block it points at in a reader. Loaded the first time a reader follows one.
|
|
3
|
-
const TOC_ANCHOR = "
|
|
3
|
+
const TOC_ANCHOR = "blockeditor-block-";
|
|
4
4
|
|
|
5
5
|
const fromB64url = (text) => {
|
|
6
6
|
const bin = atob(String(text).replace(/-/g, "+").replace(/_/g, "/"));
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
-
// A host that
|
|
2
|
-
//
|
|
3
|
-
|
|
1
|
+
// A host that lists blockeditor-tool in this document's helper list can answer tool
|
|
2
|
+
// requests. Old clients look for a blockeditor-tool/1 entry in `extensions`, which no host
|
|
3
|
+
// adds, so they never show a dead /ai. The check stays in the core: the slash menu
|
|
4
|
+
// asks it before the tool view part loads.
|
|
5
|
+
export const capabilityAdvertised = (meta) =>
|
|
6
|
+
Array.isArray(meta?.document?.helpers) &&
|
|
7
|
+
meta.document.helpers.some((helper) =>
|
|
8
|
+
helper?.name === "blockeditor-tool" && (helper.state === "ready" || helper.state === "unavailable"));
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// The blockeditor-tool helper over clay.wire. `clay.wire` is read when a request goes out,
|
|
2
|
+
// because the page plugin loads before the wire does: a page with exclude=wire must
|
|
3
|
+
// never pull the module in.
|
|
4
|
+
export class ToolTransportError extends Error {
|
|
5
|
+
constructor(code) {
|
|
6
|
+
super(code);
|
|
7
|
+
this.name = "ToolTransportError";
|
|
8
|
+
this.code = code;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function createToolTransport({ getWire = () => globalThis.window?.clay?.wire ?? null } = {}) {
|
|
13
|
+
const handles = new Map();
|
|
14
|
+
return {
|
|
15
|
+
request(payload, { onStatus = null } = {}) {
|
|
16
|
+
const wire = getWire();
|
|
17
|
+
if (!wire || typeof wire.send !== "function") return Promise.reject(new ToolTransportError("no-wire"));
|
|
18
|
+
const id = payload?.requestId;
|
|
19
|
+
let handle;
|
|
20
|
+
try {
|
|
21
|
+
handle = wire.send(payload, { helper: "blockeditor-tool", document: "none", id, onStatus });
|
|
22
|
+
} catch (error) {
|
|
23
|
+
return Promise.reject(new ToolTransportError("no-wire"));
|
|
24
|
+
}
|
|
25
|
+
handles.set(id, handle);
|
|
26
|
+
return Promise.resolve(handle.done).then((outcome) => {
|
|
27
|
+
if (handles.get(id) === handle) handles.delete(id);
|
|
28
|
+
// A reply is the wire's structured result; a failure keeps the host's own code
|
|
29
|
+
// so the page can tell a refused prompt from a lost connection.
|
|
30
|
+
if (outcome?.state === "done") {
|
|
31
|
+
const result = outcome.result ?? {};
|
|
32
|
+
return {
|
|
33
|
+
requestId: typeof result.requestId === "string" ? result.requestId : id,
|
|
34
|
+
artifact: result.artifact,
|
|
35
|
+
state: result.state,
|
|
36
|
+
model: result.model,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
requestId: id,
|
|
41
|
+
code: outcome?.errorCode || (outcome?.state === "cancelled" ? "cancelled" : "transport-error"),
|
|
42
|
+
message: outcome?.error || "the helper reported an error",
|
|
43
|
+
};
|
|
44
|
+
}, () => ({ requestId: id, code: "transport-error", message: "the helper reported an error" }));
|
|
45
|
+
},
|
|
46
|
+
cancel(id) {
|
|
47
|
+
const handle = handles.get(id);
|
|
48
|
+
handles.delete(id);
|
|
49
|
+
handle?.cancel?.();
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
package/src/page/tool-views.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
// The tool host a tool's plugin can reach, filled by the tool view part when it
|
|
2
2
|
// loads, per editor. A document whose editor has no host yet notifies nothing.
|
|
3
3
|
export const toolViews = new WeakMap();
|
|
4
|
+
|
|
5
|
+
// The mounted tool blocks of an editor, by id, so work that must pause a tool can
|
|
6
|
+
// reach the block that runs it.
|
|
7
|
+
export const toolBlockViews = new WeakMap();
|
package/src/page/tools.js
CHANGED
|
@@ -15,6 +15,7 @@ export function createToolHost({ store = null, mode, tables = () => [] }) {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
const fail = (item, error) => {
|
|
18
|
+
item.failed = true;
|
|
18
19
|
warn(item.id, item.rev, error);
|
|
19
20
|
item.readerOff?.();
|
|
20
21
|
item.readerOff = null;
|
|
@@ -46,7 +47,7 @@ export function createToolHost({ store = null, mode, tables = () => [] }) {
|
|
|
46
47
|
const host = {
|
|
47
48
|
mount(root, { id, artifact, rev, seed = {} }) {
|
|
48
49
|
if (disposed) throw new Error("tool host is disposed");
|
|
49
|
-
const item = { root, id, artifact, rev, seed, runtime: null, readerOff: null, disposed: false, signature: undefined };
|
|
50
|
+
const item = { root, id, artifact, rev, seed, runtime: null, readerOff: null, disposed: false, failed: false, signature: undefined };
|
|
50
51
|
const note = (message) => {
|
|
51
52
|
const line = root.ownerDocument.createElement("p");
|
|
52
53
|
line.setAttribute("data-tool-note", "");
|
|
@@ -58,8 +59,10 @@ export function createToolHost({ store = null, mode, tables = () => [] }) {
|
|
|
58
59
|
item.readerOff = null;
|
|
59
60
|
try { item.runtime?.dispose(); } catch (error) { warn(item.id, item.rev, error); }
|
|
60
61
|
item.runtime = null;
|
|
62
|
+
item.failed = false;
|
|
61
63
|
root.removeAttribute("data-tool-scope");
|
|
62
64
|
if (validateArtifact(item.artifact).ok === false) {
|
|
65
|
+
item.failed = true;
|
|
63
66
|
root.textContent = "Tool unavailable";
|
|
64
67
|
warn(item.id, item.rev, new Error("invalid artifact"));
|
|
65
68
|
return;
|
|
@@ -75,6 +78,7 @@ export function createToolHost({ store = null, mode, tables = () => [] }) {
|
|
|
75
78
|
? scopedStateHandle(store, item.id, item.rev)
|
|
76
79
|
: readerStateHandle(current ?? item.seed ?? {});
|
|
77
80
|
item.runtime = mountTool({ root, artifact: item.artifact, mode, state, tables, onError: (error) => warn(item.id, item.rev, error) });
|
|
81
|
+
item.failed = item.runtime.failed === true;
|
|
78
82
|
item.readerOff = state.on?.("change", () => {
|
|
79
83
|
try { item.runtime?.notifyState(); } catch (error) { fail(item, error); }
|
|
80
84
|
}) ?? null;
|
|
@@ -83,6 +87,7 @@ export function createToolHost({ store = null, mode, tables = () => [] }) {
|
|
|
83
87
|
try { item.render(); } catch (error) { fail(item, error); }
|
|
84
88
|
mounted.add(item);
|
|
85
89
|
return {
|
|
90
|
+
get failed() { return item.failed; },
|
|
86
91
|
update({ artifact: nextArtifact, rev: nextRev }) {
|
|
87
92
|
if (item.disposed) return;
|
|
88
93
|
if (nextRev === item.rev && nextArtifact === item.artifact) return;
|
package/src/page/view.js
CHANGED
|
@@ -9,9 +9,9 @@ import { stopForUpgrade, upgradeReplaces, upgradeReplacesDocument } from "../syn
|
|
|
9
9
|
import { applyPreparedArticle, keepToolVersion, prepareSavedArticle, toolInfoOf, toolsOf, toolStateOf } from "./reader-patch.js";
|
|
10
10
|
import { claim } from "./runtime-owner.js";
|
|
11
11
|
|
|
12
|
-
const ARTICLE = "article[data-
|
|
12
|
+
const ARTICLE = "article[data-blockeditor]";
|
|
13
13
|
const TOOL = 'section[data-type="tool"][data-id]';
|
|
14
|
-
const PAGE_TAG = 'script[type="application/json"][merge="
|
|
14
|
+
const PAGE_TAG = 'script[type="application/json"][merge="blockeditor"]';
|
|
15
15
|
const LINEAGE = ["live-at", "live-by"];
|
|
16
16
|
|
|
17
17
|
export { applyPreparedArticle, prepareSavedArticle };
|
|
@@ -220,7 +220,7 @@ function createReader({ doc, article, represented = null, feed = null, documentU
|
|
|
220
220
|
if (stopped || yielded) return false;
|
|
221
221
|
const prepared = prepareSavedArticle(candidate.bytes, doc);
|
|
222
222
|
if (!prepared.ok) return false;
|
|
223
|
-
if (article.querySelector(".
|
|
223
|
+
if (article.querySelector(".blockeditor-editor")) return false;
|
|
224
224
|
// A file published at another version of this document is not this reader's to
|
|
225
225
|
// show: the stream stops, this file and every later one are refused, and the
|
|
226
226
|
// notice offers a reload. Nothing of it reaches the article.
|
|
@@ -267,7 +267,7 @@ function createReader({ doc, article, represented = null, feed = null, documentU
|
|
|
267
267
|
listeners.push(["toggle", onToggle, true]);
|
|
268
268
|
|
|
269
269
|
const onTocLink = (event) => {
|
|
270
|
-
const link = event.target.closest?.('a[href^="#
|
|
270
|
+
const link = event.target.closest?.('a[href^="#blockeditor-block-"], a[href^="#"]');
|
|
271
271
|
if (!link || !article.contains(link) || !link.closest('nav[aria-label="Table of contents"]')) return;
|
|
272
272
|
event.preventDefault();
|
|
273
273
|
followTocLink(article, link.getAttribute("href"));
|
|
@@ -399,9 +399,9 @@ export function start({ represented = null, documentURL, servedEtag = null, stre
|
|
|
399
399
|
throw new TypeError("clayjs: the reader needs a file, a stream or a page to follow");
|
|
400
400
|
}
|
|
401
401
|
const articles = doc.querySelectorAll(ARTICLE);
|
|
402
|
-
if (articles.length !== 1) throw new Error("clayjs: the reader needs exactly one article[data-
|
|
402
|
+
if (articles.length !== 1) throw new Error("clayjs: the reader needs exactly one article[data-blockeditor]");
|
|
403
403
|
const article = articles[0];
|
|
404
|
-
if (article.querySelector(".
|
|
404
|
+
if (article.querySelector(".blockeditor-editor")) throw new Error("clayjs: the reader will not start over a mounted editor");
|
|
405
405
|
if (represented) {
|
|
406
406
|
const prepared = prepareSavedArticle(represented.bytes, doc);
|
|
407
407
|
if (!prepared.ok) throw new Error("clayjs: the saved file is not a readable page");
|
|
@@ -26,7 +26,7 @@ export function createYPageBinding({ store, ydoc = new Y.Doc(), onNotice = () =>
|
|
|
26
26
|
// A full or failed room stops offering at once, but the checkpoint of what it already
|
|
27
27
|
// admitted goes out before the page locks and holds every save.
|
|
28
28
|
onStopped: (reason) => {
|
|
29
|
-
if (reason !== "
|
|
29
|
+
if (reason !== "blockeditor-full" && reason !== "compaction-failed") { onStopped(reason); return; }
|
|
30
30
|
Promise.resolve(requestCheckpoint?.({ timeoutMs: 10_000 })).catch(() => {}).finally(() => onStopped(reason));
|
|
31
31
|
},
|
|
32
32
|
onLocalUpdate: debt.local,
|
|
@@ -2,7 +2,7 @@ import { cloneJson } from "../../live/ops.js";
|
|
|
2
2
|
import { canon } from "../projection.js";
|
|
3
3
|
import { migrateHybridValues, YMigrationError } from "./migrate.js";
|
|
4
4
|
|
|
5
|
-
const PAGE = /^
|
|
5
|
+
const PAGE = /^blockeditor(\.[0-9]+)?$/;
|
|
6
6
|
|
|
7
7
|
export async function prepareHybridConversion(tags) {
|
|
8
8
|
try {
|
package/src/page/ybind/layout.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as Y from "../../vendor/yjs.vendor.js";
|
|
2
2
|
import { REMOTE } from "../model.js";
|
|
3
3
|
|
|
4
|
-
export const LOCAL = "
|
|
5
|
-
export const NET = "
|
|
6
|
-
export const SEED = "
|
|
4
|
+
export const LOCAL = "blockeditor-local";
|
|
5
|
+
export const NET = "blockeditor-net";
|
|
6
|
+
export const SEED = "blockeditor-seed";
|
|
7
7
|
export const REMOTE_META = REMOTE;
|
|
8
|
-
export const HISTORY_META = Symbol("
|
|
8
|
+
export const HISTORY_META = Symbol("blockeditor-history");
|
|
9
9
|
export const PAGE_ROOTS = Object.freeze(["flow", "attrs", "gone", "boardFields", "tableFields", "origins"]);
|
|
10
10
|
|
|
11
11
|
const SKIP = new Set(["id", "pos"]);
|
|
@@ -171,7 +171,7 @@ export function migrateHybridValues(values) {
|
|
|
171
171
|
// so every rebuild of the same article is byte-identical (two tabs converge) and rebuilds of
|
|
172
172
|
// different articles never share Yjs item ids.
|
|
173
173
|
export function seedClientId(blocks) {
|
|
174
|
-
const id = parseInt(hash64(`
|
|
174
|
+
const id = parseInt(hash64(`blockeditor-seed:v1:${canon(blocks)}`).slice(0, 8), 16) >>> 0;
|
|
175
175
|
return id < 2 ? id + 2 : id;
|
|
176
176
|
}
|
|
177
177
|
|