@heycys/gallery 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +50 -2
- package/THIRD-PARTY-NOTICES.md +3303 -0
- package/assets/writing-preferences.md +107 -0
- package/bin/gallery.mjs +10 -0
- package/browser/editor/components/bookmark/icons.mjs +6 -0
- package/browser/editor/components/bookmark/index.mjs +80 -0
- package/browser/editor/components/bookmark/page.mjs +147 -0
- package/browser/editor/components/builders.mjs +19 -0
- package/browser/editor/components/callout/index.mjs +64 -0
- package/browser/editor/components/code/index.mjs +327 -0
- package/browser/editor/components/code/page.mjs +561 -0
- package/browser/editor/components/colors.mjs +50 -0
- package/browser/editor/components/columns/index.mjs +104 -0
- package/browser/editor/components/columns/page.mjs +310 -0
- package/browser/editor/components/details/index.mjs +73 -0
- package/browser/editor/components/details/page.mjs +86 -0
- package/browser/editor/components/dialog/index.mjs +84 -0
- package/browser/editor/components/dialog/page.mjs +201 -0
- package/browser/editor/components/divider/index.mjs +48 -0
- package/browser/editor/components/embed/icons.mjs +11 -0
- package/browser/editor/components/embed/index.mjs +123 -0
- package/browser/editor/components/embed/page.mjs +309 -0
- package/browser/editor/components/figure/index.mjs +87 -0
- package/browser/editor/components/figure/page.mjs +42 -0
- package/browser/editor/components/file/icons.mjs +14 -0
- package/browser/editor/components/file/index.mjs +77 -0
- package/browser/editor/components/file/page.mjs +114 -0
- package/browser/editor/components/flowchart/add.mjs +123 -0
- package/browser/editor/components/flowchart/index.mjs +246 -0
- package/browser/editor/components/flowchart/page.mjs +453 -0
- package/browser/editor/components/heading/index.mjs +53 -0
- package/browser/editor/components/heading/page.mjs +6 -0
- package/browser/editor/components/highlight/index.mjs +63 -0
- package/browser/editor/components/icon/index.mjs +57 -0
- package/browser/editor/components/icon/page.mjs +286 -0
- package/browser/editor/components/icons.mjs +48 -0
- package/browser/editor/components/image/crop.mjs +189 -0
- package/browser/editor/components/image/index.mjs +104 -0
- package/browser/editor/components/image/page.mjs +385 -0
- package/browser/editor/components/image/viewer.mjs +213 -0
- package/browser/editor/components/installed/index.mjs +179 -0
- package/browser/editor/components/installed/page.mjs +523 -0
- package/browser/editor/components/installed/served.mjs +35 -0
- package/browser/editor/components/kit.mjs +67 -0
- package/browser/editor/components/list/index.mjs +194 -0
- package/browser/editor/components/list/join.mjs +68 -0
- package/browser/editor/components/list/numbers.mjs +107 -0
- package/browser/editor/components/list/page.mjs +632 -0
- package/browser/editor/components/math/index.mjs +88 -0
- package/browser/editor/components/math/page.mjs +236 -0
- package/browser/editor/components/math/tex-logo.mjs +6 -0
- package/browser/editor/components/media/icons.mjs +19 -0
- package/browser/editor/components/media/page.mjs +192 -0
- package/browser/editor/components/media/parts.mjs +60 -0
- package/browser/editor/components/media/size.mjs +20 -0
- package/browser/editor/components/media/toolbar.mjs +37 -0
- package/browser/editor/components/media/write.mjs +7 -0
- package/browser/editor/components/pages.mjs +46 -0
- package/browser/editor/components/paragraph/index.mjs +43 -0
- package/browser/editor/components/paragraph/page.mjs +52 -0
- package/browser/editor/components/placeholder-bar.mjs +17 -0
- package/browser/editor/components/placeholder.mjs +128 -0
- package/browser/editor/components/quote/index.mjs +33 -0
- package/browser/editor/components/registry.mjs +859 -0
- package/browser/editor/components/rows.mjs +16 -0
- package/browser/editor/components/section/index.mjs +42 -0
- package/browser/editor/components/section/page.mjs +141 -0
- package/browser/editor/components/set-apart.mjs +24 -0
- package/browser/editor/components/sheets/index.mjs +137 -0
- package/browser/editor/components/sheets/page.mjs +227 -0
- package/browser/editor/components/sheets/pills.mjs +226 -0
- package/browser/editor/components/table/grid.mjs +73 -0
- package/browser/editor/components/table/index.mjs +308 -0
- package/browser/editor/components/table/page.mjs +683 -0
- package/browser/editor/components/table/slots.mjs +41 -0
- package/browser/editor/components/widget/index.mjs +50 -0
- package/browser/editor/page/annotate/anchors.mjs +230 -0
- package/browser/editor/page/annotate/card.mjs +102 -0
- package/browser/editor/page/annotate/index.mjs +1656 -0
- package/browser/editor/page/at-menu/index.mjs +317 -0
- package/browser/editor/page/autosave.mjs +1023 -0
- package/browser/editor/page/beside.mjs +21 -0
- package/browser/editor/page/block-info.mjs +63 -0
- package/browser/editor/page/block-menu/colors.mjs +84 -0
- package/browser/editor/page/block-menu/index.mjs +217 -0
- package/browser/editor/page/blocks.mjs +255 -0
- package/browser/editor/page/caret.mjs +682 -0
- package/browser/editor/page/changes/bar.mjs +102 -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/chip-fills.mjs +126 -0
- package/browser/editor/page/clipboard/import/colors.mjs +192 -0
- package/browser/editor/page/clipboard/import/html.mjs +792 -0
- package/browser/editor/page/clipboard/import/inline.mjs +232 -0
- package/browser/editor/page/clipboard/import/languages.mjs +42 -0
- package/browser/editor/page/clipboard/import/markdown.mjs +760 -0
- package/browser/editor/page/clipboard/import/math.mjs +100 -0
- package/browser/editor/page/clipboard/import/office.mjs +245 -0
- package/browser/editor/page/clipboard/import/read.mjs +120 -0
- package/browser/editor/page/clipboard/import/rich.mjs +29 -0
- package/browser/editor/page/clipboard/import/to-blocks.mjs +290 -0
- package/browser/editor/page/clipboard/index.mjs +816 -0
- package/browser/editor/page/clipboard/own/blocks.mjs +211 -0
- package/browser/editor/page/clipboard/own/chart-keys.mjs +58 -0
- package/browser/editor/page/clipboard/own/describe.mjs +124 -0
- package/browser/editor/page/clipboard/own/export.mjs +167 -0
- package/browser/editor/page/clipboard/own/ids.mjs +39 -0
- package/browser/editor/page/clipboard/own/index.mjs +13 -0
- package/browser/editor/page/clipboard/own/rules.mjs +44 -0
- package/browser/editor/page/clipboard/own/selection.mjs +159 -0
- package/browser/editor/page/clipboard/own/writers.mjs +315 -0
- package/browser/editor/page/columns/index.mjs +360 -0
- package/browser/editor/page/commit.mjs +1813 -0
- package/browser/editor/page/conflicts.mjs +249 -0
- package/browser/editor/page/convert.mjs +831 -0
- package/browser/editor/page/core.mjs +1693 -0
- package/browser/editor/page/drag/drop.mjs +307 -0
- package/browser/editor/page/drag/index.mjs +351 -0
- package/browser/editor/page/drag/preview.mjs +126 -0
- package/browser/editor/page/edge-scroll.mjs +50 -0
- package/browser/editor/page/editor.mjs +1780 -0
- package/browser/editor/page/emoji-picker/emoji-tab.mjs +287 -0
- package/browser/editor/page/emoji-picker/glyph-html.mjs +26 -0
- package/browser/editor/page/emoji-picker/grid.mjs +81 -0
- package/browser/editor/page/emoji-picker/icon-tab.mjs +217 -0
- package/browser/editor/page/emoji-picker/icons.mjs +31 -0
- package/browser/editor/page/emoji-picker/index.mjs +166 -0
- package/browser/editor/page/emoji-picker/styles.mjs +161 -0
- package/browser/editor/page/emoji-picker/support.mjs +204 -0
- package/browser/editor/page/emoji-picker/upload.mjs +236 -0
- package/browser/editor/page/export-report.mjs +23 -0
- package/browser/editor/page/fills.mjs +62 -0
- package/browser/editor/page/find/index.mjs +107 -0
- package/browser/editor/page/flags.mjs +70 -0
- 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 +449 -0
- package/browser/editor/page/format-bar/brush.mjs +77 -0
- package/browser/editor/page/format-bar/colors.mjs +46 -0
- package/browser/editor/page/format-bar/index.mjs +404 -0
- package/browser/editor/page/formula/index.mjs +236 -0
- package/browser/editor/page/formula/panel.mjs +336 -0
- package/browser/editor/page/formula/symbols.mjs +156 -0
- package/browser/editor/page/frame.mjs +74 -0
- package/browser/editor/page/frames.mjs +196 -0
- package/browser/editor/page/geometry.mjs +402 -0
- package/browser/editor/page/gesture.mjs +45 -0
- package/browser/editor/page/handle/index.mjs +650 -0
- package/browser/editor/page/handle-sizes.mjs +14 -0
- package/browser/editor/page/hints/index.mjs +84 -0
- package/browser/editor/page/history.mjs +401 -0
- package/browser/editor/page/insert/index.mjs +256 -0
- package/browser/editor/page/kept.mjs +38 -0
- package/browser/editor/page/links/address.mjs +40 -0
- package/browser/editor/page/links/index.mjs +866 -0
- package/browser/editor/page/links/pages.mjs +131 -0
- package/browser/editor/page/links/views.mjs +369 -0
- package/browser/editor/page/long-runs.mjs +75 -0
- package/browser/editor/page/look.mjs +77 -0
- package/browser/editor/page/made.mjs +24 -0
- package/browser/editor/page/margin.mjs +373 -0
- package/browser/editor/page/markdown/index.mjs +88 -0
- package/browser/editor/page/markdown/rules.mjs +33 -0
- package/browser/editor/page/marks.mjs +377 -0
- package/browser/editor/page/media-menu/index.mjs +158 -0
- package/browser/editor/page/menu.mjs +544 -0
- package/browser/editor/page/merge.mjs +124 -0
- package/browser/editor/page/notices.mjs +142 -0
- package/browser/editor/page/offered.mjs +32 -0
- package/browser/editor/page/outline/folds.mjs +53 -0
- package/browser/editor/page/outline/index.mjs +783 -0
- package/browser/editor/page/outline/list.mjs +184 -0
- package/browser/editor/page/outline/read.mjs +201 -0
- package/browser/editor/page/outline/strip.mjs +287 -0
- package/browser/editor/page/outline/tree.mjs +248 -0
- package/browser/editor/page/overlay-layer.mjs +227 -0
- package/browser/editor/page/overlays.mjs +205 -0
- package/browser/editor/page/own.mjs +28 -0
- package/browser/editor/page/pads.mjs +71 -0
- package/browser/editor/page/page-objects.mjs +105 -0
- package/browser/editor/page/panel.mjs +65 -0
- package/browser/editor/page/placement.mjs +58 -0
- package/browser/editor/page/post.mjs +41 -0
- package/browser/editor/page/present-links.mjs +50 -0
- package/browser/editor/page/quiet.mjs +48 -0
- package/browser/editor/page/resize/index.mjs +327 -0
- package/browser/editor/page/select-all/index.mjs +262 -0
- package/browser/editor/page/selection/delete.mjs +61 -0
- package/browser/editor/page/selection/index.mjs +164 -0
- package/browser/editor/page/selection/marquee.mjs +174 -0
- package/browser/editor/page/session.mjs +168 -0
- package/browser/editor/page/slash-menu/index.mjs +291 -0
- package/browser/editor/page/storage.mjs +48 -0
- package/browser/editor/page/sync-state.mjs +267 -0
- package/browser/editor/page/table/aligns.mjs +29 -0
- package/browser/editor/page/table/cell-bar.mjs +141 -0
- package/browser/editor/page/table/cells.mjs +527 -0
- package/browser/editor/page/table/icons.mjs +40 -0
- package/browser/editor/page/table/index.mjs +990 -0
- package/browser/editor/page/table/lists.mjs +187 -0
- package/browser/editor/page/table/widths.mjs +313 -0
- package/browser/editor/page/tex.mjs +32 -0
- package/browser/editor/page/text-select/index.mjs +671 -0
- package/browser/editor/page/tooltip.mjs +98 -0
- package/browser/editor/page/type-grid.mjs +83 -0
- package/browser/editor/page/typing/code-edges.mjs +274 -0
- package/browser/editor/page/typing/index.mjs +282 -0
- package/browser/editor/page/typing/leave.mjs +68 -0
- package/browser/editor/page/ui.mjs +160 -0
- package/browser/shared/annotations.mjs +569 -0
- package/browser/shared/code-folds.mjs +14 -0
- package/browser/shared/code-languages.mjs +70 -0
- package/browser/shared/code-lines.mjs +30 -0
- package/browser/shared/colors.mjs +30 -0
- package/browser/shared/component-catalog.mjs +573 -0
- package/browser/shared/components/bookmark.mjs +26 -0
- package/browser/shared/components/callout.mjs +9 -0
- package/browser/shared/components/chart.mjs +20 -0
- package/browser/shared/components/code.mjs +37 -0
- package/browser/shared/components/columns.mjs +16 -0
- package/browser/shared/components/details.mjs +15 -0
- package/browser/shared/components/dialog.mjs +28 -0
- package/browser/shared/components/diff.mjs +18 -0
- package/browser/shared/components/divider.mjs +6 -0
- package/browser/shared/components/embed.mjs +25 -0
- package/browser/shared/components/figure.mjs +14 -0
- package/browser/shared/components/file.mjs +23 -0
- package/browser/shared/components/heading.mjs +6 -0
- package/browser/shared/components/highlight.mjs +9 -0
- package/browser/shared/components/icon.mjs +18 -0
- package/browser/shared/components/image.mjs +39 -0
- package/browser/shared/components/index.mjs +396 -0
- package/browser/shared/components/installed.mjs +232 -0
- package/browser/shared/components/list.mjs +146 -0
- package/browser/shared/components/math.mjs +49 -0
- package/browser/shared/components/mention.mjs +33 -0
- package/browser/shared/components/page.mjs +46 -0
- package/browser/shared/components/paragraph.mjs +9 -0
- package/browser/shared/components/quote.mjs +6 -0
- package/browser/shared/components/section.mjs +8 -0
- package/browser/shared/components/sheets.mjs +80 -0
- package/browser/shared/components/state.mjs +20 -0
- package/browser/shared/components/table.mjs +49 -0
- package/browser/shared/components/text.mjs +14 -0
- package/browser/shared/components/widget.mjs +10 -0
- package/browser/shared/copy-ids.mjs +72 -0
- package/browser/shared/css-references.mjs +110 -0
- package/browser/shared/document-look.mjs +178 -0
- package/browser/shared/emoji/custom.mjs +91 -0
- package/browser/shared/emoji/data/LICENSE-lucide.txt +43 -0
- package/browser/shared/emoji/data/LICENSE-mingcute.txt +202 -0
- package/browser/shared/emoji/data/LICENSE-tabler.txt +21 -0
- package/browser/shared/emoji/data/README.md +28 -0
- package/browser/shared/emoji/data/categories.json +1 -0
- package/browser/shared/emoji/data/icons.json +1 -0
- package/browser/shared/emoji/data/keywords-en.json +1 -0
- package/browser/shared/emoji/data/keywords-zh.json +1 -0
- package/browser/shared/emoji/data/names.json +1 -0
- package/browser/shared/emoji/data/positions.json +1 -0
- package/browser/shared/emoji/data/twemoji-index.json +1 -0
- package/browser/shared/emoji/data/twemoji-svg.bin +0 -0
- package/browser/shared/emoji/data.mjs +194 -0
- package/browser/shared/emoji/emoji.mjs +38 -0
- package/browser/shared/emoji/glyphs.mjs +134 -0
- package/browser/shared/emoji/icon-value.mjs +91 -0
- package/browser/shared/escape.mjs +20 -0
- package/browser/shared/export-wrap.mjs +89 -0
- package/browser/shared/files.mjs +33 -0
- package/browser/shared/html-tree.mjs +59 -0
- package/browser/shared/http.mjs +22 -0
- package/browser/shared/i18n/en.mjs +1223 -0
- package/browser/shared/i18n/index.mjs +132 -0
- package/browser/shared/ids.mjs +24 -0
- package/browser/shared/import-types.mjs +23 -0
- package/browser/shared/inline-spacing.mjs +97 -0
- package/browser/shared/layers.mjs +42 -0
- package/browser/shared/long-runs.mjs +39 -0
- package/browser/shared/media.mjs +162 -0
- package/browser/shared/new-names.mjs +67 -0
- package/browser/shared/number-reading.mjs +92 -0
- package/browser/shared/old-names.mjs +143 -0
- package/browser/shared/outline.mjs +194 -0
- package/browser/shared/page-address.mjs +140 -0
- package/browser/shared/page-links.mjs +86 -0
- package/browser/shared/paths.mjs +73 -0
- package/browser/shared/preferences.mjs +116 -0
- package/browser/shared/preview-server.mjs +247 -0
- package/browser/shared/qa-levels.mjs +93 -0
- package/browser/shared/reading-place.mjs +91 -0
- package/browser/shared/renamed-storage.mjs +220 -0
- package/browser/shared/reports.mjs +46 -0
- package/browser/shared/search.mjs +85 -0
- package/browser/shared/session.mjs +77 -0
- package/browser/shared/table-chart.mjs +113 -0
- package/browser/shared/table-hides.mjs +120 -0
- package/browser/shared/table-slots.mjs +75 -0
- package/browser/shared/words.mjs +23 -0
- package/browser/shared/workspace-look.mjs +91 -0
- package/browser/shared/workspace.mjs +535 -0
- package/browser/shared/writing-preferences.mjs +68 -0
- package/browser/shared/zoom.mjs +57 -0
- package/dist/chunk-2B5E4CDJ.mjs +2 -0
- package/dist/chunk-342HXE3Q.mjs +2 -0
- package/dist/chunk-3HIRPVLU.mjs +2 -0
- package/dist/chunk-43B75J5T.mjs +2 -0
- package/dist/chunk-4FS7Z7WR.mjs +2 -0
- package/dist/chunk-4K5KC6V2.mjs +2 -0
- package/dist/chunk-5L7RYZCL.mjs +2 -0
- package/dist/chunk-5MHMDLZD.mjs +4 -0
- package/dist/chunk-5ZKJ3H4P.mjs +8 -0
- package/dist/chunk-64K7IPLO.mjs +255 -0
- package/dist/chunk-6QXGZM36.mjs +8 -0
- package/dist/chunk-6RGJOMJP.mjs +16 -0
- package/dist/chunk-742D2WWJ.mjs +19 -0
- package/dist/chunk-7DTINW6U.mjs +48 -0
- package/dist/chunk-A55HN5OK.mjs +2 -0
- package/dist/chunk-AGDILNWB.mjs +2 -0
- package/dist/chunk-AJ73XJF3.mjs +2 -0
- package/dist/chunk-AUZGSZJH.mjs +13 -0
- package/dist/chunk-BFE45AKL.mjs +2 -0
- package/dist/chunk-BGGDRNYQ.mjs +10 -0
- package/dist/chunk-BXO2ZY5P.mjs +2 -0
- package/dist/chunk-C564NU2H.mjs +77 -0
- package/dist/chunk-CEH4MRCC.mjs +2 -0
- package/dist/chunk-CY2FNNAB.mjs +16 -0
- package/dist/chunk-DFUDV4LX.mjs +2 -0
- package/dist/chunk-DKXG4XDG.mjs +2 -0
- package/dist/chunk-E7LWZRXY.mjs +4 -0
- package/dist/chunk-EZQ34M3F.mjs +124 -0
- package/dist/chunk-EZY3WC6Z.mjs +15 -0
- package/dist/chunk-FDLXYYG4.mjs +4 -0
- package/dist/chunk-FUKQNOQS.mjs +9 -0
- package/dist/chunk-GB5SOYQJ.mjs +7 -0
- package/dist/chunk-GRAXKKG4.mjs +2 -0
- package/dist/chunk-HYMEEXKN.mjs +4 -0
- package/dist/chunk-IVDLMMBD.mjs +2 -0
- package/dist/chunk-JPOSLGOC.mjs +6 -0
- package/dist/chunk-JVHHHGEA.mjs +3 -0
- package/dist/chunk-L3QKH4OK.mjs +26 -0
- package/dist/chunk-LAE5NQ4B.mjs +2 -0
- package/dist/chunk-LCTHTZIL.mjs +960 -0
- package/dist/chunk-LEF6DRCK.mjs +59 -0
- package/dist/chunk-LKX55H76.mjs +2 -0
- package/dist/chunk-LS4F7JUM.mjs +2 -0
- package/dist/chunk-MAFIGVXY.mjs +2 -0
- package/dist/chunk-NO5NJCHO.mjs +2 -0
- package/dist/chunk-NQPVAU63.mjs +2 -0
- package/dist/chunk-NSKUTQ5J.mjs +5 -0
- package/dist/chunk-O35FIXRB.mjs +2 -0
- package/dist/chunk-P2CAZPDP.mjs +3 -0
- package/dist/chunk-PL6GHLGD.mjs +15 -0
- package/dist/chunk-QAIHRH3I.mjs +13 -0
- package/dist/chunk-QJIR2BLP.mjs +6 -0
- package/dist/chunk-QR6A54KJ.mjs +3 -0
- package/dist/chunk-QUPLVPB2.mjs +7 -0
- package/dist/chunk-R7BNENLY.mjs +4 -0
- package/dist/chunk-S6O4UHLC.mjs +2 -0
- package/dist/chunk-SGJWQKEI.mjs +2 -0
- package/dist/chunk-SYGN7GLU.mjs +2 -0
- package/dist/chunk-TMYZB6AV.mjs +2 -0
- package/dist/chunk-TX6JH7TR.mjs +2 -0
- package/dist/chunk-TYK6VNAB.mjs +10 -0
- package/dist/chunk-U3SSPL4K.mjs +8 -0
- package/dist/chunk-U6KNPJPR.mjs +2 -0
- package/dist/chunk-UALRNVSE.mjs +4 -0
- package/dist/chunk-UH4SIXTR.mjs +2 -0
- package/dist/chunk-UMHUSOPJ.mjs +2 -0
- package/dist/chunk-V3HXVQEM.mjs +2 -0
- package/dist/chunk-V5JTW2LH.mjs +27 -0
- package/dist/chunk-V5VXUJKG.mjs +2 -0
- package/dist/chunk-V6XZ4VIR.mjs +2 -0
- package/dist/chunk-VBXMADMP.mjs +2 -0
- package/dist/chunk-VNV55RUA.mjs +2 -0
- package/dist/chunk-VPD2PS35.mjs +2 -0
- package/dist/chunk-W3BGBJQW.mjs +2 -0
- package/dist/chunk-W4VKN3GF.mjs +7 -0
- package/dist/chunk-W5BXXPDJ.mjs +3 -0
- package/dist/chunk-W7XHE4CT.mjs +2 -0
- package/dist/chunk-XNROSH2T.mjs +4 -0
- package/dist/chunk-XUNHRCOG.mjs +6 -0
- package/dist/chunk-Y34NR5JL.mjs +2 -0
- package/dist/chunk-Y6RLRPG3.mjs +3 -0
- package/dist/chunk-YEY3RSFQ.mjs +2 -0
- package/dist/cli.mjs +2 -0
- package/dist/server.mjs +2 -0
- package/dist/worker.mjs +5 -0
- package/kit/charts.js +355 -0
- package/kit/code.js +164 -0
- package/kit/dialogs.js +157 -0
- package/kit/math.js +2004 -0
- package/kit/report.css +2932 -0
- package/kit/runtime.js +1782 -0
- package/kit/sheets.js +123 -0
- package/kit/state.js +217 -0
- package/kit/tables.js +1499 -0
- package/kit/tokens.js +29 -0
- package/kit/ui.js +658 -0
- package/package.json +41 -4
- package/release.json +25 -0
- package/sdk/column-widths.d.ts +56 -0
- package/sdk/doc-charts.d.ts +82 -0
- package/sdk/doc-code.d.ts +28 -0
- package/sdk/doc-dialogs.d.ts +4 -0
- package/sdk/doc-kit.d.ts +147 -0
- package/sdk/doc-math.d.ts +3 -0
- package/sdk/doc-sheets.d.ts +15 -0
- package/sdk/doc-state.d.ts +41 -0
- package/sdk/doc-tables.d.ts +24 -0
- package/sdk/doc-tokens.d.ts +22 -0
- package/sdk/index.d.ts +30 -0
- package/skill/SKILL.md +150 -0
- package/skill/agents/openai.yaml +5 -0
- package/skill/references/building-components.md +367 -0
- package/skill/references/example-report.html +356 -0
- package/skill/references/writing-html.md +187 -0
- package/skill/sdk/column-widths.d.ts +56 -0
- package/skill/sdk/doc-charts.d.ts +82 -0
- package/skill/sdk/doc-code.d.ts +28 -0
- package/skill/sdk/doc-dialogs.d.ts +4 -0
- package/skill/sdk/doc-kit.d.ts +147 -0
- package/skill/sdk/doc-math.d.ts +3 -0
- package/skill/sdk/doc-sheets.d.ts +15 -0
- package/skill/sdk/doc-state.d.ts +41 -0
- package/skill/sdk/doc-tables.d.ts +24 -0
- package/skill/sdk/doc-tokens.d.ts +22 -0
- package/skill/sdk/index.d.ts +30 -0
- package/starter/doc.html +21 -0
- package/starter/doc.json +5 -0
- package/vendor/d3.v7.9.0.min.js +2 -0
- package/vendor/katex/auto-render.min.js +1 -0
- package/vendor/katex/contrib/mhchem.min.js +1 -0
- package/vendor/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/vendor/katex/katex.min.css +1 -0
- package/vendor/katex/katex.min.js +1 -0
- package/vendor/pdfjs/LICENSE +177 -0
- package/vendor/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/78-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/78-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Add-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Add-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
- package/vendor/pdfjs/cmaps/B5-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/B5pc-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/B5pc-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/CNS1-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/CNS1-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/CNS2-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/CNS2-V.bcmap +3 -0
- package/vendor/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
- package/vendor/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Ext-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Ext-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GB-H.bcmap +4 -0
- package/vendor/pdfjs/cmaps/GB-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBT-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBT-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Hankaku.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Hiragana.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Katakana.bcmap +0 -0
- package/vendor/pdfjs/cmaps/LICENSE +36 -0
- package/vendor/pdfjs/cmaps/NWP-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/NWP-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Roman.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
- package/vendor/pdfjs/legacy/build/pdf.min.mjs +27 -0
- package/vendor/pdfjs/legacy/build/pdf.worker.min.mjs +27 -0
- package/vendor/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
- package/vendor/pdfjs/standard_fonts/LICENSE_LIBERATION +363 -0
- package/vendor/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
- package/vendor/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
- package/vendor/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
- package/vendor/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
- package/vendor/types/@types/d3/LICENSE +21 -0
- package/vendor/types/@types/d3/index.d.ts +39 -0
- package/vendor/types/@types/d3/package.json +81 -0
- package/vendor/types/@types/d3-array/LICENSE +21 -0
- package/vendor/types/@types/d3-array/index.d.ts +1118 -0
- package/vendor/types/@types/d3-array/package.json +56 -0
- package/vendor/types/@types/d3-axis/LICENSE +21 -0
- package/vendor/types/@types/d3-axis/index.d.ts +293 -0
- package/vendor/types/@types/d3-axis/package.json +47 -0
- package/vendor/types/@types/d3-brush/LICENSE +21 -0
- package/vendor/types/@types/d3-brush/index.d.ts +255 -0
- package/vendor/types/@types/d3-brush/package.json +42 -0
- package/vendor/types/@types/d3-chord/LICENSE +21 -0
- package/vendor/types/@types/d3-chord/index.d.ts +471 -0
- package/vendor/types/@types/d3-chord/package.json +40 -0
- package/vendor/types/@types/d3-color/LICENSE +21 -0
- package/vendor/types/@types/d3-color/index.d.ts +669 -0
- package/vendor/types/@types/d3-color/package.json +55 -0
- package/vendor/types/@types/d3-contour/LICENSE +21 -0
- package/vendor/types/@types/d3-contour/index.d.ts +222 -0
- package/vendor/types/@types/d3-contour/package.json +38 -0
- package/vendor/types/@types/d3-delaunay/LICENSE +21 -0
- package/vendor/types/@types/d3-delaunay/index.d.ts +316 -0
- package/vendor/types/@types/d3-delaunay/package.json +30 -0
- package/vendor/types/@types/d3-dispatch/LICENSE +21 -0
- package/vendor/types/@types/d3-dispatch/index.d.ts +96 -0
- package/vendor/types/@types/d3-dispatch/package.json +51 -0
- package/vendor/types/@types/d3-drag/LICENSE +21 -0
- package/vendor/types/@types/d3-drag/index.d.ts +395 -0
- package/vendor/types/@types/d3-drag/package.json +42 -0
- package/vendor/types/@types/d3-dsv/LICENSE +21 -0
- package/vendor/types/@types/d3-dsv/index.d.ts +482 -0
- package/vendor/types/@types/d3-dsv/package.json +45 -0
- package/vendor/types/@types/d3-ease/LICENSE +21 -0
- package/vendor/types/@types/d3-ease/index.d.ts +316 -0
- package/vendor/types/@types/d3-ease/package.json +40 -0
- package/vendor/types/@types/d3-fetch/LICENSE +21 -0
- package/vendor/types/@types/d3-fetch/index.d.ts +282 -0
- package/vendor/types/@types/d3-fetch/package.json +37 -0
- package/vendor/types/@types/d3-force/LICENSE +21 -0
- package/vendor/types/@types/d3-force/index.d.ts +899 -0
- package/vendor/types/@types/d3-force/package.json +45 -0
- package/vendor/types/@types/d3-format/LICENSE +21 -0
- package/vendor/types/@types/d3-format/index.d.ts +337 -0
- package/vendor/types/@types/d3-format/package.json +45 -0
- package/vendor/types/@types/d3-geo/LICENSE +21 -0
- package/vendor/types/@types/d3-geo/index.d.ts +1371 -0
- package/vendor/types/@types/d3-geo/package.json +48 -0
- package/vendor/types/@types/d3-hierarchy/LICENSE +21 -0
- package/vendor/types/@types/d3-hierarchy/index.d.ts +928 -0
- package/vendor/types/@types/d3-hierarchy/package.json +50 -0
- package/vendor/types/@types/d3-interpolate/LICENSE +21 -0
- package/vendor/types/@types/d3-interpolate/index.d.ts +387 -0
- package/vendor/types/@types/d3-interpolate/package.json +47 -0
- package/vendor/types/@types/d3-path/LICENSE +21 -0
- package/vendor/types/@types/d3-path/index.d.ts +108 -0
- package/vendor/types/@types/d3-path/package.json +41 -0
- package/vendor/types/@types/d3-polygon/LICENSE +21 -0
- package/vendor/types/@types/d3-polygon/index.d.ts +41 -0
- package/vendor/types/@types/d3-polygon/package.json +40 -0
- package/vendor/types/@types/d3-quadtree/LICENSE +21 -0
- package/vendor/types/@types/d3-quadtree/index.d.ts +204 -0
- package/vendor/types/@types/d3-quadtree/package.json +45 -0
- package/vendor/types/@types/d3-random/LICENSE +21 -0
- package/vendor/types/@types/d3-random/index.d.ts +313 -0
- package/vendor/types/@types/d3-random/package.json +41 -0
- package/vendor/types/@types/d3-scale/LICENSE +21 -0
- package/vendor/types/@types/d3-scale/index.d.ts +2669 -0
- package/vendor/types/@types/d3-scale/package.json +53 -0
- package/vendor/types/@types/d3-scale-chromatic/LICENSE +21 -0
- package/vendor/types/@types/d3-scale-chromatic/index.d.ts +520 -0
- package/vendor/types/@types/d3-scale-chromatic/package.json +46 -0
- package/vendor/types/@types/d3-selection/LICENSE +21 -0
- package/vendor/types/@types/d3-selection/index.d.ts +1210 -0
- package/vendor/types/@types/d3-selection/package.json +56 -0
- package/vendor/types/@types/d3-shape/LICENSE +21 -0
- package/vendor/types/@types/d3-shape/index.d.ts +2792 -0
- package/vendor/types/@types/d3-shape/package.json +53 -0
- package/vendor/types/@types/d3-time/LICENSE +21 -0
- package/vendor/types/@types/d3-time/index.d.ts +697 -0
- package/vendor/types/@types/d3-time/package.json +46 -0
- package/vendor/types/@types/d3-time-format/LICENSE +21 -0
- package/vendor/types/@types/d3-time-format/index.d.ts +202 -0
- package/vendor/types/@types/d3-time-format/package.json +40 -0
- package/vendor/types/@types/d3-timer/LICENSE +21 -0
- package/vendor/types/@types/d3-timer/index.d.ts +68 -0
- package/vendor/types/@types/d3-timer/package.json +45 -0
- package/vendor/types/@types/d3-transition/LICENSE +21 -0
- package/vendor/types/@types/d3-transition/index.d.ts +664 -0
- package/vendor/types/@types/d3-transition/package.json +47 -0
- package/vendor/types/@types/d3-zoom/LICENSE +21 -0
- package/vendor/types/@types/d3-zoom/index.d.ts +611 -0
- package/vendor/types/@types/d3-zoom/package.json +48 -0
- package/vendor/types/@types/geojson/LICENSE +21 -0
- package/vendor/types/@types/geojson/index.d.ts +202 -0
- package/vendor/types/@types/geojson/package.json +46 -0
- package/vendor/typescript/LICENSE.txt +55 -0
- package/vendor/typescript/lib.decorators.d.ts +384 -0
- package/vendor/typescript/lib.decorators.legacy.d.ts +22 -0
- package/vendor/typescript/lib.dom.d.ts +39429 -0
- package/vendor/typescript/lib.dom.iterable.d.ts +571 -0
- package/vendor/typescript/lib.es2015.collection.d.ts +147 -0
- package/vendor/typescript/lib.es2015.core.d.ts +597 -0
- package/vendor/typescript/lib.es2015.d.ts +28 -0
- package/vendor/typescript/lib.es2015.generator.d.ts +77 -0
- package/vendor/typescript/lib.es2015.iterable.d.ts +605 -0
- package/vendor/typescript/lib.es2015.promise.d.ts +81 -0
- package/vendor/typescript/lib.es2015.proxy.d.ts +128 -0
- package/vendor/typescript/lib.es2015.reflect.d.ts +144 -0
- package/vendor/typescript/lib.es2015.symbol.d.ts +46 -0
- package/vendor/typescript/lib.es2015.symbol.wellknown.d.ts +326 -0
- package/vendor/typescript/lib.es2016.array.include.d.ts +116 -0
- package/vendor/typescript/lib.es2016.d.ts +21 -0
- package/vendor/typescript/lib.es2016.intl.d.ts +31 -0
- package/vendor/typescript/lib.es2017.arraybuffer.d.ts +21 -0
- package/vendor/typescript/lib.es2017.d.ts +26 -0
- package/vendor/typescript/lib.es2017.date.d.ts +31 -0
- package/vendor/typescript/lib.es2017.intl.d.ts +44 -0
- package/vendor/typescript/lib.es2017.object.d.ts +49 -0
- package/vendor/typescript/lib.es2017.sharedmemory.d.ts +135 -0
- package/vendor/typescript/lib.es2017.string.d.ts +45 -0
- package/vendor/typescript/lib.es2017.typedarrays.d.ts +53 -0
- package/vendor/typescript/lib.es2018.asyncgenerator.d.ts +77 -0
- package/vendor/typescript/lib.es2018.asynciterable.d.ts +53 -0
- package/vendor/typescript/lib.es2018.d.ts +24 -0
- package/vendor/typescript/lib.es2018.intl.d.ts +83 -0
- package/vendor/typescript/lib.es2018.promise.d.ts +30 -0
- package/vendor/typescript/lib.es2018.regexp.d.ts +37 -0
- package/vendor/typescript/lib.es2019.array.d.ts +79 -0
- package/vendor/typescript/lib.es2019.d.ts +24 -0
- package/vendor/typescript/lib.es2019.intl.d.ts +23 -0
- package/vendor/typescript/lib.es2019.object.d.ts +33 -0
- package/vendor/typescript/lib.es2019.string.d.ts +37 -0
- package/vendor/typescript/lib.es2019.symbol.d.ts +24 -0
- package/vendor/typescript/lib.es2020.bigint.d.ts +765 -0
- package/vendor/typescript/lib.es2020.d.ts +27 -0
- package/vendor/typescript/lib.es2020.date.d.ts +42 -0
- package/vendor/typescript/lib.es2020.intl.d.ts +474 -0
- package/vendor/typescript/lib.es2020.number.d.ts +28 -0
- package/vendor/typescript/lib.es2020.promise.d.ts +47 -0
- package/vendor/typescript/lib.es2020.sharedmemory.d.ts +99 -0
- package/vendor/typescript/lib.es2020.string.d.ts +44 -0
- package/vendor/typescript/lib.es2020.symbol.wellknown.d.ts +41 -0
- package/vendor/typescript/lib.es2021.d.ts +23 -0
- package/vendor/typescript/lib.es2021.intl.d.ts +166 -0
- package/vendor/typescript/lib.es2021.promise.d.ts +48 -0
- package/vendor/typescript/lib.es2021.string.d.ts +33 -0
- package/vendor/typescript/lib.es2021.weakref.d.ts +78 -0
- package/vendor/typescript/lib.es2022.array.d.ts +121 -0
- package/vendor/typescript/lib.es2022.d.ts +25 -0
- package/vendor/typescript/lib.es2022.error.d.ts +75 -0
- package/vendor/typescript/lib.es2022.intl.d.ts +145 -0
- package/vendor/typescript/lib.es2022.object.d.ts +26 -0
- package/vendor/typescript/lib.es2022.regexp.d.ts +39 -0
- package/vendor/typescript/lib.es2022.string.d.ts +25 -0
- package/vendor/typescript/lib.es5.d.ts +4601 -0
- package/vendor/typescript/package.json +4 -0
- package/vendor/typescript/typescript.js +446 -0
- package/web/assets/index-Bh74DfsV.css +1 -0
- package/web/assets/index-UW0RyFFt.js +13 -0
- package/web/index.html +14 -0
|
@@ -0,0 +1,816 @@
|
|
|
1
|
+
import { escapeMarkup, escapeTyped } from "../../../shared/escape.mjs";
|
|
2
|
+
import { mayBePage } from "../../../shared/page-address.mjs";
|
|
3
|
+
import { OUTER, boldThroughout, boxKind, can, holdsAtoms, isEmpty, isFirstLine, isHost, keepLine, nestedLists, newTail, pastedLines, removable, removalTarget, splitBelow, UNIT, textEnd, unitElement } from "../core.mjs";
|
|
4
|
+
import { formulaMaker } from "../formula/index.mjs";
|
|
5
|
+
import { inlineItems, spaceAround } from "../../../shared/inline-spacing.mjs";
|
|
6
|
+
import { caretAt, editable, hostOf, select } from "../caret.mjs";
|
|
7
|
+
import { formatRange, joinMarks, outOfMarks, rangeAt, rangeOffsets } from "../marks.mjs";
|
|
8
|
+
import { BASIC_UNITS, KIND_NAMES, accepts, clipboardOf, takesFormula, texOnly } from "../../components/registry.mjs";
|
|
9
|
+
import { listType } from "../../components/list/index.mjs";
|
|
10
|
+
import { nodeAround } from "../../components/flowchart/index.mjs";
|
|
11
|
+
import { cellsData } from "../../components/table/index.mjs";
|
|
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
|
+
import { bareAddress, externalContent, readExternal } from "./import/read.mjs";
|
|
14
|
+
import { fromMarkdown } from "./import/markdown.mjs";
|
|
15
|
+
import { addressOf } from "../links/address.mjs";
|
|
16
|
+
import { pageObjects, pageOf, typedAsIs } from "../page-objects.mjs";
|
|
17
|
+
import { richHtml, toBlocks } from "./import/to-blocks.mjs";
|
|
18
|
+
import { t } from "../../../shared/i18n/index.mjs";
|
|
19
|
+
|
|
20
|
+
// Copying, cutting and pasting (docs/editor.md, "Copying blocks", "Copying text" and "Pasting"),
|
|
21
|
+
// after notion-lite (Notion 860313). The clipboard's own format is own/ (selected blocks and text
|
|
22
|
+
// described, checked, made again, written for other programs); another program's content is
|
|
23
|
+
// import/ (HTML from web pages, Word, Google Docs, Excel…, Markdown and AI answers' formulas, as
|
|
24
|
+
// Notion reads them).
|
|
25
|
+
//
|
|
26
|
+
// Ctrl+C / Ctrl+X with blocks selected (and no text): the blocks go to the clipboard (and with
|
|
27
|
+
// Ctrl+X out of the page as Delete takes them). A button of the editor's copies its block the same
|
|
28
|
+
// way (copyBlocks: a conflict's card).
|
|
29
|
+
// Ctrl+C / Ctrl+X with text selected in a text block: the text with its marks, no block with it
|
|
30
|
+
// (no list's marker, no heading); with Ctrl+X deleted after. Across blocks (text-select/): its
|
|
31
|
+
// blocks, each of its type, its ends partly (copyAcross).
|
|
32
|
+
// Ctrl+V reads the clipboard in Notion's order: the page's own blocks (or text), else another
|
|
33
|
+
// program's content (import/read.mjs) as blocks, one formatted line, or plain text; picture
|
|
34
|
+
// files (a screenshot) become images, unless they come with Office's or a table's HTML (Excel
|
|
35
|
+
// puts a picture of the cells beside them), right after the block, where blocks pasted there go.
|
|
36
|
+
// With the caret in a text block: one line goes in at the caret, keeping the format bar's marks
|
|
37
|
+
// where the block takes them, its own alone (not the caret's: notion-lite's text pasted) (text
|
|
38
|
+
// copied in a block of the page with its line breaks); blocks
|
|
39
|
+
// split the block at the caret: the first, a paragraph, joins the text before it, the others
|
|
40
|
+
// follow (where the block's box takes them not, the list or quote splits there, its blocks after
|
|
41
|
+
// them going on after them), and the text after the caret joins the last pasted text (else a
|
|
42
|
+
// paragraph of its own); where they go out of a box that stays whole with blocks left in it after
|
|
43
|
+
// the caret, the text stays before those, a block of its own; an empty block gives them its place.
|
|
44
|
+
// In code, plain text with its lines; in a field of plain text (the page's title, a code block's
|
|
45
|
+
// title) the words of what is pasted on one line, whatever it is; in a block that cannot split (a
|
|
46
|
+
// cell, a caption), the lines joined. An address alone (read.mjs bareAddress) is a link in any
|
|
47
|
+
// block that takes links.
|
|
48
|
+
// With blocks selected: the blocks go after them, in the first box out from there that takes them all;
|
|
49
|
+
// and so with the caret on a formula block, which has no text to paste into.
|
|
50
|
+
// One undo step. Images and embeds of an address are filled once on the page (one step with the paste).
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* editing(): whether the page edits. blocks(): the block tools (blocks.mjs: picked, select, remove).
|
|
54
|
+
* struct(parents, touched, mutate) and recordText(host): undoable
|
|
55
|
+
* changes (history.mjs). say: the status line.
|
|
56
|
+
* loadKatex(): KaTeX on the page (true once there), for pasted formulas. mention(parts, same, from): a
|
|
57
|
+
* link shown with its icon pasted, as a chip of the page (`same`: from a copy of this report's own,
|
|
58
|
+
* whose icon files are its own; `from`: the report of the copy, whose blocks a link within it means). linkPasted(link, page): a web address pasted alone (a web page's link
|
|
59
|
+
* copied too), now a link of the text (links/views.mjs offers its views); `page`: what pageLink said
|
|
60
|
+
* of it. pageLink(address): what an address of this computer pasted alone is when it is a document's
|
|
61
|
+
* of the workspace, a page with its `href` (links/ pageLinkOf: the link a file writes, and its title
|
|
62
|
+
* for words), or null. titleBold(): whether bold
|
|
63
|
+
* is armed at the caret (a flowchart node's empty title: format-bar/), so that what is pasted there
|
|
64
|
+
* is bold as what is typed is. showCaret(): the caret in view after text went in (caret.mjs).
|
|
65
|
+
*/
|
|
66
|
+
export function createClipboard({ editing, blocks, struct, recordText, say, loadKatex = async () => Boolean(globalThis.katex), mention: mentionFor = null, linkPasted = () => {}, pageLink = async () => null, titleBold = () => false, showCaret = () => {} }) {
|
|
67
|
+
// ---------- copying ----------
|
|
68
|
+
|
|
69
|
+
// Ctrl+C or Ctrl+X with blocks selected (and no text): the blocks go to the clipboard, and with
|
|
70
|
+
// Ctrl+X out of the page as Delete takes them. A block the page cannot make stops the copy, and one it
|
|
71
|
+
// can make only from its unit on the page (a card) stops the cut.
|
|
72
|
+
function copy(event) {
|
|
73
|
+
const selection = getSelection();
|
|
74
|
+
if (editing() && selection.rangeCount > 0 && !selection.isCollapsed) {
|
|
75
|
+
copyText(event, selection.getRangeAt(0));
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const picked = editing() ? blocks().folds.takenWith(blocks().picked) : []; // a folded heading with what it hides (fold/)
|
|
79
|
+
if (picked.length === 0) return;
|
|
80
|
+
event.preventDefault();
|
|
81
|
+
// A list's item selected on its own carries its list's kind (notion-lite's item is a block of its
|
|
82
|
+
// type): pasted where no list takes it, it is an item of a list of that kind (asLists).
|
|
83
|
+
const described = picked.map((node) => {
|
|
84
|
+
const block = describe(node);
|
|
85
|
+
return block?.type === "item" && /^[uo]l$/.test(node.parentElement?.localName ?? "") ? { ...block, list: listType(node.parentElement) } : block;
|
|
86
|
+
});
|
|
87
|
+
const refused = picked.find((_, index) => !described[index]);
|
|
88
|
+
if (refused) {
|
|
89
|
+
say(refusalOf(unmade(refused)), "note", 6000); // the block in it the page cannot make, as a selection across blocks says it
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
// A cut takes the blocks off the page, where a card's copy is of its unit: what is made only of its unit is refused, not lost.
|
|
93
|
+
const kept = event.type === "cut" ? unmadeCopy(null, described) : null;
|
|
94
|
+
if (kept) {
|
|
95
|
+
say(t("选中的块里有{0}:它剪切之后就没法再粘贴了,所以不能剪切;可以复制它,或者拖动它来移动。", KIND_NAMES[kept.kind] ?? t("组件")), "note", 6000);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
write(event.clipboardData, { blocks: described }, formats(described));
|
|
99
|
+
if (event.type === "cut") blocks().remove(picked);
|
|
100
|
+
else say(t("已复制 {0} · 在要放的块里按 Ctrl+V 粘贴到它后面", picked.length > 1 ? t("{0} 块", picked.length) : t("这一块")));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* `nodes`, blocks of the page, to the clipboard as Ctrl+C copies them selected, where no copy event
|
|
105
|
+
* of the page's asks (a button of the editor's: a conflict's card): by the browser's copy command,
|
|
106
|
+
* whose event this answers before the page's own does. Returns whether they went.
|
|
107
|
+
*/
|
|
108
|
+
function copyBlocks(nodes) {
|
|
109
|
+
const described = nodes.map(describe);
|
|
110
|
+
if (described.length === 0 || !described.every(Boolean)) return false;
|
|
111
|
+
let done = false;
|
|
112
|
+
const answer = (event) => {
|
|
113
|
+
event.stopImmediatePropagation();
|
|
114
|
+
event.preventDefault();
|
|
115
|
+
write(event.clipboardData, { blocks: described }, formats(described));
|
|
116
|
+
done = true;
|
|
117
|
+
};
|
|
118
|
+
window.addEventListener("copy", answer, { capture: true, once: true });
|
|
119
|
+
try {
|
|
120
|
+
document.execCommand("copy");
|
|
121
|
+
} finally {
|
|
122
|
+
window.removeEventListener("copy", answer, true);
|
|
123
|
+
}
|
|
124
|
+
if (done) say(t("已复制 {0} · 在要放的块里按 Ctrl+V 粘贴到它后面", nodes.length > 1 ? t("{0} 块", nodes.length) : t("这一块")));
|
|
125
|
+
return done;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Why a block the page cannot make (describe gives none) is not copied: one not saved yet, or a
|
|
129
|
+
// block of the report's own (a whole block, a widget), the Agent's to copy.
|
|
130
|
+
const refusalOf = (node) => (node.hasAttribute("data-ge-new") ? t("选中的块还没保存,保存之后再复制。")
|
|
131
|
+
: t("选中的块里有{0}:文档自己的组件不能在页面上复制,可以让 AI 复制。", KIND_NAMES[node.getAttribute("data-ge-unit-kind")] ?? t("组件")));
|
|
132
|
+
|
|
133
|
+
// The block in `unit` (it, or the innermost of the blocks it holds) the page cannot make, or null.
|
|
134
|
+
const unmade = (unit) => {
|
|
135
|
+
if (describe(unit)) return null;
|
|
136
|
+
const inner = [...unit.querySelectorAll(UNIT)].find((node) => !describe(node));
|
|
137
|
+
return inner ? unmade(inner) : unit;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// The clipboard's own data (`own`: { blocks } | { html }) and what other programs read of it.
|
|
141
|
+
const write = (data, own, { html, text }) => {
|
|
142
|
+
const payload = JSON.stringify({ v: 1, report: reportOf(document), ...own });
|
|
143
|
+
data.setData(MIME, payload);
|
|
144
|
+
data.setData(OLD_MIME, payload); // a page of the old version (before 2026-10-26) reads this one
|
|
145
|
+
data.setData("text/html", html);
|
|
146
|
+
data.setData("text/plain", text);
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// Text selected in one text block (notion-lite's text of one text area): its inline HTML, the
|
|
150
|
+
// format bar's marks and the chips, as the clipboard's own data, as HTML and as its plain text for
|
|
151
|
+
// other programs; no type of block goes with it (a list item's marker, a heading's size). A cut
|
|
152
|
+
// deletes it after, as typing would (one step). One ending at the start of a block an item holds
|
|
153
|
+
// (a triple click's in such an item) is the item's text; one holding some of that block (an
|
|
154
|
+
// item's text and a block it holds) is the browser's.
|
|
155
|
+
function copyText(event, range) {
|
|
156
|
+
const host = editable(range.startContainer);
|
|
157
|
+
if (!host?.closest("main") || !(editable(range.endContainer) === host || endsAtHeld(host, range))) return;
|
|
158
|
+
const part = ownRange(host, range);
|
|
159
|
+
if (part.collapsed) return;
|
|
160
|
+
event.preventDefault();
|
|
161
|
+
const html = selectedHtml(host, part);
|
|
162
|
+
write(event.clipboardData, { html }, textFormats(html));
|
|
163
|
+
if (event.type !== "cut") return;
|
|
164
|
+
select(part);
|
|
165
|
+
document.execCommand("delete");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Whether `range` from `host`'s text ends in a block the host holds with nothing of it selected
|
|
169
|
+
// (its end at that block's start: no text, no picture, no formula).
|
|
170
|
+
function endsAtHeld(host, range) {
|
|
171
|
+
if (!host.contains(range.endContainer)) return false;
|
|
172
|
+
const beyond = document.createRange();
|
|
173
|
+
beyond.setStart(host, textEnd(host));
|
|
174
|
+
beyond.setEnd(range.endContainer, range.endOffset);
|
|
175
|
+
if (beyond.collapsed) return false;
|
|
176
|
+
const held = beyond.cloneContents();
|
|
177
|
+
return held.textContent.trim() === "" && !held.querySelector("img, svg, video, iframe, hr, [data-ge-atom]");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* A selection across blocks copied (text-select/: `range` the selection, `pieces` its texts and the
|
|
182
|
+
* blocks it takes whole) to `data`: its blocks, each of its type, the first from where it starts and
|
|
183
|
+
* the last up to where it ends (own/ describeAcross, notion-lite's segmentSpecs). A cut holding a
|
|
184
|
+
* card's copy is refused as a cut of blocks is, and so is one taking whole a block the page cannot
|
|
185
|
+
* make (a whole block: its copy is its words, which would put no block of it back): nothing goes,
|
|
186
|
+
* as for blocks selected. Returns whether it went to the clipboard.
|
|
187
|
+
*/
|
|
188
|
+
function copyAcross(data, range, pieces, cut) {
|
|
189
|
+
const lost = cut ? pieces.wholes.map(unmade).find(Boolean) : null;
|
|
190
|
+
if (lost) {
|
|
191
|
+
say(refusalOf(lost), "note", 6000);
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
const described = describeAcross(range, pieces);
|
|
195
|
+
if (described.length === 0) return false;
|
|
196
|
+
const kept = cut ? unmadeCopy(null, described) : null;
|
|
197
|
+
if (kept) {
|
|
198
|
+
say(t("选中的块里有{0}:它剪切之后就没法再粘贴了,所以不能剪切;可以复制它,或者拖动它来移动。", KIND_NAMES[kept.kind] ?? t("组件")), "note", 6000);
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
write(data, { blocks: described }, formats(described));
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// ---------- what is pasted ----------
|
|
206
|
+
|
|
207
|
+
// The clipboard as { kind: "blocks", blocks } | { kind: "rich", html } | { kind: "plain", text }:
|
|
208
|
+
// the page's own blocks first (or its text copied in a block), then another program's content
|
|
209
|
+
// (import/). `own`: the page's own; `same`: of this report.
|
|
210
|
+
function read(data) {
|
|
211
|
+
const own = ownData(data);
|
|
212
|
+
const mine = own ? parse(own) : null;
|
|
213
|
+
if (mine) return { kind: "blocks", blocks: mine, own: true, ...origin(own) };
|
|
214
|
+
const text = own ? parseText(own) : null;
|
|
215
|
+
if (text !== null) return { kind: "rich", html: text, own: true, ...origin(own) };
|
|
216
|
+
// Cells of a table of the page (its tools' copy): one cell its text, as its words copied in it
|
|
217
|
+
// are (its HTML, a table of one cell, the import unwraps with a divider after it); more a table
|
|
218
|
+
// of them as they were, not as another program's table comes in (made over: a header row, its
|
|
219
|
+
// numbers read).
|
|
220
|
+
const cells = parseCells(cellsData(data) || "null");
|
|
221
|
+
if (cells?.length === 1 && cells[0].length === 1) return { kind: "rich", html: cells[0][0], own: true };
|
|
222
|
+
const table = cells ? checkBlocks([{ type: "table", rows: cells }]) : null;
|
|
223
|
+
if (table) return { kind: "blocks", blocks: table, own: true };
|
|
224
|
+
// Text of this page copied by the browser (a selection in a block): one line holding the page's
|
|
225
|
+
// chips (a formula, a link shown with its icon, one left empty) is its text again, each chip as
|
|
226
|
+
// it was (pastedLines), not what another program's HTML would make of it.
|
|
227
|
+
const html = data.getData("text/html");
|
|
228
|
+
if (html && !/\n/.test((data.getData("text/plain") || "").trim()) && holdsAtoms(document, html)) return { kind: "rich", html };
|
|
229
|
+
const external = readExternal(data);
|
|
230
|
+
if (external.kind === "rich") return { kind: "rich", html: richHtml(external.title) };
|
|
231
|
+
if (external.kind === "plain") return external;
|
|
232
|
+
// Made as blocks the page takes (not checked as the clipboard's own data is): none is refused for
|
|
233
|
+
// another's sake, however many there are.
|
|
234
|
+
const made = toBlocks(external.specs, null, HELD);
|
|
235
|
+
return made.length > 0 ? { kind: "blocks", blocks: made } : { kind: "plain", text: data.getData("text/plain") };
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// The report the clipboard's own data was copied from (`from`), and whether that is this one (`same`:
|
|
239
|
+
// their links' icons its files).
|
|
240
|
+
const origin = (own) => {
|
|
241
|
+
try {
|
|
242
|
+
const from = JSON.parse(own)?.report ?? null;
|
|
243
|
+
return { from, same: from === reportOf(document) };
|
|
244
|
+
} catch {
|
|
245
|
+
return { from: null, same: false };
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// Links shown with their icon pasted as the page's own (mentionFor).
|
|
250
|
+
let mention = null;
|
|
251
|
+
|
|
252
|
+
// Inline formulas pasted as the page's own (KaTeX loaded: formula/ formulaMaker).
|
|
253
|
+
let formula = null;
|
|
254
|
+
|
|
255
|
+
// Images and embeds pasted with an address: filled now they are on the page.
|
|
256
|
+
const fillMedia = (made) => {
|
|
257
|
+
for (const figure of made.flatMap((node) => [node, ...node.querySelectorAll(`[${PASTED_SOURCE}]`)]).filter((node) => node.hasAttribute?.(PASTED_SOURCE))) {
|
|
258
|
+
const src = figure.getAttribute(PASTED_SOURCE);
|
|
259
|
+
figure.removeAttribute(PASTED_SOURCE);
|
|
260
|
+
pageOf(figure)?.fromLink?.(figure, src, { pasted: true }); // the selection left as it is
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
// Files pasted by `at`: a block for the first of them the first component takes, in the order of the
|
|
265
|
+
// page objects (`acceptsFile`, `fromFiles`: notion-lite's fileBlockDef; a picture an image, any other
|
|
266
|
+
// file a file block). Where it goes is the paste's (notion-lite's pasteFiles, moveBlocks(ids, { parent:
|
|
267
|
+
// anchor.parent, after })): right after the block of `at` (unitElement: a new code block's code stands
|
|
268
|
+
// for the block), whole, where a block pasted there goes (placeFor: the first box out that takes it, a
|
|
269
|
+
// list or quote that does not splitting after the block), one undo step (`put`, handed to the
|
|
270
|
+
// component, which makes the block and fills it). Returns whether one did.
|
|
271
|
+
const fromFiles = (at, files) => {
|
|
272
|
+
const unit = unitElement(at);
|
|
273
|
+
if (!unit?.closest("main")) return false;
|
|
274
|
+
const put = (block) => {
|
|
275
|
+
const place = placeFor(unit, [block.getAttribute("data-ge-unit-kind")]);
|
|
276
|
+
if (!place) {
|
|
277
|
+
say(t("这里放不下这种块。"));
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
struct(place.parents, [], () => ({ touched: [], focus: null, created: placeAfter(place, [block]) }));
|
|
281
|
+
return true;
|
|
282
|
+
};
|
|
283
|
+
return pageObjects().some((page) => {
|
|
284
|
+
const file = page.acceptsFile && [...files].find(page.acceptsFile);
|
|
285
|
+
return Boolean(file) && page.fromFiles(put, [file]);
|
|
286
|
+
});
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
// ---------- blocks into the page ----------
|
|
290
|
+
|
|
291
|
+
// Out from `anchor`, the first box that takes every one of `kinds`: { anchor (the block they go
|
|
292
|
+
// after), box, parents (the boxes involved), splits ([container, its blocks after the anchor]:
|
|
293
|
+
// a list or quote that does not take them splits there, unless they leave a box around it, which
|
|
294
|
+
// keeps what it holds), stays (they leave a box with blocks in it after the anchor) }, or null. A
|
|
295
|
+
// list item holding blocks is such a box too (notion-lite's children of an item: blocks pasted by
|
|
296
|
+
// one of them stay in the item).
|
|
297
|
+
function placeFor(anchor, kinds) {
|
|
298
|
+
const takes = (box) => box?.hasAttribute("data-ge-box") && kinds.every((kind) => accepts(box.getAttribute("data-ge-box-kind"), kind));
|
|
299
|
+
const parents = [];
|
|
300
|
+
let splits = [];
|
|
301
|
+
let stays = false;
|
|
302
|
+
let box = anchor.parentElement;
|
|
303
|
+
while (!takes(box)) {
|
|
304
|
+
// A container made on the page and not written yet (a list just made of "- ", whose
|
|
305
|
+
// contenteditable OUTER passes over) is the block around what it holds, as the file's is.
|
|
306
|
+
const outer = box?.closest(`${OUTER}, [data-ge-new][data-ge-box]`);
|
|
307
|
+
if (!outer?.closest("main")) return null;
|
|
308
|
+
parents.push(box);
|
|
309
|
+
// A list or a quote whose box does not take them splits after the anchor.
|
|
310
|
+
const after = [];
|
|
311
|
+
for (let next = anchor.nextElementSibling; next; next = next.nextElementSibling) after.push(next);
|
|
312
|
+
if (box === outer && (outer.localName === "ul" || outer.localName === "ol" || outer.localName === "blockquote")) {
|
|
313
|
+
if (after.length) splits.push([outer, after]);
|
|
314
|
+
} else if (boxKind(box) !== "nest" || after.length) {
|
|
315
|
+
stays ||= after.length > 0 || splits.length > 0;
|
|
316
|
+
splits = [];
|
|
317
|
+
}
|
|
318
|
+
anchor = outer;
|
|
319
|
+
box = outer.parentElement;
|
|
320
|
+
}
|
|
321
|
+
parents.push(box);
|
|
322
|
+
return { anchor, box, parents, splits, stays };
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// The blocks to make of `list` where they go after `anchor`: as they are, unless items copied on
|
|
326
|
+
// their own (a list's items selected, `list`: their list's kind) go where the box does not take
|
|
327
|
+
// them all, or into a list of another kind; then each run of items of one kind is a list of that
|
|
328
|
+
// kind (notion-lite's item is a block of its type wherever it is pasted: a disclosure's content, a
|
|
329
|
+
// highlight block, a column…; in a list of another kind, the list splits around them). A flowchart's
|
|
330
|
+
// nodes copied on their own are a flowchart of their own the same way, but by a block of a node,
|
|
331
|
+
// where they go after that node in its flowchart as they are (nodes never nest: placeFor finds it).
|
|
332
|
+
function asLists(anchor, list) {
|
|
333
|
+
if (list.every((block) => block.type === "step") && nodeAround(anchor)) return list;
|
|
334
|
+
const parent = anchor.parentElement;
|
|
335
|
+
const box = parent?.getAttribute("data-ge-box-kind");
|
|
336
|
+
const own = parent?.localName === "ul" || parent?.localName === "ol" ? listType(parent) : null;
|
|
337
|
+
const takes = (block) => accepts(box, kindOfBlock(block)) && !(block.type === "item" && own && block.list && block.list !== own);
|
|
338
|
+
return !list.some((block) => clipboardOf(block.type).run) || list.every(takes) ? list : groupItems(list);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// The blocks after `anchor` (in the first box out that takes them), the containers that split
|
|
342
|
+
// there going on after them. Returns the containers made by splitting.
|
|
343
|
+
function placeAfter(place, made) {
|
|
344
|
+
const { anchor, splits } = place;
|
|
345
|
+
anchor.after(...made);
|
|
346
|
+
const created = [];
|
|
347
|
+
let last = made.at(-1);
|
|
348
|
+
for (const [container, after] of splits) {
|
|
349
|
+
const next = newTail(container, container.localName === "blockquote" ? "quote" : listType(container));
|
|
350
|
+
next.append(...after);
|
|
351
|
+
last.after(next);
|
|
352
|
+
created.push(next);
|
|
353
|
+
last = next;
|
|
354
|
+
}
|
|
355
|
+
return created;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// The text block a paste's last text goes on in: the last of a block of text (itself, the blocks a
|
|
359
|
+
// list, a quote, a flowchart or a node holds) that is a block of its own, no part of one, and whose
|
|
360
|
+
// text may be any text (no `plain` one, whose text is code or a formula's TeX alone). What a
|
|
361
|
+
// container or a card holds stays its own.
|
|
362
|
+
const lastLine = (node) => (BASIC_UNITS.has(node.getAttribute("data-ge-unit-kind"))
|
|
363
|
+
? textsOf([node]).filter((text) => unitElement(text) === text && !can(text, "plain") && !heldApart(text, node)).at(-1) ?? null : null);
|
|
364
|
+
|
|
365
|
+
// Whether a text block in the block `node` is in a container or a card `node` holds.
|
|
366
|
+
const heldApart = (text, node) => {
|
|
367
|
+
for (let at = text; at !== node; at = at.parentElement) {
|
|
368
|
+
if (at.hasAttribute("data-ge-unit-kind") && !BASIC_UNITS.has(at.getAttribute("data-ge-unit-kind"))) return true;
|
|
369
|
+
}
|
|
370
|
+
return false;
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
// The place of `made` (of `kinds`) at a caret in `unit`: the first box out that takes them and, when
|
|
374
|
+
// the last of them has no text block for what stands after the caret, the paragraph of its own that is.
|
|
375
|
+
const placeAtCaret = (unit, made, kinds) => placeFor(unit, lastLine(made.at(-1)) ? kinds : [...kinds, kindOfBlock(TAIL)]);
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* The one step the two ways in share (notion-lite commands/paste.js pasteBlocks): the text block
|
|
379
|
+
* `host` is split at `range`, `made` (blocks of the page's own making) stand after it in `place`
|
|
380
|
+
* (placeFor), and the text after the caret goes on where `tail` says: "join", in the last of
|
|
381
|
+
* `made` that holds text, the caret between them (else in a paragraph of its own, the caret at its
|
|
382
|
+
* start); "paragraph", in a paragraph of its own with the spaces at the ends of the cut taken off, the
|
|
383
|
+
* caret at its start. Where `made` leaves blocks after the caret in a box that stays whole
|
|
384
|
+
* (`place.stays`), it stays before them, a block of its own below the text before the caret, and the
|
|
385
|
+
* caret goes by `made`. `first`: the lines of a paste's first block, which join the text before the
|
|
386
|
+
* caret; `replace`: the host is empty and goes in the place of `made` (else it goes when the step
|
|
387
|
+
* leaves it empty and `tail` is "paragraph"); `bold`: the lines of `first` made bold (a node's
|
|
388
|
+
* title: titled). One undo step. Returns { placed (`made` and the
|
|
389
|
+
* paragraph the tail went to), caret }, or null when nothing was done.
|
|
390
|
+
*/
|
|
391
|
+
function splitAndPlace(host, range, place, made, { tail, first = null, replace = false, bold = false }) {
|
|
392
|
+
const unit = unitElement(host);
|
|
393
|
+
const placed = [...made];
|
|
394
|
+
let caret = null;
|
|
395
|
+
const stays = place.stays && !replace;
|
|
396
|
+
const result = struct([...new Set([host.parentElement, ...place.parents, ...(stays ? [host, ...nestedLists(host).slice(0, 1)] : [])])], [host], () => {
|
|
397
|
+
// The text after the caret, and what joins before it.
|
|
398
|
+
const cut = cutAtCaret(host, range);
|
|
399
|
+
// With no text before it for it to stand apart from, it stays where it is.
|
|
400
|
+
const stayed = stays && holdsWords(cut) && (first || holdsWords(before(host, cut)));
|
|
401
|
+
const title = stayed && isFirstLine(host) && boldThroughout(host);
|
|
402
|
+
const rest = replace || (stays && !stayed) ? null : cut.extractContents();
|
|
403
|
+
if (tail === "paragraph") trimText(host, true);
|
|
404
|
+
if (first) {
|
|
405
|
+
const holder = document.createElement("div");
|
|
406
|
+
holder.append(...pastedLines(document, first.html, { formula, mention }).flatMap((line, index) => (index > 0 ? [document.createElement("br"), ...line] : line)));
|
|
407
|
+
outOfMarks(host, range).insertNode(holder); // its own marks alone, as at a caret
|
|
408
|
+
const lines = [...holder.childNodes];
|
|
409
|
+
holder.replaceWith(...lines);
|
|
410
|
+
if (lines.length && bold) { // a node's title: bold, as typed there (titled)
|
|
411
|
+
const all = document.createRange();
|
|
412
|
+
all.setStartBefore(lines[0]);
|
|
413
|
+
all.setEndAfter(lines.at(-1));
|
|
414
|
+
formatRange(host, all, "bold", true);
|
|
415
|
+
} else if (lines.length) joinBeside(lines[0], lines.at(-1));
|
|
416
|
+
spaceItems(host); // the pasted code and formulas beside the text they joined
|
|
417
|
+
}
|
|
418
|
+
const created = made.length ? placeAfter(place, made) : [];
|
|
419
|
+
const below = stayed ? splitBelow(host, rest, title) : null;
|
|
420
|
+
if (below && below.parentElement.parentElement === host && below.parentElement.hasAttribute("data-ge-new")) created.push(below.parentElement);
|
|
421
|
+
const text = !below && Boolean(rest?.textContent?.trim() || rest?.querySelector?.("[data-ge-atom]"));
|
|
422
|
+
// Where the text after the caret goes on.
|
|
423
|
+
let target = tail === "join" ? (made.length ? lastLine(made.at(-1)) : host) : null;
|
|
424
|
+
if (target) caret = text ? goesOn(target, rest) : { host: target, end: true };
|
|
425
|
+
else if (below) caret = { host: below, start: true };
|
|
426
|
+
else if (text) {
|
|
427
|
+
target = build(document, TAIL);
|
|
428
|
+
if (tail === "paragraph") {
|
|
429
|
+
target.append(rest);
|
|
430
|
+
trimText(target, false);
|
|
431
|
+
caret = { host: target, start: true };
|
|
432
|
+
} else caret = goesOn(target, rest);
|
|
433
|
+
made.at(-1).after(target); // before a list or quote split there
|
|
434
|
+
placed.push(target);
|
|
435
|
+
}
|
|
436
|
+
const gone = replace || (tail === "paragraph" && removableEmpty(host, unit));
|
|
437
|
+
if (gone) removalTarget(host).remove();
|
|
438
|
+
else keepLine(host); // an item left with no text over what it holds
|
|
439
|
+
return { touched: [...new Set([...(gone ? [] : [host]), ...textsOf(placed), ...(below ? [below] : [])])], focus: caret?.host ?? null, select: tail === "join" ? placed : made, created, caret };
|
|
440
|
+
});
|
|
441
|
+
return result ? { placed, caret } : null;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// The text after the caret (`rest`) on at the end of `target`'s own text, before the blocks an item
|
|
445
|
+
// holds, the caret between the two.
|
|
446
|
+
function goesOn(target, rest) {
|
|
447
|
+
const marker = document.createTextNode("");
|
|
448
|
+
const end = target.childNodes[textEndOf(target)] ?? null;
|
|
449
|
+
target.insertBefore(marker, end);
|
|
450
|
+
target.insertBefore(rest, end);
|
|
451
|
+
spaceItems(target);
|
|
452
|
+
return { host: target, marker };
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// The caret as splitAndPlace left it (`caret`: { host, end } | { host, marker } | { host, start }),
|
|
456
|
+
// else `placed` selected as blocks.
|
|
457
|
+
function restoreCaret(caret, placed) {
|
|
458
|
+
if (caret?.marker) {
|
|
459
|
+
caret.host.focus({ preventScroll: true });
|
|
460
|
+
const at = document.createRange();
|
|
461
|
+
at.setStartBefore(caret.marker);
|
|
462
|
+
at.collapse(true);
|
|
463
|
+
caret.marker.remove();
|
|
464
|
+
select(at);
|
|
465
|
+
} else if (caret) caretAt(caret.host, caret.start ? "start" : "end");
|
|
466
|
+
else blocks().select(placed, { quiet: true });
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Blocks pasted at the caret in `host` (`range` there; notion-lite commands/paste.js). Returns
|
|
471
|
+
* whether it took them.
|
|
472
|
+
*/
|
|
473
|
+
function pasteIntoText(host, range, list, bold = false) {
|
|
474
|
+
const unit = unitElement(host);
|
|
475
|
+
if (!unit?.closest("main")) return false;
|
|
476
|
+
// A node's title, however empty, stays (nothing goes before it in its node): its first paragraph
|
|
477
|
+
// joins it, the others go after it. What is selected goes first, so a block all of it selected
|
|
478
|
+
// is as an empty one (notion-lite's pasteBlocks).
|
|
479
|
+
const replace = host === unit && removable(host) && emptiedBy(host, range) && !isFirstLine(host);
|
|
480
|
+
const [first, ...rest] = list;
|
|
481
|
+
const joins = !replace && first.type === "paragraph" && !first.color;
|
|
482
|
+
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
|
|
485
|
+
prefixCopies(document, made); // a copy's drawing names its own markers
|
|
486
|
+
const place = made.length ? placeAtCaret(unit, made, placed.map(kindOfBlock)) : { anchor: unit, box: unit.parentElement, parents: [unit.parentElement], splits: [] };
|
|
487
|
+
if (!place) {
|
|
488
|
+
say(t("这里放不下这些块。"));
|
|
489
|
+
return true;
|
|
490
|
+
}
|
|
491
|
+
const done = splitAndPlace(host, range, place, made, { tail: "join", first: joins ? first : null, replace, bold });
|
|
492
|
+
if (!done) return true;
|
|
493
|
+
restoreCaret(done.caret, done.placed);
|
|
494
|
+
(done.caret?.host ?? done.placed.at(-1))?.scrollIntoView?.({ block: "nearest" });
|
|
495
|
+
fillMedia(done.placed);
|
|
496
|
+
say(t("已粘贴 {0} · Ctrl+Z 撤销", list.length > 1 ? t("{0} 块", list.length) : t("一块")));
|
|
497
|
+
return true;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// Spaces at the end of a text block's own text, or at its start, taken off.
|
|
501
|
+
const trimText = (host, end) => {
|
|
502
|
+
const node = end ? host.childNodes[textEndOf(host) - 1] : host.firstChild;
|
|
503
|
+
if (node?.nodeType === 3) node.data = end ? node.data.replace(/[ ]+$/, "") : node.data.replace(/^[ ]+/, "");
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Blocks made elsewhere (`made`, of `kinds`) in the place of `range` in `host` (links/views.mjs: a
|
|
508
|
+
* link turned into a bookmark, Feishu's linkToBookmark): the text before it stays in the block, the
|
|
509
|
+
* text after it goes on in a paragraph after them, and a block left empty goes; a list or a quote
|
|
510
|
+
* that does not take them splits there, as for a paste. One undo step, the caret at the start of
|
|
511
|
+
* the text after them, else they are selected. Returns whether they went in.
|
|
512
|
+
*/
|
|
513
|
+
function blocksAt(host, range, made, kinds) {
|
|
514
|
+
const unit = unitElement(host);
|
|
515
|
+
const place = unit?.closest("main") ? placeFor(unit, [...kinds, kindOfBlock(TAIL)]) : null;
|
|
516
|
+
if (!place) {
|
|
517
|
+
say(t("这里放不下这种块。"));
|
|
518
|
+
return false;
|
|
519
|
+
}
|
|
520
|
+
const done = splitAndPlace(host, range, place, made, { tail: "paragraph" });
|
|
521
|
+
if (!done) return false;
|
|
522
|
+
restoreCaret(done.caret, made);
|
|
523
|
+
return true;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// Blocks pasted with blocks selected: after them, in the first box out that takes them all; the
|
|
527
|
+
// new blocks selected.
|
|
528
|
+
function pasteAfter(anchor, pasted) {
|
|
529
|
+
if (!anchor?.closest("main")) {
|
|
530
|
+
say(t("这里不能粘贴块。"));
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
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
|
|
536
|
+
prefixCopies(document, made); // a copy's drawing names its own markers
|
|
537
|
+
const place = placeFor(anchor, list.map(kindOfBlock));
|
|
538
|
+
if (!place) {
|
|
539
|
+
say(t("这里放不下这些块。"));
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
struct(place.parents, [], () => {
|
|
543
|
+
const created = placeAfter(place, made);
|
|
544
|
+
const texts = textsOf(made);
|
|
545
|
+
return { touched: texts, focus: null, select: made, created };
|
|
546
|
+
});
|
|
547
|
+
blocks().select(made, { quiet: true });
|
|
548
|
+
fillMedia(made);
|
|
549
|
+
say(t("已粘贴 {0} · Ctrl+Z 撤销", pasted.length > 1 ? t("{0} 块", pasted.length) : t("一块")));
|
|
550
|
+
return made;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// ---------- text into a text block ----------
|
|
554
|
+
|
|
555
|
+
const caretAfter = (node) => {
|
|
556
|
+
const after = document.createRange();
|
|
557
|
+
if (node.nodeType === 3) after.setStart(node, node.length);
|
|
558
|
+
else after.setStartAfter(node);
|
|
559
|
+
after.collapse(true);
|
|
560
|
+
select(after);
|
|
561
|
+
};
|
|
562
|
+
|
|
563
|
+
// Inline code and formulas in `root` stand a space apart from the words beside them, which a paste
|
|
564
|
+
// joined them to (shared/inline-spacing.mjs). Returns the space put after `end`, where it is one of them.
|
|
565
|
+
function spaceItems(root, end = null) {
|
|
566
|
+
let trailing = null;
|
|
567
|
+
for (const item of inlineItems(root)) {
|
|
568
|
+
const { after } = spaceAround(item);
|
|
569
|
+
if (item === end) trailing = after;
|
|
570
|
+
}
|
|
571
|
+
return trailing;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// Nodes in at the caret, in place of what is selected; one text step. The caret goes after them,
|
|
575
|
+
// past the space put between a last piece of code or formula and the text that follows it. With
|
|
576
|
+
// `own` they carry their own marks alone (pasted HTML: notion-lite's text pasted keeps its own),
|
|
577
|
+
// the marks around the caret split there and (`join`) a mark beside one the same made one with it;
|
|
578
|
+
// else (plain text) they take the caret's marks, as typing does. `bold`: made bold, the caret at
|
|
579
|
+
// their end inside the bold (a flowchart node's title: titled), as text typed there is.
|
|
580
|
+
function insertNodes(host, range, nodes, { own = false, join = own, bold = false } = {}) {
|
|
581
|
+
if (nodes.length === 0) return;
|
|
582
|
+
range.deleteContents();
|
|
583
|
+
const at = own ? outOfMarks(host, range) : range;
|
|
584
|
+
const fragment = document.createDocumentFragment();
|
|
585
|
+
fragment.append(...nodes);
|
|
586
|
+
const last = nodes.at(-1);
|
|
587
|
+
at.insertNode(fragment);
|
|
588
|
+
if (bold) {
|
|
589
|
+
const all = document.createRange();
|
|
590
|
+
all.setStartBefore(nodes[0]);
|
|
591
|
+
all.setEndAfter(last);
|
|
592
|
+
const covered = formatRange(host, all, "bold", true);
|
|
593
|
+
spaceItems(host);
|
|
594
|
+
covered.collapse(false);
|
|
595
|
+
select(covered);
|
|
596
|
+
recordText(host);
|
|
597
|
+
showCaret();
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
caretAfter(spaceItems(host, last) ?? last);
|
|
601
|
+
if (join) {
|
|
602
|
+
const selection = getSelection();
|
|
603
|
+
const caret = selection.rangeCount ? rangeOffsets(host, selection.getRangeAt(0)) : null;
|
|
604
|
+
if (joinBeside(nodes[0], last) && caret) select(rangeAt(host, caret));
|
|
605
|
+
}
|
|
606
|
+
recordText(host);
|
|
607
|
+
showCaret();
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// The marks at either end of pasted nodes (`first` to `last`) made one with the same mark beside
|
|
611
|
+
// them (bold pasted by bold). Returns whether any were.
|
|
612
|
+
function joinBeside(first, last) {
|
|
613
|
+
const before = joinMarks(first.previousSibling, first);
|
|
614
|
+
const end = last.isConnected ? last : before;
|
|
615
|
+
return Boolean(joinMarks(end, end?.nextSibling) || before);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// One formatted line at the caret: the format bar's marks the block takes. Text copied in a block
|
|
619
|
+
// of the page keeps its line breaks (`breaks`, as notion-lite's text keeps its "\n").
|
|
620
|
+
function pasteRich(host, range, html, breaks = false, bold = false) {
|
|
621
|
+
const lines = pastedLines(document, html, { links: can(host, "links"), formula, mention });
|
|
622
|
+
insertNodes(host, range, lines.flatMap((line, index) => (index > 0 ? [breaks ? document.createElement("br") : document.createTextNode(" "), ...line] : line)), { own: true, bold });
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// Into a block that cannot split (a cell, a title): the lines of what is pasted, joined, with the
|
|
626
|
+
// marks the block takes: what read() made of it (a formatted line, or its blocks' text: no list's
|
|
627
|
+
// marker, no Markdown), of the page's own blocks as of another program's.
|
|
628
|
+
function pasteJoined(host, range, content, data) {
|
|
629
|
+
const html = content.kind === "rich" ? content.html : content.kind === "blocks" ? joinedHtml(content.blocks) : "";
|
|
630
|
+
// The page's own blocks with no words have none here: their Markdown is for other programs.
|
|
631
|
+
const raw = content.own ? "" : (data.getData("text/plain") || "").replace(/\r\n?/g, "\n");
|
|
632
|
+
const rich = html && !can(host, "plain") ? pastedLines(document, html, { links: can(host, "links"), formula, formulas: takesFormula(host), mention }) : [];
|
|
633
|
+
const lines = rich.length > 0 ? rich : raw.split("\n").map((line) => line.replace(/\s+/g, " ").trim()).filter(Boolean);
|
|
634
|
+
const nodes = rich.length > 0 ? rich.flatMap((line, index) => (index > 0 ? [document.createTextNode(" "), ...line] : line)) : [document.createTextNode(lines.length > 1 ? lines.join(" ") : raw)];
|
|
635
|
+
if (nodes.length === 1 && nodes[0].nodeType === 3 && !nodes[0].data) return;
|
|
636
|
+
insertNodes(host, range, nodes, { own: rich.length > 0 });
|
|
637
|
+
if (lines.length > 1) say(t("这里不能分段,多行文字已合并为一行。"));
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// ---------- the paste ----------
|
|
641
|
+
|
|
642
|
+
async function paste(event) {
|
|
643
|
+
if (!editing()) return;
|
|
644
|
+
const data = event.clipboardData;
|
|
645
|
+
// A formula block has no text a paste goes into, its TeX changing in its editor alone (notion-lite's
|
|
646
|
+
// has no text area): with the caret on one (a right click puts it there), what is pasted goes after
|
|
647
|
+
// it, as with it selected.
|
|
648
|
+
const at = hostOf(event);
|
|
649
|
+
const host = texOnly(at) ? null : at;
|
|
650
|
+
const picked = host ? [] : texOnly(at) ? [unitElement(at)] : blocks().picked;
|
|
651
|
+
if (!data || (!host && picked.length === 0)) return;
|
|
652
|
+
event.preventDefault();
|
|
653
|
+
const anchor = host ?? picked.at(-1);
|
|
654
|
+
// Picture or other files (a screenshot): an image or a file block after the block, unless they
|
|
655
|
+
// come with the page's own blocks, or Office's or a table's HTML (Excel's picture of its cells).
|
|
656
|
+
const files = data.files;
|
|
657
|
+
if (files?.length > 0 && !ownData(data)) {
|
|
658
|
+
const external = externalContent(data);
|
|
659
|
+
if (!external.fromOffice && !external.isTable && fromFiles(host ?? anchor, files)) return;
|
|
660
|
+
}
|
|
661
|
+
const selection = getSelection();
|
|
662
|
+
const range = host && selection.rangeCount && host.contains(selection.getRangeAt(0).startContainer) ? selection.getRangeAt(0).cloneRange() : null;
|
|
663
|
+
if (host && !range) return;
|
|
664
|
+
// In code: the text with its lines.
|
|
665
|
+
if (host && typedAsIs(host, (data.getData("text/plain") || "").replace(/\r\n?/g, "\n"))) return;
|
|
666
|
+
let content = read(data);
|
|
667
|
+
// A field of plain text takes the words of what is pasted, whatever that is (notion-lite's
|
|
668
|
+
// plainOnly). What follows is for blocks and marks and has no say here: a copy with no unit on
|
|
669
|
+
// this page goes in as its words, and nothing waits for KaTeX.
|
|
670
|
+
if (host && can(host, "plain")) {
|
|
671
|
+
const text = plainOf(content, data);
|
|
672
|
+
if (text) insertNodes(host, range, [document.createTextNode(text)]);
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
// A copy of a block of another page (or one gone since) pastes from its data, where it has any.
|
|
676
|
+
const unmade = content.kind === "blocks" ? unmadeCopy(document, content.blocks) : null;
|
|
677
|
+
if (unmade) {
|
|
678
|
+
say(t("复制的{0}只能粘贴到它所在的文档里,而且它还要在页面上。", KIND_NAMES[unmade.kind] ?? t("组件")));
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
// Formulas want KaTeX on the page (the first time it loads).
|
|
682
|
+
const formulas = content.kind === "blocks" ? holdsFormulas(content.blocks) : content.kind === "rich" && content.html.includes("doc-math-inline");
|
|
683
|
+
if (formulas && (!host || takesFormula(host)) && (await loadKatex())) formula = formulaMaker();
|
|
684
|
+
if (mentionFor) mention = (parts) => mentionFor(parts, Boolean(content.same), content.from);
|
|
685
|
+
// An address alone, which HTML that reads as no text beside it does not change.
|
|
686
|
+
const href = content.own && content.kind === "blocks" ? null : bareAddress(data) ?? (content.kind === "plain" ? addressOf(content.text) : null);
|
|
687
|
+
const words = href ? (data.getData("text/plain") || content.text || href).trim() : ""; // read now: the clipboard's data goes with its event
|
|
688
|
+
// An address of this computer may be a document's, which the list of them says: the link a file
|
|
689
|
+
// writes, by its title, so that no file holds a port. Never a web page's views.
|
|
690
|
+
const page = href && mayBePage(href) && (!host || can(host, "links")) ? await pageLink(href) : null;
|
|
691
|
+
if (page) content = { kind: "rich", html: `<a href="${escapeMarkup(page.href)}">${escapeMarkup(page.title)}</a>` };
|
|
692
|
+
try {
|
|
693
|
+
if (!host) {
|
|
694
|
+
// With blocks selected: blocks after them (text as paragraphs, Markdown read).
|
|
695
|
+
const list = content.kind === "blocks" ? content.blocks
|
|
696
|
+
: content.kind === "rich" ? [{ type: "paragraph", html: content.html }] : toBlocks(fromMarkdown(content.text), null, HELD);
|
|
697
|
+
const made = list.length > 0 ? pasteAfter(anchor, list) : null;
|
|
698
|
+
const link = href ? made?.[0].querySelector("a[href]") : null;
|
|
699
|
+
if (link) linkPasted(link, page);
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
if (!host.isConnected || !host.contains(range.startContainer)) return;
|
|
703
|
+
// An address alone: a link wherever the block takes them (a cell, a caption too).
|
|
704
|
+
if (href && can(host, "links")) {
|
|
705
|
+
const link = document.createElement("a");
|
|
706
|
+
link.setAttribute("href", page?.href ?? href);
|
|
707
|
+
link.textContent = page?.title ?? words;
|
|
708
|
+
insertNodes(host, range, [link], { own: true, join: false }); // the link stays the one its views are offered for
|
|
709
|
+
linkPasted(link, page); // 选择视图: its views (Feishu's, notion-lite's 粘贴为)
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
if (!can(host, "split")) return pasteJoined(host, range, content, data);
|
|
713
|
+
// A flowchart node's title made by paste looks as one made by typing: what lands in it bold
|
|
714
|
+
// where bold is armed (its empty title: format-bar/), and plain text bold in a title bold
|
|
715
|
+
// throughout, as typed there (the caret's marks); rich text in a title written keeps its own.
|
|
716
|
+
const titled = isFirstLine(host) && ((isEmpty(host) && titleBold()) || (content.kind === "plain" && boldThroughout(host)));
|
|
717
|
+
if (content.kind === "plain") {
|
|
718
|
+
const text = content.text.replace(/\r?\n/g, " ");
|
|
719
|
+
if (/\n/.test(content.text)) content = { kind: "blocks", blocks: content.text.split(/\r?\n/).filter((line) => line.trim()).map((line) => ({ type: "paragraph", html: escapeTyped(line) })) };
|
|
720
|
+
else return insertNodes(host, range, [document.createTextNode(text)], { bold: titled });
|
|
721
|
+
}
|
|
722
|
+
if (content.kind === "rich") return pasteRich(host, range, content.html, Boolean(content.own), titled);
|
|
723
|
+
// A text block of no block of the page (the title, one beside a detail card's content) has no place for blocks after it.
|
|
724
|
+
if (!pasteIntoText(host, range, content.blocks, titled)) pasteJoined(host, range, content, data);
|
|
725
|
+
} finally {
|
|
726
|
+
formula = null;
|
|
727
|
+
mention = null;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* The page's own text or blocks on the clipboard as rows of cells' inline HTML (table/, cells
|
|
733
|
+
* selected): text copied in a block one cell of it; a table copied alone its cells as they are (one
|
|
734
|
+
* with merged cells left to its HTML); other blocks one cell of their lines (joinedHtml: no list's
|
|
735
|
+
* marker, no Markdown); null for anything else (the HTML table of blocks holding one is read).
|
|
736
|
+
*/
|
|
737
|
+
function ownCells(data) {
|
|
738
|
+
const own = ownData(data);
|
|
739
|
+
const text = own ? parseText(own) : null;
|
|
740
|
+
if (text !== null) return [[text]];
|
|
741
|
+
const list = own ? parse(own) : null;
|
|
742
|
+
if (!list) return null;
|
|
743
|
+
const table = list.length === 1 ? (list[0].type === "copy" ? list[0].data : list[0]) : null;
|
|
744
|
+
if (table?.type === "table") return table.spans ? null : table.rows;
|
|
745
|
+
if (/"(type|kind)":"table"/.test(JSON.stringify(list))) return null;
|
|
746
|
+
const html = joinedHtml(list);
|
|
747
|
+
return html ? [[html]] : null;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
return { copy, copyAcross, copyBlocks, ownCells, paste, blocksAt };
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
// What a field of plain text takes of the clipboard, as one line: the text of the page's own blocks
|
|
754
|
+
// (their lines, no list's marker, no Markdown), else the clipboard's plain text.
|
|
755
|
+
function plainOf(content, data) {
|
|
756
|
+
if (content.own && content.kind === "blocks") {
|
|
757
|
+
const template = document.createElement("template");
|
|
758
|
+
template.innerHTML = joinedHtml(content.blocks);
|
|
759
|
+
return [...template.content.children].map((line) => plainText(line.innerHTML).replace(/\s+/g, " ").trim()).filter(Boolean).join(" ");
|
|
760
|
+
}
|
|
761
|
+
return (data.getData("text/plain") || "").replace(/\r?\n/g, " ");
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
// Another program's blocks as the page makes them: a list item holds its blocks, as notion-lite's does.
|
|
765
|
+
const HELD = { held: true };
|
|
766
|
+
|
|
767
|
+
// What the text after the caret is when no block pasted takes it: a paragraph of its own.
|
|
768
|
+
const TAIL = { type: "paragraph", html: "" };
|
|
769
|
+
|
|
770
|
+
// Whether a text block is empty and a paste may take its place (or take it away): one of its own
|
|
771
|
+
// (not a part of another block), that can be removed, that is not kept, and holds no lists.
|
|
772
|
+
const removableEmpty = (host, unit) => host === unit && isEmpty(host) && removable(host);
|
|
773
|
+
|
|
774
|
+
// Whether a range holds any words or a formula.
|
|
775
|
+
function holdsWords(range) {
|
|
776
|
+
const held = range.cloneContents();
|
|
777
|
+
return Boolean(held.textContent.trim() || held.querySelector("[data-ge-atom]"));
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// The range of a text block's text before `range`.
|
|
781
|
+
function before(host, range) {
|
|
782
|
+
const head = document.createRange();
|
|
783
|
+
head.setStart(host, 0);
|
|
784
|
+
head.setEnd(range.startContainer, range.startOffset);
|
|
785
|
+
return head;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
// Whether a text block holds nothing but what `range` selects: no text and no formula beside it.
|
|
789
|
+
function emptiedBy(host, range) {
|
|
790
|
+
const before = document.createRange();
|
|
791
|
+
before.setStart(host, 0);
|
|
792
|
+
before.setEnd(range.startContainer, range.startOffset);
|
|
793
|
+
const after = document.createRange();
|
|
794
|
+
after.setStart(range.endContainer, range.endOffset);
|
|
795
|
+
after.setEnd(host, textEndOf(host));
|
|
796
|
+
const left = document.createElement("div");
|
|
797
|
+
left.append(before.cloneContents(), after.cloneContents());
|
|
798
|
+
return isEmpty(left);
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
// The text blocks of new nodes: the nodes themselves and the editable ones in them (what a change touches).
|
|
802
|
+
const textsOf = (nodes) => nodes.flatMap((node) => [node, ...node.querySelectorAll('[contenteditable="true"]')]).filter(isHost);
|
|
803
|
+
|
|
804
|
+
// The caret's range emptied (what was selected goes), and the range of what stands after it to the
|
|
805
|
+
// end of the block's own text (taken out by extractContents()).
|
|
806
|
+
function cutAtCaret(host, range) {
|
|
807
|
+
range.deleteContents();
|
|
808
|
+
const tail = document.createRange();
|
|
809
|
+
tail.setStart(range.startContainer, range.startOffset);
|
|
810
|
+
tail.setEnd(host, textEndOf(host));
|
|
811
|
+
return tail;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
// The end of a block's own text (a list item's text ends before the blocks it holds).
|
|
815
|
+
const textEndOf = (host) => textEnd(host);
|
|
816
|
+
|