@panphora/clayjs 1.16.0 → 1.18.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/dist/all.js +1 -1
- 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 +72519 -59839
- package/dist/m/attrs/refetch-on-save-ZUE7PSCI.js +1 -0
- package/dist/m/attrs/save-freeze-LWGF6XUN.js +1 -0
- package/dist/m/c-2GRUM77Q.js +30 -0
- package/dist/m/c-2KIEGNC4.js +1 -0
- package/dist/m/{c-5R4PTRG2.js → c-2KL3BD52.js} +1 -1
- package/dist/m/c-2YYDMLNZ.js +1 -0
- package/dist/m/c-2ZZBC45O.js +1 -0
- package/dist/m/c-372N6H3B.js +1 -0
- package/dist/m/{c-4WKFKEKF.js → c-3G2DGZUP.js} +1 -1
- package/dist/m/c-3LDGIBMN.js +1 -0
- package/dist/m/c-3O7OBDCM.js +1 -0
- package/dist/m/c-4ASQPRQL.js +1 -0
- package/dist/m/c-4TXNLX4K.js +6 -0
- package/dist/m/c-4YU3BR4D.js +6 -0
- package/dist/m/c-5734MF2P.js +1 -0
- package/dist/m/c-57XDY6HC.js +1 -0
- package/dist/m/{c-VFX45IZQ.js → c-5B4YBZXC.js} +1 -1
- package/dist/m/c-5ONTYIUI.js +1 -0
- package/dist/m/c-5OOVFCJM.js +1 -0
- package/dist/m/c-5T6NZHNM.js +1 -0
- package/dist/m/{c-YDH7Q3NY.js → c-5ZQV7KC4.js} +1 -1
- package/dist/m/{c-Z36J63PP.js → c-6DB2OLRJ.js} +1 -1
- package/dist/m/c-6DNRCPNM.js +1 -0
- package/dist/m/c-6UGWFMQC.js +2 -0
- package/dist/m/c-7K4SCQB7.js +1 -0
- package/dist/m/c-7MG5RU63.js +1 -0
- package/dist/m/c-7PRJCA3E.js +1 -0
- package/dist/m/c-A6L3FMUS.js +1 -0
- package/dist/m/c-AMU3BPPR.js +4 -0
- package/dist/m/c-AMYEFA2E.js +1 -0
- package/dist/m/c-AQYCG7QW.js +1 -0
- package/dist/m/c-ATKAOH23.js +1 -0
- package/dist/m/c-B3JM5ZXC.js +1 -0
- package/dist/m/c-B5CS55WR.js +1 -0
- package/dist/m/c-B5UJQT7W.js +1 -0
- package/dist/m/c-B7J4K2AE.js +3 -0
- package/dist/m/c-BHZYSHW4.js +1 -0
- package/dist/m/c-BIJALSRD.js +1 -0
- package/dist/m/c-BJ7YQ5QZ.js +1 -0
- package/dist/m/c-BPF2NSPV.js +1 -0
- package/dist/m/{c-KIPQJX4B.js → c-BRLCTNMC.js} +1 -1
- package/dist/m/c-BUAYFEV5.js +1 -0
- package/dist/m/c-C6IPRG34.js +1 -0
- package/dist/m/{c-2JL6E75N.js → c-CAS3NND4.js} +1 -1
- package/dist/m/{c-4DRMS4QG.js → c-CCQ25GFY.js} +1 -1
- package/dist/m/c-CJFDLD43.js +1 -0
- package/dist/m/c-COPTL5WB.js +1 -0
- package/dist/m/c-D3E4WJ4M.js +166 -0
- package/dist/m/c-D5IKEKXW.js +7 -0
- package/dist/m/c-DHBRA6DL.js +1 -0
- package/dist/m/c-DKLS74XB.js +72 -0
- package/dist/m/c-DVYGFTSK.js +3 -0
- package/dist/m/c-E3ZXARWA.js +1 -0
- package/dist/m/c-EK63G3CG.js +1 -0
- package/dist/m/c-ERQSNR6K.js +13 -0
- package/dist/m/c-EVYAISP3.js +1 -0
- package/dist/m/c-EXKHPOVC.js +3 -0
- package/dist/m/{c-7VGZ7RU5.js → c-FWKHM4E7.js} +1 -1
- package/dist/m/{c-4Q2XTQ2N.js → c-GBKB5WDL.js} +1 -1
- package/dist/m/c-GNDL3TKB.js +1 -0
- package/dist/m/c-GRWMD6O5.js +1 -0
- package/dist/m/c-GRXHHFPO.js +1 -0
- package/dist/m/{c-OYTFP5QN.js → c-GY422N3Q.js} +1 -1
- package/dist/m/c-HAWFNBYG.js +1 -0
- package/dist/m/c-HG2C77BM.js +4 -0
- package/dist/m/c-HHGJBU4D.js +1 -0
- package/dist/m/c-HMV6P4RX.js +1 -0
- package/dist/m/c-HMYWIHFG.js +1 -0
- package/dist/m/c-HT2DKBV2.js +1 -0
- package/dist/m/c-I2SCCUEW.js +1 -0
- package/dist/m/{c-HRDCD3WN.js → c-ICJYHABF.js} +2 -2
- package/dist/m/c-IMZCWYHR.js +7 -0
- package/dist/m/c-IVMD3FEM.js +1 -0
- package/dist/m/c-IVTRVENZ.js +1 -0
- package/dist/m/c-IW6GGOU2.js +1 -0
- package/dist/m/c-JKZJIUIP.js +1 -0
- package/dist/m/{c-NZMNXVF6.js → c-JNLX3RJB.js} +1 -1
- package/dist/m/c-JRKY44DK.js +1 -0
- package/dist/m/c-K3ADYNLU.js +1 -0
- package/dist/m/c-KBS3UV6B.js +1 -0
- package/dist/m/c-KGHVFRR3.js +1 -0
- package/dist/m/c-KJJPV77R.js +1 -0
- package/dist/m/{c-CZUSOB7V.js → c-KNPDOMDY.js} +1 -1
- package/dist/m/{c-5Y6TNX5W.js → c-KP64LT2A.js} +2 -2
- package/dist/m/c-KQ7E3PYY.js +1 -0
- package/dist/m/c-L3F5ZLIV.js +1 -0
- package/dist/m/{c-LR4CGEPT.js → c-L42OLXWM.js} +3 -2
- package/dist/m/c-L5VFATT6.js +1 -0
- package/dist/m/c-L7JL5TL3.js +3 -0
- package/dist/m/c-LKSL4AUJ.js +1 -0
- package/dist/m/c-M6FNQCTQ.js +1 -0
- package/dist/m/c-MCOOHCSG.js +1 -0
- package/dist/m/c-MHI3GYKF.js +1 -0
- package/dist/m/c-MWXFLW4J.js +1 -0
- package/dist/m/c-NEL7HQW3.js +1 -0
- package/dist/m/c-NQJRVJ56.js +1 -0
- package/dist/m/c-NWX3MFT4.js +1 -0
- package/dist/m/{c-HPURYVZS.js → c-OJYM642Q.js} +1 -1
- package/dist/m/c-OKXI52N7.js +1 -0
- package/dist/m/{c-MMUIUUZG.js → c-OPLUZR3A.js} +1 -1
- package/dist/m/{c-J7CA54IP.js → c-OTMKN2OO.js} +1 -1
- package/dist/m/{c-LTGMXXKO.js → c-OYRZ7XG2.js} +1 -1
- package/dist/m/c-P3OFYUMA.js +1 -0
- package/dist/m/c-PLN76GF3.js +6 -0
- package/dist/m/c-PLP4JKFC.js +1 -0
- package/dist/m/c-Q26MME6N.js +1 -0
- package/dist/m/{c-S7H2DRCB.js → c-Q3XOWZEV.js} +1 -1
- package/dist/m/{c-SWRJFCNN.js → c-QIKT6SKM.js} +1 -1
- package/dist/m/c-QIXT3Q7C.js +28 -0
- package/dist/m/c-QO4HNGCQ.js +1 -0
- package/dist/m/c-R27DWQKX.js +1 -0
- package/dist/m/{c-HVYXIS72.js → c-R2XUODVY.js} +1 -1
- package/dist/m/{c-QNKREOL6.js → c-R7LBFMF5.js} +1 -1
- package/dist/m/c-RND3G2S2.js +1 -0
- package/dist/m/c-S2U6NJU4.js +1 -0
- package/dist/m/c-SPZPGD3R.js +1 -0
- package/dist/m/c-SW4YEG2D.js +8 -0
- package/dist/m/c-SZGYW5HT.js +1 -0
- package/dist/m/c-T637T7SN.js +1 -0
- package/dist/m/c-TJAXGIRV.js +1 -0
- package/dist/m/{c-KKWLDOPM.js → c-TNEM3RNM.js} +1 -1
- package/dist/m/c-TTB5EK4S.js +32 -0
- package/dist/m/c-U7SHNWDH.js +1 -0
- package/dist/m/c-UDHIVLYH.js +20 -0
- package/dist/m/{c-BBVGTQG7.js → c-UGNV5MFB.js} +1 -1
- package/dist/m/{c-TQZ2JYHD.js → c-UORXLSD3.js} +1 -1
- package/dist/m/c-UPD33ZPE.js +1 -0
- package/dist/m/c-URSMSFCB.js +1 -0
- package/dist/m/c-UY4QX42B.js +1 -0
- package/dist/m/c-V44KWI2L.js +4 -0
- package/dist/m/c-VG5XIN4T.js +1 -0
- package/dist/m/c-VILENZTD.js +1 -0
- package/dist/m/{c-33HUYEDI.js → c-VJYEVRYK.js} +1 -1
- package/dist/m/c-VR2BJ4AN.js +1 -0
- package/dist/m/c-W4JCVLAB.js +1 -0
- package/dist/m/c-W6DQSHXI.js +135 -0
- package/dist/m/c-WBGWGOM7.js +1 -0
- package/dist/m/{c-4L3BTFRK.js → c-WCXLG3MV.js} +1 -1
- package/dist/m/c-WGW764WX.js +1 -0
- package/dist/m/c-WMRJKQ2V.js +5 -0
- package/dist/m/c-WNTYKCDG.js +1 -0
- package/dist/m/c-WQWIRWO3.js +72 -0
- package/dist/m/c-X5LNHET5.js +1 -0
- package/dist/m/c-X5TSXZYJ.js +2 -0
- package/dist/m/c-XGH4GS2T.js +1 -0
- package/dist/m/c-Y6F2FORL.js +1 -0
- package/dist/m/c-YBKHUAK7.js +10 -0
- package/dist/m/c-YBSS55KU.js +20 -0
- package/dist/m/c-YCLU4UNT.js +2 -0
- package/dist/m/c-YVZ2L7CE.js +1 -0
- package/dist/m/c-ZK4GIZH2.js +1 -0
- package/dist/m/c-ZRXJD4G6.js +1 -0
- package/dist/m/c-ZWBI4HYK.js +1 -0
- package/dist/m/{c-HT33EQRN.js → c-ZWIOJGMT.js} +1 -1
- package/dist/m/core/admin-attrs-YY7T5FGU.js +1 -0
- package/dist/m/core/autosave-S6OMNDCK.js +1 -0
- package/dist/m/core/conflict-notice-IWHMHH43.js +1 -0
- package/dist/m/core/host-permission-6EVJGNPL.js +1 -0
- package/dist/m/core/is-edit-mode-GCX6767E.js +1 -0
- package/dist/m/core/{persist-HKHA66IY.js → persist-UKXV5KLA.js} +1 -1
- package/dist/m/core/recovery-DRFZRJED.js +1 -0
- package/dist/m/core/save-LYY7K6U7.js +1 -0
- package/dist/m/core/save-core-MKRPSEEO.js +1 -0
- package/dist/m/core/snapshot-NU3YM6GR.js +1 -0
- package/dist/m/core/unsaved-warning-7QTKEN7Z.js +1 -0
- package/dist/m/events/index-RN2JNGBV.js +1 -0
- package/dist/m/internals/index-TGLQINN3.js +1 -0
- package/dist/m/lib/cache-bust-MUMFXZK6.js +1 -0
- package/dist/m/loader-3BBNZZGM.js +1 -0
- package/dist/m/manifest-F449FF98.js +1 -0
- package/dist/m/manifest-edit-4396A009.js +1 -0
- package/dist/m/manifest.json +2509 -1474
- package/dist/m/options/options-EJMS3K24.js +1 -0
- package/dist/m/page/editor-6LRB3GE4.js +304 -0
- package/dist/m/plugins/ai-edit-UTV7YO2I.js +6 -0
- package/dist/m/plugins/{cms-HP3LSTPN.js → cms-LRAOZHT7.js} +9 -9
- package/dist/m/plugins/demo-OYO5GCAO.js +1 -0
- package/dist/m/plugins/{derive-UAAA4V4S.js → derive-FRE5JJQE.js} +1 -1
- package/dist/m/plugins/indicator-4VDXWYTD.js +1 -0
- package/dist/m/plugins/live-AD4H6XSL.js +1 -0
- package/dist/m/plugins/menu-M5WW7DBF.js +1 -0
- package/dist/m/plugins/page-MD3T2ZX3.js +2 -0
- package/dist/m/plugins/page-view-PAWVZNFY.js +1 -0
- package/dist/m/plugins/people-JCHVPF7P.js +1 -0
- package/dist/m/plugins/quickcrop-BQ5YYFCH.js +26 -0
- package/dist/m/plugins/{richclay-RC3L2F6X.js → richclay-KLGETK77.js} +2 -2
- package/dist/m/plugins/sortable-4S6SQC3D.js +1 -0
- package/dist/m/plugins/source-TJXOIOYY.js +1 -0
- package/dist/m/plugins/undo-NLPGCJQY.js +1 -0
- package/dist/m/plugins/{unsent-HJFLQJ2O.js → unsent-OA4RGBUT.js} +1 -1
- package/dist/m/plugins/upgrade-HSUNDNJD.js +1 -0
- package/dist/m/plugins/upload-NHGJXZK2.js +1 -0
- package/dist/m/plugins/visitor-drafts-BW43DGY3.js +20 -0
- package/dist/m/plugins/visitor-drafts-owner-7ODQG7JX.js +1 -0
- package/dist/m/plugins/wire-VBWXEXU2.js +1 -0
- package/dist/m/reader-core-4W2KYEWQ.js +77 -0
- package/dist/m/route/route-62CHXL5B.js +1 -0
- package/dist/m/sync/live-sync-MO5DH33W.js +1 -0
- package/dist/m/ui/index-IVWN2QC4.js +1 -0
- package/dist/m/vendor/sap-core.vendor-RN4ZVY4X.js +6 -0
- package/dist/offline-manifest.json +1560 -889
- package/dist/page/themes/light-1.css +33 -8
- package/dist/server/core.cjs +1554 -311
- package/dist/server/offline-runtime.cjs +63 -63
- package/dist/server/offline-runtime.mjs +63 -63
- package/dist/server/page-compaction-worker.cjs +3710 -0
- package/dist/server/rooms.mjs +5 -0
- package/docs/guide.md +653 -101
- package/entries/sap.js +5 -5
- package/package.json +1 -1
- package/src/core/admin-contenteditable.js +5 -2
- package/src/core/admin-inputs.js +1 -0
- package/src/core/admin-onclick.js +2 -1
- package/src/core/boot-phase.js +2 -1
- package/src/core/conflict-download.js +3 -29
- package/src/core/conflict-notice-ui.js +4 -7
- package/src/core/download.js +32 -0
- package/src/core/host-meta.js +56 -0
- package/src/core/is-edit-mode.js +17 -1
- package/src/core/mode-key.js +125 -19
- package/src/core/mode-support.js +5 -0
- package/src/core/mode-transition.js +20 -6
- package/src/core/preserve-authored.js +4 -4
- package/src/core/recovery.js +121 -33
- package/src/core/save-accepted.js +33 -0
- package/src/core/save-core.js +111 -32
- package/src/core/save-job.js +108 -0
- package/src/core/save-prepare.js +53 -0
- package/src/core/save-size-notice.js +3 -1
- package/src/core/save-slices.js +15 -0
- package/src/core/save.js +557 -127
- package/src/core/serialize-steps.js +109 -0
- package/src/core/snapshot.js +209 -40
- package/src/core/source-map.js +83 -38
- package/src/core/stale-host-notice.js +1 -0
- package/src/core/upgrade-run.js +59 -8
- package/src/dom/active-element.js +5 -0
- package/src/lib/assets.js +1 -0
- package/src/lib/autosave-scheduler.js +3 -4
- package/src/lib/slice.js +65 -0
- package/src/lib/uimotion.js +774 -0
- package/src/lib/unsaved-state.js +2 -2
- package/src/live/fast-lane.js +10 -3
- package/src/live/local-lane.js +202 -11
- package/src/live/ops.js +16 -0
- package/src/live/page-compaction.js +162 -0
- package/src/live/server-lane.js +1 -0
- package/src/live/store.js +11 -3
- package/src/loader-logic.js +3 -1
- package/src/loader.js +14 -4
- package/src/page/adopt-boot.js +2 -1
- package/src/page/awareness.js +33 -2
- package/src/page/blocks.js +122 -27
- package/src/page/board-views.js +2 -16
- package/src/page/boot-pack.js +1 -1
- package/src/page/chart-tables.js +29 -0
- package/src/page/chart.js +411 -72
- package/src/page/checklist.js +10 -135
- package/src/page/checkpoint-proof.js +295 -0
- package/src/page/chrome.js +257 -40
- package/src/page/clipboard-shape.js +126 -0
- package/src/page/document-title-dom.js +12 -0
- package/src/page/document-title-runtime.js +15 -1
- package/src/page/document-title.js +4 -1
- package/src/page/drag.js +33 -3
- package/src/page/editor.js +207 -31
- package/src/page/emoji-data.js +162 -0
- package/src/page/export-assets.js +357 -0
- package/src/page/export-html.js +209 -0
- package/src/page/export-markdown.js +361 -0
- package/src/page/features/board.js +12 -3
- package/src/page/features/chart.js +11 -0
- package/src/page/features/checklist.js +428 -0
- package/src/page/features/dates.js +180 -0
- package/src/page/features/emoji.js +187 -0
- package/src/page/features/export-html.js +189 -0
- package/src/page/features/export-markdown.js +169 -0
- package/src/page/features/import-markdown.js +349 -0
- package/src/page/features/media.js +61 -5
- package/src/page/features/mentions.js +188 -0
- package/src/page/features/registry.js +24 -1
- package/src/page/features/table.js +375 -85
- package/src/page/features/title-cover.js +331 -0
- package/src/page/features/title-icon.js +213 -0
- package/src/page/features/toc.js +87 -0
- package/src/page/format-command.js +33 -0
- package/src/page/format-gate.js +68 -18
- package/src/page/format-host.js +71 -0
- package/src/page/format-native-commands.js +158 -0
- package/src/page/format-native.js +42 -0
- package/src/page/image-actions.js +64 -0
- package/src/page/import-markdown.js +262 -0
- package/src/page/inline.js +32 -8
- package/src/page/items.js +141 -11
- package/src/page/markdown.js +30 -2
- package/src/page/media.js +35 -119
- package/src/page/mention-picker.js +99 -0
- package/src/page/merge.js +1 -1
- package/src/page/placeholder.js +14 -1
- package/src/page/projection.js +156 -25
- package/src/page/recover.js +10 -12
- package/src/page/recovery-ui.js +464 -0
- package/src/page/rich/chart.js +63 -7
- package/src/page/save-projection.js +67 -0
- package/src/page/save-states.js +14 -4
- package/src/page/schema.js +52 -3
- package/src/page/table-paste.js +3 -1
- package/src/page/table-style.js +4 -4
- package/src/page/table.js +44 -2
- package/src/page/themes/content.css +25 -1
- package/src/page/themes/light-1.css +33 -8
- package/src/page/themes/light-1.source.css +8 -7
- package/src/page/toc-link.js +31 -0
- package/src/page/toc.js +5 -0
- package/src/page/view-hooks.js +58 -0
- package/src/page/view.js +13 -0
- package/src/page/ybind/binding.js +116 -6
- package/src/page/ybind/bridge.js +187 -20
- package/src/page/ybind/containment.js +162 -0
- package/src/page/ybind/doc.js +17 -9
- package/src/page/ybind/file-debt.js +63 -0
- package/src/page/ybind/layout.js +7 -2
- package/src/page/ybind/marks.js +2 -1
- package/src/page/ybind/moves.js +5 -4
- package/src/page/ybind/origins.js +106 -4
- package/src/page/ybind/parts.js +8 -1
- package/src/page/ybind/provider.js +125 -18
- package/src/page/ybind/recovery-proof.js +32 -9
- package/src/page/ybind/recovery-replay.js +905 -4
- package/src/page/ybind/recovery.js +174 -45
- package/src/page/ybind/table.js +67 -11
- package/src/page/ybind/walk-delta.js +258 -0
- package/src/page/ybind/walk.js +54 -29
- package/src/page/ybind/writer.js +1 -1
- package/src/plugins/ai-edit.js +13 -9
- package/src/plugins/indicator-chip.js +91 -0
- package/src/plugins/indicator.js +13 -80
- package/src/plugins/live.js +126 -15
- package/src/plugins/menu/actions.js +196 -0
- package/src/plugins/menu/people.js +279 -0
- package/src/plugins/menu/placement.js +121 -0
- package/src/plugins/menu/preferences.js +9 -0
- package/src/plugins/menu/seo.js +316 -397
- package/src/plugins/menu/style.js +171 -0
- package/src/plugins/menu/variants.js +296 -0
- package/src/plugins/menu.js +186 -183
- package/src/plugins/page-view.js +3 -2
- package/src/plugins/page.js +362 -43
- package/src/plugins/sortable.js +8 -1
- package/src/plugins/source.js +6 -0
- package/src/plugins/upgrade.js +51 -17
- package/src/plugins/upload-ui.js +12 -17
- package/src/plugins/visitor-drafts/bottom-ui.js +12 -4
- package/src/plugins/visitor-drafts/intro-style.js +7 -2
- package/src/plugins/visitor-drafts/intro.js +7 -4
- package/src/plugins/visitor-drafts/owner-chip.js +8 -12
- package/src/plugins/visitor-drafts/prompt.js +11 -9
- package/src/plugins/visitor-drafts/source.js +4 -3
- package/src/plugins/visitor-drafts/store.js +138 -9
- package/src/plugins/visitor-drafts/ui-memory.js +2 -2
- package/src/plugins/visitor-drafts-owner.js +4 -6
- package/src/plugins/visitor-drafts.js +5 -3
- package/src/recovery/store.js +1 -1
- package/src/route/route.js +4 -0
- package/src/server/checkpoint/index.js +2 -2
- package/src/server/rooms/index.js +5 -1
- package/src/server/rooms/live-data-rooms.js +302 -50
- package/src/server/rooms/page-compaction-worker.js +12 -0
- package/src/server/rooms/page-compactor.js +92 -0
- package/src/server/rooms/page-room-conformance.js +461 -0
- package/src/source/parse-steps.js +94 -0
- package/src/source/session.js +233 -57
- package/src/sync/editing-sender.js +12 -0
- package/src/sync/live-sync-edit.js +22 -2
- package/src/sync/live-sync.js +150 -23
- package/src/sync/page-relay.js +52 -0
- package/src/sync/presence-store.js +44 -4
- package/src/sync/presence.js +6 -3
- package/src/sync/saved-stream.js +28 -14
- package/src/ui/bevel-controls.js +1 -0
- package/src/ui/bevel-dialog.js +5 -2
- package/src/ui/editor-ui.js +77 -0
- package/src/ui/page-colour.js +281 -0
- package/src/ui/toast.js +16 -7
- package/src/vendor/hyper-html-api-upgrade.vendor.js +2 -2
- package/src/vendor/hyper-undo.vendor.js +1 -1
- package/src/vendor/hypercms.vendor.js +9 -9
- package/src/vendor/parse5.vendor.js +2 -2
- package/src/vendor/sap-core.vendor.js +5 -5
- package/dist/m/attrs/refetch-on-save-NWPPXOCZ.js +0 -1
- package/dist/m/attrs/save-freeze-FUP4Q4X3.js +0 -1
- package/dist/m/c-2M73252O.js +0 -1
- package/dist/m/c-2SPVQSHC.js +0 -1
- package/dist/m/c-35NBGMZB.js +0 -1
- package/dist/m/c-3IQRECYS.js +0 -1
- package/dist/m/c-4B6H4G5V.js +0 -1
- package/dist/m/c-4FFHZM32.js +0 -1
- package/dist/m/c-4YSCRICO.js +0 -1
- package/dist/m/c-54RCDCBU.js +0 -1
- package/dist/m/c-5M4YEKCX.js +0 -4
- package/dist/m/c-5V3MOVJT.js +0 -1
- package/dist/m/c-66O32MV3.js +0 -28
- package/dist/m/c-6HMB24EV.js +0 -1
- package/dist/m/c-7O6AFR65.js +0 -1
- package/dist/m/c-ANQTJ3B5.js +0 -2
- package/dist/m/c-AYVOREBE.js +0 -1
- package/dist/m/c-B2ZXPOS3.js +0 -3
- package/dist/m/c-BMIZKMPV.js +0 -1
- package/dist/m/c-BTDI4Y23.js +0 -1
- package/dist/m/c-CJZSLMVQ.js +0 -1
- package/dist/m/c-DBE6ORSI.js +0 -1
- package/dist/m/c-EDHUR4MX.js +0 -1
- package/dist/m/c-EY6UOM54.js +0 -1
- package/dist/m/c-F3CKJTJS.js +0 -1
- package/dist/m/c-F7Y6FLPY.js +0 -1
- package/dist/m/c-FA4DZVTC.js +0 -1
- package/dist/m/c-G2BUZITR.js +0 -1
- package/dist/m/c-GB3JTV6E.js +0 -1
- package/dist/m/c-GBGWXTX4.js +0 -1
- package/dist/m/c-GHBCCVG4.js +0 -1
- package/dist/m/c-GJAEGGXY.js +0 -1
- package/dist/m/c-GOWBDM6J.js +0 -1
- package/dist/m/c-IB52R237.js +0 -1
- package/dist/m/c-IKWNE4R4.js +0 -1
- package/dist/m/c-IU3IYEU6.js +0 -1
- package/dist/m/c-IZ2EBRAJ.js +0 -1
- package/dist/m/c-KR4UW4KW.js +0 -1
- package/dist/m/c-KY3VJGUA.js +0 -8
- package/dist/m/c-LFPHCXY3.js +0 -1
- package/dist/m/c-LRPUO2MX.js +0 -1
- package/dist/m/c-LXENEBV7.js +0 -1
- package/dist/m/c-NMJRXKPC.js +0 -8
- package/dist/m/c-OIBUTDXI.js +0 -1
- package/dist/m/c-PPOSCAQD.js +0 -1
- package/dist/m/c-QIX5BJYN.js +0 -1
- package/dist/m/c-QQHEX6HA.js +0 -1
- package/dist/m/c-R7RMANJI.js +0 -9
- package/dist/m/c-RI4NT75Y.js +0 -1
- package/dist/m/c-RM7J7BV2.js +0 -1
- package/dist/m/c-RUJKSUQW.js +0 -1
- package/dist/m/c-SGCCC4FW.js +0 -25
- package/dist/m/c-T4VO4OCB.js +0 -1
- package/dist/m/c-TQEMVJCS.js +0 -1
- package/dist/m/c-TR6RMDQ7.js +0 -3
- package/dist/m/c-UKHTLWUW.js +0 -1
- package/dist/m/c-UNN7LWCT.js +0 -1
- package/dist/m/c-UXBMRDZB.js +0 -235
- package/dist/m/c-V7PZZRG7.js +0 -1
- package/dist/m/c-VL52ADDR.js +0 -1
- package/dist/m/c-WNYBLIOZ.js +0 -1
- package/dist/m/c-WWDBYXLK.js +0 -1
- package/dist/m/c-XNNW2CWK.js +0 -1
- package/dist/m/c-Y6USGTS5.js +0 -5
- package/dist/m/c-YG2NJYS6.js +0 -135
- package/dist/m/c-Z4VRC7GU.js +0 -7
- package/dist/m/c-Z6K52OLP.js +0 -19
- package/dist/m/c-ZDY2MDAA.js +0 -21
- package/dist/m/c-ZUCOKOHT.js +0 -1
- package/dist/m/core/admin-attrs-VGNLAUDK.js +0 -1
- package/dist/m/core/autosave-E4PEFPZ6.js +0 -1
- package/dist/m/core/conflict-notice-VQ6Y64PH.js +0 -1
- package/dist/m/core/host-permission-XN3K2IW3.js +0 -1
- package/dist/m/core/is-edit-mode-JXHDVGUL.js +0 -1
- package/dist/m/core/recovery-TBBSICE2.js +0 -1
- package/dist/m/core/save-WUCHTQBE.js +0 -1
- package/dist/m/core/save-core-FJVHT5M3.js +0 -1
- package/dist/m/core/snapshot-F3SWDZMM.js +0 -1
- package/dist/m/core/unsaved-warning-STKBHE6G.js +0 -1
- package/dist/m/events/index-23DPTUT4.js +0 -1
- package/dist/m/internals/index-WOVAP3RU.js +0 -1
- package/dist/m/lib/cache-bust-CGWT6ZJI.js +0 -1
- package/dist/m/loader-HXX6YNH5.js +0 -1
- package/dist/m/manifest-F22DEDAC.js +0 -1
- package/dist/m/manifest-edit-C3C7376B.js +0 -1
- package/dist/m/options/options-2LH76JQ3.js +0 -1
- package/dist/m/page/editor-XUTB2HB2.js +0 -189
- package/dist/m/plugins/ai-edit-ZQ4CGWIP.js +0 -6
- package/dist/m/plugins/demo-ZIBFAA3R.js +0 -1
- package/dist/m/plugins/indicator-PV4YW2ID.js +0 -1
- package/dist/m/plugins/live-NUTTXSBS.js +0 -1
- package/dist/m/plugins/menu-HCKO3DSP.js +0 -138
- package/dist/m/plugins/page-KSUH7G6J.js +0 -2
- package/dist/m/plugins/page-view-W73OW7WI.js +0 -1
- package/dist/m/plugins/people-AJJ32YCG.js +0 -1
- package/dist/m/plugins/quickcrop-QNY3PKLD.js +0 -26
- package/dist/m/plugins/sortable-YRMQX3ZU.js +0 -1
- package/dist/m/plugins/source-KHK5UUSK.js +0 -1
- package/dist/m/plugins/undo-OF2L3CXU.js +0 -1
- package/dist/m/plugins/upgrade-ZNYODP5Y.js +0 -1
- package/dist/m/plugins/upload-XSGNILUY.js +0 -1
- package/dist/m/plugins/visitor-drafts-XK5GW55Q.js +0 -21
- package/dist/m/plugins/visitor-drafts-owner-KSSH75EV.js +0 -1
- package/dist/m/plugins/wire-ZWVWKF76.js +0 -1
- package/dist/m/reader-core-ILWLXVMP.js +0 -68
- package/dist/m/route/route-KOCZSEGN.js +0 -1
- package/dist/m/sync/live-sync-4AUVXVJU.js +0 -1
- package/dist/m/ui/index-EVHKMKBL.js +0 -1
- package/dist/m/vendor/sap-core.vendor-A7BMUYZT.js +0 -6
- /package/dist/m/{c-FILLTJA7.js → c-QTTJYJMA.js} +0 -0
- /package/dist/m/plugins/{quickcrop-QNY3PKLD.js.LEGAL.txt → quickcrop-BQ5YYFCH.js.LEGAL.txt} +0 -0
- /package/dist/m/plugins/{richclay-RC3L2F6X.js.LEGAL.txt → richclay-KLGETK77.js.LEGAL.txt} +0 -0
package/src/page/projection.js
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
import { chartModel, renderChartSvg } from "./rich/chart.js";
|
|
12
12
|
import { cellText } from "./rich/cell.js";
|
|
13
13
|
import { bounded, descriptors, entriesOf, keyOf, normalizeEntries } from "./format-codec.js";
|
|
14
|
+
import { nativeAttrs } from "./format-native.js";
|
|
15
|
+
import { safeSrc } from "./address.js";
|
|
14
16
|
|
|
15
17
|
export const ATOM = "";
|
|
16
18
|
export const BREAK = '@{"type":"hard_break"}';
|
|
@@ -26,6 +28,13 @@ const KNOWN = new Set(CODES);
|
|
|
26
28
|
export const OPAQUE = "data-clay-page-opaque";
|
|
27
29
|
export const VALUE = "data-clay-page-value";
|
|
28
30
|
export const MARKS = "data-clay-page-marks";
|
|
31
|
+
// A person mention's span states its id plainly beside the envelope that carries it:
|
|
32
|
+
// the label is the text, and a reader without the editor shows a name, never a link.
|
|
33
|
+
export const MENTION = "data-page-mention";
|
|
34
|
+
// A date mention reads as a `time` element: the text is the ISO date and `datetime`
|
|
35
|
+
// repeats it, so a reader without the editor shows the day and no zone or reminder.
|
|
36
|
+
export const DATE = "data-page-date";
|
|
37
|
+
const DAY = /^\d{4}-\d{2}-\d{2}$/;
|
|
29
38
|
const ENVELOPE = "1";
|
|
30
39
|
const STRUCTURAL = new Set(["id", "t", "parent", "c", "m"]);
|
|
31
40
|
const knownType = (t) => Object.hasOwn(DEFAULTS, t);
|
|
@@ -33,12 +42,14 @@ const knownType = (t) => Object.hasOwn(DEFAULTS, t);
|
|
|
33
42
|
// Mirrors schema.js attrs minus id and pos (a test pins the two together).
|
|
34
43
|
export const DEFAULTS = {
|
|
35
44
|
paragraph: { parent: null },
|
|
36
|
-
heading: { parent: null, level: 2 },
|
|
45
|
+
heading: { parent: null, level: 2, pageIcon: null, pageCoverSrc: null, pageCoverAlt: "", pageCoverX: 50, pageCoverY: 50 },
|
|
37
46
|
list_item: { parent: null, kind: "bullet", indent: 0, checked: false, owner: null, due: null },
|
|
38
47
|
callout: { parent: null },
|
|
48
|
+
quote: { parent: null },
|
|
39
49
|
code_block: { parent: null, lang: "" },
|
|
40
|
-
toggle: { parent: null, open: false },
|
|
50
|
+
toggle: { parent: null, open: false, level: null },
|
|
41
51
|
divider: { parent: null },
|
|
52
|
+
toc: { parent: null, maxLevel: null },
|
|
42
53
|
image: { parent: null, src: "", alt: "", caption: "", width: null, align: null },
|
|
43
54
|
file: { parent: null, src: "", name: "", size: null, mime: null },
|
|
44
55
|
table: { parent: null, cols: {}, sort: null },
|
|
@@ -47,7 +58,44 @@ export const DEFAULTS = {
|
|
|
47
58
|
tool: { parent: null, artifact: null, rev: null, state: {} },
|
|
48
59
|
preserved: { parent: null, html: "" },
|
|
49
60
|
};
|
|
50
|
-
const TEXT = new Set(["paragraph", "heading", "list_item", "callout", "code_block", "toggle"]);
|
|
61
|
+
const TEXT = new Set(["paragraph", "heading", "list_item", "callout", "quote", "code_block", "toggle"]);
|
|
62
|
+
export const TOC_LABEL = "Table of contents";
|
|
63
|
+
export const TOC_ANCHOR = "page-block-";
|
|
64
|
+
export const blockAnchor = (id) => `${TOC_ANCHOR}${b64url(String(id ?? ""))}`;
|
|
65
|
+
const TOC_MAX_LEVEL = 3;
|
|
66
|
+
const tocLevel = (item) => (item.t === "heading"
|
|
67
|
+
? Math.min(6, Math.max(1, Number.isInteger(item.level) ? item.level : 2))
|
|
68
|
+
: item.t === "toggle" && (item.level === 1 || item.level === 2 || item.level === 3) ? item.level : 0);
|
|
69
|
+
const tocTitle = (item) => item.t === "heading" && (item.level ?? 2) === 1 && (item.parent ?? null) === null;
|
|
70
|
+
const tocMax = (value) => (Number.isInteger(value) && value >= 1 && value <= 6 ? value : TOC_MAX_LEVEL);
|
|
71
|
+
const tocText = (item) => String(item.c ?? "").replace(/[\s\uFFFC]+/gu, " ").trim() || "Untitled";
|
|
72
|
+
|
|
73
|
+
export function tocEntries(model, maxLevel = TOC_MAX_LEVEL) {
|
|
74
|
+
const max = tocMax(maxLevel);
|
|
75
|
+
const title = model.find(tocTitle) ?? null;
|
|
76
|
+
const out = [];
|
|
77
|
+
for (const item of model) {
|
|
78
|
+
const level = tocLevel(item);
|
|
79
|
+
if (!item.id || !level || level > max || item === title) continue;
|
|
80
|
+
out.push({ id: item.id, level, text: tocText(item) });
|
|
81
|
+
}
|
|
82
|
+
return out;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function tocHtml(item, model) {
|
|
86
|
+
const entries = tocEntries(model, item.maxLevel);
|
|
87
|
+
const root = { level: 0, children: [] };
|
|
88
|
+
const stack = [root];
|
|
89
|
+
for (const entry of entries) {
|
|
90
|
+
while (stack.length > 1 && stack[stack.length - 1].level >= entry.level) stack.pop();
|
|
91
|
+
const node = { ...entry, children: [] };
|
|
92
|
+
stack[stack.length - 1].children.push(node);
|
|
93
|
+
stack.push(node);
|
|
94
|
+
}
|
|
95
|
+
const list = (nodes) => `<ul>${nodes.map((node) => `<li><a href="#${blockAnchor(node.id)}">${escText(node.text)}</a>${node.children.length ? list(node.children) : ""}</li>`).join("")}</ul>`;
|
|
96
|
+
const level = item.maxLevel == null ? "" : ` data-max-level="${escAttr(item.maxLevel)}"`;
|
|
97
|
+
return `<nav aria-label="${TOC_LABEL}" data-type="toc" data-id="${escAttr(item.id ?? "")}"${level}>${entries.length ? list(root.children) : ""}</nav>`;
|
|
98
|
+
}
|
|
51
99
|
|
|
52
100
|
const same = (a, b) => canon(a) === canon(b);
|
|
53
101
|
|
|
@@ -146,18 +194,25 @@ export function runsOf(units) {
|
|
|
146
194
|
return out;
|
|
147
195
|
}
|
|
148
196
|
|
|
149
|
-
// A mark key as { marks: { b: true, a: ["href"] ... }, entries: [...] }
|
|
150
|
-
//
|
|
151
|
-
// the
|
|
197
|
+
// A mark key as { marks: { b: true, a: ["href"] ... }, native: [...], entries: [...] }:
|
|
198
|
+
// the codes this runtime knows, the named descriptors of the four formats it
|
|
199
|
+
// writes (format-native.js), and the entries of every mark it has no code for,
|
|
200
|
+
// each in the codec's canonical order.
|
|
152
201
|
function marksOfKey(key) {
|
|
153
|
-
const marks = {};
|
|
154
|
-
if (!key || key[0] === "@") return { marks, entries: [] };
|
|
202
|
+
const marks = {}, native = [];
|
|
203
|
+
if (!key || key[0] === "@") return { marks, native: [], entries: [] };
|
|
155
204
|
const opaque = [];
|
|
156
205
|
for (const desc of descriptors(key)) {
|
|
157
|
-
if (desc.name === undefined
|
|
206
|
+
if (desc.name === undefined) {
|
|
207
|
+
if (KNOWN.has(desc.code)) marks[desc.code] = desc.attrs ?? true;
|
|
208
|
+
else opaque.push(desc);
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
const attrs = nativeAttrs(desc.name, desc.attrs);
|
|
212
|
+
if (attrs) native.push({ name: desc.name, attrs });
|
|
158
213
|
else opaque.push(desc);
|
|
159
214
|
}
|
|
160
|
-
return { marks, entries: opaque.length ? entriesOf(opaque) : [] };
|
|
215
|
+
return { marks, native, entries: opaque.length ? entriesOf(opaque) : [] };
|
|
161
216
|
}
|
|
162
217
|
|
|
163
218
|
// One unit's key, as the record keeps it: the codes this runtime knows, then
|
|
@@ -165,8 +220,8 @@ function marksOfKey(key) {
|
|
|
165
220
|
const unitKey = (key, text, i) => {
|
|
166
221
|
if (!key) return "";
|
|
167
222
|
if (key[0] === "@") return key === BREAK && text[i] === ATOM ? key : "";
|
|
168
|
-
const { marks, entries } = marksOfKey(key);
|
|
169
|
-
return keyOfMarks(safeMarks(marks), entries);
|
|
223
|
+
const { marks, native, entries } = marksOfKey(key);
|
|
224
|
+
return keyOfMarks(safeMarks(marks), native.length ? [...entries, ...entriesOf(native)] : entries);
|
|
170
225
|
};
|
|
171
226
|
|
|
172
227
|
// A link to a script URL is never kept: it would run on the page's origin when a
|
|
@@ -277,6 +332,8 @@ const omitDefaults = (t, fields) => {
|
|
|
277
332
|
return out;
|
|
278
333
|
};
|
|
279
334
|
|
|
335
|
+
const focal = (v) => Math.min(100, Math.max(0, Number.isFinite(+v) && v !== null && v !== "" ? +v : 50));
|
|
336
|
+
|
|
280
337
|
const columnWidth = (value) => (typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.round(value) : null);
|
|
281
338
|
|
|
282
339
|
function cellModel(value) {
|
|
@@ -324,9 +381,12 @@ const recordOfItem = (item) => {
|
|
|
324
381
|
|
|
325
382
|
// The fields of a known block the runtime has no schema attribute for. They are
|
|
326
383
|
// merged back only when serialized, inside the inert payload.
|
|
384
|
+
// Fields the renderer writes as visible markup, which the reader rebuilds from it.
|
|
385
|
+
const VISIBLE = { table: new Set(["rows"]) };
|
|
386
|
+
|
|
327
387
|
const extrasOfItem = (item) => {
|
|
328
388
|
const out = {};
|
|
329
|
-
for (const [k, v] of Object.entries(item)) if (!STRUCTURAL.has(k) && !(knownType(item.t) && Object.hasOwn(DEFAULTS[item.t], k))) out[k] = v;
|
|
389
|
+
for (const [k, v] of Object.entries(item)) if (!STRUCTURAL.has(k) && !VISIBLE[item.t]?.has(k) && !(knownType(item.t) && Object.hasOwn(DEFAULTS[item.t], k))) out[k] = v;
|
|
330
390
|
return Object.keys(out).length ? envelopeOf(out) : "";
|
|
331
391
|
};
|
|
332
392
|
|
|
@@ -355,7 +415,8 @@ function projectOne({ id, b, t, parent, indent }) {
|
|
|
355
415
|
for (const k of Object.keys(extras)) delete attrs[k];
|
|
356
416
|
const fields = { ...attrs, parent };
|
|
357
417
|
if (t === "list_item") fields.indent = indent;
|
|
358
|
-
if (t === "heading") fields
|
|
418
|
+
if (t === "heading") Object.assign(fields, { level: clampLevel(attrs.level ?? 2), pageCoverSrc: safeSrc(fields.pageCoverSrc ?? null), pageCoverX: focal(fields.pageCoverX), pageCoverY: focal(fields.pageCoverY) });
|
|
419
|
+
if (t === "toggle") fields.level = toggleLevel(attrs.level);
|
|
359
420
|
if (t === "image" && fields.width != null) fields.width = widthOf(String(fields.width));
|
|
360
421
|
if (t === "image") fields.align = alignOf(fields.align);
|
|
361
422
|
if (t === "image" && typeof fields.caption === "string") fields.caption = normalizeText(fields.caption, null).c;
|
|
@@ -378,7 +439,23 @@ function projectOne({ id, b, t, parent, indent }) {
|
|
|
378
439
|
return item;
|
|
379
440
|
}
|
|
380
441
|
|
|
442
|
+
// A record a newer writer left in an older writer's envelope, for a block type this
|
|
443
|
+
// build knows: the same projection a peer's record gets, without the fields this
|
|
444
|
+
// type does not declare.
|
|
445
|
+
function knownRecordItem(id, record, parent) {
|
|
446
|
+
const { t } = record;
|
|
447
|
+
const malformed = new SyntaxError(`page: an envelope names the known block type ${t}`);
|
|
448
|
+
if (TEXT.has(t) ? record.c != null && typeof record.c !== "string" : record.c != null || record.m != null) throw malformed;
|
|
449
|
+
let item;
|
|
450
|
+
try { item = projectOne({ id, b: record, t, parent, indent: 0 }); }
|
|
451
|
+
catch { throw malformed; }
|
|
452
|
+
const fields = DEFAULTS[t];
|
|
453
|
+
return Object.fromEntries(Object.entries(item).filter(([k]) => k === "id" || k === "t" || STRUCTURAL.has(k) || k === "rows" || Object.hasOwn(fields, k)));
|
|
454
|
+
}
|
|
455
|
+
|
|
381
456
|
const clampLevel = (l) => Math.min(6, Math.max(1, Number.isInteger(l) ? l : 2));
|
|
457
|
+
// A toggle heading is level 1 to 3; anything else is a plain toggle.
|
|
458
|
+
export const toggleLevel = (l) => (l === 1 || l === 2 || l === 3 ? l : null);
|
|
382
459
|
const widthOf = (s) => (/^\d+$/.test(s) ? Number(s) : s);
|
|
383
460
|
export const alignOf = (a) => (a === "left" || a === "right" ? a : null);
|
|
384
461
|
|
|
@@ -410,6 +487,10 @@ const escText = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>
|
|
|
410
487
|
const escAttr = (s) => escText(String(s)).replace(/"/g, """);
|
|
411
488
|
const attr = (name, value) => (value === null || value === undefined ? "" : ` ${name}="${escAttr(value)}"`);
|
|
412
489
|
|
|
490
|
+
// The element each of the four formats is read as in the saved article; the
|
|
491
|
+
// text color and the highlight carry their palette key as data-color.
|
|
492
|
+
const NATIVE_TAGS = { underline: "u", text_color: "span", highlight: "mark" };
|
|
493
|
+
|
|
413
494
|
export function renderInline(c, m, marksEnvelopes = true) {
|
|
414
495
|
const units = unitsOf(m, c.length) || [];
|
|
415
496
|
let html = "";
|
|
@@ -425,13 +506,22 @@ export function renderInline(c, m, marksEnvelopes = true) {
|
|
|
425
506
|
}
|
|
426
507
|
let j = i + 1;
|
|
427
508
|
while (j < c.length && (units[j] || "") === key && !(c[j] === ATOM && key[0] === "@")) j++;
|
|
428
|
-
const { marks, entries } = marksOfKey(key);
|
|
509
|
+
const { marks, native, entries } = marksOfKey(key);
|
|
429
510
|
const want = NEST.filter((code) => marks[code]).map((code) => ({ code, sig: code + JSON.stringify(marks[code]), tag: code === "a" ? "a" : TAGS[code], href: code === "a" ? marks.a[0] : null }));
|
|
430
|
-
|
|
511
|
+
for (const n of native) want.push({ sig: `native${n.name}${canon(n.attrs)}`, tag: NATIVE_TAGS[n.name], color: n.attrs.color ?? null });
|
|
512
|
+
const mention = entries.find((entry) => entry.name === "mention");
|
|
513
|
+
const date = entries.find((entry) => entry.name === "date");
|
|
514
|
+
const day = date && DAY.test(String(date.attrs.date)) ? String(date.attrs.date) : null;
|
|
515
|
+
if (entries.length && marksEnvelopes) want.push({ sig: `marks${canon(entries)}`, tag: day ? "time" : "span", entries, mention: mention?.attrs.id, day });
|
|
431
516
|
let keep = 0;
|
|
432
517
|
while (keep < open.length && keep < want.length && open[keep].sig === want[keep].sig) keep++;
|
|
433
518
|
closeTo(keep);
|
|
434
|
-
for (const w of want.slice(keep)) {
|
|
519
|
+
for (const w of want.slice(keep)) {
|
|
520
|
+
if (w.entries) html += w.day ? `<time${attr("datetime", w.day)}${attr(DATE, "")}${marksEnvelope(w.entries)}>` : `<span${marksEnvelope(w.entries)}${attr(MENTION, w.mention)}>`;
|
|
521
|
+
else if (w.tag === "a") html += `<a${attr("href", w.href)}>`;
|
|
522
|
+
else html += w.color ? `<${w.tag}${attr("data-color", w.color)}>` : `<${w.tag}>`;
|
|
523
|
+
open.push(w);
|
|
524
|
+
}
|
|
435
525
|
html += escText(c.slice(i, j));
|
|
436
526
|
i = j;
|
|
437
527
|
}
|
|
@@ -440,9 +530,13 @@ export function renderInline(c, m, marksEnvelopes = true) {
|
|
|
440
530
|
}
|
|
441
531
|
|
|
442
532
|
const inlineOf = (item) => renderInline(item.c ?? "", item.m);
|
|
533
|
+
const titleHtml = (item) => `<header${attr("data-id", item.id)} data-page-heading="1"${extrasOfItem(item)}>${item.pageCoverSrc ? `<img data-page-cover${attr("src", item.pageCoverSrc)}${attr("alt", item.pageCoverAlt ?? "")} style="object-position:${item.pageCoverX ?? 50}% ${item.pageCoverY ?? 50}%">` : ""}${item.pageIcon ? `<span data-page-icon aria-hidden="true">${escText(item.pageIcon)}</span>` : ""}<h1>${inlineOf(item)}</h1></header>`;
|
|
443
534
|
const toolData = (item) => item.artifact || item.rev || (item.state && Object.keys(item.state).length)
|
|
444
535
|
? `<script type="application/json" data-tool>${canon({ artifact: item.artifact ?? null, rev: item.rev ?? null, state: item.state ?? {} }).replace(/</g, "\\u003c")}</script>`
|
|
445
536
|
: "";
|
|
537
|
+
// A header names its column for every cell under it: the table id and the column
|
|
538
|
+
// id together, so a copied column keeps a name no other table shares.
|
|
539
|
+
const headerId = (tableId, colId) => `${tableId}-${colId}`;
|
|
446
540
|
const cellHtml = (cell) => (typeof cell === "string" ? escText(cell) : cell && typeof cell === "object" ? renderInline(String(cell.c ?? ""), cell.m) : "");
|
|
447
541
|
const dataAttrs = (obj) => Object.entries(obj).map(([k, v]) => attr(`data-${k}`, v)).join("");
|
|
448
542
|
|
|
@@ -454,6 +548,7 @@ function renderLeaf(item, clean, tables) {
|
|
|
454
548
|
case "paragraph": return `<p${at}>${inlineOf(item)}</p>`;
|
|
455
549
|
case "heading": { const h = `h${item.level ?? 2}`; return `<${h}${at}>${inlineOf(item)}</${h}>`; }
|
|
456
550
|
case "callout": return `<aside${at} class="page-callout">${inlineOf(item)}</aside>`;
|
|
551
|
+
case "quote": return `<blockquote${at}>${inlineOf(item)}</blockquote>`;
|
|
457
552
|
case "code_block": return `<pre${at}${attr("data-lang", item.lang || null)}><code>${escText(item.c ?? "")}</code></pre>`;
|
|
458
553
|
case "divider": return `<hr${at}>`;
|
|
459
554
|
case "image": return `<figure${at} data-type="image"${attr("data-align", item.align ?? null)}><img${attr("src", item.src ?? "")}${attr("alt", item.alt ?? "")}${attr("width", item.width ?? null)}>${item.caption ? `<figcaption>${escText(item.caption)}</figcaption>` : ""}</figure>`;
|
|
@@ -462,9 +557,12 @@ function renderLeaf(item, clean, tables) {
|
|
|
462
557
|
return `<div${at} data-type="file"${attr("data-src", item.src ?? "")}${attr("data-name", item.name ?? "")}${attr("data-size", item.size ?? null)}${attr("data-mime", item.mime ?? null)}><a${attr("href", href)} rel="noopener noreferrer">${escText(item.name || "file")}</a></div>`;
|
|
463
558
|
}
|
|
464
559
|
case "table": {
|
|
465
|
-
const head = item.cols.map((c) =>
|
|
466
|
-
|
|
467
|
-
|
|
560
|
+
const head = item.cols.map((c) => {
|
|
561
|
+
const sorted = item.sort?.col === c.id ? (item.sort.dir === "desc" ? "descending" : "ascending") : null;
|
|
562
|
+
return `<th${attr("data-col", c.id)}${attr("id", headerId(item.id, c.id))}${attr("data-kind", c.kind ?? null)}${attr("data-width", c.width ?? null)}${attr("style", c.width ? `width:${c.width}px` : null)} scope="col"${attr("aria-sort", sorted)}>${escText(c.name)}</th>`;
|
|
563
|
+
}).join("");
|
|
564
|
+
const body = item.rows.map((r) => `<tr${attr("data-id", r.id)}>${item.cols.map((c) => `<td${attr("headers", headerId(item.id, c.id))}>${cellHtml(r.cells[c.id])}</td>`).join("")}</tr>`).join("\n");
|
|
565
|
+
return `<table${at} aria-label="Table"${attr("data-sort", item.sort != null ? JSON.stringify(item.sort) : null)}>\n<thead><tr>${head}</tr></thead>\n<tbody>\n${body}\n</tbody>\n</table>`;
|
|
468
566
|
}
|
|
469
567
|
case "chart": {
|
|
470
568
|
const data = dataAttrs({ source: item.source ?? null, kind: item.kind ?? null, x: item.x ?? null, series: item.series ? JSON.stringify(item.series) : null, highlight: item.highlight ?? null });
|
|
@@ -517,6 +615,7 @@ export function fragmentCleaner(doc) {
|
|
|
517
615
|
export function renderModel(model, { fallbackOf = () => "", clean = RAW } = {}) {
|
|
518
616
|
const lines = [];
|
|
519
617
|
const tables = new Map(model.filter((item) => item.t === "table").map((item) => [item.id, item]));
|
|
618
|
+
const title = model.find(tocTitle) ?? null;
|
|
520
619
|
const stack = [null];
|
|
521
620
|
const lists = [];
|
|
522
621
|
const add = (s) => { if (lists.length) lines[lines.length - 1] += s; else lines.push(s); };
|
|
@@ -539,11 +638,14 @@ export function renderModel(model, { fallbackOf = () => "", clean = RAW } = {})
|
|
|
539
638
|
continue;
|
|
540
639
|
}
|
|
541
640
|
if (item.t === "toggle") {
|
|
542
|
-
|
|
641
|
+
const h = toggleLevel(item.level);
|
|
642
|
+
add(`<details${attr("data-id", item.id)}${extrasOfItem(item)}${item.open ? " open" : ""}>${h ? `<summary><h${h}>${inlineOf(item)}</h${h}></summary>` : `<summary>${inlineOf(item)}</summary>`}`);
|
|
543
643
|
stack.push(item.id);
|
|
544
644
|
continue;
|
|
545
645
|
}
|
|
546
646
|
if (item.t === "tool") { add(`<section${attr("data-id", item.id)} data-type="tool">${toolData(item)}${clean.fallback(fallbackOf(item.id))}</section>`); continue; }
|
|
647
|
+
if (item.t === "toc") { add(tocHtml(item, model)); continue; }
|
|
648
|
+
if (item === title && (item.pageIcon || item.pageCoverSrc)) { add(titleHtml(item)); continue; }
|
|
547
649
|
add(renderLeaf(item, clean, tables));
|
|
548
650
|
}
|
|
549
651
|
closeLists();
|
|
@@ -561,6 +663,17 @@ export function renderBlocks(blocks, opts) {
|
|
|
561
663
|
const DROP_TAGS = new Set(["SCRIPT", "STYLE", "TEMPLATE", "NOSCRIPT"]);
|
|
562
664
|
const INLINE_TAGS = new Set(["A", "ABBR", "B", "BDI", "BDO", "BR", "CITE", "CODE", "DATA", "DEL", "DFN", "EM", "FONT", "I", "INS", "KBD", "LABEL", "MARK", "Q", "S", "SAMP", "SMALL", "SPAN", "STRIKE", "STRONG", "SUB", "SUP", "TIME", "U", "VAR", "WBR"]);
|
|
563
665
|
|
|
666
|
+
// The named descriptor an inline element stands for, when it is one of the four
|
|
667
|
+
// formats: <u>, <mark> and a <span data-color> with a palette key. Anything else
|
|
668
|
+
// is not a format this runtime reads natively.
|
|
669
|
+
function nativeOfEl(tag, el) {
|
|
670
|
+
if (tag === "u") return { name: "underline", attrs: {} };
|
|
671
|
+
if (tag !== "mark" && tag !== "span") return null;
|
|
672
|
+
if (tag === "span" && !el.hasAttribute("data-color")) return null;
|
|
673
|
+
const name = tag === "mark" ? "highlight" : "text_color";
|
|
674
|
+
return { name, attrs: { color: el.getAttribute("data-color") } };
|
|
675
|
+
}
|
|
676
|
+
|
|
564
677
|
// Inline content of el as { c, units }, minus the children skip(child) names.
|
|
565
678
|
function inlineOfEl(el, skip = () => false) {
|
|
566
679
|
let c = "";
|
|
@@ -579,7 +692,7 @@ function inlineOfEl(el, skip = () => false) {
|
|
|
579
692
|
if (tag === "br") { c += ATOM; units.push(BREAK); continue; }
|
|
580
693
|
if (tag === "span" && child.hasAttribute("data-atom")) { c += ATOM; units.push(child.getAttribute("data-atom")); continue; }
|
|
581
694
|
const next = { ...marks };
|
|
582
|
-
if (tag === "span" && child.hasAttribute(MARKS)) {
|
|
695
|
+
if ((tag === "span" || tag === "time") && child.hasAttribute(MARKS)) {
|
|
583
696
|
walk(child, next, normalizeEntries([...entries, ...entriesOfEnvelope(child.getAttribute(MARKS))]));
|
|
584
697
|
continue;
|
|
585
698
|
}
|
|
@@ -588,7 +701,8 @@ function inlineOfEl(el, skip = () => false) {
|
|
|
588
701
|
else if (tag === "s" || tag === "del" || tag === "strike") next.s = true;
|
|
589
702
|
else if (tag === "code") next.c = true;
|
|
590
703
|
else if (tag === "a" && child.hasAttribute("href")) next.a = [child.getAttribute("href")];
|
|
591
|
-
|
|
704
|
+
const named = nativeOfEl(tag, child);
|
|
705
|
+
walk(child, next, named ? [...entries, named] : entries);
|
|
592
706
|
}
|
|
593
707
|
};
|
|
594
708
|
walk(el, {}, []);
|
|
@@ -663,7 +777,11 @@ export function parseArticle(article) {
|
|
|
663
777
|
const P = { parent };
|
|
664
778
|
const record = envelopeAt(el);
|
|
665
779
|
if (record && typeof record.t === "string") {
|
|
666
|
-
if (
|
|
780
|
+
if (record.t === "opaque_block") throw new SyntaxError(`page: an envelope names the known block type ${record.t}`);
|
|
781
|
+
if (knownType(record.t)) {
|
|
782
|
+
items.push(knownRecordItem(idOf(el), record, parent));
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
667
785
|
const { t, ...fields } = record;
|
|
668
786
|
items.push({ id: idOf(el), t, parent, ...fields });
|
|
669
787
|
return;
|
|
@@ -671,17 +789,30 @@ export function parseArticle(article) {
|
|
|
671
789
|
const onlyImage = tag === "P" && el.children.length === 1 && el.children[0].tagName === "IMG" && !el.textContent.trim();
|
|
672
790
|
if (tag === "P" && !onlyImage) return push(el, "paragraph", parent, { ...omitDefaults("paragraph", P), ...tf(el) });
|
|
673
791
|
if (/^H[1-6]$/.test(tag)) return push(el, "heading", parent, { ...omitDefaults("heading", { ...P, level: +tag[1] }), ...tf(el) });
|
|
792
|
+
if (tag === "HEADER" && el.getAttribute("data-page-heading") === ENVELOPE) {
|
|
793
|
+
const icon = el.querySelector(":scope > [data-page-icon]");
|
|
794
|
+
const cover = el.querySelector(":scope > img");
|
|
795
|
+
const [, x, y] = /object-position:\s*([-\d.]+)%\s+([-\d.]+)%/.exec(cover?.getAttribute("style") ?? "") ?? [];
|
|
796
|
+
const cover0 = cover ? { pageCoverSrc: safeSrc(cover.getAttribute("src")), pageCoverAlt: cover.getAttribute("alt") ?? "", pageCoverX: focal(x), pageCoverY: focal(y) } : {};
|
|
797
|
+
return push(el, "heading", parent, { ...omitDefaults("heading", { ...P, level: 1, pageIcon: icon ? icon.textContent : null, ...cover0 }), ...tf(el.querySelector(":scope > h1")) });
|
|
798
|
+
}
|
|
674
799
|
if (tag === "ASIDE") return push(el, "callout", parent, { ...omitDefaults("callout", P), ...tf(el) });
|
|
800
|
+
if (tag === "BLOCKQUOTE") return push(el, "quote", parent, { ...omitDefaults("quote", P), ...tf(el) });
|
|
675
801
|
if (tag === "PRE") {
|
|
676
802
|
const code = el.querySelector(":scope > code");
|
|
677
803
|
return push(el, "code_block", parent, { ...omitDefaults("code_block", { ...P, lang: el.getAttribute("data-lang") || "" }), c: (code || el).textContent });
|
|
678
804
|
}
|
|
679
805
|
if (tag === "HR") return push(el, "divider", parent, omitDefaults("divider", P));
|
|
806
|
+
if (tag === "NAV" && el.getAttribute("aria-label") === TOC_LABEL) {
|
|
807
|
+
const maxLevel = +(el.getAttribute("data-max-level") ?? 0);
|
|
808
|
+
return push(el, "toc", parent, omitDefaults("toc", { ...P, maxLevel: maxLevel >= 1 && maxLevel <= 6 ? maxLevel : null }));
|
|
809
|
+
}
|
|
680
810
|
if (tag === "UL" || tag === "OL") return list(el, parent, 0);
|
|
681
811
|
if (tag === "DETAILS") {
|
|
682
812
|
const summary = el.querySelector(":scope > summary");
|
|
813
|
+
const head = summary?.querySelector(":scope > h1, :scope > h2, :scope > h3");
|
|
683
814
|
const at = items.length;
|
|
684
|
-
push(el, "toggle", parent, { ...omitDefaults("toggle", { ...P, open: el.hasAttribute("open") }), ...tf(summary) });
|
|
815
|
+
push(el, "toggle", parent, { ...omitDefaults("toggle", { ...P, open: el.hasAttribute("open"), level: head ? Number(head.tagName[1]) : null }), ...tf(summary) });
|
|
685
816
|
const body = el.ownerDocument.createElement("div");
|
|
686
817
|
for (const n of [...el.childNodes]) if (n !== summary) body.appendChild(n.cloneNode(true));
|
|
687
818
|
walk(body, { ref: at });
|
package/src/page/recover.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import toast, { toastPersistent, dismissPersistent } from "../ui/toast-lazy.js";
|
|
2
2
|
import { state as pmState } from "../vendor/prosemirror.vendor.js";
|
|
3
|
+
import { mountEditorUI } from "../ui/editor-ui.js";
|
|
3
4
|
|
|
4
5
|
export const NOTICE_TEXT = "Some text you typed was kept aside when its block moved or was removed.";
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
// The control and its panel sit in one shadow root inside the page shell, so the page's
|
|
8
|
+
// CSS cannot restyle them. The page's --page-* tokens still reach them, and they keep
|
|
9
|
+
// the page's font and colour.
|
|
7
10
|
const STYLES = `
|
|
11
|
+
:host { font: inherit !important; color: inherit !important; }
|
|
12
|
+
.page-recover-root { display: contents; }
|
|
8
13
|
.page-recover { position: fixed; right: 16px; bottom: 16px; z-index: 20; min-height: 36px; padding: 0 14px; font: inherit; font-size: 14px; color: var(--page-ink); background: var(--page-pop-bg); border: 1px solid var(--page-chrome-line-rest); border-radius: 999px; cursor: pointer; }
|
|
9
14
|
.page-recover[hidden], .page-recover-panel[hidden] { display: none; }
|
|
10
15
|
.page-recover-panel { position: fixed; right: 16px; bottom: 64px; z-index: 21; width: min(380px, calc(100vw - 32px)); max-height: 60vh; overflow-y: auto; color: var(--page-ink); background: var(--page-pop-bg); border: 1px solid var(--page-chrome-line-rest); border-radius: var(--page-chrome-radius); padding: 8px; box-sizing: border-box; }
|
|
@@ -33,13 +38,6 @@ const el = (doc, tag, className, attrs = {}) => {
|
|
|
33
38
|
return node;
|
|
34
39
|
};
|
|
35
40
|
|
|
36
|
-
function ensureStyle(doc) {
|
|
37
|
-
if (doc.getElementById(STYLE_ID)) return;
|
|
38
|
-
const style = doc.createElement("style");
|
|
39
|
-
style.id = STYLE_ID;
|
|
40
|
-
style.textContent = STYLES;
|
|
41
|
-
doc.head.append(style);
|
|
42
|
-
}
|
|
43
41
|
|
|
44
42
|
function previewOf(doc, record) {
|
|
45
43
|
const out = el(doc, "div", "page-recover-text");
|
|
@@ -74,13 +72,14 @@ export function focusBlock(view, id) {
|
|
|
74
72
|
|
|
75
73
|
export function createRecoverList({ binding, mount, ownTokens = [], onRestored = () => {}, onStale = () => {} }) {
|
|
76
74
|
const doc = mount.ownerDocument;
|
|
77
|
-
ensureStyle(doc);
|
|
78
75
|
const own = new Set(ownTokens.filter(Boolean));
|
|
79
76
|
const button = el(doc, "button", "page-recover", { type: "button", "aria-haspopup": "dialog", "aria-expanded": "false" });
|
|
80
77
|
const panel = el(doc, "div", "page-recover-panel", { role: "dialog", "aria-label": "Recover changes" });
|
|
81
78
|
button.hidden = true;
|
|
82
79
|
panel.hidden = true;
|
|
83
|
-
|
|
80
|
+
const content = el(doc, "div", "page-recover-root");
|
|
81
|
+
content.append(button, panel);
|
|
82
|
+
const ui = mountEditorUI({ name: "page-recover", content, css: [STYLES], parent: mount });
|
|
84
83
|
|
|
85
84
|
let snapshot = { recoverable: [], notices: [] };
|
|
86
85
|
let target = null;
|
|
@@ -186,8 +185,7 @@ export function createRecoverList({ binding, mount, ownTokens = [], onRestored =
|
|
|
186
185
|
destroy() {
|
|
187
186
|
off();
|
|
188
187
|
dismissPersistent(NOTICE_TEXT);
|
|
189
|
-
|
|
190
|
-
panel.remove();
|
|
188
|
+
ui.remove();
|
|
191
189
|
},
|
|
192
190
|
};
|
|
193
191
|
}
|