@panphora/clayjs 1.15.1 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -5
- package/THIRD-PARTY-NOTICES.md +16 -0
- package/compat/highlight-11.9.0.min.js +1213 -0
- package/compat/highlight-LICENSE +29 -0
- package/compat/journal-assets.lock.json +22 -0
- package/compat/overtype-2.6.1.min.js +116 -0
- package/compat/overtype-LICENSE +21 -0
- package/dist/all.js +90 -0
- package/dist/clay-dom.js +84 -0
- package/dist/clay-events.js +103 -0
- package/dist/clay-internals.js +85 -0
- package/dist/clay-options.js +93 -0
- package/dist/clay-router.js +98 -0
- package/dist/clay-ui.js +95 -0
- package/dist/clay-utils.js +84 -0
- package/dist/clay.js +146 -0
- package/dist/clay.standalone.js +83090 -58706
- package/dist/m/attrs/add-from-T5LJXFFI.js +1 -0
- package/dist/m/attrs/onaftersave-OKSWEJQF.js +1 -0
- package/dist/m/attrs/refetch-on-save-NWPPXOCZ.js +1 -0
- package/dist/m/attrs/save-freeze-FUP4Q4X3.js +1 -0
- package/dist/m/c-2AZDZWCK.js +1 -0
- package/dist/m/c-2JL6E75N.js +1 -0
- package/dist/m/c-2M73252O.js +1 -0
- package/dist/m/c-2SPVQSHC.js +1 -0
- package/dist/m/c-33HUYEDI.js +1 -0
- package/dist/m/c-33JJ6CBX.js +2 -0
- package/dist/m/c-35NBGMZB.js +1 -0
- package/dist/m/c-3GJ4SDE2.js +1 -0
- package/dist/m/c-3IQRECYS.js +1 -0
- package/dist/m/c-3OWDMNJR.js +2 -0
- package/dist/m/c-46XYM55L.js +1 -0
- package/dist/m/c-4B6H4G5V.js +1 -0
- package/dist/m/c-4DRMS4QG.js +9 -0
- package/dist/m/c-4FFHZM32.js +1 -0
- package/dist/m/c-4JZDZFF6.js +1 -0
- package/dist/m/c-4L3BTFRK.js +1 -0
- package/dist/m/c-4Q2XTQ2N.js +2 -0
- package/dist/m/c-4WKFKEKF.js +1 -0
- package/dist/m/c-4YSCRICO.js +1 -0
- package/dist/m/c-54RCDCBU.js +1 -0
- package/dist/m/c-5M4YEKCX.js +4 -0
- package/dist/m/c-5R4PTRG2.js +1 -0
- package/dist/m/c-5V3MOVJT.js +1 -0
- package/dist/m/c-5VYOWDTI.js +1 -0
- package/dist/m/c-5Y6TNX5W.js +34 -0
- package/dist/m/c-5YIHJ3TJ.js +1 -0
- package/dist/m/c-66O32MV3.js +28 -0
- package/dist/m/c-6HMB24EV.js +1 -0
- package/dist/m/c-7DJDKPGL.js +1 -0
- package/dist/m/c-7O6AFR65.js +1 -0
- package/dist/m/c-7SWMYKAI.js +1 -0
- package/dist/m/c-7VGZ7RU5.js +1 -0
- package/dist/m/c-A7LS5UZW.js +1 -0
- package/dist/m/c-ANQTJ3B5.js +2 -0
- package/dist/m/c-AQLFEATB.js +1 -0
- package/dist/m/c-AYVOREBE.js +1 -0
- package/dist/m/c-B2ZXPOS3.js +3 -0
- package/dist/m/c-BBVGTQG7.js +1 -0
- package/dist/m/c-BMIZKMPV.js +1 -0
- package/dist/m/c-BTDI4Y23.js +1 -0
- package/dist/m/c-BWFVSBDF.js +1 -0
- package/dist/m/c-BYTKL6UX.js +1 -0
- package/dist/m/c-CFHW5AMY.js +6 -0
- package/dist/m/c-CJZSLMVQ.js +1 -0
- package/dist/m/c-CYWLPPUS.js +1 -0
- package/dist/m/c-CZUSOB7V.js +1 -0
- package/dist/m/c-DBE6ORSI.js +1 -0
- package/dist/m/c-DCFSEJZG.js +1 -0
- package/dist/m/c-DNZ5IFM6.js +1 -0
- package/dist/m/c-EDHUR4MX.js +1 -0
- package/dist/m/c-EJTGYSLN.js +1 -0
- package/dist/m/c-EY6UOM54.js +1 -0
- package/dist/m/c-F3CKJTJS.js +1 -0
- package/dist/m/c-F7Y6FLPY.js +1 -0
- package/dist/m/c-FA4DZVTC.js +1 -0
- package/dist/m/c-FILLTJA7.js +1 -0
- package/dist/m/c-G2BUZITR.js +1 -0
- package/dist/m/c-GB3JTV6E.js +1 -0
- package/dist/m/c-GBGWXTX4.js +1 -0
- package/dist/m/c-GHBCCVG4.js +1 -0
- package/dist/m/c-GJAEGGXY.js +1 -0
- package/dist/m/c-GOWBDM6J.js +1 -0
- package/dist/m/c-GQ6F6IDK.js +1 -0
- package/dist/m/c-H4LG442Q.js +1 -0
- package/dist/m/c-HA6INT6J.js +1 -0
- package/dist/m/c-HPURYVZS.js +2 -0
- package/dist/m/c-HRDCD3WN.js +67 -0
- package/dist/m/c-HT33EQRN.js +1 -0
- package/dist/m/c-HVYXIS72.js +1 -0
- package/dist/m/c-IB52R237.js +1 -0
- package/dist/m/c-IJUK2GPW.js +1 -0
- package/dist/m/c-IKWNE4R4.js +1 -0
- package/dist/m/c-IU3IYEU6.js +1 -0
- package/dist/m/c-IZ2EBRAJ.js +1 -0
- package/dist/m/c-J7CA54IP.js +1 -0
- package/dist/m/c-JAX2667S.js +6 -0
- package/dist/m/c-KI7M4AY3.js +1 -0
- package/dist/m/c-KIPQJX4B.js +1 -0
- package/dist/m/c-KKWLDOPM.js +1 -0
- package/dist/m/c-KR4UW4KW.js +1 -0
- package/dist/m/c-KY3VJGUA.js +8 -0
- package/dist/m/c-L4WQSC27.js +1 -0
- package/dist/m/c-LFPHCXY3.js +1 -0
- package/dist/m/c-LR4CGEPT.js +91 -0
- package/dist/m/c-LRPUO2MX.js +1 -0
- package/dist/m/c-LTGMXXKO.js +1 -0
- package/dist/m/c-LXENEBV7.js +1 -0
- package/dist/m/c-LZJPNR2W.js +1 -0
- package/dist/m/c-MMUIUUZG.js +2 -0
- package/dist/m/c-MTQHWQC3.js +1 -0
- package/dist/m/c-N326R2JD.js +1 -0
- package/dist/m/c-N7JPUPGC.js +1 -0
- package/dist/m/c-NMJRXKPC.js +8 -0
- package/dist/m/c-NRPJEVJS.js +1 -0
- package/dist/m/c-NUHP2XDB.js +1 -0
- package/dist/m/c-NZMNXVF6.js +1 -0
- package/dist/m/c-OCSZ4QGN.js +1 -0
- package/dist/m/c-OIBUTDXI.js +1 -0
- package/dist/m/c-OIDRZKAF.js +1 -0
- package/dist/m/c-OYTFP5QN.js +1 -0
- package/dist/m/c-P7KNDG34.js +1 -0
- package/dist/m/c-PPOSCAQD.js +1 -0
- package/dist/m/c-PQ5LK6QE.js +993 -0
- package/dist/m/c-PZ4XEPUP.js +2 -0
- package/dist/m/c-QHIWXHRO.js +1 -0
- package/dist/m/c-QHWJ5ZIJ.js +1 -0
- package/dist/m/c-QIX5BJYN.js +1 -0
- package/dist/m/c-QNKREOL6.js +1 -0
- package/dist/m/c-QQHEX6HA.js +1 -0
- package/dist/m/c-R7RMANJI.js +9 -0
- package/dist/m/c-RI4NT75Y.js +1 -0
- package/dist/m/c-RM7J7BV2.js +1 -0
- package/dist/m/c-RUJKSUQW.js +1 -0
- package/dist/m/c-RVMWGXEJ.js +1 -0
- package/dist/m/c-S7H2DRCB.js +1 -0
- package/dist/m/c-S7LK4KUE.js +1 -0
- package/dist/m/c-SGCCC4FW.js +25 -0
- package/dist/m/c-SGIA4IEQ.js +188 -0
- package/dist/m/c-SWRJFCNN.js +1 -0
- package/dist/m/c-T4VO4OCB.js +1 -0
- package/dist/m/c-TCCA5BZN.js +2 -0
- package/dist/m/c-TQEMVJCS.js +1 -0
- package/dist/m/c-TQZ2JYHD.js +1 -0
- package/dist/m/c-TR6RMDQ7.js +3 -0
- package/dist/m/c-TRS6TM6O.js +1 -0
- package/dist/m/c-UGHH4MB3.js +1 -0
- package/dist/m/c-UKHTLWUW.js +1 -0
- package/dist/m/c-UL2YUY52.js +1 -0
- package/dist/m/c-UNN7LWCT.js +1 -0
- package/dist/m/c-UXBMRDZB.js +235 -0
- package/dist/m/c-V7PZZRG7.js +1 -0
- package/dist/m/c-VAK7SG37.js +1 -0
- package/dist/m/c-VDSS4K3Z.js +1 -0
- package/dist/m/c-VFX45IZQ.js +1 -0
- package/dist/m/c-VHNSBD2M.js +1 -0
- package/dist/m/c-VKEDWYDF.js +1 -0
- package/dist/m/c-VL52ADDR.js +1 -0
- package/dist/m/c-WN5AY3OZ.js +1 -0
- package/dist/m/c-WNYBLIOZ.js +1 -0
- package/dist/m/c-WRBKEJD4.js +1 -0
- package/dist/m/c-WWDBYXLK.js +1 -0
- package/dist/m/c-WYFDLITL.js +1 -0
- package/dist/m/c-XN6MBKI6.js +67 -0
- package/dist/m/c-XNNW2CWK.js +1 -0
- package/dist/m/c-XPELB6E5.js +1 -0
- package/dist/m/c-XQXZAO7N.js +1 -0
- package/dist/m/c-Y6USGTS5.js +5 -0
- package/dist/m/c-YDH7Q3NY.js +1 -0
- package/dist/m/c-YG2NJYS6.js +135 -0
- package/dist/m/c-Z36J63PP.js +1 -0
- package/dist/m/c-Z4VRC7GU.js +7 -0
- package/dist/m/c-Z6K52OLP.js +19 -0
- package/dist/m/c-ZDY2MDAA.js +21 -0
- package/dist/m/c-ZE46QDIH.js +1 -0
- package/dist/m/c-ZUCOKOHT.js +1 -0
- package/dist/m/core/admin-attrs-VGNLAUDK.js +1 -0
- package/dist/m/core/autosave-E4PEFPZ6.js +1 -0
- package/dist/m/core/conflict-notice-VQ6Y64PH.js +1 -0
- package/dist/m/core/draft-mode-WSQAT67S.js +1 -0
- package/dist/m/core/host-permission-XN3K2IW3.js +1 -0
- package/dist/m/core/is-edit-mode-JXHDVGUL.js +1 -0
- package/dist/m/core/persist-HKHA66IY.js +3 -0
- package/dist/m/core/recovery-TBBSICE2.js +1 -0
- package/dist/m/core/save-WUCHTQBE.js +1 -0
- package/dist/m/core/save-core-FJVHT5M3.js +1 -0
- package/dist/m/core/snapshot-F3SWDZMM.js +1 -0
- package/dist/m/core/unsaved-warning-STKBHE6G.js +1 -0
- package/dist/m/dom/all-APS5ZSKP.js +1 -0
- package/dist/m/dom/dom-helpers-L7OSR6S4.js +1 -0
- package/dist/m/events/index-23DPTUT4.js +1 -0
- package/dist/m/internals/index-WOVAP3RU.js +1 -0
- package/dist/m/lib/cache-bust-CGWT6ZJI.js +1 -0
- package/dist/m/lib/region-policy-SB2AWVG5.js +1 -0
- package/dist/m/loader-HXX6YNH5.js +1 -0
- package/dist/m/manifest-F22DEDAC.js +1 -0
- package/dist/m/manifest-edit-C3C7376B.js +1 -0
- package/dist/m/manifest.json +3491 -0
- package/dist/m/options/options-2LH76JQ3.js +1 -0
- package/dist/m/page/editor-XUTB2HB2.js +189 -0
- package/dist/m/plugins/ai-edit-ZQ4CGWIP.js +6 -0
- package/dist/m/plugins/bind-text-NX46N5UV.js +1 -0
- package/dist/m/plugins/cms-HP3LSTPN.js +2293 -0
- package/dist/m/plugins/demo-ZIBFAA3R.js +1 -0
- package/dist/m/plugins/derive-UAAA4V4S.js +1 -0
- package/dist/m/plugins/indicator-PV4YW2ID.js +1 -0
- package/dist/m/plugins/live-NUTTXSBS.js +1 -0
- package/dist/m/plugins/menu-HCKO3DSP.js +138 -0
- package/dist/m/plugins/message-LQ6EDH4V.js +1 -0
- package/dist/m/plugins/page-KSUH7G6J.js +2 -0
- package/dist/m/plugins/page-view-W73OW7WI.js +1 -0
- package/dist/m/plugins/people-AJJ32YCG.js +1 -0
- package/dist/m/plugins/quickcrop-QNY3PKLD.js +26 -0
- package/dist/m/plugins/quickcrop-QNY3PKLD.js.LEGAL.txt +7 -0
- package/dist/m/plugins/richclay-RC3L2F6X.js +517 -0
- package/dist/m/plugins/richclay-RC3L2F6X.js.LEGAL.txt +1 -0
- package/dist/m/plugins/sortable-YRMQX3ZU.js +1 -0
- package/dist/m/plugins/source-KHK5UUSK.js +1 -0
- package/dist/m/plugins/undo-OF2L3CXU.js +1 -0
- package/dist/m/plugins/unsent-HJFLQJ2O.js +1 -0
- package/dist/m/plugins/upgrade-ZNYODP5Y.js +1 -0
- package/dist/m/plugins/upload-XSGNILUY.js +1 -0
- package/dist/m/plugins/visitor-drafts-XK5GW55Q.js +21 -0
- package/dist/m/plugins/visitor-drafts-owner-KSSH75EV.js +1 -0
- package/dist/m/plugins/wire-ZWVWKF76.js +1 -0
- package/dist/m/reader-core-ILWLXVMP.js +68 -0
- package/dist/m/route/route-KOCZSEGN.js +1 -0
- package/dist/m/sync/live-sync-4AUVXVJU.js +1 -0
- package/dist/m/ui/index-EVHKMKBL.js +1 -0
- package/dist/m/utils/index-4TJCVLT7.js +1 -0
- package/dist/m/vendor/Sortable.vendor-A755ITLN.js +3 -0
- package/dist/m/vendor/Sortable.vendor-A755ITLN.js.LEGAL.txt +1 -0
- package/dist/m/vendor/sap-core.vendor-A7BMUYZT.js +6 -0
- package/dist/offline-manifest.json +3800 -0
- package/dist/page/themes/light-1.css +406 -0
- package/dist/server/core.cjs +23662 -22860
- package/dist/server/offline-runtime.cjs +4954 -0
- package/dist/server/offline-runtime.mjs +4923 -0
- package/dist/server/rooms.mjs +9 -0
- package/docs/guide.md +1078 -669
- package/entries/all.js +2 -0
- package/entries/clay-data.js +1 -1
- package/entries/clay-dom.js +2 -0
- package/entries/clay-events.js +2 -0
- package/entries/clay-internals.js +2 -0
- package/entries/clay-options.js +2 -0
- package/entries/clay-router.js +2 -0
- package/entries/clay-ui.js +2 -0
- package/entries/clay-utils.js +2 -0
- package/entries/clay.js +2 -0
- package/entries/sap.js +6 -6
- package/fonts/ibm-plex-mono-LICENSE +93 -0
- package/fonts/ibm-plex-mono-latin-300-normal.woff2 +0 -0
- package/fonts/ibm-plex-mono-latin-400-italic.woff2 +0 -0
- package/fonts/ibm-plex-mono-latin-400-normal.woff2 +0 -0
- package/fonts/ibm-plex-mono-latin-500-normal.woff2 +0 -0
- package/fonts/ibm-plex-mono-latin-600-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-LICENSE +93 -0
- package/fonts/ibm-plex-sans-latin-400-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-500-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-600-normal.woff2 +0 -0
- package/fonts/ibm-plex.css +71 -0
- package/fonts/inter-LICENSE +93 -0
- package/fonts/inter-cyrillic-ext-wght-normal.woff2 +0 -0
- package/fonts/inter-cyrillic-wght-normal.woff2 +0 -0
- package/fonts/inter-greek-ext-wght-normal.woff2 +0 -0
- package/fonts/inter-greek-wght-normal.woff2 +0 -0
- package/fonts/inter-latin-ext-wght-normal.woff2 +0 -0
- package/fonts/inter-latin-wght-normal.woff2 +0 -0
- package/fonts/inter-vietnamese-wght-normal.woff2 +0 -0
- package/fonts/inter.css +62 -0
- package/fonts/newsreader-LICENSE +93 -0
- package/fonts/newsreader-latin-ext-opsz-normal.woff2 +0 -0
- package/fonts/newsreader-latin-opsz-normal.woff2 +0 -0
- package/fonts/newsreader-vietnamese-opsz-normal.woff2 +0 -0
- package/fonts/newsreader.css +26 -0
- package/fonts/work-sans-LICENSE +93 -0
- package/fonts/work-sans-latin-wght-normal.woff2 +0 -0
- package/fonts/work-sans.css +8 -0
- package/package.json +20 -3
- package/packed-contract.json +1 -0
- package/src/attrs/add-from.js +27 -4
- package/src/attrs/save-freeze.js +7 -52
- package/src/core/admin-attrs.js +119 -12
- package/src/core/admin-contenteditable.js +12 -10
- package/src/core/admin-inputs.js +14 -15
- package/src/core/admin-onclick.js +2 -0
- package/src/core/autosave.js +74 -21
- package/src/core/conflict-download.js +22 -0
- package/src/core/conflict-notice-ui.js +1173 -0
- package/src/core/conflict-notice.js +140 -697
- package/src/core/edit-mode.js +147 -14
- package/src/core/etag.js +30 -12
- package/src/core/host-meta.js +72 -8
- package/src/core/host-permission.js +29 -0
- package/src/core/is-edit-mode.js +145 -12
- package/src/core/mode-key.js +125 -0
- package/src/core/mode-lifecycle.js +544 -0
- package/src/core/mode-receipt.js +30 -0
- package/src/core/mode-refusal.js +13 -0
- package/src/core/mode-resources.js +52 -0
- package/src/core/mode-support.js +82 -0
- package/src/core/mode-switch.js +259 -0
- package/src/core/mode-transition.js +112 -0
- package/src/core/page-data-write.js +305 -0
- package/src/core/page-data.js +26 -227
- package/src/core/page-format-wire.js +4 -0
- package/src/core/page-format.js +58 -0
- package/src/core/persist.js +37 -9
- package/src/core/preserve-authored.js +114 -0
- package/src/core/recovery.js +772 -0
- package/src/core/runtime-url.js +105 -0
- package/src/core/save-core.js +109 -12
- package/src/core/save-replace.js +72 -0
- package/src/core/save-size-notice.js +134 -0
- package/src/core/save-size.js +140 -0
- package/src/core/save.js +805 -118
- package/src/core/snapshot.js +121 -11
- package/src/core/source-map.js +157 -9
- package/src/core/unsaved-warning.js +14 -4
- package/src/core/upgrade-run.js +408 -0
- package/src/core/version.js +18 -0
- package/src/lib/assets.js +30 -0
- package/src/lib/autosave-debug-gate.js +50 -0
- package/src/lib/autosave-scheduler.js +141 -0
- package/src/lib/boot-imports.js +8 -0
- package/src/lib/derived.js +3 -1
- package/src/lib/dirty-gate.js +15 -0
- package/src/lib/doc-storage.js +33 -0
- package/src/lib/effect.js +9 -4
- package/src/lib/mutation.js +4 -2
- package/src/lib/offline-runtime.js +226 -0
- package/src/lib/preload.js +48 -0
- package/src/lib/root-attrs.js +1 -1
- package/src/lib/trash.js +18 -0
- package/src/lib/undo/capture-move.js +152 -0
- package/src/live/local-channel.js +61 -0
- package/src/live/local-lane.js +60 -9
- package/src/live/server-lane.js +6 -3
- package/src/loader-logic.js +76 -15
- package/src/loader.js +218 -30
- package/src/page/adopt-boot.js +76 -22
- package/src/page/adopt.js +25 -4
- package/src/page/awareness.js +230 -0
- package/src/page/blocks.js +79 -5
- package/src/page/blocksel.js +20 -4
- package/src/page/board-face.js +13 -0
- package/src/page/board-panel.js +5 -17
- package/src/page/board-style.js +2 -13
- package/src/page/board-view.js +1 -11
- package/src/page/board-views.js +17 -0
- package/src/page/board.js +2 -2
- package/src/page/boot-pack.js +26 -0
- package/src/page/boot.js +237 -0
- package/src/page/checklist.js +1 -1
- package/src/page/chrome.js +411 -61
- package/src/page/csv-import.js +17 -2
- package/src/page/document-title-dom.js +40 -0
- package/src/page/document-title-runtime.js +76 -0
- package/src/page/document-title.js +9 -0
- package/src/page/drag.js +48 -13
- package/src/page/drop.js +2 -1
- package/src/page/editor.js +330 -86
- package/src/page/feature-loader.js +72 -0
- package/src/page/features/board.js +12 -0
- package/src/page/features/code.js +13 -0
- package/src/page/features/media.js +290 -0
- package/src/page/features/registry.js +23 -0
- package/src/page/features/table.js +383 -0
- package/src/page/{tool-view.js → features/tool.js} +33 -2
- package/src/page/format-codec.js +215 -0
- package/src/page/format-gate.js +179 -0
- package/src/page/format-level.js +157 -0
- package/src/page/highlight-slot.js +23 -0
- package/src/page/highlight.js +30 -16
- package/src/page/history-intent.js +78 -0
- package/src/page/inline.js +18 -25
- package/src/page/items.js +52 -11
- package/src/page/link.js +1 -0
- package/src/page/markdown.js +86 -1
- package/src/page/media-views.js +3 -0
- package/src/page/media.js +33 -245
- package/src/page/outline-cache.js +11 -0
- package/src/page/placeholder.js +27 -7
- package/src/page/projection.js +196 -50
- package/src/page/reader-patch.js +306 -0
- package/src/page/recover.js +1 -1
- package/src/page/rich/page-tool.js +1 -4
- package/src/page/runtime-owner.js +27 -0
- package/src/page/save-projection.js +7 -4
- package/src/page/schema.js +14 -0
- package/src/page/table-rect-key.js +3 -0
- package/src/page/table-select.js +4 -3
- package/src/page/table-style.js +1 -1
- package/src/page/table-views.js +3 -0
- package/src/page/table.js +8 -293
- package/src/page/themes/light-1.css +139 -2
- package/src/page/themes/light-1.source.css +269 -0
- package/src/page/tool-capability.js +3 -0
- package/src/page/tool-views.js +3 -0
- package/src/page/view.js +390 -107
- package/src/page/ybind/awareness.js +172 -0
- package/src/page/ybind/binding.js +9 -1
- package/src/page/ybind/bridge.js +50 -47
- package/src/page/ybind/decode.js +52 -19
- package/src/page/ybind/doc.js +27 -2
- package/src/page/ybind/group.js +12 -3
- package/src/page/ybind/index.js +2 -0
- package/src/page/ybind/lineage.js +71 -0
- package/src/page/ybind/marks.js +25 -1
- package/src/page/ybind/migrate.js +48 -13
- package/src/page/ybind/moves.js +32 -21
- package/src/page/ybind/positions.js +50 -0
- package/src/page/ybind/provider.js +84 -22
- package/src/page/ybind/recovery-proof.js +191 -0
- package/src/page/ybind/recovery-replay.js +130 -0
- package/src/page/ybind/tokens.js +15 -6
- package/src/page/ybind/walk.js +10 -3
- package/src/page/ybind/writer.js +48 -4
- package/src/plugins/ai-edit.js +167 -32
- package/src/plugins/bind-text.js +218 -0
- package/src/plugins/cms.js +93 -0
- package/src/plugins/indicator.js +57 -5
- package/src/plugins/live.js +282 -34
- package/src/plugins/menu/claygoo.svg.js +1 -0
- package/src/plugins/menu/seo-head.js +323 -0
- package/src/plugins/menu/seo.js +849 -0
- package/src/plugins/menu.js +425 -0
- package/src/plugins/page-view.js +131 -0
- package/src/plugins/page.js +1022 -275
- package/src/plugins/people.js +158 -31
- package/src/plugins/richclay.js +119 -9
- package/src/plugins/sortable.js +370 -60
- package/src/plugins/source.js +189 -366
- package/src/plugins/undo.js +289 -19
- package/src/plugins/unsent.js +132 -0
- package/src/plugins/upgrade-run.js +1 -0
- package/src/plugins/upgrade.js +210 -0
- package/src/plugins/upload-task.js +571 -0
- package/src/plugins/upload-ui.js +265 -0
- package/src/plugins/upload.js +34 -153
- package/src/plugins/visitor-drafts/inert.js +32 -0
- package/src/plugins/visitor-drafts/owner-chip.js +3 -0
- package/src/plugins/visitor-drafts/prompt.js +2 -2
- package/src/plugins/visitor-drafts-owner.js +85 -0
- package/src/plugins/visitor-drafts.js +31 -42
- package/src/plugins/wire.js +82 -1
- package/src/reader-core.js +26 -0
- package/src/recovery/conflicts.js +287 -0
- package/src/recovery/identity.js +154 -0
- package/src/recovery/store.js +792 -0
- package/src/recovery/undo.js +257 -0
- package/src/server/checkpoint/index.js +68 -4
- package/src/server/offline-runtime/index.js +214 -0
- package/src/server/rooms/index.js +2 -1
- package/src/server/rooms/live-data-rooms.js +2 -2
- package/src/server/rooms/page-admission.js +33 -0
- package/src/server/rooms/page-lineage.js +56 -0
- package/src/server/rooms/page-rebase.js +11 -5
- package/src/server/rooms/page-state.js +2 -0
- package/src/server/rooms/page-write-admission.js +9 -3
- package/src/source/session.js +705 -0
- package/src/sync/conflict-revert.js +5 -4
- package/src/sync/conflicts-edit.js +119 -0
- package/src/sync/conflicts-facade.js +49 -0
- package/src/sync/conflicts.js +99 -1
- package/src/sync/editing-marker.js +37 -6
- package/src/sync/editing-sender.js +8 -1
- package/src/sync/live-sync-edit.js +63 -0
- package/src/sync/live-sync.js +364 -119
- package/src/sync/local-presence.js +187 -0
- package/src/sync/merge-declarations.js +10 -0
- package/src/sync/merge-engine.js +12 -0
- package/src/sync/presence-store.js +412 -0
- package/src/sync/presence-target.js +243 -0
- package/src/sync/presence.js +72 -41
- package/src/sync/saved-handoff.js +200 -0
- package/src/sync/saved-stream.js +535 -0
- package/src/sync/version-guard.js +92 -0
- package/src/sync/wire-profile.js +81 -0
- package/src/ui/bevel-controls.js +2 -8
- package/src/ui/page-scheme.js +7 -0
- package/src/ui/skins/cms.js +1 -1
- package/src/ui/theme-config.js +150 -0
- package/src/ui/theme.js +6 -138
- package/src/ui/toast-lazy.js +11 -0
- package/src/vendor/LICENSES-optional.md +253 -0
- package/src/vendor/highlight.vendor.js +3 -0
- package/src/vendor/hljs-bash.vendor.js +2 -0
- package/src/vendor/hljs-css.vendor.js +2 -0
- package/src/vendor/hljs-javascript.vendor.js +2 -0
- package/src/vendor/hljs-json.vendor.js +2 -0
- package/src/vendor/hljs-python.vendor.js +2 -0
- package/src/vendor/hljs-xml.vendor.js +2 -0
- package/src/vendor/hyper-html-api-data.vendor.js +1 -1
- package/src/vendor/hyper-html-api-upgrade.vendor.js +5 -0
- package/src/vendor/hyper-morph-identity.vendor.js +2 -0
- package/src/vendor/hyper-morph-json.vendor.js +3 -0
- package/src/vendor/hyper-morph.vendor.js +6 -6
- package/src/vendor/hyper-undo.vendor.js +1 -1
- package/src/vendor/hypercms.vendor.js +169 -84
- package/src/vendor/marked.vendor.js +68 -0
- package/src/vendor/overtype.vendor.js +994 -0
- package/src/vendor/richclay.vendor.js +17 -17
- package/src/vendor/sap-core.vendor.js +5 -5
- package/src/vendor/sap-ownership.vendor.js +11 -7
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
// Projecting an accepted saved file onto the article a reader is showing.
|
|
2
|
+
//
|
|
3
|
+
// The saved markup is already the rendered form of the writer's model, so this is
|
|
4
|
+
// not a second merge engine: it never combines concurrent authored changes. It only
|
|
5
|
+
// brings a read-only article up to one accepted file while keeping the nodes that
|
|
6
|
+
// file did not change, so a mounted tool, an open toggle and find-in-page survive.
|
|
7
|
+
//
|
|
8
|
+
// Identity comes from logical block `data-id` values. Lists and toggle bodies are
|
|
9
|
+
// walked; boards, tables, charts, media and tools are opaque interiors, so a board
|
|
10
|
+
// card id can never match an article block id. An id that appears twice is not
|
|
11
|
+
// reused at all: neither occurrence promises node identity.
|
|
12
|
+
|
|
13
|
+
const ARTICLE = "article[data-page]";
|
|
14
|
+
const TOOL = 'section[data-type="tool"][data-id]';
|
|
15
|
+
const CONTAINERS = new Set(["UL", "OL", "LI", "DETAILS"]);
|
|
16
|
+
const LISTS = new Set(["UL", "OL"]);
|
|
17
|
+
|
|
18
|
+
export const isTool = (el) => el.tagName === "SECTION" && el.getAttribute("data-type") === "tool" && el.hasAttribute("data-id");
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The tools an article holds, keyed by id, with the revision and artifact their
|
|
22
|
+
* root names. A decode failure is kept as `invalid` so a reader can say so and
|
|
23
|
+
* leave the saved fallback markup visible instead of mounting garbage.
|
|
24
|
+
*/
|
|
25
|
+
export function toolInfoOf(el) {
|
|
26
|
+
return toolInfo(el);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function toolInfo(el) {
|
|
30
|
+
const data = el.querySelector(':scope > script[type="application/json"][data-tool]');
|
|
31
|
+
let parsed = {};
|
|
32
|
+
try {
|
|
33
|
+
parsed = data ? JSON.parse(data.textContent) : {};
|
|
34
|
+
} catch (error) {
|
|
35
|
+
return { rev: null, artifact: null, state: {}, signature: null, invalid: true, error };
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
rev: parsed.rev ?? null,
|
|
39
|
+
artifact: parsed.artifact ?? null,
|
|
40
|
+
state: parsed.state ?? {},
|
|
41
|
+
signature: JSON.stringify(parsed.artifact ?? null),
|
|
42
|
+
invalid: false,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function toolsOf(root) {
|
|
47
|
+
const tools = new Map();
|
|
48
|
+
const duplicated = new Set();
|
|
49
|
+
for (const el of root.querySelectorAll(TOOL)) {
|
|
50
|
+
const id = el.getAttribute("data-id");
|
|
51
|
+
if (duplicated.has(id)) continue;
|
|
52
|
+
if (tools.has(id)) {
|
|
53
|
+
tools.delete(id);
|
|
54
|
+
duplicated.add(id);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
tools.set(id, toolInfo(el));
|
|
58
|
+
}
|
|
59
|
+
return tools;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function toolStateOf(doc) {
|
|
63
|
+
const tag = doc.querySelector('script[type="application/json"][merge="page.tools"]');
|
|
64
|
+
if (!tag) return {};
|
|
65
|
+
try { return JSON.parse(tag.textContent); } catch { return {}; }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function indexBlocks(root) {
|
|
69
|
+
const found = new Map();
|
|
70
|
+
const duplicated = new Set();
|
|
71
|
+
const walk = (container) => {
|
|
72
|
+
for (const child of container.children) {
|
|
73
|
+
const id = child.getAttribute("data-id");
|
|
74
|
+
if (id) {
|
|
75
|
+
if (duplicated.has(id)) continue;
|
|
76
|
+
if (found.has(id)) {
|
|
77
|
+
found.delete(id);
|
|
78
|
+
duplicated.add(id);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
found.set(id, child);
|
|
82
|
+
}
|
|
83
|
+
if (CONTAINERS.has(child.tagName)) walk(child);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
walk(root);
|
|
87
|
+
return found;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function retainedIds(root) {
|
|
91
|
+
const ids = new Set();
|
|
92
|
+
const walk = (container) => {
|
|
93
|
+
for (const child of container.children) {
|
|
94
|
+
const id = child.getAttribute("data-id");
|
|
95
|
+
if (id) ids.add(id);
|
|
96
|
+
if (CONTAINERS.has(child.tagName)) walk(child);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
walk(root);
|
|
100
|
+
return ids;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Validate one full saved file before anything is replaced. Exactly one page
|
|
105
|
+
* article must be present, and the bytes must be the string the host sent, not a
|
|
106
|
+
* live DOM snapshot.
|
|
107
|
+
*/
|
|
108
|
+
export function prepareSavedArticle(html, doc = document) {
|
|
109
|
+
if (typeof html !== "string" || html === "") return { ok: false, reason: "bytes" };
|
|
110
|
+
const parser = (doc.defaultView ?? globalThis).DOMParser;
|
|
111
|
+
if (typeof parser !== "function") return { ok: false, reason: "parser" };
|
|
112
|
+
const source = new parser().parseFromString(html, "text/html");
|
|
113
|
+
const articles = [...source.querySelectorAll(ARTICLE)];
|
|
114
|
+
if (articles.length !== 1) return { ok: false, reason: "article" };
|
|
115
|
+
const article = articles[0];
|
|
116
|
+
const savedOpen = new Map();
|
|
117
|
+
for (const details of article.querySelectorAll("details[data-id]")) {
|
|
118
|
+
savedOpen.set(details.getAttribute("data-id"), details.hasAttribute("open"));
|
|
119
|
+
}
|
|
120
|
+
const tools = toolsOf(article);
|
|
121
|
+
return {
|
|
122
|
+
ok: true,
|
|
123
|
+
article,
|
|
124
|
+
source,
|
|
125
|
+
rev: article.getAttribute("data-rev"),
|
|
126
|
+
title: source.title || null,
|
|
127
|
+
savedOpen,
|
|
128
|
+
tools,
|
|
129
|
+
toolState: tools.size ? toolStateOf(source) : {},
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export const keepToolVersion = (live, incoming) => {
|
|
134
|
+
const a = toolInfo(live);
|
|
135
|
+
const b = toolInfo(incoming);
|
|
136
|
+
return !a.invalid && !b.invalid && a.rev === b.rev && a.signature === b.signature;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Apply one prepared file to the live article. Returns whether anything changed.
|
|
141
|
+
*
|
|
142
|
+
* Each container's children are reconciled in saved order: an equal keyed block is
|
|
143
|
+
* reused, a compatible keyed block is moved rather than cloned, a changed ordinary
|
|
144
|
+
* leaf is replaced, and a changed list or toggle is recursed into so its unchanged
|
|
145
|
+
* descendants survive. A tool whose id, revision and artifact still match is left
|
|
146
|
+
* untouched: its runtime subtree and reader-local interaction state are the host's.
|
|
147
|
+
*/
|
|
148
|
+
export function applyPreparedArticle(prepared, { article, readerOpen = new Map(), savedOpen = null, keepTool = keepToolVersion } = {}) {
|
|
149
|
+
if (!prepared?.ok || !article) return { changed: false };
|
|
150
|
+
for (const details of prepared.article.querySelectorAll("details[data-id]")) {
|
|
151
|
+
const id = details.getAttribute("data-id");
|
|
152
|
+
if (!readerOpen.has(id)) continue;
|
|
153
|
+
if (details.hasAttribute("open") !== readerOpen.get(id)) details.toggleAttribute("open", readerOpen.get(id));
|
|
154
|
+
}
|
|
155
|
+
const index = indexBlocks(article);
|
|
156
|
+
const used = new Set();
|
|
157
|
+
let changed = false;
|
|
158
|
+
|
|
159
|
+
const fresh = (incoming) => {
|
|
160
|
+
changed = true;
|
|
161
|
+
return incoming.cloneNode(true);
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const matchingUnkeyed = (incoming, container) => {
|
|
165
|
+
const wanted = retainedIds(incoming);
|
|
166
|
+
for (const live of container.children) {
|
|
167
|
+
if (used.has(live) || live.hasAttribute("data-id")) continue;
|
|
168
|
+
if (live.tagName !== incoming.tagName) continue;
|
|
169
|
+
if (!wanted.size) return live;
|
|
170
|
+
const have = retainedIds(live);
|
|
171
|
+
for (const id of wanted) if (have.has(id)) return live;
|
|
172
|
+
}
|
|
173
|
+
return null;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const matchingLeaf = (incoming, container) => {
|
|
177
|
+
for (const live of container.children) {
|
|
178
|
+
if (used.has(live) || live.hasAttribute("data-id")) continue;
|
|
179
|
+
if (live.tagName === incoming.tagName) return live;
|
|
180
|
+
}
|
|
181
|
+
return null;
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const syncAttributes = (live, incoming, skip = null) => {
|
|
185
|
+
for (const { name, value } of [...incoming.attributes]) {
|
|
186
|
+
if (name === skip || live.getAttribute(name) === value) continue;
|
|
187
|
+
live.setAttribute(name, value);
|
|
188
|
+
changed = true;
|
|
189
|
+
}
|
|
190
|
+
for (const { name } of [...live.attributes]) {
|
|
191
|
+
if (name === skip || incoming.hasAttribute(name)) continue;
|
|
192
|
+
live.removeAttribute(name);
|
|
193
|
+
changed = true;
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const reuseNode = (incoming, live, at) => {
|
|
198
|
+
const same = (candidate) =>
|
|
199
|
+
candidate && candidate.nodeType === incoming.nodeType && candidate.nodeValue === incoming.nodeValue && !used.has(candidate);
|
|
200
|
+
const found = same(live.childNodes[at]) ? live.childNodes[at] : [...live.childNodes].find(same);
|
|
201
|
+
if (!found) return incoming.cloneNode(true);
|
|
202
|
+
used.add(found);
|
|
203
|
+
return found;
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const reconcileContainer = (live, incoming) => {
|
|
207
|
+
const ordered = [];
|
|
208
|
+
const children = [...incoming.childNodes];
|
|
209
|
+
for (let i = 0; i < children.length; i++) {
|
|
210
|
+
const child = children[i];
|
|
211
|
+
if (child.nodeType !== 1) {
|
|
212
|
+
ordered.push(reuseNode(child, live, i));
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
const node = pick(child, live);
|
|
216
|
+
used.add(node);
|
|
217
|
+
ordered.push(node);
|
|
218
|
+
}
|
|
219
|
+
const kept = new Set(ordered);
|
|
220
|
+
let walk = live.firstChild;
|
|
221
|
+
for (const node of ordered) {
|
|
222
|
+
while (walk && !kept.has(walk)) walk = walk.nextSibling;
|
|
223
|
+
if (walk === node) {
|
|
224
|
+
walk = walk.nextSibling;
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
live.insertBefore(node, walk);
|
|
228
|
+
changed = true;
|
|
229
|
+
}
|
|
230
|
+
for (const child of [...live.childNodes]) {
|
|
231
|
+
if (kept.has(child)) continue;
|
|
232
|
+
child.remove();
|
|
233
|
+
changed = true;
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
const freshShell = (incoming) => {
|
|
238
|
+
changed = true;
|
|
239
|
+
const node = incoming.cloneNode(false);
|
|
240
|
+
reconcileContainer(node, incoming);
|
|
241
|
+
return node;
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
const reconcileDetails = (live, incoming) => {
|
|
245
|
+
changed = true;
|
|
246
|
+
const id = live.getAttribute("data-id");
|
|
247
|
+
const open = readerOpen.has(id) ? readerOpen.get(id) : incoming.hasAttribute("open");
|
|
248
|
+
syncAttributes(live, incoming, "open");
|
|
249
|
+
if (live.hasAttribute("open") !== open) live.toggleAttribute("open", open);
|
|
250
|
+
reconcileContainer(live, incoming);
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
const reconcileItem = (live, incoming) => {
|
|
254
|
+
changed = true;
|
|
255
|
+
syncAttributes(live, incoming);
|
|
256
|
+
reconcileContainer(live, incoming);
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
function pick(incoming, container) {
|
|
260
|
+
const id = incoming.getAttribute("data-id");
|
|
261
|
+
if (id) {
|
|
262
|
+
const live = index.get(id);
|
|
263
|
+
if (!live || used.has(live) || live === container || live.contains(container)) return fresh(incoming);
|
|
264
|
+
used.add(live);
|
|
265
|
+
if (isTool(live) && isTool(incoming)) return keepTool(live, incoming) ? live : fresh(incoming);
|
|
266
|
+
if (live.tagName !== incoming.tagName) return fresh(incoming);
|
|
267
|
+
if (live.isEqualNode(incoming)) return live;
|
|
268
|
+
if (incoming.tagName === "DETAILS") {
|
|
269
|
+
reconcileDetails(live, incoming);
|
|
270
|
+
return live;
|
|
271
|
+
}
|
|
272
|
+
if (incoming.tagName === "LI") {
|
|
273
|
+
reconcileItem(live, incoming);
|
|
274
|
+
return live;
|
|
275
|
+
}
|
|
276
|
+
if (LISTS.has(incoming.tagName)) {
|
|
277
|
+
syncAttributes(live, incoming);
|
|
278
|
+
reconcileContainer(live, incoming);
|
|
279
|
+
return live;
|
|
280
|
+
}
|
|
281
|
+
return fresh(incoming);
|
|
282
|
+
}
|
|
283
|
+
if (LISTS.has(incoming.tagName)) {
|
|
284
|
+
const live = matchingUnkeyed(incoming, container);
|
|
285
|
+
if (!live) return freshShell(incoming);
|
|
286
|
+
used.add(live);
|
|
287
|
+
syncAttributes(live, incoming);
|
|
288
|
+
reconcileContainer(live, incoming);
|
|
289
|
+
return live;
|
|
290
|
+
}
|
|
291
|
+
const live = matchingLeaf(incoming, container);
|
|
292
|
+
if (!live) return fresh(incoming);
|
|
293
|
+
used.add(live);
|
|
294
|
+
if (live.isEqualNode(incoming)) return live;
|
|
295
|
+
changed = true;
|
|
296
|
+
return fresh(incoming);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
reconcileContainer(article, prepared.article);
|
|
300
|
+
if (savedOpen) {
|
|
301
|
+
savedOpen.clear();
|
|
302
|
+
for (const [id, open] of prepared.savedOpen) savedOpen.set(id, open);
|
|
303
|
+
}
|
|
304
|
+
for (const id of [...readerOpen.keys()]) if (!prepared.savedOpen.has(id)) readerOpen.delete(id);
|
|
305
|
+
return { changed };
|
|
306
|
+
}
|
package/src/page/recover.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import toast, { toastPersistent, dismissPersistent } from "../ui/toast.js";
|
|
1
|
+
import toast, { toastPersistent, dismissPersistent } from "../ui/toast-lazy.js";
|
|
2
2
|
import { state as pmState } from "../vendor/prosemirror.vendor.js";
|
|
3
3
|
|
|
4
4
|
export const NOTICE_TEXT = "Some text you typed was kept aside when its block moved or was removed.";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { cloneJson } from "../../live/ops.js";
|
|
2
2
|
import { validateArtifact, validateState } from "./tool-runtime.js";
|
|
3
|
+
export { capabilityAdvertised } from "../tool-capability.js";
|
|
3
4
|
|
|
4
5
|
const CONTEXT_LIMIT = 16384;
|
|
5
6
|
const bytes = (value) => new TextEncoder().encode(JSON.stringify(value)).length;
|
|
@@ -30,10 +31,6 @@ function trimmedContext(context) {
|
|
|
30
31
|
return copy;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
export function capabilityAdvertised(meta) {
|
|
34
|
-
return Array.isArray(meta?.extensions) && meta.extensions.includes("page-tool/1");
|
|
35
|
-
}
|
|
36
|
-
|
|
37
34
|
export function createToolClient({ transport, newId }) {
|
|
38
35
|
let active = null;
|
|
39
36
|
const discard = (candidate) => {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// One runtime owns an article at a time. A reader owns the article it projects;
|
|
2
|
+
// the editor owns it from the moment it mounts, including the noneditable period
|
|
3
|
+
// while saved feature views are still arriving. A mode flag is not enough: two
|
|
4
|
+
// runtimes both think they may write, and a late frame lands over a mounted tool.
|
|
5
|
+
//
|
|
6
|
+
// The kind is diagnostic, not permission to share. A second claim on the same
|
|
7
|
+
// article throws even when it names the same kind, so a double start fails loudly
|
|
8
|
+
// instead of leaving two listeners on one article.
|
|
9
|
+
|
|
10
|
+
const owners = new WeakMap();
|
|
11
|
+
|
|
12
|
+
export function claim(article, kind) {
|
|
13
|
+
if (!article || article.nodeType !== 1) throw new TypeError("clayjs: claim needs an element to own");
|
|
14
|
+
if (owners.has(article)) throw new Error(`clayjs: the article already has a ${owners.get(article).kind} runtime`);
|
|
15
|
+
const token = { kind: String(kind ?? "runtime"), active: true };
|
|
16
|
+
owners.set(article, token);
|
|
17
|
+
return function release() {
|
|
18
|
+
if (!token.active) return false;
|
|
19
|
+
token.active = false;
|
|
20
|
+
if (owners.get(article) === token) owners.delete(article);
|
|
21
|
+
return true;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function ownerOf(article) {
|
|
26
|
+
return owners.get(article)?.kind ?? null;
|
|
27
|
+
}
|
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
// never run after this and undo it.
|
|
6
6
|
import "../attrs/save-freeze.js";
|
|
7
7
|
import { addDocumentTransform } from "../core/snapshot.js";
|
|
8
|
-
import {
|
|
8
|
+
import { parseJsonRelaxed } from "../vendor/hyper-morph-json.vendor.js";
|
|
9
9
|
import { fragmentCleaner, project, renderModel, revOf } from "./projection.js";
|
|
10
|
+
import { documentTitle } from "./document-title.js";
|
|
11
|
+
import { customTitle, writeTitle } from "./document-title-dom.js";
|
|
10
12
|
import { blocksFromPageValues } from "./ybind/decode.js";
|
|
11
13
|
import { YDecodeError } from "./ybind/provider.js";
|
|
12
14
|
|
|
@@ -27,7 +29,7 @@ export function renderFromTags(texts) {
|
|
|
27
29
|
const key = texts.join("\u0000");
|
|
28
30
|
if (memo && memo.key === key) return memo;
|
|
29
31
|
const values = texts.map((text) => {
|
|
30
|
-
try { return
|
|
32
|
+
try { return parseJsonRelaxed(text); }
|
|
31
33
|
catch { throw new YDecodeError("invalid-json", "Cannot read the page data as JSON"); }
|
|
32
34
|
});
|
|
33
35
|
const blocks = blocksFromPageValues(values);
|
|
@@ -36,7 +38,7 @@ export function renderFromTags(texts) {
|
|
|
36
38
|
const html = blocks[id]?.artifact?.fallbackHtml;
|
|
37
39
|
return typeof html === "string" ? html : "";
|
|
38
40
|
};
|
|
39
|
-
memo = { key, html: renderModel(model, { fallbackOf, clean: fragmentCleaner(document) }), rev: revOf(model) };
|
|
41
|
+
memo = { key, html: renderModel(model, { fallbackOf, clean: fragmentCleaner(document) }), rev: revOf(model), model, title: documentTitle(model) };
|
|
40
42
|
return memo;
|
|
41
43
|
}
|
|
42
44
|
|
|
@@ -45,9 +47,10 @@ export function projectInto(clone) {
|
|
|
45
47
|
if (!article) return;
|
|
46
48
|
const tags = pageTags(clone);
|
|
47
49
|
if (!tags.length) return;
|
|
48
|
-
const { html, rev } = renderFromTags(tags.map((el) => el.textContent));
|
|
50
|
+
const { html, rev, title } = renderFromTags(tags.map((el) => el.textContent));
|
|
49
51
|
if (article.innerHTML !== html) article.innerHTML = html;
|
|
50
52
|
article.setAttribute("data-rev", rev);
|
|
53
|
+
if (!customTitle(clone)) writeTitle(clone, title);
|
|
51
54
|
}
|
|
52
55
|
|
|
53
56
|
addDocumentTransform(projectInto);
|
package/src/page/schema.js
CHANGED
|
@@ -141,6 +141,20 @@ export const schema = new model.Schema({
|
|
|
141
141
|
attrs: { ...block, html: { default: "" } },
|
|
142
142
|
toDOM: (n) => ["div", ref(n, { "data-type": "preserved" })],
|
|
143
143
|
},
|
|
144
|
+
// A block type a newer peer wrote and this runtime has no schema for. It keeps
|
|
145
|
+
// the original record in raw and its inline content for mapping, and it shows
|
|
146
|
+
// an inert fallback: no content DOM to edit, no command that rewrites it.
|
|
147
|
+
opaque_block: {
|
|
148
|
+
group: "block",
|
|
149
|
+
content: "inline*",
|
|
150
|
+
atom: true,
|
|
151
|
+
isolating: true,
|
|
152
|
+
selectable: true,
|
|
153
|
+
attrs: { ...block, raw: { default: null } },
|
|
154
|
+
toDOM: (n) => ["div", ref(n, { "data-type": "newer-format", "data-format": String(n.attrs.raw?.t ?? ""), contenteditable: "false" }),
|
|
155
|
+
["span", { class: "page-newer-format" }, `Newer format: ${String(n.attrs.raw?.t ?? "")}`],
|
|
156
|
+
["span", { class: "page-newer-format-text" }, n.textContent]],
|
|
157
|
+
},
|
|
144
158
|
|
|
145
159
|
text: { group: "inline" },
|
|
146
160
|
hard_break: {
|
package/src/page/table-select.js
CHANGED
|
@@ -11,10 +11,11 @@ import { clipboardSerializer } from "./blocks.js";
|
|
|
11
11
|
import { asStep } from "./blocksel.js";
|
|
12
12
|
import { announce } from "./announce.js";
|
|
13
13
|
import { REMOTE_META } from "./ybind/layout.js";
|
|
14
|
+
import { rectKey } from "./table-rect-key.js";
|
|
14
15
|
|
|
15
|
-
const { Plugin,
|
|
16
|
+
const { Plugin, TextSelection } = state;
|
|
16
17
|
const N = schema.nodes;
|
|
17
|
-
export
|
|
18
|
+
export { rectKey };
|
|
18
19
|
|
|
19
20
|
const findTable = (doc, id) => {
|
|
20
21
|
let found = null;
|
|
@@ -171,7 +172,7 @@ export function tableSelectPlugin() {
|
|
|
171
172
|
const step = { ArrowUp: [-1, 0], ArrowDown: [1, 0], ArrowLeft: [0, -1], ArrowRight: [0, 1] }[event.key];
|
|
172
173
|
if (step) return extend(...step)(st, view.dispatch, view);
|
|
173
174
|
}
|
|
174
|
-
if (MODIFIERS.has(event.key) || ((event.metaKey || event.ctrlKey) && (event.key === "c" || event.key === "x" || event.key === "v"))) return false;
|
|
175
|
+
if (MODIFIERS.has(event.key) || ((event.metaKey || event.ctrlKey) && (event.key === "a" || event.key === "c" || event.key === "x" || event.key === "v"))) return false;
|
|
175
176
|
view.dispatch(st.tr.setMeta(rectKey, null));
|
|
176
177
|
return false;
|
|
177
178
|
},
|
package/src/page/table-style.js
CHANGED
|
@@ -8,7 +8,7 @@ export const TABLE_CSS = `
|
|
|
8
8
|
.page-table table.is-sized { table-layout: fixed; min-width: 0; }
|
|
9
9
|
.page-table table.is-sized th, .page-table table.is-sized td { min-width: 0; overflow-wrap: anywhere; }
|
|
10
10
|
.page-table-resize { position: absolute; top: 0; bottom: 0; inset-inline-end: -4px; width: 8px; z-index: 2; cursor: col-resize; touch-action: none; }
|
|
11
|
-
.page-table-resize:hover, .page-table-resize:active { background: var(--page-accent); opacity: 0.4; }
|
|
11
|
+
.page-table-resize:hover, .page-table-resize:active, .page-table-resize:focus-visible { background: var(--page-accent); opacity: 0.4; }
|
|
12
12
|
.page-table-add-row, .page-table-add-col { position: absolute; z-index: 1; border: 0; padding: 0; background: var(--page-chrome-bg-rest); color: var(--page-chrome-ink-rest); font: inherit; line-height: 1; cursor: pointer; opacity: 0; transition: opacity 120ms; }
|
|
13
13
|
.page-table-add-row { left: 0; right: 0; top: 100%; height: 14px; border-radius: 0 0 6px 6px; }
|
|
14
14
|
.page-table-add-col { top: 0; bottom: 0; left: 100%; width: 14px; border-radius: 0 6px 6px 0; }
|