@heycys/gallery 0.1.0 → 0.1.2
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/THIRD-PARTY-NOTICES.md +51 -1
- package/browser/editor/components/callout/index.mjs +40 -15
- package/browser/editor/components/columns/page.mjs +45 -32
- package/browser/editor/components/details/index.mjs +2 -1
- package/browser/editor/components/dialog/index.mjs +2 -1
- package/browser/editor/components/dialog/page.mjs +0 -18
- package/browser/editor/components/divider/index.mjs +1 -1
- package/browser/editor/components/embed/index.mjs +2 -2
- package/browser/editor/components/figure/page.mjs +10 -1
- package/browser/editor/components/file/page.mjs +2 -2
- package/browser/editor/components/flowchart/add.mjs +7 -6
- package/browser/editor/components/flowchart/page.mjs +1 -1
- package/browser/editor/components/heading/index.mjs +2 -0
- package/browser/editor/components/heading/page.mjs +6 -0
- package/browser/editor/components/highlight/index.mjs +4 -20
- package/browser/editor/components/icons.mjs +13 -2
- package/browser/editor/components/image/crop.mjs +6 -9
- package/browser/editor/components/image/page.mjs +2 -2
- package/browser/editor/components/installed/index.mjs +82 -29
- package/browser/editor/components/installed/page.mjs +146 -34
- package/browser/editor/components/installed/served.mjs +6 -5
- package/browser/editor/components/instances.mjs +18 -0
- package/browser/editor/components/kit.mjs +3 -0
- package/browser/editor/components/list/page.mjs +3 -6
- package/browser/editor/components/media/page.mjs +44 -14
- package/browser/editor/components/pages.mjs +2 -2
- package/browser/editor/components/registry.mjs +68 -33
- package/browser/editor/components/section/index.mjs +2 -1
- package/browser/editor/components/set-apart.mjs +24 -0
- package/browser/editor/components/table/index.mjs +64 -5
- package/browser/editor/components/table/page.mjs +30 -19
- package/browser/editor/page/annotate/anchors.mjs +4 -3
- package/browser/editor/page/annotate/card.mjs +3 -6
- package/browser/editor/page/annotate/index.mjs +61 -34
- package/browser/editor/page/autosave.mjs +357 -38
- package/browser/editor/page/beside.mjs +5 -5
- package/browser/editor/page/block-menu/colors.mjs +3 -1
- package/browser/editor/page/block-menu/index.mjs +8 -6
- package/browser/editor/page/blocks.mjs +16 -7
- package/browser/editor/page/board/client.mjs +57 -0
- package/browser/editor/page/board/hint.mjs +145 -0
- package/browser/editor/page/board/history.mjs +119 -0
- package/browser/editor/page/board/index.mjs +970 -0
- package/browser/editor/page/board/settings.mjs +209 -0
- package/browser/editor/page/caret.mjs +5 -2
- package/browser/editor/page/changes/bar.mjs +94 -0
- package/browser/editor/page/changes/ghost.mjs +206 -0
- package/browser/editor/page/changes/gone-words.mjs +94 -0
- package/browser/editor/page/changes/index.mjs +447 -0
- package/browser/editor/page/changes/words.mjs +27 -0
- package/browser/editor/page/clipboard/import/colors.mjs +3 -3
- package/browser/editor/page/clipboard/import/html.mjs +29 -6
- package/browser/editor/page/clipboard/import/inline.mjs +32 -0
- package/browser/editor/page/clipboard/import/markdown.mjs +58 -13
- package/browser/editor/page/clipboard/import/read.mjs +6 -1
- package/browser/editor/page/clipboard/import/to-blocks.mjs +44 -12
- package/browser/editor/page/clipboard/import/yuque.mjs +622 -0
- package/browser/editor/page/clipboard/index.mjs +156 -26
- package/browser/editor/page/clipboard/own/blocks.mjs +25 -16
- package/browser/editor/page/clipboard/own/chart-keys.mjs +41 -28
- package/browser/editor/page/clipboard/own/describe.mjs +16 -7
- package/browser/editor/page/clipboard/own/export.mjs +6 -6
- package/browser/editor/page/clipboard/own/selection.mjs +3 -3
- package/browser/editor/page/clipboard/own/writers.mjs +0 -11
- package/browser/editor/page/columns/index.mjs +48 -46
- package/browser/editor/page/commit.mjs +98 -25
- package/browser/editor/page/conflicts.mjs +13 -33
- package/browser/editor/page/convert.mjs +8 -7
- package/browser/editor/page/core.mjs +81 -27
- package/browser/editor/page/custom-page.mjs +106 -0
- package/browser/editor/page/drag/index.mjs +40 -24
- package/browser/editor/page/drag/preview.mjs +9 -4
- package/browser/editor/page/editor.mjs +120 -28
- package/browser/editor/page/emoji-picker/emoji-tab.mjs +22 -13
- package/browser/editor/page/emoji-picker/grid.mjs +7 -5
- package/browser/editor/page/emoji-picker/icon-tab.mjs +4 -4
- package/browser/editor/page/emoji-picker/icons.mjs +0 -1
- package/browser/editor/page/emoji-picker/index.mjs +11 -9
- package/browser/editor/page/emoji-picker/styles.mjs +156 -2
- package/browser/editor/page/emoji-picker/support.mjs +6 -4
- package/browser/editor/page/emoji-picker/upload.mjs +14 -13
- package/browser/editor/page/fills.mjs +5 -3
- package/browser/editor/page/fold/index.mjs +348 -0
- package/browser/editor/page/fold/rule.mjs +125 -0
- package/browser/editor/page/folded.mjs +23 -0
- package/browser/editor/page/format-bar/bar.mjs +2 -1
- package/browser/editor/page/format-bar/index.mjs +1 -1
- package/browser/editor/page/geometry.mjs +8 -6
- package/browser/editor/page/handle/index.mjs +22 -14
- package/browser/editor/page/hints/index.mjs +1 -1
- package/browser/editor/page/history.mjs +24 -4
- package/browser/editor/page/insert/index.mjs +30 -17
- package/browser/editor/page/links/index.mjs +5 -3
- package/browser/editor/page/links/pages.mjs +27 -9
- package/browser/editor/page/long-runs.mjs +75 -0
- package/browser/editor/page/look.mjs +69 -6
- package/browser/editor/page/margin.mjs +63 -27
- package/browser/editor/page/media-menu/index.mjs +6 -7
- package/browser/editor/page/menu.mjs +86 -31
- package/browser/editor/page/merge.mjs +24 -0
- package/browser/editor/page/notices.mjs +3 -3
- package/browser/editor/page/offered.mjs +1 -1
- package/browser/editor/page/outline/folds.mjs +11 -10
- package/browser/editor/page/outline/index.mjs +131 -45
- package/browser/editor/page/outline/list.mjs +23 -11
- package/browser/editor/page/outline/read.mjs +1 -1
- package/browser/editor/page/outline/strip.mjs +7 -1
- package/browser/editor/page/page-objects.mjs +13 -2
- package/browser/editor/page/panel.mjs +9 -13
- package/browser/editor/page/present-links.mjs +11 -2
- package/browser/editor/page/resize/index.mjs +42 -29
- package/browser/editor/page/selection/delete.mjs +8 -6
- package/browser/editor/page/selection/index.mjs +10 -3
- package/browser/editor/page/served.mjs +14 -0
- package/browser/editor/page/session.mjs +101 -6
- package/browser/editor/page/slash-menu/index.mjs +3 -3
- package/browser/editor/page/table/cell-bar.mjs +4 -1
- package/browser/editor/page/table/cells.mjs +103 -47
- package/browser/editor/page/table/icons.mjs +3 -1
- package/browser/editor/page/table/index.mjs +40 -16
- package/browser/editor/page/table/pictures.mjs +299 -0
- package/browser/editor/page/table/views.mjs +150 -0
- package/browser/editor/page/table/widths.mjs +9 -4
- package/browser/editor/page/text-select/index.mjs +43 -14
- package/browser/editor/page/todo-writes.mjs +75 -0
- package/browser/editor/page/tooltip.mjs +1 -1
- package/browser/editor/page/type-grid.mjs +4 -3
- package/browser/editor/page/typing/code-edges.mjs +63 -17
- package/browser/editor/page/typing/index.mjs +65 -9
- package/browser/editor/page/typing/leave.mjs +1 -1
- package/browser/editor/page/ui.mjs +13 -0
- package/browser/shared/annotations.mjs +8 -10
- package/browser/shared/block-packs.mjs +404 -0
- package/browser/shared/board-places.mjs +224 -0
- package/browser/shared/card-size.mjs +59 -0
- package/browser/shared/code-folds.mjs +5 -1
- package/browser/shared/colors.mjs +17 -14
- package/browser/shared/component-catalog.mjs +345 -54
- package/browser/shared/component-source.mjs +37 -0
- package/browser/shared/components/callout.mjs +4 -2
- package/browser/shared/components/index.mjs +72 -9
- package/browser/shared/components/installed.mjs +110 -8
- package/browser/shared/components/page.mjs +22 -3
- package/browser/shared/components/state.mjs +5 -1
- package/browser/shared/components/table.mjs +1 -1
- package/browser/shared/components/text.mjs +2 -2
- package/browser/shared/document-look.mjs +183 -0
- package/browser/shared/drafts.mjs +432 -0
- package/browser/shared/emoji/data/LICENSE-lucide.txt +43 -0
- package/browser/shared/emoji/data/README.md +4 -2
- package/browser/shared/emoji/data/categories.json +1 -1
- package/browser/shared/emoji/data/keywords-en.json +1 -1
- package/browser/shared/emoji/data/keywords-zh.json +1 -1
- package/browser/shared/emoji/data/names.json +1 -1
- package/browser/shared/emoji/data/positions.json +1 -1
- package/browser/shared/emoji/data/twemoji-index.json +1 -1
- package/browser/shared/emoji/data/twemoji-svg.bin +0 -0
- package/browser/shared/emoji/data.mjs +10 -12
- package/browser/shared/emoji/emoji.mjs +8 -7
- package/browser/shared/emoji/icon-value.mjs +4 -3
- package/browser/shared/extension-sidebar.mjs +126 -0
- package/browser/shared/extensions.mjs +79 -0
- package/browser/shared/file-table.mjs +101 -0
- package/browser/shared/html-tree.mjs +11 -5
- package/browser/shared/i18n/en.mjs +374 -35
- package/browser/shared/json-layout.mjs +47 -0
- package/browser/shared/long-runs.mjs +39 -0
- package/browser/shared/net-cache.mjs +133 -0
- package/browser/shared/net-keys.mjs +32 -0
- package/browser/shared/net-policy.mjs +177 -0
- package/browser/shared/new-names.mjs +5 -2
- package/browser/shared/outline-shape.mjs +128 -0
- package/browser/shared/outline.mjs +458 -0
- package/browser/shared/pack-manifest.mjs +77 -0
- package/browser/shared/page-address.mjs +6 -3
- package/browser/shared/page-cards.mjs +308 -0
- package/browser/shared/page-links.mjs +69 -6
- package/browser/shared/pages.mjs +388 -0
- package/browser/shared/paths.mjs +6 -0
- package/browser/shared/preferences.mjs +10 -4
- package/browser/shared/preview-server.mjs +3 -7
- package/browser/shared/session.mjs +13 -5
- package/browser/shared/shipped-blocks.mjs +299 -0
- package/browser/shared/table-chart.mjs +33 -1
- package/browser/shared/todos.mjs +83 -0
- package/browser/shared/user-directory.mjs +24 -0
- package/browser/shared/versions.mjs +14 -0
- package/browser/shared/web-links.mjs +134 -0
- package/browser/shared/workspace-columns.mjs +120 -0
- package/browser/shared/workspace-look.mjs +91 -0
- package/browser/shared/workspace-name.mjs +154 -0
- package/browser/shared/workspace-query.mjs +125 -0
- package/browser/shared/workspace-registry.mjs +272 -0
- package/browser/shared/workspace.mjs +171 -20
- package/browser/shared/zoom.mjs +5 -5
- package/dist/chunk-2NRBY6AJ.mjs +2 -0
- package/dist/chunk-32ZUEFZ7.mjs +2 -0
- package/dist/chunk-35NQ4PLQ.mjs +2 -0
- package/dist/chunk-3KJHLHUO.mjs +2 -0
- package/dist/chunk-3NJACR4W.mjs +2 -0
- package/dist/chunk-4AV456RQ.mjs +2 -0
- package/dist/chunk-4OZWXZE5.mjs +5 -0
- package/dist/chunk-5XYHDBJ5.mjs +2 -0
- package/dist/chunk-5ZJA7CXT.mjs +2 -0
- package/dist/chunk-6A53MZYZ.mjs +2 -0
- package/dist/chunk-6EXH3ORZ.mjs +166 -0
- package/dist/chunk-6EZ7FNIK.mjs +3 -0
- package/dist/{chunk-UXUK4PMC.mjs → chunk-6QBHU4DF.mjs} +1 -1
- package/dist/{chunk-6U2SLSDN.mjs → chunk-6VTU6KEO.mjs} +1 -1
- package/dist/chunk-B4P2CM2J.mjs +3 -0
- package/dist/chunk-BPL64HGA.mjs +4 -0
- package/dist/chunk-BVEFGE4B.mjs +2 -0
- package/dist/chunk-BZ5RAF7L.mjs +2 -0
- package/dist/chunk-CRJEG7MT.mjs +2 -0
- package/dist/{chunk-B3VTYBYR.mjs → chunk-D4CKRD3V.mjs} +91 -91
- package/dist/chunk-D4EURAX4.mjs +4 -0
- package/dist/chunk-DQCE7TJY.mjs +5 -0
- package/dist/chunk-DR73Y2UJ.mjs +3 -0
- package/dist/{chunk-TMYZB6AV.mjs → chunk-EKNHM3P4.mjs} +1 -1
- package/dist/{chunk-DB4WKGYF.mjs → chunk-ERLAIBOA.mjs} +2 -2
- package/dist/chunk-EURLTOTZ.mjs +4 -0
- package/dist/chunk-FJYN7RTH.mjs +4 -0
- package/dist/chunk-FWNRPMCJ.mjs +12 -0
- package/dist/chunk-FWW4CSAZ.mjs +2 -0
- package/dist/{chunk-2B5E4CDJ.mjs → chunk-GPIWQ4X4.mjs} +1 -1
- package/dist/chunk-GY3FAUVM.mjs +2 -0
- package/dist/chunk-HLYV7RIH.mjs +2 -0
- package/dist/chunk-HMYTM3GT.mjs +15 -0
- package/dist/chunk-IA4PSIMD.mjs +2 -0
- package/dist/chunk-JEUK3ZO7.mjs +2 -0
- package/dist/chunk-JVHHHGEA.mjs +3 -0
- package/dist/chunk-KTKHRC6H.mjs +2 -0
- package/dist/chunk-L7UP52JO.mjs +2 -0
- package/dist/chunk-MHW7ZKOU.mjs +2 -0
- package/dist/chunk-N76HWBA3.mjs +10 -0
- package/dist/chunk-N7AZZLGT.mjs +548 -0
- package/dist/chunk-NAMN3RAF.mjs +2 -0
- package/dist/{chunk-YXAUQPVK.mjs → chunk-NFMCP2HI.mjs} +3 -3
- package/dist/chunk-NG375ILQ.mjs +2 -0
- package/dist/chunk-NVRNLK25.mjs +6 -0
- package/dist/chunk-NWFBE2YA.mjs +2 -0
- package/dist/chunk-NWR2LT5B.mjs +2 -0
- package/dist/chunk-OJKMINIU.mjs +20 -0
- package/dist/chunk-OUUP3WKT.mjs +2 -0
- package/dist/chunk-OW5NWPOJ.mjs +10 -0
- package/dist/chunk-PAREWQGB.mjs +4 -0
- package/dist/chunk-POQSE4C2.mjs +2 -0
- package/dist/chunk-PUOQ65NC.mjs +2 -0
- package/dist/{chunk-Z52HTUW7.mjs → chunk-PVER7LSC.mjs} +2 -2
- package/dist/chunk-PZDLJJTJ.mjs +3 -0
- package/dist/chunk-Q47PLKIJ.mjs +15 -0
- package/dist/chunk-Q4UEPUWF.mjs +2 -0
- package/dist/chunk-QKXMPUXC.mjs +2 -0
- package/dist/chunk-QOUEFUCH.mjs +16 -0
- package/dist/chunk-RFDZXFJF.mjs +13 -0
- package/dist/chunk-RKPWLGZ3.mjs +4 -0
- package/dist/chunk-RMECZA2K.mjs +2 -0
- package/dist/{chunk-EUX7IC5J.mjs → chunk-SQ6Y2ZMA.mjs} +2 -2
- package/dist/chunk-SX4LJYT6.mjs +8 -0
- package/dist/chunk-SXHBYZST.mjs +16 -0
- package/dist/chunk-TANZRINB.mjs +2 -0
- package/dist/chunk-TEZAWDSQ.mjs +2 -0
- package/dist/chunk-UBBRTJ2R.mjs +24 -0
- package/dist/chunk-UFNYFFKO.mjs +20 -0
- package/dist/chunk-UGWYKHBL.mjs +170 -0
- package/dist/chunk-UKSHDZZ6.mjs +2 -0
- package/dist/chunk-UMHUSOPJ.mjs +2 -0
- package/dist/chunk-UNOYVIYR.mjs +2 -0
- package/dist/chunk-V6RIYQZZ.mjs +4 -0
- package/dist/chunk-VJPFVNNW.mjs +15 -0
- package/dist/chunk-VS3ZMVGX.mjs +5 -0
- package/dist/chunk-VTKNEYT3.mjs +6 -0
- package/dist/chunk-VXACTLO3.mjs +3 -0
- package/dist/chunk-W3BGBJQW.mjs +2 -0
- package/dist/chunk-YI43RG4P.mjs +2 -0
- package/dist/chunk-YQGT4AB2.mjs +6 -0
- package/dist/chunk-ZB4H7ZN4.mjs +2 -0
- package/dist/{chunk-ACOPDCNB.mjs → chunk-ZHEHPMBK.mjs} +1 -1
- package/dist/chunk-ZTHICSSF.mjs +2 -0
- package/dist/chunk-ZUNVAXLH.mjs +2 -0
- package/dist/chunk-ZWPMCK7P.mjs +2 -0
- package/dist/cli.mjs +1 -1
- package/dist/server.mjs +1 -1
- package/dist/{chunk-EVJ3BX3M.mjs → update-fetch.mjs} +1 -1
- package/dist/worker.mjs +1 -1
- package/kit/board.css +95 -0
- package/kit/board.js +250 -0
- package/kit/charts.js +5 -71
- package/kit/code.js +14 -14
- package/kit/math.js +18 -2
- package/kit/report.css +500 -151
- package/kit/runtime.js +1720 -170
- package/kit/state.js +10 -1
- package/kit/tables.js +172 -37
- package/kit/ui.js +166 -27
- package/package.json +2 -1
- package/packs/gallery/card/component.json +14 -0
- package/packs/gallery/card/example.html +10 -0
- package/packs/gallery/card/preview.svg +1 -0
- package/packs/gallery/card/style.css +6 -0
- package/packs/gallery/card/template.html +6 -0
- package/packs/gallery/card/writing.md +14 -0
- package/packs/gallery/chart-card/component.json +15 -0
- package/packs/gallery/chart-card/example.html +14 -0
- package/packs/gallery/chart-card/kit.js +130 -0
- package/packs/gallery/chart-card/preview.svg +1 -0
- package/packs/gallery/chart-card/style.css +42 -0
- package/packs/gallery/chart-card/template.html +13 -0
- package/packs/gallery/chart-card/writing.md +20 -0
- package/packs/gallery/chart-view/component.json +20 -0
- package/packs/gallery/chart-view/example.html +13 -0
- package/packs/gallery/chart-view/kit.js +355 -0
- package/packs/gallery/chart-view/preview.svg +1 -0
- package/packs/gallery/chart-view/style.css +94 -0
- package/packs/gallery/chart-view/template.html +3 -0
- package/packs/gallery/chart-view/writing.md +22 -0
- package/packs/gallery/countdown/component.json +18 -0
- package/packs/gallery/countdown/example.html +3 -0
- package/packs/gallery/countdown/kit.js +156 -0
- package/packs/gallery/countdown/preview.svg +1 -0
- package/packs/gallery/countdown/style.css +130 -0
- package/packs/gallery/countdown/template.html +3 -0
- package/packs/gallery/countdown/writing.md +22 -0
- package/packs/gallery/habit/component.json +14 -0
- package/packs/gallery/habit/example.html +3 -0
- package/packs/gallery/habit/kit.js +295 -0
- package/packs/gallery/habit/preview.svg +1 -0
- package/packs/gallery/habit/style.css +246 -0
- package/packs/gallery/habit/template.html +3 -0
- package/packs/gallery/habit/writing.md +21 -0
- package/packs/gallery/heatmap/component.json +18 -0
- package/packs/gallery/heatmap/example.html +3 -0
- package/packs/gallery/heatmap/kit.js +351 -0
- package/packs/gallery/heatmap/preview.svg +1 -0
- package/packs/gallery/heatmap/style.css +201 -0
- package/packs/gallery/heatmap/template.html +3 -0
- package/packs/gallery/heatmap/writing.md +21 -0
- package/packs/gallery/kanban/component.json +18 -0
- package/packs/gallery/kanban/example.html +12 -0
- package/packs/gallery/kanban/kit.js +540 -0
- package/packs/gallery/kanban/preview.svg +1 -0
- package/packs/gallery/kanban/style.css +212 -0
- package/packs/gallery/kanban/template.html +3 -0
- package/packs/gallery/kanban/writing.md +20 -0
- package/packs/gallery/metric/component.json +22 -0
- package/packs/gallery/metric/example.html +15 -0
- package/packs/gallery/metric/kit.js +248 -0
- package/packs/gallery/metric/preview.svg +1 -0
- package/packs/gallery/metric/style.css +92 -0
- package/packs/gallery/metric/template.html +3 -0
- package/packs/gallery/metric/writing.md +23 -0
- package/packs/gallery/note/component.json +14 -0
- package/packs/gallery/note/example.html +3 -0
- package/packs/gallery/note/kit.js +102 -0
- package/packs/gallery/note/preview.svg +1 -0
- package/packs/gallery/note/style.css +76 -0
- package/packs/gallery/note/template.html +3 -0
- package/packs/gallery/note/writing.md +18 -0
- package/packs/gallery/pack.json +8 -0
- package/packs/gallery/recent/component.json +13 -0
- package/packs/gallery/recent/example.html +1 -0
- package/packs/gallery/recent/kit.js +238 -0
- package/packs/gallery/recent/preview.svg +1 -0
- package/packs/gallery/recent/style.css +158 -0
- package/packs/gallery/recent/template.html +1 -0
- package/packs/gallery/recent/writing.md +15 -0
- package/packs/gallery/static/component.json +13 -0
- package/packs/gallery/static/example.html +11 -0
- package/packs/gallery/static/preview.svg +1 -0
- package/packs/gallery/static/style.css +138 -0
- package/packs/gallery/static/template.html +1 -0
- package/packs/gallery/static/writing.md +18 -0
- package/packs/gallery/stats/component.json +13 -0
- package/packs/gallery/stats/example.html +1 -0
- package/packs/gallery/stats/kit.js +166 -0
- package/packs/gallery/stats/preview.svg +1 -0
- package/packs/gallery/stats/style.css +151 -0
- package/packs/gallery/stats/template.html +1 -0
- package/packs/gallery/stats/writing.md +11 -0
- package/packs/gallery/today/component.json +12 -0
- package/packs/gallery/today/example.html +1 -0
- package/packs/gallery/today/kit.js +185 -0
- package/packs/gallery/today/preview.svg +1 -0
- package/packs/gallery/today/style.css +120 -0
- package/packs/gallery/today/template.html +1 -0
- package/packs/gallery/today/writing.md +14 -0
- package/packs/gallery/todos/component.json +19 -0
- package/packs/gallery/todos/example.html +3 -0
- package/packs/gallery/todos/kit.js +342 -0
- package/packs/gallery/todos/preview.svg +1 -0
- package/packs/gallery/todos/style.css +267 -0
- package/packs/gallery/todos/template.html +3 -0
- package/packs/gallery/todos/writing.md +30 -0
- package/packs/gallery/weather/component.json +19 -0
- package/packs/gallery/weather/example.html +3 -0
- package/packs/gallery/weather/kit.js +312 -0
- package/packs/gallery/weather/preview.svg +1 -0
- package/packs/gallery/weather/style.css +258 -0
- package/packs/gallery/weather/template.html +3 -0
- package/packs/gallery/weather/writing.md +26 -0
- package/packs/gallery-soft/pack.json +8 -0
- package/release.json +13 -11
- package/sdk/doc-kit.d.ts +404 -7
- package/sdk/doc-state.d.ts +2 -0
- package/skill/SKILL.md +71 -26
- package/skill/references/block-script.md +140 -0
- package/skill/references/building-blocks.md +257 -0
- package/skill/references/example-report.html +1 -1
- package/skill/references/extensions.md +59 -0
- package/skill/references/pages-and-data.md +221 -0
- package/skill/references/writing-html.md +9 -7
- package/skill/sdk/doc-kit.d.ts +404 -7
- package/skill/sdk/doc-state.d.ts +2 -0
- package/web/assets/index-BK2e_07w.js +13 -0
- package/web/assets/index-CWFI83mF.css +1 -0
- package/web/index.html +2 -2
- package/browser/editor/components/callout/page.mjs +0 -13
- package/dist/chunk-2PBALTR3.mjs +0 -57
- package/dist/chunk-3LA3EMDE.mjs +0 -15
- package/dist/chunk-5FRMCDPY.mjs +0 -16
- package/dist/chunk-5LEK2CBS.mjs +0 -2
- package/dist/chunk-5OFN5AHC.mjs +0 -2
- package/dist/chunk-5SIYS5HN.mjs +0 -2
- package/dist/chunk-5TEK3RAD.mjs +0 -2
- package/dist/chunk-6CYG3Z4V.mjs +0 -2
- package/dist/chunk-7GHT2UCA.mjs +0 -15
- package/dist/chunk-7QQBR7PB.mjs +0 -2
- package/dist/chunk-ATCJYAR4.mjs +0 -2
- package/dist/chunk-C7HWOBIF.mjs +0 -2
- package/dist/chunk-E7VYDG2X.mjs +0 -2
- package/dist/chunk-EZY3WC6Z.mjs +0 -15
- package/dist/chunk-FQGQH4KM.mjs +0 -2
- package/dist/chunk-G7TOXONE.mjs +0 -6
- package/dist/chunk-GPF4YWWB.mjs +0 -9
- package/dist/chunk-GYQV7Y4J.mjs +0 -120
- package/dist/chunk-HMHK3EQ6.mjs +0 -2
- package/dist/chunk-HQQMJCQJ.mjs +0 -10
- package/dist/chunk-IERUOGC3.mjs +0 -6
- package/dist/chunk-ITNLYXXV.mjs +0 -3
- package/dist/chunk-L4DVONOG.mjs +0 -2
- package/dist/chunk-LAE5NQ4B.mjs +0 -2
- package/dist/chunk-LC7YNQFG.mjs +0 -2
- package/dist/chunk-LHTFLRB6.mjs +0 -4
- package/dist/chunk-NFIBI4IP.mjs +0 -26
- package/dist/chunk-NSKUTQ5J.mjs +0 -5
- package/dist/chunk-O52JMOCZ.mjs +0 -2
- package/dist/chunk-P2CAZPDP.mjs +0 -3
- package/dist/chunk-QMQUXTU4.mjs +0 -12
- package/dist/chunk-QVWVFC5K.mjs +0 -6
- package/dist/chunk-QYKCJ7FG.mjs +0 -8
- package/dist/chunk-QZY6Q64C.mjs +0 -2
- package/dist/chunk-TDQP3DKQ.mjs +0 -10
- package/dist/chunk-TX6JH7TR.mjs +0 -2
- package/dist/chunk-UNUEWH4S.mjs +0 -2
- package/dist/chunk-V4CPWKMZ.mjs +0 -2
- package/dist/chunk-VACRB2NE.mjs +0 -3
- package/dist/chunk-W63L7367.mjs +0 -7
- package/dist/chunk-W7CXPCRV.mjs +0 -6
- package/dist/chunk-XINNG4F2.mjs +0 -4
- package/dist/chunk-YL2DPWVS.mjs +0 -4
- package/dist/chunk-YZ5Z6H4W.mjs +0 -4
- package/dist/chunk-ZBIM6ARY.mjs +0 -216
- package/skill/references/building-components.md +0 -327
- package/web/assets/index-B6Ai3wsa.js +0 -13
- package/web/assets/index-SYPC3EZy.css +0 -1
|
@@ -14,12 +14,12 @@ import { groupItems } from "./rules.mjs";
|
|
|
14
14
|
// starts, those between whole, the last up to where it ends; a list's items each an
|
|
15
15
|
// item of its kind (`list`, as an item selected on its own) with its checked state
|
|
16
16
|
// and what of the blocks it holds the selection reaches, a quote's paragraphs in a
|
|
17
|
-
// quote, and a highlight block, a disclosure or a section the selection ends in
|
|
17
|
+
// quote, and a highlight block, a callout, a disclosure or a section the selection ends in
|
|
18
18
|
// with what of it comes before the end (its icon, its title), a tabs area with the
|
|
19
19
|
// tab shown and what of its panel comes before the end; a flowchart's nodes a
|
|
20
20
|
// flowchart with its direction (never loose paragraphs: its steps are no items),
|
|
21
21
|
// the node it ends in a node with what of it comes before the end. Around where it
|
|
22
|
-
// starts, a highlight block, a disclosure, a section, a flowchart's node, an item
|
|
22
|
+
// starts, a highlight block, a callout, a disclosure, a section, a flowchart's node, an item
|
|
23
23
|
// whose own text comes before it, a row of columns, a column or a tabs area are not
|
|
24
24
|
// copied, only what of them it holds (notion-lite copies no block its start is in:
|
|
25
25
|
// a callout, a toggle, a list item's parent; a row of columns it flattens wherever).
|
|
@@ -124,7 +124,7 @@ export function describeAcross(range, { texts, wholes }) {
|
|
|
124
124
|
const html = selectedHtml(host, pieces.get(host));
|
|
125
125
|
const part = askClipboard("piece", host, html, what);
|
|
126
126
|
if (part) return part;
|
|
127
|
-
const type = host.parentElement?.hasAttribute("data-ge-box") ? copiedType(host) : null;
|
|
127
|
+
const type = host.parentElement?.hasAttribute("data-ge-box") && (host.getAttribute("data-ge-kind") ?? "flow") === "flow" ? copiedType(host) : null;
|
|
128
128
|
const color = colorOf(host);
|
|
129
129
|
return { type: type ?? "paragraph", html, ...(color ? { color } : {}) };
|
|
130
130
|
};
|
|
@@ -180,8 +180,6 @@ const paragraph = {
|
|
|
180
180
|
html: (block, how) => `<p>${how.portable(block.html ?? "")}</p>`,
|
|
181
181
|
};
|
|
182
182
|
|
|
183
|
-
const inAside = (text) => ["<aside>", ...text.split("\n"), "</aside>"];
|
|
184
|
-
|
|
185
183
|
const todo = list("ul", (_, checked, gap) => `- [${checked ? "x" : " "}]${gap}`);
|
|
186
184
|
|
|
187
185
|
export const WRITERS = {
|
|
@@ -218,15 +216,6 @@ export const WRITERS = {
|
|
|
218
216
|
},
|
|
219
217
|
html: (block, how) => `<div>${block.blocks.map(how.html).join("")}</div>`,
|
|
220
218
|
},
|
|
221
|
-
// A text block in one <aside>: its text alone, no blocks to set apart from it by an empty line. Its
|
|
222
|
-
// HTML is a paragraph of its text, as notion-lite's is no block of HTML: an <aside> would be rich
|
|
223
|
-
// formatting, for which the import reads the HTML of all that is copied with it, and has no block
|
|
224
|
-
// of its own. An empty one has none: an empty element would be read for it.
|
|
225
|
-
callout: {
|
|
226
|
-
copied: (block, how) => inAside(how.inline(block.html ?? "")),
|
|
227
|
-
exported: (unit, how) => inAside(how.own(unit)),
|
|
228
|
-
html: (block, how) => (block.html?.trim() ? `<p>${how.portable(block.html)}</p>` : ""),
|
|
229
|
-
},
|
|
230
219
|
// A disclosure: "- " and its title, its blocks 4 spaces in (Notion writes a toggle as an item), but
|
|
231
220
|
// no list: an empty line stands between it and a list beside it.
|
|
232
221
|
toggle: {
|
|
@@ -13,17 +13,20 @@ import { t } from "../../../shared/i18n/index.mjs";
|
|
|
13
13
|
// and blocks/grid.css), and between the nodes of a flowchart's row (步骤流程图: the same tool, the
|
|
14
14
|
// user's of 2026-10-25). With the pointer in the gap between two of them, a thin line stands down
|
|
15
15
|
// it, and the cursor says it resizes: dragging it moves only the two beside it (ratiosAfterResize:
|
|
16
|
-
// snapping to their equal split and to tenths of the row, each keeping its least
|
|
17
|
-
// share
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
16
|
+
// snapping to their equal split and to tenths of the row within SNAP px, each keeping its least
|
|
17
|
+
// share), the bottom notice saying the row's shares while it lasts (no badge on the parts: the user,
|
|
18
|
+
// 2026-11-07, who also found the old snap of 1% of the row too strong); letting go writes the shares
|
|
19
|
+
// as one undo step, Esc cancels, and a double click makes the row's parts equal again. The line is
|
|
20
|
+
// a gray, never a bright blue (the guide tokens, look.mjs): faint where a drag may start, darker
|
|
21
|
+
// while it is dragged, darkest where it snaps. A kind of row (KINDS) says how its parts are found,
|
|
22
|
+
// measured, shown while dragged and written:
|
|
23
|
+
// - a row of columns: the line darker in the row (fainter above it, up to its pin); above each gap,
|
|
24
|
+
// and right of the last column, a dot turns into a round + that adds a column there (新增分栏). While the
|
|
22
25
|
// pointer is over a row, or the caret in it, its columns are tinted, so the reader sees where they
|
|
23
26
|
// are. A row stacked on a narrow screen has no gaps. Its shares (--doc-column-ratio) are shown
|
|
24
27
|
// as the columns' flex-grow while dragged, written as one structural step.
|
|
25
28
|
// - a flowchart's row, as the kit laid it out (its nodes whose cards stand at one height:
|
|
26
|
-
// components/flowchart/page.mjs rowsOfFlow): the line
|
|
29
|
+
// components/flowchart/page.mjs rowsOfFlow): the line faint, darker once pressed, the
|
|
27
30
|
// arrow under it dimmed while it shows; no pin (a node is added by the "+" at a node's right,
|
|
28
31
|
// add.mjs). A node keeps the least width the kit gives a card beside others (leastWidth: 116px and
|
|
29
32
|
// its longest word), so the row never wraps under the pointer. Its shares are each node's weight
|
|
@@ -42,26 +45,30 @@ const STYLE = `
|
|
|
42
45
|
}
|
|
43
46
|
${gestureLock("data-ge-gap", { cursor: "col-resize" })}
|
|
44
47
|
html[data-ge-gap-drag] { -webkit-user-select: none; user-select: none; }
|
|
45
|
-
.ge-gap-line { width: 2px; border-radius:
|
|
46
|
-
.ge-gap-line[data-hot] { background:
|
|
47
|
-
.ge-gap-
|
|
48
|
-
.ge-gap-pin
|
|
49
|
-
.ge-gap-pin > .ge-gap-dot { left: 6px; top: 6.5px; }
|
|
50
|
-
.ge-gap-pin > .ge-gap-add { left: -
|
|
48
|
+
.ge-gap-line { width: 2px; border-radius: 1px; background: var(--ge-guide); pointer-events: none; }
|
|
49
|
+
.ge-gap-line[data-hot] { background: var(--ge-guide-hot); }
|
|
50
|
+
.ge-gap-line[data-hot][data-snap] { background: var(--ge-guide-snap); }
|
|
51
|
+
.ge-gap-pin { width: 16px; height: 16px; color: var(--ge-ico3); cursor: pointer; pointer-events: auto; }
|
|
52
|
+
.ge-gap-pin > .ge-gap-dot { position: absolute; left: 6px; top: 6.5px; display: block; }
|
|
53
|
+
.ge-gap-pin > .ge-gap-add { position: absolute; left: -2px; top: -2px; display: grid; place-items: center; box-sizing: border-box; width: 20px; height: 20px; border-radius: 50%;
|
|
54
|
+
background: var(--ge-bg); color: var(--ge-ico); box-shadow: 0 1px 3px light-dark(rgb(25 25 25 / 18%), rgb(0 0 0 / 45%)); opacity: 0; transform: scale(.6); transition: opacity .15s, transform .15s; }
|
|
55
|
+
.ge-gap-pin > .ge-gap-add > svg { display: block; }
|
|
51
56
|
.ge-gap-pin:hover > .ge-gap-dot { opacity: 0; }
|
|
52
57
|
.ge-gap-pin:hover > .ge-gap-add { opacity: 1; transform: scale(1); }
|
|
53
|
-
.ge-gap-badge { padding: 0 4px; border-radius: 4px; color: #fff; background: rgb(0 0 0 / 30%); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); font: 12px/18px var(--doc-font, system-ui, sans-serif); pointer-events: none; white-space: nowrap; }
|
|
54
58
|
/* The arrow under a flowchart's gap line (the node's ::after, the kit's) dimmed while the line shows. */
|
|
55
59
|
ol.doc-flow > li::after { transition: opacity .12s; }
|
|
56
60
|
ol.doc-flow > li[data-ge-gap-dim]::after { opacity: .15; }
|
|
57
61
|
@media (prefers-reduced-motion: reduce) { ol.doc-flow > li::after { transition: none; } }
|
|
58
62
|
`;
|
|
59
|
-
// Feishu's dot
|
|
60
|
-
|
|
61
|
-
const
|
|
63
|
+
// Feishu's dot, in the handle's quietest gray; under the pointer it turns into a round + in the
|
|
64
|
+
// look of the editor's small floating buttons (a white disc, a hairline, a gray +), not Feishu's blue pin.
|
|
65
|
+
const DOT = '<svg class="ge-gap-dot" width="4" height="3" viewBox="0 0 4 3" aria-hidden="true"><path d="M3.5 1.5a1.5 1.5 0 11-3 0 1.5 1.5 0 013 0z" fill="currentColor"/></svg>';
|
|
66
|
+
const PIN = '<span class="ge-gap-add"><svg width="12" height="12" viewBox="0 0 12 12" aria-hidden="true"><path d="M6 1.75v8.5M1.75 6h8.5" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg></span>';
|
|
62
67
|
const TAIL = 20; // right of the last column, the pin's gap (Feishu's last gap)
|
|
63
68
|
const ABOVE = 30; // the pin stands this far above the row: the gap reaches up to it
|
|
64
69
|
const DOUBLE = { time: 500, distance: 4 }; // two presses on a gap this soon and this near: a double click (ms, px)
|
|
70
|
+
const SNAP = 5; // px: how near the equal split or a tenth of the row a dragged gap snaps to it
|
|
71
|
+
const LIVE = 60000; // ms: the notice saying the shares stays while the drag lasts (it is taken off when it ends)
|
|
65
72
|
|
|
66
73
|
const percent = (ratios) => ratios.map((ratio) => `${Math.round(100 * ratio)}%`).join(" / ");
|
|
67
74
|
const same = (a, b) => a.every((ratio, index) => Math.abs(ratio - b[index]) < 0.0005);
|
|
@@ -69,16 +76,17 @@ const same = (a, b) => a.every((ratio, index) => Math.abs(ratio - b[index]) < 0.
|
|
|
69
76
|
/**
|
|
70
77
|
* active(): whether the tools may show. struct(parents, touched, mutate): the editor's undoable
|
|
71
78
|
* structural change (it records the columns' widths). look(elements, changes): the editor's undoable
|
|
72
|
-
* change of blocks' looks (a flowchart's nodes' weights, history.mjs lookStep). say
|
|
79
|
+
* change of blocks' looks (a flowchart's nodes' weights, history.mjs lookStep). say(text, kind, hold):
|
|
80
|
+
* the bottom notice; settle(): the notice taken off.
|
|
73
81
|
* What is resized is known by the page objects that say so: `columnOps` (a row's ratios, add(row,
|
|
74
82
|
* index): a new column there) and `rowOps` (a row of nodes, its shares and weights).
|
|
75
83
|
*/
|
|
76
|
-
export function createColumnGaps({ active, struct, look, say }) {
|
|
84
|
+
export function createColumnGaps({ active, struct, look, say, settle = () => {} }) {
|
|
77
85
|
addStyle(STYLE);
|
|
78
86
|
const { add, columnsOf, ratiosAfterResize, ratiosOf, setRatios, sized } = columnOps() ?? {};
|
|
79
87
|
const { leastWidth, rowShares, rowsOfFlow, weightValue } = rowOps() ?? {};
|
|
80
88
|
let hover = null; // { row, index, last, line, pin }: the gap after part `index` of `row` (last: right of the last column)
|
|
81
|
-
let drag = null; // { row, index, start, before, least, ratios, span, x, line,
|
|
89
|
+
let drag = null; // { row, index, start, before, least, ratios, snapped, span, x, line, told }
|
|
82
90
|
|
|
83
91
|
// ---------- the kinds of row ----------
|
|
84
92
|
// A row: { kind, el: the element holding it (a row of columns, a flowchart), parts: its parts in
|
|
@@ -86,6 +94,7 @@ export function createColumnGaps({ active, struct, look, say }) {
|
|
|
86
94
|
const KINDS = {
|
|
87
95
|
columns: {
|
|
88
96
|
label: "column", // what its overlays are listed as (overlays.mjs)
|
|
97
|
+
live: (ratios) => t("栏宽:{0}", percent(ratios)), // the notice while a gap is dragged
|
|
89
98
|
containers: kept(() => [...document.querySelectorAll(".doc-columns[data-ge-box]")]),
|
|
90
99
|
// Its one row, side by side (a stacked one has no gaps).
|
|
91
100
|
rows: (el) => (getComputedStyle(el).flexDirection.startsWith("column") ? [] : [columnsOf(el)]),
|
|
@@ -118,6 +127,7 @@ export function createColumnGaps({ active, struct, look, say }) {
|
|
|
118
127
|
},
|
|
119
128
|
flowchart: {
|
|
120
129
|
label: "flowchart",
|
|
130
|
+
live: (ratios) => t("节点宽度:{0}", percent(ratios)),
|
|
121
131
|
containers: kept(() => [...document.querySelectorAll("ol.doc-flow[data-ge-box]:not([data-ge-keep])")]),
|
|
122
132
|
// Its rows of two nodes or more, laid out in rows by the kit (one node a row has no gaps).
|
|
123
133
|
rows: (el) => (getComputedStyle(el).flexDirection.startsWith("column") ? [] : rowsOfFlow(el).filter((steps) => steps.length > 1 && steps.every((step) => step.hasAttribute("data-ge-box")))),
|
|
@@ -256,7 +266,8 @@ export function createColumnGaps({ active, struct, look, say }) {
|
|
|
256
266
|
before: kind.before(row),
|
|
257
267
|
least: kind.least(row, span),
|
|
258
268
|
line: hover?.line ?? null,
|
|
259
|
-
|
|
269
|
+
snapped: false,
|
|
270
|
+
told: null, // what the notice says now
|
|
260
271
|
};
|
|
261
272
|
hover?.pin?.remove();
|
|
262
273
|
hover?.line.setAttribute("data-hot", "");
|
|
@@ -268,43 +279,34 @@ export function createColumnGaps({ active, struct, look, say }) {
|
|
|
268
279
|
}
|
|
269
280
|
|
|
270
281
|
// The two parts beside the gap as the pointer has moved (none until it has: a press alone changes
|
|
271
|
-
// nothing), shown
|
|
282
|
+
// nothing), shown; the row's shares in the bottom notice (said again only when they change), the
|
|
283
|
+
// line darkest where they snapped.
|
|
272
284
|
function update(x) {
|
|
273
285
|
const { row, index, start, span, least } = drag;
|
|
274
286
|
const kind = kindOf(row);
|
|
275
|
-
|
|
287
|
+
const moved = (x - drag.x) / span;
|
|
288
|
+
drag.ratios = Math.abs(x - drag.x) < 1 ? start : ratiosAfterResize(start, index, moved, least, SNAP / span);
|
|
289
|
+
drag.snapped = Math.abs(x - drag.x) >= 1 && !same(drag.ratios, ratiosAfterResize(start, index, moved, least, 0));
|
|
276
290
|
if (same(drag.ratios, start)) kind.reset(row, drag.before);
|
|
277
291
|
else kind.show(row, drag.ratios);
|
|
292
|
+
drag.line?.toggleAttribute("data-snap", drag.snapped);
|
|
293
|
+
const told = drag.told || Math.abs(x - drag.x) >= 1 ? kind.live(drag.ratios) : null; // a press alone says nothing
|
|
294
|
+
if (told && told !== drag.told) say(told, "note", LIVE);
|
|
295
|
+
drag.told = told ?? drag.told;
|
|
278
296
|
// A row of columns is laid out again at once; a flowchart's by the kit, in a frame of its own
|
|
279
|
-
// asked for as the weights are written (after this one's):
|
|
280
|
-
if (kind.pins)
|
|
281
|
-
else requestAnimationFrame(() => requestAnimationFrame(() => { if (drag?.row === row)
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Each share at its part's top right (a node's 10px in from its right edge, across its border: the mock's).
|
|
285
|
-
function placeBadges() {
|
|
286
|
-
const { row, ratios, badges } = drag;
|
|
287
|
-
const layer = layerOf(row.el);
|
|
288
|
-
const flowchart = !kindOf(row).pins;
|
|
289
|
-
row.parts.forEach((part, at) => {
|
|
290
|
-
const rect = part.getBoundingClientRect();
|
|
291
|
-
badges[at].textContent = `${Math.round(100 * ratios[at])}%`;
|
|
292
|
-
if (badges[at].parentNode !== layer) layer.append(badges[at]);
|
|
293
|
-
const size = badges[at].getBoundingClientRect();
|
|
294
|
-
const right = flowchart ? rect.right - 10 : rect.right + 2;
|
|
295
|
-
const top = flowchart ? rect.top - size.height / 2 : rect.top - 2;
|
|
296
|
-
drawBox(badges[at], layer, { left: right - size.width, top, right, bottom: top + size.height });
|
|
297
|
-
});
|
|
298
|
-
if (hover) place(hover);
|
|
297
|
+
// asked for as the weights are written (after this one's): the line placed again the frame after that.
|
|
298
|
+
if (kind.pins) { if (hover) place(hover); }
|
|
299
|
+
else requestAnimationFrame(() => requestAnimationFrame(() => { if (drag?.row === row && hover) place(hover); }));
|
|
299
300
|
}
|
|
300
301
|
|
|
301
302
|
function finish(commit) {
|
|
302
303
|
if (!drag) return;
|
|
303
|
-
const { row, start, ratios,
|
|
304
|
+
const { row, start, ratios, before, line, told } = drag;
|
|
304
305
|
const kind = kindOf(row);
|
|
305
306
|
drag = null;
|
|
306
307
|
note(row.kind, commit ? "gap released" : "gap cancelled");
|
|
307
|
-
|
|
308
|
+
line?.removeAttribute("data-snap");
|
|
309
|
+
if (told) settle(); // the shares dragged to: what is said next (or nothing) replaces them
|
|
308
310
|
kind.reset(row, before);
|
|
309
311
|
row.el.removeAttribute("data-ge-gap-drag");
|
|
310
312
|
document.documentElement.removeAttribute("data-ge-gap-drag");
|
|
@@ -355,6 +357,6 @@ export function createColumnGaps({ active, struct, look, say }) {
|
|
|
355
357
|
/** Whether a gap is being dragged (a flowchart's row shows the weights dragged, not yet a step: commits wait). */
|
|
356
358
|
get dragging() { return Boolean(drag); },
|
|
357
359
|
/** The editor's UI nodes to keep in the top layer when a modal dialog opens. */
|
|
358
|
-
get nodes() { return
|
|
360
|
+
get nodes() { return hover ? [hover.line, ...(hover.pin ? [hover.pin] : [])] : []; },
|
|
359
361
|
};
|
|
360
362
|
}
|
|
@@ -7,7 +7,7 @@ import { rangeAt, rangeOffsets } from "./marks.mjs";
|
|
|
7
7
|
import { pageOfKind, pageOfUnit } from "./page-objects.mjs";
|
|
8
8
|
import { containerTypeOf, pack, project } from "./sync-state.mjs";
|
|
9
9
|
import { outsideKey, randomBlockId } from "../../shared/ids.mjs";
|
|
10
|
-
import {
|
|
10
|
+
import { CHART_SOURCE, TABLE_READERS } from "../../shared/table-chart.mjs";
|
|
11
11
|
|
|
12
12
|
// The page's commits (autosave; docs/editor.md, "Commits"). A commit is what changed on the page
|
|
13
13
|
// since the last one, as collectEdits finds it against the layout and baselines the last commit
|
|
@@ -803,12 +803,18 @@ export function createCommits({ root, map, baselines, units, boxes, getLayout, s
|
|
|
803
803
|
baselines.set(id, html);
|
|
804
804
|
return id;
|
|
805
805
|
};
|
|
806
|
+
// How many blocks holding text blocks of their own (a list item's paragraphs) asLoaded made anew, those
|
|
807
|
+
// in them made anew with them: pathIndex finds a unit's blocks again then.
|
|
808
|
+
let rewrites = 0;
|
|
809
|
+
const holdsBlocks = (host) => host.querySelector("[contenteditable='true']") !== null;
|
|
806
810
|
// A text block as a load of the page shows the file's (its inline elements of the report's own
|
|
807
811
|
// atoms, written back as they are: core.mjs prepareBlock), the caret where it stood.
|
|
808
812
|
const asLoaded = (host, { inner, atoms = [], kind, caps }) => {
|
|
809
813
|
const selection = host.ownerDocument.getSelection();
|
|
810
814
|
const place = selection?.rangeCount && host.contains(selection.anchorNode) ? rangeOffsets(host, selection.getRangeAt(0)) : null;
|
|
815
|
+
const held = holdsBlocks(host);
|
|
811
816
|
prepareBlock(host, { inner, atoms, kind, caps });
|
|
817
|
+
if (held || holdsBlocks(host)) rewrites++;
|
|
812
818
|
if (place) select(rangeAt(host, place));
|
|
813
819
|
};
|
|
814
820
|
// The selection in a text block someone else's words are about to be merged into, as it stands among the
|
|
@@ -883,14 +889,26 @@ export function createCommits({ root, map, baselines, units, boxes, getLayout, s
|
|
|
883
889
|
const hosts = [...element.querySelectorAll("[contenteditable='true']")].filter((host) => host.parentElement?.closest("[data-ge-unit], [data-ge-unit-kind]") === element);
|
|
884
890
|
return hosts.length === blocks.length ? hosts : null;
|
|
885
891
|
};
|
|
886
|
-
// The text block of `element` (a unit of the page) that is the file's { self } or { path } one
|
|
887
|
-
|
|
892
|
+
// The text block of `element` (a unit of the page) that is the file's { self } or { path } one: the first
|
|
893
|
+
// of its own whose path (pathFrom) is that one. `find`: the unit's text blocks by path (pathIndex), which a
|
|
894
|
+
// caller asking of each of a unit's blocks makes once: found anew for each block, a table of 500 rows had
|
|
895
|
+
// its thousand cells walked, each past its row's 500 siblings, for each of the thousand the answer named,
|
|
896
|
+
// the page standing still for a minute after each commit there.
|
|
897
|
+
const blockElement = (element, block, find = pathIndex(element)) => {
|
|
888
898
|
// Its own text: the element itself, or the span of its own its description's `title` names (a Sheet tab's name).
|
|
889
899
|
if (block.self) return element.matches("[contenteditable='true']") ? element : BLOCK_TYPES[blockTypeOf(element)]?.title?.(element) ?? null;
|
|
890
900
|
if (!Array.isArray(block.path) || block.path[0] !== "unit") return null;
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
901
|
+
return find(JSON.stringify(block.path));
|
|
902
|
+
};
|
|
903
|
+
// The text blocks of `element` by path, for asking of many in turn: found once (hostsByPath), and again only
|
|
904
|
+
// once a block holding blocks of its own was made anew as the file gives it (asLoaded's `rewrites`).
|
|
905
|
+
const pathIndex = (element) => {
|
|
906
|
+
let index = null;
|
|
907
|
+
let made = -1;
|
|
908
|
+
return (want) => {
|
|
909
|
+
if (made !== rewrites) [index, made] = [hostsByPath(element), rewrites];
|
|
910
|
+
return index.get(want) ?? null;
|
|
911
|
+
};
|
|
894
912
|
};
|
|
895
913
|
|
|
896
914
|
/**
|
|
@@ -1003,8 +1021,9 @@ export function createCommits({ root, map, baselines, units, boxes, getLayout, s
|
|
|
1003
1021
|
// of the page's (its words would go over theirs): it keeps the one the page had, but where nobody else wrote.
|
|
1004
1022
|
const matched = new Set();
|
|
1005
1023
|
const inOrder = inFileOrder(element, fact.blocks);
|
|
1024
|
+
const find = pathIndex(element);
|
|
1006
1025
|
for (const [index, block] of fact.blocks.entries()) {
|
|
1007
|
-
const host = blockElement(element, block) ?? inOrder?.[index];
|
|
1026
|
+
const host = blockElement(element, block, find) ?? inOrder?.[index];
|
|
1008
1027
|
if (!host) continue;
|
|
1009
1028
|
const fresh = blockOf(host) === null;
|
|
1010
1029
|
const own = registerBlock(host, pending, block, unit);
|
|
@@ -1196,7 +1215,8 @@ export function createCommits({ root, map, baselines, units, boxes, getLayout, s
|
|
|
1196
1215
|
* Take in the answer to a commit (build's `pending`, the endpoint's receipt; `alone`: nobody but
|
|
1197
1216
|
* this page wrote the file since it showed it, see adopt). Returns { conflicts, merged: hosts now
|
|
1198
1217
|
* showing a merge, stale: a merge the page could not show, outdated: it runs a manifest that is no
|
|
1199
|
-
* more, forced: the page units a change the reader said to make anyway went in for, all it held
|
|
1218
|
+
* more, forced: the page units a change the reader said to make anyway went in for, all it held,
|
|
1219
|
+
* rekeyed: the keys of tables it set otherwise on the page, [element, name, old, new | null] }.
|
|
1200
1220
|
* A conflict of a change sent as the reader said to make it anyway says so (`again`).
|
|
1201
1221
|
*/
|
|
1202
1222
|
function apply(pending, receipt, { alone = true } = {}) {
|
|
@@ -1221,24 +1241,31 @@ export function createCommits({ root, map, baselines, units, boxes, getLayout, s
|
|
|
1221
1241
|
else if (element) proposals.set(identityOf(element), id);
|
|
1222
1242
|
}
|
|
1223
1243
|
for (const [key, hash] of Object.entries(receipt.hashes ?? {})) if (map.units[Number(key)]) map.units[Number(key)].hash = hash;
|
|
1224
|
-
// The keys of
|
|
1225
|
-
//
|
|
1226
|
-
//
|
|
1244
|
+
// The keys of tables the file gave the blocks the commit made and the tables it keyed (a view's
|
|
1245
|
+
// 视图 ›: the key its frame took, an attribute of the unit), other than the page chose
|
|
1246
|
+
// (source/chart-keys.mjs: one the file had meanwhile): theirs on the page too, so that each card and
|
|
1247
|
+
// view reads the table the file links it to ({ old: new | null }, null: off a table); `rekeyed` says
|
|
1248
|
+
// which it changed ([element, name, old, new | null]), for the undo steps that recorded them (history.mjs).
|
|
1249
|
+
const rekeyed = [];
|
|
1227
1250
|
if (receipt.chartKeys) {
|
|
1228
|
-
|
|
1251
|
+
const keyed = [...pending.units.values()].filter(({ change }) => change?.attribute === CHART_SOURCE).map(({ id }) => unitElement(id)).filter(Boolean);
|
|
1252
|
+
for (const element of [...pending.made.values(), ...keyed]) {
|
|
1229
1253
|
// A copy not written yet sends its keys again: the file's now.
|
|
1230
1254
|
const sent = element?.getAttribute(COPY_KEYS);
|
|
1231
1255
|
if (sent) {
|
|
1232
1256
|
const keys = Object.fromEntries(Object.entries(JSON.parse(sent)).map(([from, to]) => [from, to !== null && Object.hasOwn(receipt.chartKeys, to) ? receipt.chartKeys[to] : to]));
|
|
1233
1257
|
element.setAttribute(COPY_KEYS, JSON.stringify(keys));
|
|
1234
1258
|
}
|
|
1235
|
-
|
|
1236
|
-
|
|
1259
|
+
const names = [CHART_SOURCE, ...TABLE_READERS];
|
|
1260
|
+
for (const node of element ? [element, ...element.querySelectorAll(names.map((name) => `[${name}]`).join(", "))] : []) {
|
|
1261
|
+
for (const name of names) {
|
|
1237
1262
|
const key = node.getAttribute(name);
|
|
1238
1263
|
if (key === null || !Object.hasOwn(receipt.chartKeys, key)) continue;
|
|
1239
1264
|
const next = receipt.chartKeys[key];
|
|
1240
1265
|
if (typeof next === "string") node.setAttribute(name, next);
|
|
1241
1266
|
else if (next === null && name === CHART_SOURCE) node.removeAttribute(name);
|
|
1267
|
+
else continue;
|
|
1268
|
+
rekeyed.push([node, name, key, next]);
|
|
1242
1269
|
}
|
|
1243
1270
|
}
|
|
1244
1271
|
}
|
|
@@ -1498,13 +1525,14 @@ export function createCommits({ root, map, baselines, units, boxes, getLayout, s
|
|
|
1498
1525
|
}
|
|
1499
1526
|
setLayout(next);
|
|
1500
1527
|
marks();
|
|
1501
|
-
return { conflicts, merged, stale, outdated: shownAgain, forced: [...landed] };
|
|
1528
|
+
return { conflicts, merged, stale, outdated: shownAgain, forced: [...landed], rekeyed };
|
|
1502
1529
|
}
|
|
1503
1530
|
|
|
1504
1531
|
// A text committed: what it replaced (the first time this page committed it), what it is now, and what
|
|
1505
1532
|
// the commits of it between left it as (`earlier`, the newest TEXTS_KEPT): someone writing back what
|
|
1506
1533
|
// they read then puts back what the page committed after. Back as it was first, it is asked of what it
|
|
1507
1534
|
// was between, as a part of what a component writes is (noteWrite): an undo is a commit like any other.
|
|
1535
|
+
// `at`: when it was last committed, which puts the journals of two tabs' pages in order (autosave.mjs).
|
|
1508
1536
|
function committedText(key, sent) {
|
|
1509
1537
|
const mine = sources.get(sent.id);
|
|
1510
1538
|
const was = journal.get(key);
|
|
@@ -1512,7 +1540,7 @@ export function createCommits({ root, map, baselines, units, boxes, getLayout, s
|
|
|
1512
1540
|
if (mine === undefined) return void journal.delete(key);
|
|
1513
1541
|
const earlier = [...new Set([...(was?.earlier ?? []), ...(was ? [was.mine] : [])])].filter((text) => text !== mine && text !== original).slice(-TEXTS_KEPT);
|
|
1514
1542
|
if (mine === original && earlier.length === 0) return void journal.delete(key);
|
|
1515
|
-
journal.set(key, { key, block: blockRef(sent.id), original, mine, ...(earlier.length > 0 ? { earlier } : {}) });
|
|
1543
|
+
journal.set(key, { key, block: blockRef(sent.id), original, mine, ...(earlier.length > 0 ? { earlier } : {}), at: Date.now() });
|
|
1516
1544
|
}
|
|
1517
1545
|
|
|
1518
1546
|
// A part of what a unit's component writes, written by a commit (`before`, `after`: the hashes the file
|
|
@@ -1598,21 +1626,40 @@ export function createCommits({ root, map, baselines, units, boxes, getLayout, s
|
|
|
1598
1626
|
* Someone else's write put back a unit this load made (`gone`) or moved (`moved`), and the reader
|
|
1599
1627
|
* keeps theirs (`mine`): one it made is a block made on the page again, written anew (around its
|
|
1600
1628
|
* blocks from the source it was put back with, if it was); one it moved goes where the page has it
|
|
1601
|
-
* again. Otherwise it is no longer checked.
|
|
1629
|
+
* again. Otherwise it is no longer checked. `within`: the units inside one made that the write took out
|
|
1630
|
+
* with it (the revert check's, heldWithin), decided with it.
|
|
1602
1631
|
*/
|
|
1603
|
-
function putBack(unit, { gone, mine }) {
|
|
1632
|
+
function putBack(unit, { gone, mine, within = [] }) {
|
|
1604
1633
|
const { around } = placed.get(unit) ?? {};
|
|
1605
|
-
|
|
1634
|
+
// What the write took out with it: kept or given up with it, made on the page again inside it (the
|
|
1635
|
+
// blocks of an instance's slots, of a disclosure made this load). What it holds that the file still
|
|
1636
|
+
// has (a block moved in, kept where the Agent unwrapped it) stays the file's, a unit the commit
|
|
1637
|
+
// making it again takes along, as one it was put back around, and is decided by its own card if any.
|
|
1638
|
+
const inner = gone ? within : [];
|
|
1639
|
+
for (const id of [unit, ...inner]) placed.delete(id);
|
|
1606
1640
|
if (!mine) return;
|
|
1607
1641
|
touched(); // the layout changes in place
|
|
1608
1642
|
if (gone) {
|
|
1609
1643
|
const key = map.units[unit].cid;
|
|
1610
1644
|
drop(unit);
|
|
1645
|
+
inner.forEach(drop);
|
|
1611
1646
|
if (around && dropped.has(key)) dropped.get(key).around = around;
|
|
1612
1647
|
} else for (const [box, order] of getLayout()?.orders ?? []) getLayout().orders.set(box, order.filter((id) => id !== unit));
|
|
1613
1648
|
marks();
|
|
1614
1649
|
}
|
|
1615
1650
|
|
|
1651
|
+
// The units the page shows inside unit `unit`'s element, at any depth.
|
|
1652
|
+
const unitsWithin = (unit) => [...(unitElement(unit)?.querySelectorAll("[data-ge-unit]") ?? [])].map(idOf).filter((id) => id !== null);
|
|
1653
|
+
|
|
1654
|
+
/** Whether unit `unit` stands inside one of `units` on the page: what someone else's write took out with it is decided with it. */
|
|
1655
|
+
const heldWithin = (unit, units) => units.some((other) => other !== unit && unitsWithin(other).includes(unit));
|
|
1656
|
+
|
|
1657
|
+
/** The unit the page shows with file id `id` (not deleted on the page), or null: a block an earlier load made, still there. */
|
|
1658
|
+
const unitOf = (id) => {
|
|
1659
|
+
const unit = typeof id === "string" ? map.units.findIndex((each, index) => each?.blockId === id && !removed.has(index) && unitElement(index)) : -1;
|
|
1660
|
+
return unit < 0 ? null : unit;
|
|
1661
|
+
};
|
|
1662
|
+
|
|
1616
1663
|
/** The text of the blocks in a unit the page shows (the reader's words), or "". */
|
|
1617
1664
|
const unitText = (unit) => {
|
|
1618
1665
|
const element = unitElement(unit);
|
|
@@ -1728,9 +1775,11 @@ export function createCommits({ root, map, baselines, units, boxes, getLayout, s
|
|
|
1728
1775
|
}
|
|
1729
1776
|
|
|
1730
1777
|
return {
|
|
1731
|
-
build, apply, collect, current, marks, counts, buffer, texts, resolve, committed, unjournal, placedUnits, putBack, unitText, written, carry, dataOfUnit, heldOtherwise, rewrite, issues, removed, pageIds, idFor,
|
|
1778
|
+
build, apply, collect, current, marks, counts, buffer, texts, resolve, committed, unjournal, placedUnits, putBack, heldWithin, unitOf, unitText, written, carry, dataOfUnit, heldOtherwise, rewrite, issues, removed, pageIds, idFor,
|
|
1732
1779
|
/** The id a unit of the page has in the file, or the one it proposes for it; null for none. */
|
|
1733
1780
|
fileId: (unit) => map.units[unit]?.blockId ?? map.units[unit]?.proposed ?? null,
|
|
1781
|
+
/** The hash a unit of the page has in the file now (its map's, kept by every answer); null for none (changes/ finds the Agent's blocks by it). */
|
|
1782
|
+
fileHash: (unit) => map.units[unit]?.hash ?? null,
|
|
1734
1783
|
/** save(pending) as JSON, with the page's body (sync-state.mjs pack). */
|
|
1735
1784
|
keep: (pending) => pack(root, save(pending)),
|
|
1736
1785
|
/** Identities more than one element on the page carries (none, ever). */
|
|
@@ -1788,11 +1837,35 @@ export const nodeHTML = (node) => [node?.title, node?.html, node?.restore?.sourc
|
|
|
1788
1837
|
// Where a text block of the page sits in its unit, as the server's scan writes it (pathIn): the
|
|
1789
1838
|
// element steps from the unit down, each [tag, index among the parent's children of that tag, how
|
|
1790
1839
|
// many there are]. Only to find the element a path of the file names (blockElement), never to say where a block is.
|
|
1791
|
-
|
|
1792
|
-
|
|
1840
|
+
// `steps`: each element's step, kept for the next path asked of the same unit (hostsByPath): its parent's
|
|
1841
|
+
// children are counted once, for all of them.
|
|
1842
|
+
function pathFrom(unit, host, steps = new Map()) {
|
|
1843
|
+
const path = [];
|
|
1793
1844
|
for (let node = host; node && node !== unit; node = node.parentElement) {
|
|
1794
|
-
|
|
1795
|
-
|
|
1845
|
+
if (!steps.has(node)) {
|
|
1846
|
+
const children = node.parentElement?.children ?? [node];
|
|
1847
|
+
const counts = new Map();
|
|
1848
|
+
for (const child of children) {
|
|
1849
|
+
const at = counts.get(child.localName) ?? 0;
|
|
1850
|
+
counts.set(child.localName, at + 1);
|
|
1851
|
+
steps.set(child, [child.localName, node.parentElement ? at : -1]);
|
|
1852
|
+
}
|
|
1853
|
+
for (const child of children) steps.get(child).push(node.parentElement ? counts.get(child.localName) : 0);
|
|
1854
|
+
}
|
|
1855
|
+
path.unshift(steps.get(node));
|
|
1856
|
+
}
|
|
1857
|
+
return ["unit", ...path];
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
// The text blocks of `unit` (a unit of the page) that are its own, no unit's inside it, by their path (pathFrom,
|
|
1861
|
+
// as JSON): the first of each, in the page's order.
|
|
1862
|
+
function hostsByPath(unit) {
|
|
1863
|
+
const steps = new Map();
|
|
1864
|
+
const found = new Map();
|
|
1865
|
+
for (const host of unit.querySelectorAll("[contenteditable='true']")) {
|
|
1866
|
+
if (host.parentElement?.closest("[data-ge-unit], [data-ge-unit-kind]") !== unit) continue;
|
|
1867
|
+
const path = JSON.stringify(pathFrom(unit, host, steps));
|
|
1868
|
+
if (!found.has(path)) found.set(path, host);
|
|
1796
1869
|
}
|
|
1797
|
-
return
|
|
1870
|
+
return found;
|
|
1798
1871
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { blocksText, partOwner, plainText } from "./core.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { reveal } from "./folded.mjs";
|
|
3
|
+
import { wordDiff } from "./merge.mjs";
|
|
3
4
|
import { PANEL_STYLE, panelGone, panelShown } from "./panel.mjs";
|
|
4
|
-
import { addStyle,
|
|
5
|
+
import { addStyle, element, mount, textButton } from "./ui.mjs";
|
|
5
6
|
import { t } from "../../shared/i18n/index.mjs";
|
|
6
7
|
|
|
7
8
|
// The conflicts the page holds back (docs/editor.md, "Conflicts"), each a card in one panel: what
|
|
@@ -26,7 +27,7 @@ import { t } from "../../shared/i18n/index.mjs";
|
|
|
26
27
|
// a popover like the workbench's, no colored frame, the flagged block is what stands out; the
|
|
27
28
|
// reader's words and the file's are told apart by one pair of colors.
|
|
28
29
|
const STYLE = `
|
|
29
|
-
.ge-conflicts { --ge-mine:
|
|
30
|
+
.ge-conflicts { --ge-mine: var(--ge-diff-del); --ge-mine-text: var(--ge-diff-del-text); --ge-theirs: var(--ge-diff-add); --ge-theirs-text: var(--ge-diff-add-text); }
|
|
30
31
|
.ge-conflict[data-ge-current] { background: var(--ge-hover); }
|
|
31
32
|
.ge-conflict-label { display: flex; gap: 6px; margin: 10px 0 3px; color: var(--ge-tx2); font-size: 12px; }
|
|
32
33
|
.ge-conflict :is(ins, del, .ge-chip) { border-radius: 3px; text-decoration: none; }
|
|
@@ -65,7 +66,7 @@ function describe(entry, restorable) {
|
|
|
65
66
|
if (entry.reason === "changed") return { text: t("这一段你和 AI 同时改了同一处。"), both: true, diff: true, actions: [[t("保留我的"), "mine", true], [t("使用最新版本"), "theirs"]] };
|
|
66
67
|
if (entry.reason === "missing") return { text: t("你修改的这一块已被 AI 删除。"), actions: [...(restorable ? [[t("恢复我的"), "restore", true]] : []), [t("接受删除"), "accept"], copy] };
|
|
67
68
|
if (entry.reason === "structure") return { text: t("你修改的这一处所在的组件已被 AI 改过结构,没法确定对应的位置。"), actions: [[t("使用最新版本"), "theirs"], copy] };
|
|
68
|
-
if (packageChanged(entry)) return { text: t("
|
|
69
|
+
if (packageChanged(entry)) return { text: t("这个自定义块刚刚变了,这处文字不再能修改,你的修改没有写进文件。"), actions: [[t("使用最新版本"), "theirs"], copy] };
|
|
69
70
|
return { text: t("这一处在文件里找不到唯一对应的位置,没有保存。"), actions: [[t("使用最新版本"), "theirs"], copy] };
|
|
70
71
|
}
|
|
71
72
|
if (entry.kind === "unit") {
|
|
@@ -84,29 +85,8 @@ function describe(entry, restorable) {
|
|
|
84
85
|
return { text: t("你新建(或放回)的这一块没法放进文件(周围的块已被 AI 改动或删除)。"), actions: [[t("放到附近"), "nearby", true], [t("撤销这一块"), "undo"], copy] };
|
|
85
86
|
}
|
|
86
87
|
|
|
87
|
-
//
|
|
88
|
-
|
|
89
|
-
// the del it stands beside). Words are runs of letters and digits, spaces, single other characters
|
|
90
|
-
// (each Chinese character on its own); at most 1500 words of each (merge.mjs commonRun finds what is shared).
|
|
91
|
-
export function wordDiff(mine, theirs) {
|
|
92
|
-
const tokens = (text) => (text.match(/[A-Za-z0-9]+|\s+|[^A-Za-z0-9\s]/gu) ?? []).slice(0, 1500);
|
|
93
|
-
const a = tokens(mine);
|
|
94
|
-
const b = tokens(theirs);
|
|
95
|
-
const runs = [];
|
|
96
|
-
const add = (tag, text) => {
|
|
97
|
-
if (runs.at(-1)?.tag === tag) runs.at(-1).text += text;
|
|
98
|
-
else runs.push({ tag, text });
|
|
99
|
-
};
|
|
100
|
-
let [i, j] = [0, 0];
|
|
101
|
-
for (const [x, y] of [...commonRun(a, b), [a.length, b.length]]) {
|
|
102
|
-
while (j < y) add("ins", b[j++]);
|
|
103
|
-
while (i < x) add("del", a[i++]);
|
|
104
|
-
if (x < a.length) add(null, a[i++]);
|
|
105
|
-
j++;
|
|
106
|
-
}
|
|
107
|
-
return runs;
|
|
108
|
-
}
|
|
109
|
-
|
|
88
|
+
// The word diff (merge.mjs wordDiff): its runs as the card's nodes.
|
|
89
|
+
export { wordDiff };
|
|
110
90
|
const diffNodes = (mine, theirs) => wordDiff(mine, theirs).map(({ tag, text }) => tag ? element(tag, { text }) : document.createTextNode(text));
|
|
111
91
|
|
|
112
92
|
/**
|
|
@@ -143,7 +123,7 @@ export function createConflicts({ act, nodeOf, restorable, copyBlock, say }) {
|
|
|
143
123
|
panelShown(panel);
|
|
144
124
|
}
|
|
145
125
|
const conflicts = [...cards.values()].every(({ entry }) => !unfit(entry));
|
|
146
|
-
const head = element("div", { class: "ge-conflicts-head" }, element("span", { text: conflicts ? t("{0} 处冲突待处理", cards.size) : t("{0} 处内容待处理", cards.size) }),
|
|
126
|
+
const head = element("div", { class: "ge-conflicts-head" }, element("span", { text: conflicts ? t("{0} 处冲突待处理", cards.size) : t("{0} 处内容待处理", cards.size) }), textButton(t("收起"), () => { panel.hidden = true; }, { quiet: true }));
|
|
147
127
|
panel.replaceChildren(head, ...[...cards.values()].map(({ node }) => node));
|
|
148
128
|
}
|
|
149
129
|
|
|
@@ -159,7 +139,7 @@ export function createConflicts({ act, nodeOf, restorable, copyBlock, say }) {
|
|
|
159
139
|
const buttons = element("div", { class: "ge-actions" });
|
|
160
140
|
const quiet = element("span", { class: "ge-conflict-quiet" }); // looking, not deciding: on the right
|
|
161
141
|
for (const [label, action, primary] of actions) {
|
|
162
|
-
buttons.append(
|
|
142
|
+
buttons.append(textButton(label, async () => {
|
|
163
143
|
if (action === "copy-block") {
|
|
164
144
|
const node = nodeOf(entry);
|
|
165
145
|
if (!node?.isConnected || !copyBlock(node)) say(t("没能完成,请再试一次。"), "error");
|
|
@@ -186,16 +166,16 @@ export function createConflicts({ act, nodeOf, restorable, copyBlock, say }) {
|
|
|
186
166
|
if (diff && mine && theirs) {
|
|
187
167
|
const legend = element("div", { class: "ge-conflict-label" }, element("span", { class: "ge-chip", "data-mine": "", text: t("你的") }), element("span", { class: "ge-chip", "data-theirs": "", text: t("AI 的") }));
|
|
188
168
|
const view = element("div", { hidden: "" }, legend, element("div", { class: "ge-version" }));
|
|
189
|
-
const toggle =
|
|
169
|
+
const toggle = textButton(t("查看局部差异"), () => {
|
|
190
170
|
view.hidden = !view.hidden;
|
|
191
171
|
versions.hidden = !view.hidden;
|
|
192
172
|
toggle.textContent = view.hidden ? t("查看局部差异") : t("查看两个版本");
|
|
193
173
|
if (!view.hidden) view.lastElementChild.replaceChildren(...diffNodes(mine, theirs));
|
|
194
|
-
}, {
|
|
174
|
+
}, { quiet: true });
|
|
195
175
|
quiet.append(toggle);
|
|
196
176
|
node.append(view);
|
|
197
177
|
}
|
|
198
|
-
if (nodeOf(entry)) quiet.append(
|
|
178
|
+
if (nodeOf(entry)) quiet.append(textButton(t("定位"), () => locate(entry.key), { quiet: true }));
|
|
199
179
|
if (quiet.childElementCount > 0) buttons.append(quiet);
|
|
200
180
|
node.append(buttons);
|
|
201
181
|
return node;
|
|
@@ -240,7 +220,7 @@ export function createConflicts({ act, nodeOf, restorable, copyBlock, say }) {
|
|
|
240
220
|
function locate(key) {
|
|
241
221
|
const found = cards.get(key);
|
|
242
222
|
const node = found && nodeOf(found.entry);
|
|
243
|
-
if (node)
|
|
223
|
+
if (node) reveal(node); // a folded heading's section too (fold/)
|
|
244
224
|
node?.scrollIntoView({ block: "center", behavior: "smooth" });
|
|
245
225
|
for (const other of cards.values()) other.node.toggleAttribute("data-ge-current", other === found);
|
|
246
226
|
}
|