@heycys/gallery 0.1.1 → 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 +1 -1
- package/browser/editor/components/columns/page.mjs +4 -4
- package/browser/editor/components/embed/index.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/icons.mjs +8 -0
- package/browser/editor/components/image/crop.mjs +6 -9
- package/browser/editor/components/installed/index.mjs +11 -4
- package/browser/editor/components/installed/page.mjs +27 -16
- package/browser/editor/components/installed/served.mjs +6 -5
- package/browser/editor/components/instances.mjs +18 -0
- package/browser/editor/components/list/page.mjs +3 -6
- package/browser/editor/components/registry.mjs +13 -4
- package/browser/editor/components/table/index.mjs +59 -2
- package/browser/editor/components/table/page.mjs +1 -1
- package/browser/editor/page/annotate/card.mjs +3 -6
- package/browser/editor/page/autosave.mjs +310 -37
- 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 +1 -1
- package/browser/editor/page/changes/bar.mjs +6 -14
- package/browser/editor/page/changes/index.mjs +2 -2
- 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 +124 -13
- package/browser/editor/page/clipboard/own/blocks.mjs +11 -11
- package/browser/editor/page/clipboard/own/chart-keys.mjs +41 -28
- package/browser/editor/page/clipboard/own/selection.mjs +1 -1
- package/browser/editor/page/columns/index.mjs +48 -46
- package/browser/editor/page/commit.mjs +80 -22
- package/browser/editor/page/conflicts.mjs +7 -7
- package/browser/editor/page/core.mjs +31 -15
- package/browser/editor/page/custom-page.mjs +106 -0
- package/browser/editor/page/editor.mjs +51 -14
- package/browser/editor/page/emoji-picker/styles.mjs +7 -12
- package/browser/editor/page/emoji-picker/upload.mjs +2 -2
- package/browser/editor/page/handle/index.mjs +5 -8
- package/browser/editor/page/history.mjs +24 -4
- package/browser/editor/page/links/index.mjs +5 -3
- package/browser/editor/page/links/pages.mjs +27 -9
- package/browser/editor/page/look.mjs +54 -3
- package/browser/editor/page/margin.mjs +18 -3
- package/browser/editor/page/media-menu/index.mjs +6 -7
- package/browser/editor/page/menu.mjs +18 -7
- package/browser/editor/page/notices.mjs +2 -2
- package/browser/editor/page/page-objects.mjs +13 -2
- package/browser/editor/page/panel.mjs +4 -9
- package/browser/editor/page/present-links.mjs +11 -2
- package/browser/editor/page/resize/index.mjs +42 -29
- package/browser/editor/page/served.mjs +14 -0
- package/browser/editor/page/session.mjs +48 -4
- package/browser/editor/page/slash-menu/index.mjs +3 -3
- package/browser/editor/page/table/cells.mjs +102 -46
- package/browser/editor/page/table/icons.mjs +2 -0
- package/browser/editor/page/table/index.mjs +29 -10
- package/browser/editor/page/table/pictures.mjs +299 -0
- package/browser/editor/page/table/views.mjs +150 -0
- package/browser/editor/page/text-select/index.mjs +26 -12
- package/browser/editor/page/todo-writes.mjs +75 -0
- package/browser/editor/page/typing/index.mjs +53 -3
- package/browser/editor/page/ui.mjs +13 -0
- 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/colors.mjs +3 -2
- package/browser/shared/component-catalog.mjs +323 -46
- package/browser/shared/component-source.mjs +37 -0
- package/browser/shared/components/index.mjs +12 -3
- package/browser/shared/components/installed.mjs +35 -3
- package/browser/shared/components/page.mjs +18 -8
- package/browser/shared/components/state.mjs +5 -1
- package/browser/shared/document-look.mjs +10 -5
- package/browser/shared/drafts.mjs +432 -0
- 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/i18n/en.mjs +307 -27
- package/browser/shared/json-layout.mjs +47 -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/outline-shape.mjs +128 -0
- package/browser/shared/outline.mjs +331 -67
- 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/preview-server.mjs +3 -7
- package/browser/shared/session.mjs +8 -1
- 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-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/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-V5JTW2LH.mjs → chunk-6QBHU4DF.mjs} +1 -1
- package/dist/{chunk-Y6RLRPG3.mjs → chunk-6VTU6KEO.mjs} +1 -1
- package/dist/chunk-B4P2CM2J.mjs +3 -0
- package/dist/{chunk-FDLXYYG4.mjs → chunk-BPL64HGA.mjs} +1 -1
- package/dist/chunk-BVEFGE4B.mjs +2 -0
- package/dist/{chunk-LS4F7JUM.mjs → chunk-BZ5RAF7L.mjs} +1 -1
- package/dist/chunk-CRJEG7MT.mjs +2 -0
- package/dist/{chunk-LCTHTZIL.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-GB5SOYQJ.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-KTKHRC6H.mjs +2 -0
- package/dist/chunk-L7UP52JO.mjs +2 -0
- package/dist/{chunk-SYGN7GLU.mjs → chunk-MHW7ZKOU.mjs} +1 -1
- package/dist/chunk-N76HWBA3.mjs +10 -0
- package/dist/chunk-N7AZZLGT.mjs +548 -0
- package/dist/chunk-NAMN3RAF.mjs +2 -0
- package/dist/{chunk-5ZKJ3H4P.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-4FS7Z7WR.mjs → chunk-OUUP3WKT.mjs} +1 -1
- package/dist/{chunk-BGGDRNYQ.mjs → chunk-OW5NWPOJ.mjs} +1 -1
- package/dist/chunk-PAREWQGB.mjs +4 -0
- package/dist/chunk-POQSE4C2.mjs +2 -0
- package/dist/chunk-PUOQ65NC.mjs +2 -0
- package/dist/{chunk-XNROSH2T.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-7DTINW6U.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-UNOYVIYR.mjs +2 -0
- package/dist/{chunk-E7LWZRXY.mjs → chunk-V6RIYQZZ.mjs} +1 -1
- 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-YI43RG4P.mjs +2 -0
- package/dist/chunk-YQGT4AB2.mjs +6 -0
- package/dist/chunk-ZB4H7ZN4.mjs +2 -0
- package/dist/{chunk-IVDLMMBD.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-U6KNPJPR.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/report.css +255 -17
- package/kit/runtime.js +1600 -125
- package/kit/state.js +10 -1
- package/kit/tables.js +128 -43
- package/kit/ui.js +77 -35
- 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 +12 -10
- package/sdk/doc-kit.d.ts +396 -5
- package/sdk/doc-state.d.ts +2 -0
- package/skill/SKILL.md +56 -23
- package/skill/references/block-script.md +140 -0
- package/skill/references/building-blocks.md +257 -0
- package/skill/references/extensions.md +59 -0
- package/skill/references/pages-and-data.md +221 -0
- package/skill/references/writing-html.md +6 -4
- package/skill/sdk/doc-kit.d.ts +396 -5
- 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/dist/chunk-3HIRPVLU.mjs +0 -2
- package/dist/chunk-5MHMDLZD.mjs +0 -4
- package/dist/chunk-64K7IPLO.mjs +0 -255
- package/dist/chunk-6QXGZM36.mjs +0 -8
- package/dist/chunk-6RGJOMJP.mjs +0 -16
- package/dist/chunk-AJ73XJF3.mjs +0 -2
- package/dist/chunk-AUZGSZJH.mjs +0 -13
- package/dist/chunk-BFE45AKL.mjs +0 -2
- package/dist/chunk-BXO2ZY5P.mjs +0 -2
- package/dist/chunk-CEH4MRCC.mjs +0 -2
- package/dist/chunk-CY2FNNAB.mjs +0 -16
- package/dist/chunk-DFUDV4LX.mjs +0 -2
- package/dist/chunk-DKXG4XDG.mjs +0 -2
- package/dist/chunk-EZQ34M3F.mjs +0 -124
- package/dist/chunk-EZY3WC6Z.mjs +0 -15
- package/dist/chunk-FUKQNOQS.mjs +0 -9
- package/dist/chunk-JPOSLGOC.mjs +0 -6
- package/dist/chunk-L3QKH4OK.mjs +0 -26
- package/dist/chunk-LAE5NQ4B.mjs +0 -2
- package/dist/chunk-LEF6DRCK.mjs +0 -59
- package/dist/chunk-NO5NJCHO.mjs +0 -2
- package/dist/chunk-NQPVAU63.mjs +0 -2
- package/dist/chunk-NSKUTQ5J.mjs +0 -5
- package/dist/chunk-O35FIXRB.mjs +0 -2
- package/dist/chunk-P2CAZPDP.mjs +0 -3
- package/dist/chunk-PL6GHLGD.mjs +0 -15
- package/dist/chunk-QJIR2BLP.mjs +0 -6
- package/dist/chunk-QUPLVPB2.mjs +0 -7
- package/dist/chunk-R7BNENLY.mjs +0 -4
- package/dist/chunk-S6O4UHLC.mjs +0 -2
- package/dist/chunk-SGJWQKEI.mjs +0 -2
- package/dist/chunk-TX6JH7TR.mjs +0 -2
- package/dist/chunk-TYK6VNAB.mjs +0 -10
- package/dist/chunk-UALRNVSE.mjs +0 -4
- package/dist/chunk-V3HXVQEM.mjs +0 -2
- package/dist/chunk-V5VXUJKG.mjs +0 -2
- package/dist/chunk-VBXMADMP.mjs +0 -2
- package/dist/chunk-VNV55RUA.mjs +0 -2
- package/dist/chunk-VPD2PS35.mjs +0 -2
- package/dist/chunk-W4VKN3GF.mjs +0 -7
- package/dist/chunk-W5BXXPDJ.mjs +0 -3
- package/dist/chunk-XUNHRCOG.mjs +0 -6
- package/skill/references/building-components.md +0 -367
- package/web/assets/index-Bh74DfsV.css +0 -1
- package/web/assets/index-UW0RyFFt.js +0 -13
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import { escapeMarkup, escapeTyped } from "../../../shared/escape.mjs";
|
|
1
|
+
import { escapeMarkup, escapeText, escapeTyped } from "../../../shared/escape.mjs";
|
|
2
2
|
import { mayBePage } from "../../../shared/page-address.mjs";
|
|
3
3
|
import { OUTER, boldThroughout, boxKind, can, holdsAtoms, isEmpty, isFirstLine, isHost, keepLine, nestedLists, newTail, pastedLines, removable, removalTarget, splitBelow, UNIT, textEnd, unitElement } from "../core.mjs";
|
|
4
4
|
import { formulaMaker } from "../formula/index.mjs";
|
|
5
5
|
import { inlineItems, spaceAround } from "../../../shared/inline-spacing.mjs";
|
|
6
6
|
import { caretAt, editable, hostOf, select } from "../caret.mjs";
|
|
7
7
|
import { formatRange, joinMarks, outOfMarks, rangeAt, rangeOffsets } from "../marks.mjs";
|
|
8
|
-
import { BASIC_UNITS, KIND_NAMES, accepts, clipboardOf, takesFormula, texOnly } from "../../components/registry.mjs";
|
|
8
|
+
import { BASIC_UNITS, HOSTS, KIND_NAMES, accepts, clipboardOf, takesFormula, texOnly } from "../../components/registry.mjs";
|
|
9
9
|
import { listType } from "../../components/list/index.mjs";
|
|
10
10
|
import { nodeAround } from "../../components/flowchart/index.mjs";
|
|
11
11
|
import { cellsData } from "../../components/table/index.mjs";
|
|
12
12
|
import { MIME, OLD_MIME, PASTED_SOURCE, build, checkBlocks, describe, describeAcross, formats, groupItems, holdsFormulas, joinedHtml, kindOfBlock, ownData, ownRange, parse, parseCells, parseText, plainText, prefixCopies, relinkCopies, reportOf, selectedHtml, textFormats, unmadeCopy } from "./own/index.mjs";
|
|
13
13
|
import { bareAddress, externalContent, readExternal } from "./import/read.mjs";
|
|
14
|
+
import { parseClipboardHTML, tableRows } from "./import/html.mjs";
|
|
14
15
|
import { fromMarkdown } from "./import/markdown.mjs";
|
|
15
16
|
import { addressOf } from "../links/address.mjs";
|
|
16
17
|
import { pageObjects, pageOf, typedAsIs } from "../page-objects.mjs";
|
|
@@ -47,6 +48,9 @@ import { t } from "../../../shared/i18n/index.mjs";
|
|
|
47
48
|
// block that takes links.
|
|
48
49
|
// With blocks selected: the blocks go after them, in the first box out from there that takes them all;
|
|
49
50
|
// and so with the caret on a formula block, which has no text to paste into.
|
|
51
|
+
// Into a table's cells (table/cells.mjs, what the clipboard holds as cells: cellsOf), cells go from
|
|
52
|
+
// the caret's cell or the selected ones; in a cell, picture files are pictures of the cell
|
|
53
|
+
// (单元格里的图片, table/pictures.mjs), and a table pasted anywhere keeps its cells' pictures.
|
|
50
54
|
// One undo step. Images and embeds of an address are filled once on the page (one step with the paste).
|
|
51
55
|
|
|
52
56
|
/**
|
|
@@ -62,8 +66,9 @@ import { t } from "../../../shared/i18n/index.mjs";
|
|
|
62
66
|
* for words), or null. titleBold(): whether bold
|
|
63
67
|
* is armed at the caret (a flowchart node's empty title: format-bar/), so that what is pasted there
|
|
64
68
|
* is bold as what is typed is. showCaret(): the caret in view after text went in (caret.mjs).
|
|
69
|
+
* pictures(): the pictures of table cells (table/pictures.mjs: fromFiles, resolve, maker), or null.
|
|
65
70
|
*/
|
|
66
|
-
export function createClipboard({ editing, blocks, struct, recordText, say, loadKatex = async () => Boolean(globalThis.katex), mention: mentionFor = null, linkPasted = () => {}, pageLink = async () => null, titleBold = () => false, showCaret = () => {} }) {
|
|
71
|
+
export function createClipboard({ editing, blocks, struct, recordText, say, loadKatex = async () => Boolean(globalThis.katex), mention: mentionFor = null, linkPasted = () => {}, pageLink = async () => null, titleBold = () => false, showCaret = () => {}, pictures = () => null }) {
|
|
67
72
|
// ---------- copying ----------
|
|
68
73
|
|
|
69
74
|
// Ctrl+C or Ctrl+X with blocks selected (and no text): the blocks go to the clipboard, and with
|
|
@@ -217,10 +222,14 @@ export function createClipboard({ editing, blocks, struct, recordText, say, load
|
|
|
217
222
|
// are (its HTML, a table of one cell, the import unwraps with a divider after it); more a table
|
|
218
223
|
// of them as they were, not as another program's table comes in (made over: a header row, its
|
|
219
224
|
// numbers read).
|
|
220
|
-
|
|
221
|
-
|
|
225
|
+
// The report they were copied from: their pictures are its files.
|
|
226
|
+
const copied = cellsData(data);
|
|
227
|
+
const cells = parseCells(copied || "null");
|
|
228
|
+
const from = cells ? reportIn(copied) : null;
|
|
229
|
+
const whence = from ? { from, same: from === reportOf(document) } : {};
|
|
230
|
+
if (cells?.length === 1 && cells[0].length === 1) return { kind: "rich", html: cells[0][0], own: true, ...whence };
|
|
222
231
|
const table = cells ? checkBlocks([{ type: "table", rows: cells }]) : null;
|
|
223
|
-
if (table) return { kind: "blocks", blocks: table, own: true };
|
|
232
|
+
if (table) return { kind: "blocks", blocks: table, own: true, ...whence };
|
|
224
233
|
// Text of this page copied by the browser (a selection in a block): one line holding the page's
|
|
225
234
|
// chips (a formula, a link shown with its icon, one left empty) is its text again, each chip as
|
|
226
235
|
// it was (pastedLines), not what another program's HTML would make of it.
|
|
@@ -252,6 +261,14 @@ export function createClipboard({ editing, blocks, struct, recordText, say, load
|
|
|
252
261
|
// Inline formulas pasted as the page's own (KaTeX loaded: formula/ formulaMaker).
|
|
253
262
|
let formula = null;
|
|
254
263
|
|
|
264
|
+
// A table's cells' pictures pasted (made files of the document's folder first: table/pictures.mjs
|
|
265
|
+
// resolve), what a cell built of them shows (maker).
|
|
266
|
+
let picture = null;
|
|
267
|
+
|
|
268
|
+
// Whether what is pasted was copied in this document (`same`): the keys of tables in it are kept,
|
|
269
|
+
// given anew or taken off by that (own/chart-keys.mjs relinkCopies).
|
|
270
|
+
let here = true;
|
|
271
|
+
|
|
255
272
|
// Images and embeds pasted with an address: filled now they are on the page.
|
|
256
273
|
const fillMedia = (made) => {
|
|
257
274
|
for (const figure of made.flatMap((node) => [node, ...node.querySelectorAll(`[${PASTED_SOURCE}]`)]).filter((node) => node.hasAttribute?.(PASTED_SOURCE))) {
|
|
@@ -480,8 +497,8 @@ export function createClipboard({ editing, blocks, struct, recordText, say, load
|
|
|
480
497
|
const [first, ...rest] = list;
|
|
481
498
|
const joins = !replace && first.type === "paragraph" && !first.color;
|
|
482
499
|
const placed = asLists(unit, joins ? rest : list);
|
|
483
|
-
const made = placed.map((block) => build(document, block, { formula, mention }));
|
|
484
|
-
relinkCopies(document, made); // a pasted card and its table linked to each other alone
|
|
500
|
+
const made = placed.map((block) => build(document, block, { formula, mention, picture }));
|
|
501
|
+
relinkCopies(document, made, { same: here }); // a pasted card or view and its table linked to each other alone
|
|
485
502
|
prefixCopies(document, made); // a copy's drawing names its own markers
|
|
486
503
|
const place = made.length ? placeAtCaret(unit, made, placed.map(kindOfBlock)) : { anchor: unit, box: unit.parentElement, parents: [unit.parentElement], splits: [] };
|
|
487
504
|
if (!place) {
|
|
@@ -531,8 +548,8 @@ export function createClipboard({ editing, blocks, struct, recordText, say, load
|
|
|
531
548
|
return;
|
|
532
549
|
}
|
|
533
550
|
const list = asLists(anchor, pasted);
|
|
534
|
-
const made = list.map((block) => build(document, block, { formula, mention }));
|
|
535
|
-
relinkCopies(document, made); // a pasted card and its table linked to each other alone
|
|
551
|
+
const made = list.map((block) => build(document, block, { formula, mention, picture }));
|
|
552
|
+
relinkCopies(document, made, { same: here }); // a pasted card or view and its table linked to each other alone
|
|
536
553
|
prefixCopies(document, made); // a copy's drawing names its own markers
|
|
537
554
|
const place = placeFor(anchor, list.map(kindOfBlock));
|
|
538
555
|
if (!place) {
|
|
@@ -654,12 +671,19 @@ export function createClipboard({ editing, blocks, struct, recordText, say, load
|
|
|
654
671
|
// Picture or other files (a screenshot): an image or a file block after the block, unless they
|
|
655
672
|
// come with the page's own blocks, or Office's or a table's HTML (Excel's picture of its cells).
|
|
656
673
|
const files = data.files;
|
|
674
|
+
const selection = getSelection();
|
|
675
|
+
const range = host && selection.rangeCount && host.contains(selection.getRangeAt(0).startContainer) ? selection.getRangeAt(0).cloneRange() : null;
|
|
657
676
|
if (files?.length > 0 && !ownData(data)) {
|
|
658
677
|
const external = externalContent(data);
|
|
678
|
+
// In a table's cell: pictures of the cell, at the caret (单元格里的图片).
|
|
679
|
+
if (!external.fromOffice && !external.isTable && range && HOSTS[host.getAttribute("data-ge-kind")]?.pictures && pictures() && [...files].some((file) => /^image\//.test(file.type))) {
|
|
680
|
+
const at = rangeOffsets(host, range);
|
|
681
|
+
const made = await pictures().fromFiles(files);
|
|
682
|
+
if (made.length > 0 && host.isConnected) insertNodes(host, rangeAt(host, at), made, { own: true, join: false });
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
659
685
|
if (!external.fromOffice && !external.isTable && fromFiles(host ?? anchor, files)) return;
|
|
660
686
|
}
|
|
661
|
-
const selection = getSelection();
|
|
662
|
-
const range = host && selection.rangeCount && host.contains(selection.getRangeAt(0).startContainer) ? selection.getRangeAt(0).cloneRange() : null;
|
|
663
687
|
if (host && !range) return;
|
|
664
688
|
// In code: the text with its lines.
|
|
665
689
|
if (host && typedAsIs(host, (data.getData("text/plain") || "").replace(/\r\n?/g, "\n"))) return;
|
|
@@ -682,6 +706,7 @@ export function createClipboard({ editing, blocks, struct, recordText, say, load
|
|
|
682
706
|
const formulas = content.kind === "blocks" ? holdsFormulas(content.blocks) : content.kind === "rich" && content.html.includes("doc-math-inline");
|
|
683
707
|
if (formulas && (!host || takesFormula(host)) && (await loadKatex())) formula = formulaMaker();
|
|
684
708
|
if (mentionFor) mention = (parts) => mentionFor(parts, Boolean(content.same), content.from);
|
|
709
|
+
here = content.same !== false;
|
|
685
710
|
// An address alone, which HTML that reads as no text beside it does not change.
|
|
686
711
|
const href = content.own && content.kind === "blocks" ? null : bareAddress(data) ?? (content.kind === "plain" ? addressOf(content.text) : null);
|
|
687
712
|
const words = href ? (data.getData("text/plain") || content.text || href).trim() : ""; // read now: the clipboard's data goes with its event
|
|
@@ -689,6 +714,9 @@ export function createClipboard({ editing, blocks, struct, recordText, say, load
|
|
|
689
714
|
// writes, by its title, so that no file holds a port. Never a web page's views.
|
|
690
715
|
const page = href && mayBePage(href) && (!host || can(host, "links")) ? await pageLink(href) : null;
|
|
691
716
|
if (page) content = { kind: "rich", html: `<a href="${escapeMarkup(page.href)}">${escapeMarkup(page.title)}</a>` };
|
|
717
|
+
// A table's cells' pictures, made files of the document's folder before the table is (one undo step with it).
|
|
718
|
+
const celled = content.kind === "blocks" ? pictureTexts(content.blocks) : [];
|
|
719
|
+
if (celled.length > 0 && pictures()) picture = pictures().maker(await pictures().resolve(celled, content.from ?? null));
|
|
692
720
|
try {
|
|
693
721
|
if (!host) {
|
|
694
722
|
// With blocks selected: blocks after them (text as paragraphs, Markdown read).
|
|
@@ -725,7 +753,43 @@ export function createClipboard({ editing, blocks, struct, recordText, say, load
|
|
|
725
753
|
} finally {
|
|
726
754
|
formula = null;
|
|
727
755
|
mention = null;
|
|
756
|
+
picture = null;
|
|
757
|
+
here = true;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* The clipboard as rows of cells for a paste into a table's cells (table/cells.mjs: the caret in a
|
|
764
|
+
* cell, or cells selected), each cell its inline HTML: { rows, from } (`from`: the report the
|
|
765
|
+
* page's own was copied from, whose files its pictures are), or null when it holds nothing. In
|
|
766
|
+
* Notion's order (872952): the page's cells (the table tools' copy), its text or blocks (ownCells);
|
|
767
|
+
* another program's table, HTML that is one table and no words outside it (Excel, Google Sheets,
|
|
768
|
+
* Feishu, Notion, Yuque, a web page's: import/html.mjs tableRows), its cells with their marks, links,
|
|
769
|
+
* colors as the import maps them, line breaks and pictures, a table of one column too; a Markdown
|
|
770
|
+
* table (its text alone: Yuque's Markdown, a .md file's), read as a paste's Markdown with its cells'
|
|
771
|
+
* pictures; tab-separated lines (Excel's and Google Sheets' text), two lines or more of as many cells,
|
|
772
|
+
* two or more, a cell in quotes holding tabs, line breaks and "" a quote; else its text, one cell
|
|
773
|
+
* holding its lines.
|
|
774
|
+
*/
|
|
775
|
+
function cellsOf(data) {
|
|
776
|
+
const copied = cellsData(data);
|
|
777
|
+
const cells = parseCells(copied || "null");
|
|
778
|
+
if (cells) return { rows: cells, from: reportIn(copied) };
|
|
779
|
+
const own = ownCells(data);
|
|
780
|
+
if (own) return { rows: own, from: origin(ownData(data)).from };
|
|
781
|
+
const external = externalContent(data);
|
|
782
|
+
const table = external.html ? tableRows(parseClipboardHTML(external.html), { colors: external.colors }) : null;
|
|
783
|
+
if (table?.length) return { rows: table.map((row) => row.map((cell) => richHtml(cell, { pictures: true }))), from: null };
|
|
784
|
+
const text = external.text.replace(/\n+$/, "");
|
|
785
|
+
if (/^\s*\|/m.test(text)) {
|
|
786
|
+
const made = toBlocks(fromMarkdown(text), null, HELD);
|
|
787
|
+
if (made.length === 1 && Array.isArray(made[0].rows)) return { rows: made[0].rows, from: null }; // a table alone
|
|
728
788
|
}
|
|
789
|
+
const lines = tabbed(text);
|
|
790
|
+
const html = (words) => escapeText(words).replace(/\n/g, "<br>");
|
|
791
|
+
if (lines) return { rows: lines.map((row) => row.map(html)), from: null };
|
|
792
|
+
return text.trim() ? { rows: [[html(text)]], from: null } : null;
|
|
729
793
|
}
|
|
730
794
|
|
|
731
795
|
/**
|
|
@@ -747,7 +811,54 @@ export function createClipboard({ editing, blocks, struct, recordText, say, load
|
|
|
747
811
|
return html ? [[html]] : null;
|
|
748
812
|
}
|
|
749
813
|
|
|
750
|
-
return { copy, copyAcross, copyBlocks,
|
|
814
|
+
return { copy, copyAcross, copyBlocks, cellsOf, paste, blocksAt };
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
// The inline HTML among described blocks (`value`, at any depth) that holds pictures: a table's cells' (单元格里的图片).
|
|
818
|
+
function pictureTexts(value, found = []) {
|
|
819
|
+
if (typeof value === "string") {
|
|
820
|
+
if (value.includes("<img")) found.push(value);
|
|
821
|
+
} else if (Array.isArray(value)) value.forEach((each) => pictureTexts(each, found));
|
|
822
|
+
else if (value && typeof value === "object") Object.values(value).forEach((each) => pictureTexts(each, found));
|
|
823
|
+
return found;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// The report the table tools' copy of cells says it was copied from, or null.
|
|
827
|
+
function reportIn(copied) {
|
|
828
|
+
try {
|
|
829
|
+
const from = JSON.parse(copied)?.report;
|
|
830
|
+
return typeof from === "string" ? from : null;
|
|
831
|
+
} catch {
|
|
832
|
+
return null;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
/**
|
|
837
|
+
* Tab-separated lines as rows of cells (Excel's and Google Sheets' text, Notion's rule, 872952: two
|
|
838
|
+
* lines or more, each of as many cells, two or more), or null. A cell starting with a quote is in
|
|
839
|
+
* quotes, holding tabs and line breaks, "" a quote in it (Excel's quoting).
|
|
840
|
+
*/
|
|
841
|
+
export function tabbed(text) {
|
|
842
|
+
if (!text.includes("\t")) return null;
|
|
843
|
+
const rows = [[]];
|
|
844
|
+
let cell = "";
|
|
845
|
+
let quoted = false;
|
|
846
|
+
for (let i = 0; i < text.length; i++) {
|
|
847
|
+
const character = text[i];
|
|
848
|
+
if (quoted) {
|
|
849
|
+
if (character !== '"') cell += character;
|
|
850
|
+
else if (text[i + 1] === '"') cell += text[++i];
|
|
851
|
+
else quoted = false;
|
|
852
|
+
} else if (character === '"' && cell === "") quoted = true;
|
|
853
|
+
else if (character === "\t" || character === "\n") {
|
|
854
|
+
rows.at(-1).push(cell);
|
|
855
|
+
cell = "";
|
|
856
|
+
if (character === "\n") rows.push([]);
|
|
857
|
+
} else cell += character;
|
|
858
|
+
}
|
|
859
|
+
rows.at(-1).push(cell);
|
|
860
|
+
const width = rows[0].length;
|
|
861
|
+
return rows.length > 1 && width > 1 && rows.every((row) => row.length === width) ? rows : null;
|
|
751
862
|
}
|
|
752
863
|
|
|
753
864
|
// What a field of plain text takes of the clipboard, as one line: the text of the page's own blocks
|
|
@@ -4,7 +4,7 @@ import { pageBuild } from "../../../components/builders.mjs";
|
|
|
4
4
|
import { BLOCK_TYPES, COPIED_AS_ITSELF, HOLDS_ONE, TEXT_TYPES, TOGGLES, UNSAID, accepts, clipboardHooks, clipboardOf, isLead, sizeValue } from "../../../components/registry.mjs";
|
|
5
5
|
import { BLOCK_COLORS } from "../../../components/colors.mjs";
|
|
6
6
|
import { MAX_CELL_HTML } from "../../../components/table/index.mjs";
|
|
7
|
-
import { copied, copyOf
|
|
7
|
+
import { copied, copyOf } from "./describe.mjs";
|
|
8
8
|
import { imageSource, kindOfBlock, webPage } from "./rules.mjs";
|
|
9
9
|
|
|
10
10
|
// Described blocks (describe.mjs and selection.mjs, and import/to-blocks.mjs for other programs' content) made (build),
|
|
@@ -113,10 +113,10 @@ export function parseText(data) {
|
|
|
113
113
|
/**
|
|
114
114
|
* Inline HTML as nodes of the format bar's marks only, its lines with <br> between them; formulas
|
|
115
115
|
* of other pages made the page's own by `formula(tex)` where given, links shown with their icon by
|
|
116
|
-
* `mention(parts)` (pastedLines).
|
|
116
|
+
* `mention(parts)`, pictures by `picture(img)` (a table cell's: pastedLines).
|
|
117
117
|
*/
|
|
118
|
-
function inline(doc, html, { formula = null, mention = null } = {}) {
|
|
119
|
-
return pastedLines(doc, html, { formula, mention }).flatMap((line, index) => (index > 0 ? [doc.createElement("br"), ...line] : line));
|
|
118
|
+
function inline(doc, html, { formula = null, mention = null, picture = null } = {}) {
|
|
119
|
+
return pastedLines(doc, html, { formula, mention, picture }).flatMap((line, index) => (index > 0 ? [doc.createElement("br"), ...line] : line));
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
|
|
@@ -129,7 +129,8 @@ function colored(element, block) {
|
|
|
129
129
|
/**
|
|
130
130
|
* A new block of the page from a described one (checked). `formula(tex)`: an inline formula chip of
|
|
131
131
|
* the page (none: their TeX as text); `mention(parts)`: a link shown with its icon (none: a link of
|
|
132
|
-
* its title)
|
|
132
|
+
* its title); `picture(img)`: a table cell's picture (none: nothing; `what.inline(html, { pictures:
|
|
133
|
+
* true })` asks for it, a cell's text alone holding pictures). What each type adds is its definition's: `clipboard.build`, or the `build` of its
|
|
133
134
|
* page.mjs (builders.mjs); a container is filled with its blocks, a text type with its inline HTML.
|
|
134
135
|
*/
|
|
135
136
|
export function build(doc, block, options = {}) {
|
|
@@ -144,18 +145,17 @@ export function build(doc, block, options = {}) {
|
|
|
144
145
|
copy.setAttribute("data-ge-unit-kind", block.kind);
|
|
145
146
|
return copy;
|
|
146
147
|
}
|
|
147
|
-
// Elsewhere: a new one of its data (pasteBlocks checked it has some), the key a chart
|
|
148
|
-
// table by
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
return build(doc, data, options);
|
|
148
|
+
// Elsewhere: a new one of its data (pasteBlocks checked it has some), with the key a chart or a
|
|
149
|
+
// view reads a table by, which the paste then keeps, gives anew or takes off, in another document
|
|
150
|
+
// too (chart-keys.mjs relinkCopies: a table pasted there alone loses it, one with its reader is a pair).
|
|
151
|
+
return build(doc, block.data, options);
|
|
152
152
|
}
|
|
153
153
|
const what = {
|
|
154
154
|
doc,
|
|
155
155
|
block,
|
|
156
156
|
host: (type = block.type) => newHost(doc, type),
|
|
157
157
|
box: (type = block.type) => newContainer(doc, type),
|
|
158
|
-
inline: (html) => inline(doc, html, options),
|
|
158
|
+
inline: (html, { pictures = false } = {}) => inline(doc, html, pictures ? options : { ...options, picture: null }),
|
|
159
159
|
inner: (blocks) => blocks.map((each) => build(doc, each, options)),
|
|
160
160
|
one: (each) => build(doc, each, options),
|
|
161
161
|
colored: (element) => colored(element, block),
|
|
@@ -1,53 +1,66 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CHART_SOURCE, TABLE_READERS, nextChartKey } from "../../../../shared/table-chart.mjs";
|
|
2
2
|
import { COPY_KEYS } from "../../../components/figure/index.mjs";
|
|
3
3
|
|
|
4
|
-
// The keys of
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
4
|
+
// The keys of tables in what a paste made (docs/editor.md, "Copying blocks"): a chart drawn from a
|
|
5
|
+
// table and a view of one (an instance of a custom block that reads tables) name the table by a key
|
|
6
|
+
// (src/shared/table-chart.mjs: TABLE_READERS, a reader), and what a paste makes of a card, a view or a
|
|
7
|
+
// table carries its original's: a copy of it (data-ge-type="copy"), what a clipboard carried of a view
|
|
8
|
+
// (its markup), or a table made anew of its data (components/table tableData `chart`: one cut, one whose
|
|
9
|
+
// original is gone or changed since the copy, one of another document). The rules, by key:
|
|
10
|
+
// - a reader and a table pasted together are a pair of their own: both take a new key, the first of
|
|
11
|
+
// t1, t2 … the page does not hold, so that two pairs never cross (a table copied with its board
|
|
12
|
+
// is a board of its own), in its document or another;
|
|
13
|
+
// - a table pasted without its reader keeps its key while no table on the page carries it (a cut
|
|
14
|
+
// table put back, one whose original was deleted: the card draws it again); otherwise, and in
|
|
15
|
+
// another document, it is a table alone, its key taken off (a reader reads the first table of its
|
|
16
|
+
// key, which could be it; another document's readers are no readers of it);
|
|
17
|
+
// - a reader pasted alone keeps its key in its document: it reads the same table as its original,
|
|
18
|
+
// both reading it; in another document it takes it off (`same` false: the clipboard's document is
|
|
19
|
+
// not this one), as the table it read is not there and one there carrying the key is no table of
|
|
20
|
+
// its (keys are t1, t2 … in every document): a view of no table, never one reading and changing that.
|
|
15
21
|
// A copy's new keys ride on it (COPY_KEYS) to the server, which writes them into the copy's source
|
|
16
22
|
// (core.mjs nodeOf: { copy, keys }; source/text.mjs copiedSource); a table made anew is written with
|
|
17
|
-
// its own
|
|
18
|
-
// says what it changed (page/commit.mjs).
|
|
23
|
+
// its own, a view with its own or none (components/installed extras `from`). The commit makes sure of
|
|
24
|
+
// them against the file as it is then (source/chart-keys.mjs) and says what it changed (page/commit.mjs).
|
|
19
25
|
|
|
20
26
|
// What carries a key in `root` and in what its templates hold.
|
|
27
|
+
const NAMES = [CHART_SOURCE, ...TABLE_READERS];
|
|
28
|
+
const CARRIES = NAMES.map((name) => `[${name}]`).join(", ");
|
|
21
29
|
const carriers = (root) => [
|
|
22
|
-
...(root.matches?.(
|
|
23
|
-
...root.querySelectorAll(
|
|
30
|
+
...(root.matches?.(CARRIES) ? [root] : []),
|
|
31
|
+
...root.querySelectorAll(CARRIES),
|
|
24
32
|
...[...root.querySelectorAll("template")].flatMap((template) => carriers(template.content)),
|
|
25
33
|
];
|
|
26
|
-
const keysOf = (node) =>
|
|
34
|
+
const keysOf = (node) => NAMES.map((name) => node.getAttribute(name)).filter((key) => key !== null);
|
|
35
|
+
const readerKey = (node) => TABLE_READERS.map((name) => node.getAttribute(name)).find((key) => key !== null) ?? null;
|
|
27
36
|
|
|
28
|
-
/**
|
|
29
|
-
|
|
37
|
+
/**
|
|
38
|
+
* The blocks a paste made (`made`, not on the page yet), the keys of their cards, views and tables made
|
|
39
|
+
* their own; `same`: the clipboard's document is this one (clipboard/index.mjs origin).
|
|
40
|
+
*/
|
|
41
|
+
export function relinkCopies(doc, made, { same = true } = {}) {
|
|
30
42
|
const inMade = made.flatMap(carriers);
|
|
31
|
-
const hosts = inMade.filter((node) => node
|
|
43
|
+
const hosts = inMade.filter((node) => readerKey(node) !== null);
|
|
32
44
|
const frames = inMade.filter((node) => node.hasAttribute(CHART_SOURCE));
|
|
33
|
-
if (frames.length === 0) return;
|
|
45
|
+
if (frames.length === 0 && (same || hosts.length === 0)) return;
|
|
34
46
|
const onPage = carriers(doc);
|
|
35
47
|
const taken = new Set([...onPage, ...inMade].flatMap(keysOf));
|
|
36
|
-
const renamed = new Map(); // a key -> its new value, null: taken off
|
|
37
|
-
|
|
38
|
-
|
|
48
|
+
const renamed = new Map(); // a key -> its new value, null: taken off
|
|
49
|
+
const tabled = new Set(frames.map((frame) => frame.getAttribute(CHART_SOURCE)));
|
|
50
|
+
for (const key of tabled) {
|
|
51
|
+
if (hosts.some((host) => readerKey(host) === key)) {
|
|
39
52
|
const next = nextChartKey(taken);
|
|
40
53
|
taken.add(next);
|
|
41
54
|
renamed.set(key, next);
|
|
42
|
-
} else if (onPage.some((node) => node.getAttribute(CHART_SOURCE) === key)) renamed.set(key, null);
|
|
55
|
+
} else if (!same || onPage.some((node) => node.getAttribute(CHART_SOURCE) === key)) renamed.set(key, null);
|
|
43
56
|
}
|
|
57
|
+
if (!same) for (const host of hosts) if (!tabled.has(readerKey(host))) renamed.set(readerKey(host), null);
|
|
44
58
|
const sent = new Map(); // a copy -> its keys { old: new | null }
|
|
45
|
-
for (const [name, nodes] of [[
|
|
59
|
+
for (const [name, nodes] of [...TABLE_READERS.map((reader) => [reader, hosts]), [CHART_SOURCE, frames]]) {
|
|
46
60
|
for (const node of nodes) {
|
|
47
61
|
const key = node.getAttribute(name);
|
|
48
|
-
if (!renamed.has(key)) continue;
|
|
62
|
+
if (key === null || !renamed.has(key)) continue;
|
|
49
63
|
const next = renamed.get(key);
|
|
50
|
-
if (next === null && name === CHART_DATA) continue; // a card keeps the key of a table pasted alone
|
|
51
64
|
if (next === null) node.removeAttribute(name);
|
|
52
65
|
else node.setAttribute(name, next);
|
|
53
66
|
const copy = node.closest('[data-ge-type="copy"]');
|
|
@@ -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
|
};
|
|
@@ -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-sans-font, 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
|
}
|