@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,569 @@
|
|
|
1
|
+
import { attr, hasClass } from "./html-tree.mjs";
|
|
2
|
+
import { BLOCK_ID, randomId } from "./ids.mjs";
|
|
3
|
+
|
|
4
|
+
// 批注 (docs/workbench.md "Annotations", docs/editor.md "Annotations"): the reader's suggestions for a
|
|
5
|
+
// local Agent, each about a piece of a report: words of its text, or blocks taken whole. One has
|
|
6
|
+
// words: an item with none is none (cleanItem). Kept in reports/<slug>/annotations.json, never in report.html:
|
|
7
|
+
//
|
|
8
|
+
// { v: 1, items: [{ id, created, updated, text, anchor }] }
|
|
9
|
+
// anchor: { kind: "text", blocks: [data-block-id…], quote, prefix, suffix }
|
|
10
|
+
// | { kind: "blocks", blocks: [data-block-id…], quote }
|
|
11
|
+
//
|
|
12
|
+
// What the page and the server share, pure (no parser, no DOM): reading a block's text alike on both
|
|
13
|
+
// sides (the page from its DOM, editor/page/annotate/anchors.mjs; the server from the parsed file,
|
|
14
|
+
// treeText), finding an anchor's words again after edits (findQuote), the check that deletes an
|
|
15
|
+
// annotation with its text (checkAnnotations), the Markdown 复制批注 hands an Agent
|
|
16
|
+
// (annotationsMarkdown), and the numbers of the page's markers and card (stackItems, RAIL; where the
|
|
17
|
+
// column goes is editor/page/margin.mjs's).
|
|
18
|
+
//
|
|
19
|
+
// Text is compared with its white space taken out (squash): the page and the file break lines and
|
|
20
|
+
// space words differently around tags, and a quote is the same words either way. A block's text is
|
|
21
|
+
// its words with formulas as their TeX, runs of spaces as one, blocks inside it a line each.
|
|
22
|
+
|
|
23
|
+
export const FILE = "annotations.json";
|
|
24
|
+
export const VERSION = 1;
|
|
25
|
+
/** The most of a selection a text anchor quotes, and of a block anchor's text (for the copy only). */
|
|
26
|
+
export const QUOTE_MOST = 2000;
|
|
27
|
+
export const BLOCKS_QUOTE_MOST = 200;
|
|
28
|
+
/** The words kept before and after a quote, to tell two places with the same words apart. */
|
|
29
|
+
export const CONTEXT = 32;
|
|
30
|
+
/** A quote shorter than this is found only as it is (a few characters found "half" would be anywhere). */
|
|
31
|
+
export const EXACT_UNDER = 10;
|
|
32
|
+
/** How much of its context a quote not found as it is must still have beside it, on each side (characters). */
|
|
33
|
+
export const CONTEXT_KEPT = 3;
|
|
34
|
+
/** The most a suggestion holds. */
|
|
35
|
+
export const TEXT_MOST = 20000;
|
|
36
|
+
|
|
37
|
+
const BLANK = /[\s]/;
|
|
38
|
+
const FORMULA = /\\\(([\s\S]*?)\\\)|\\\[([\s\S]*?)\\\]|\$\$([\s\S]*?)\$\$/g;
|
|
39
|
+
|
|
40
|
+
/** Runs of white space as one space, the ends trimmed, zero-width characters out. */
|
|
41
|
+
export const tidy = (text) => String(text ?? "").replace(/[]/g, "").replace(/\s+/g, " ").trim();
|
|
42
|
+
|
|
43
|
+
/** Each line tidied, empty lines out, joined by line breaks: a text of several blocks. */
|
|
44
|
+
export const tidyLines = (text) => String(text ?? "").split("\n").map(tidy).filter(Boolean).join("\n");
|
|
45
|
+
|
|
46
|
+
/** `text` with all its white space out: how two texts are compared. */
|
|
47
|
+
export const squash = (text) => String(text ?? "").replace(/[\s]+/g, "");
|
|
48
|
+
|
|
49
|
+
/** `text` squashed, and where each of its characters is in `text`. */
|
|
50
|
+
export function glyphsOf(text) {
|
|
51
|
+
const at = [];
|
|
52
|
+
let squashed = "";
|
|
53
|
+
for (let index = 0; index < text.length; index++) {
|
|
54
|
+
if (BLANK.test(text[index])) continue;
|
|
55
|
+
at.push(index);
|
|
56
|
+
squashed += text[index];
|
|
57
|
+
}
|
|
58
|
+
return { squashed, at };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ---------- reading a block's text (the server's side; the page's is anchors.mjs) ----------
|
|
62
|
+
|
|
63
|
+
const SKIP_TAGS = new Set(["script", "style", "template", "noscript", "svg", "head", "title"]);
|
|
64
|
+
/** Elements that are a line of their own in a block's text (the page reads the same ones). */
|
|
65
|
+
export const LINE_TAGS = new Set(["p", "li", "ul", "ol", "h1", "h2", "h3", "h4", "h5", "h6", "table", "tr", "td", "th", "caption", "summary", "details", "figure", "figcaption", "pre", "blockquote", "div", "section", "article", "aside", "dl", "dt", "dd", "hr", "br", "header", "footer", "nav", "main", "dialog"]);
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The text of a parsed element (parse5's tree, shared/html-tree.mjs) as a block's text is compared:
|
|
69
|
+
* its words, a formula as its TeX, the lines of the blocks in it, no script, style or drawing.
|
|
70
|
+
*/
|
|
71
|
+
export function treeText(node) {
|
|
72
|
+
let raw = "";
|
|
73
|
+
const walk = (parent) => {
|
|
74
|
+
for (const child of parent.childNodes ?? []) {
|
|
75
|
+
if (child.nodeName === "#text") raw += child.value;
|
|
76
|
+
if (!child.tagName || SKIP_TAGS.has(child.tagName)) continue;
|
|
77
|
+
if (child.tagName === "button" && !hasClass(child, "doc-sheet-tab")) continue; // the page's own controls
|
|
78
|
+
if (attr(child, "aria-hidden") === "true") continue;
|
|
79
|
+
const line = LINE_TAGS.has(child.tagName);
|
|
80
|
+
if (line) raw += "\n";
|
|
81
|
+
walk(child.tagName === "template" ? child.content : child);
|
|
82
|
+
if (line) raw += "\n";
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
walk(node);
|
|
86
|
+
// A formula as the page reads one (its TeX in \( \), or \[ \] for one shown apart: the page cannot
|
|
87
|
+
// tell $$ from \[), so a quote of it is found on both sides and in the file by an Agent.
|
|
88
|
+
return tidyLines(raw.replace(FORMULA, (_, inline, display, dollars) => (inline !== undefined ? ` \\(${inline}\\) ` : ` \\[${display ?? dollars}\\] `)));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ---------- finding a quote ----------
|
|
92
|
+
|
|
93
|
+
// The longest common end of two strings (`a`'s end with `b`'s end), and the longest common start.
|
|
94
|
+
const commonEnd = (a, b) => {
|
|
95
|
+
let n = 0;
|
|
96
|
+
while (n < a.length && n < b.length && a[a.length - 1 - n] === b[b.length - 1 - n]) n++;
|
|
97
|
+
return n;
|
|
98
|
+
};
|
|
99
|
+
const commonStart = (a, b) => {
|
|
100
|
+
let n = 0;
|
|
101
|
+
while (n < a.length && n < b.length && a[n] === b[n]) n++;
|
|
102
|
+
return n;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// The most cells the alignment below works through (the quote's characters times the text's): a
|
|
106
|
+
// quote of 200 characters in a text of 20000; beyond, a quote not found as it is stays as it was.
|
|
107
|
+
const ALIGN_MOST = 4_000_000;
|
|
108
|
+
// What a character of the text inside the stretch that is none of the quote's costs, against 1 for
|
|
109
|
+
// one of the quote's kept: a word typed into the quote is bridged, a far-off piece of it is not.
|
|
110
|
+
const EXTRA = 0.1;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* The stretch of `hay` (squashed) that keeps the most of `needle`'s characters in their order, each
|
|
114
|
+
* character of the stretch that is not one of them costing EXTRA: { start, end, kept }, or null.
|
|
115
|
+
* One pass over the text, two rows of the quote's length.
|
|
116
|
+
*/
|
|
117
|
+
export function alignQuote(needle, hay) {
|
|
118
|
+
const m = needle.length;
|
|
119
|
+
const n = hay.length;
|
|
120
|
+
if (m === 0 || n === 0) return null;
|
|
121
|
+
let score = new Float64Array(m + 1);
|
|
122
|
+
let kept = new Int32Array(m + 1);
|
|
123
|
+
let from = new Int32Array(m + 1);
|
|
124
|
+
let nextScore = new Float64Array(m + 1);
|
|
125
|
+
let nextKept = new Int32Array(m + 1);
|
|
126
|
+
let nextFrom = new Int32Array(m + 1);
|
|
127
|
+
// Column 0: nothing of the text taken, every character of the quote skipped.
|
|
128
|
+
for (let i = 0; i <= m; i++) { score[i] = 0; kept[i] = 0; from[i] = 0; }
|
|
129
|
+
let best = null;
|
|
130
|
+
for (let j = 1; j <= n; j++) {
|
|
131
|
+
const char = hay[j - 1];
|
|
132
|
+
nextScore[0] = 0;
|
|
133
|
+
nextKept[0] = 0;
|
|
134
|
+
nextFrom[0] = j; // an empty stretch, starting here
|
|
135
|
+
for (let i = 1; i <= m; i++) {
|
|
136
|
+
// The quote's character skipped (not in the text).
|
|
137
|
+
let s = nextScore[i - 1];
|
|
138
|
+
let k = nextKept[i - 1];
|
|
139
|
+
let f = nextFrom[i - 1];
|
|
140
|
+
// The text's character taken as one the quote does not have (inside the stretch only).
|
|
141
|
+
if (kept[i] > 0) {
|
|
142
|
+
const extra = score[i] - EXTRA;
|
|
143
|
+
if (extra > s || (extra === s && from[i] > f)) { s = extra; k = kept[i]; f = from[i]; }
|
|
144
|
+
}
|
|
145
|
+
// Both taken: the same character.
|
|
146
|
+
if (needle[i - 1] === char) {
|
|
147
|
+
const start = kept[i - 1] > 0 ? from[i - 1] : j - 1;
|
|
148
|
+
const both = score[i - 1] + 1;
|
|
149
|
+
if (both > s || (both === s && start > f)) { s = both; k = kept[i - 1] + 1; f = start; }
|
|
150
|
+
}
|
|
151
|
+
nextScore[i] = s;
|
|
152
|
+
nextKept[i] = k;
|
|
153
|
+
nextFrom[i] = f;
|
|
154
|
+
}
|
|
155
|
+
if (nextKept[m] > 0 && (!best || nextScore[m] > best.score || (nextScore[m] === best.score && j - nextFrom[m] < best.end - best.start))) {
|
|
156
|
+
best = { score: nextScore[m], kept: nextKept[m], start: nextFrom[m], end: j };
|
|
157
|
+
}
|
|
158
|
+
[score, nextScore] = [nextScore, score];
|
|
159
|
+
[kept, nextKept] = [nextKept, kept];
|
|
160
|
+
[from, nextFrom] = [nextFrom, from];
|
|
161
|
+
}
|
|
162
|
+
return best && { start: best.start, end: best.end, kept: best.kept };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Where an anchor's quote is in `text` (a block's text, or several blocks' joined by line breaks):
|
|
167
|
+
* { start, end, exact } (offsets in `text`), null when it is gone, or { unknown: true } when the
|
|
168
|
+
* text is too long to look for a quote not found as it is (it is kept as it was).
|
|
169
|
+
* 1. The quote as it is (white space aside): of several, the one whose prefix and suffix agree most, else the first.
|
|
170
|
+
* 2. Not as it is (edited in part): the stretch keeping at least half of its characters in their
|
|
171
|
+
* order, no longer than one and a half times the quote (alignQuote), and standing where the quote
|
|
172
|
+
* stood: on each side what was around it is still right beside it (the last CONTEXT_KEPT
|
|
173
|
+
* characters of the prefix before it, the first of the suffix after it, with room between for
|
|
174
|
+
* words that replaced the quote's first or last ones), or, where it had nothing around it, the
|
|
175
|
+
* text's edge. So a quote deleted never moves onto other words that share its characters (a
|
|
176
|
+
* parallel sentence beside it), and one edited where what is around it was rewritten too is
|
|
177
|
+
* taken as gone. A quote under EXACT_UNDER characters is found only as it is.
|
|
178
|
+
* With `exact`, only 1 (the page's first look, before it follows the reader's edit: editor/page/annotate/).
|
|
179
|
+
*/
|
|
180
|
+
export function findQuote(text, { quote, prefix = "", suffix = "" }, { exact = false } = {}) {
|
|
181
|
+
const hay = glyphsOf(String(text ?? ""));
|
|
182
|
+
const needle = squash(quote);
|
|
183
|
+
if (!needle) return null;
|
|
184
|
+
const span = (a, b, exact) => ({ start: hay.at[a], end: hay.at[b - 1] + 1, exact });
|
|
185
|
+
const hits = [];
|
|
186
|
+
for (let at = hay.squashed.indexOf(needle); at >= 0; at = hay.squashed.indexOf(needle, at + 1)) hits.push(at);
|
|
187
|
+
if (hits.length > 0) {
|
|
188
|
+
const before = squash(prefix);
|
|
189
|
+
const after = squash(suffix);
|
|
190
|
+
let pick = hits[0];
|
|
191
|
+
let most = -1;
|
|
192
|
+
for (const at of hits) {
|
|
193
|
+
const agree = commonEnd(before, hay.squashed.slice(Math.max(0, at - before.length), at)) + commonStart(after, hay.squashed.slice(at + needle.length, at + needle.length + after.length));
|
|
194
|
+
if (agree > most) { most = agree; pick = at; }
|
|
195
|
+
}
|
|
196
|
+
return span(pick, pick + needle.length, true);
|
|
197
|
+
}
|
|
198
|
+
if (exact || needle.length < EXACT_UNDER) return null;
|
|
199
|
+
if (needle.length * hay.squashed.length > ALIGN_MOST) return { unknown: true };
|
|
200
|
+
const found = alignQuote(needle, hay.squashed);
|
|
201
|
+
if (!found || found.kept * 2 < needle.length || found.end - found.start > needle.length * 1.5) return null;
|
|
202
|
+
if (!standsBetween(hay.squashed, found, squash(prefix), squash(suffix), Math.ceil(needle.length / 2))) return null;
|
|
203
|
+
return span(found.start, found.end, false);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Whether the stretch `found` of `hay` (squashed) stands where a quote with `before` and `after`
|
|
207
|
+
// around it stood: the end of `before` ends at most `slack` characters before it (what replaced the
|
|
208
|
+
// quote's first words), the start of `after` starts at most `slack` after it; for an empty side,
|
|
209
|
+
// the text's edge as near.
|
|
210
|
+
function standsBetween(hay, found, before, after, slack) {
|
|
211
|
+
const tail = before.slice(-CONTEXT_KEPT);
|
|
212
|
+
const head = after.slice(0, CONTEXT_KEPT);
|
|
213
|
+
let left = !tail && found.start <= slack;
|
|
214
|
+
for (let end = found.start; tail && !left && end >= Math.max(tail.length, found.start - slack); end--) {
|
|
215
|
+
if (hay.slice(end - tail.length, end) === tail) left = true;
|
|
216
|
+
}
|
|
217
|
+
if (!left) return false;
|
|
218
|
+
if (!head) return hay.length - found.end <= slack;
|
|
219
|
+
for (let start = found.end; start <= Math.min(hay.length - head.length, found.end + slack); start++) {
|
|
220
|
+
if (hay.slice(start, start + head.length) === head) return true;
|
|
221
|
+
}
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** An anchor's quote, prefix and suffix as `text` has them from `start` to `end`. */
|
|
226
|
+
export function excerptOf(text, start, end) {
|
|
227
|
+
const quote = tidyLines(text.slice(start, end)).slice(0, QUOTE_MOST);
|
|
228
|
+
const before = tidy(text.slice(0, start).replace(/\n/g, " "));
|
|
229
|
+
const after = tidy(text.slice(end).replace(/\n/g, " "));
|
|
230
|
+
return { quote, prefix: before.slice(Math.max(0, before.length - CONTEXT)), suffix: after.slice(0, CONTEXT) };
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// ---------- the check: an annotation goes with its text ----------
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Where an anchor is in a report's units (`units`: [{ id (its data-block-id, or null), text, parent
|
|
237
|
+
* (its index in units, or null) }], in page order): { at (the index of its first unit), offset,
|
|
238
|
+
* anchor (as the file has it now: its blocks, its quote and what is around it) } or null when it is
|
|
239
|
+
* gone, { unknown: true, at } when it cannot be told (kept as it is).
|
|
240
|
+
* - text: the quote in its blocks' text (findQuote); none of its blocks there, the quote as it is
|
|
241
|
+
* found exactly once in the report, in the innermost block holding it (a block without an id yet:
|
|
242
|
+
* its blocks stay as they were, the page names it).
|
|
243
|
+
* - blocks: kept while at least one of its blocks is there; its quote their text now.
|
|
244
|
+
*/
|
|
245
|
+
export function locateAnchor(anchor, units) {
|
|
246
|
+
const index = new Map(units.map((unit, at) => [unit.id, at]).filter(([id]) => id));
|
|
247
|
+
const present = [...new Set((anchor.blocks ?? []).filter((id) => index.has(id)))].sort((a, b) => index.get(a) - index.get(b));
|
|
248
|
+
if (anchor.kind === "blocks") {
|
|
249
|
+
if (present.length === 0) return null;
|
|
250
|
+
const text = present.map((id) => units[index.get(id)].text).join("\n");
|
|
251
|
+
return { at: index.get(present[0]), offset: 0, anchor: { kind: "blocks", blocks: present, quote: tidyLines(text).slice(0, BLOCKS_QUOTE_MOST) } };
|
|
252
|
+
}
|
|
253
|
+
if (present.length > 0) {
|
|
254
|
+
let texts = present.map((id) => units[index.get(id)].text);
|
|
255
|
+
let found = findQuote(texts.join("\n"), anchor);
|
|
256
|
+
// Split by Enter in its middle: the words as they are, across its blocks and the one right after
|
|
257
|
+
// them (begun in its own, gone on in that one: not words of their own further on).
|
|
258
|
+
if (!found) {
|
|
259
|
+
const next = unitAfter(units, index.get(present.at(-1)));
|
|
260
|
+
const more = next === null || !units[next].id ? null : [...texts, units[next].text];
|
|
261
|
+
const own = texts.join("\n").length;
|
|
262
|
+
const split = more ? findQuote(more.join("\n"), anchor, { exact: true }) : null;
|
|
263
|
+
if (split && split.start < own && split.end > own) {
|
|
264
|
+
present.push(units[next].id);
|
|
265
|
+
texts = more;
|
|
266
|
+
found = split;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
const text = texts.join("\n");
|
|
270
|
+
if (found?.unknown) return { unknown: true, at: index.get(present[0]) };
|
|
271
|
+
if (!found) return null;
|
|
272
|
+
// The blocks the words are in now: those of the joined text the stretch reaches.
|
|
273
|
+
const blocks = [];
|
|
274
|
+
let start = 0;
|
|
275
|
+
texts.forEach((part, k) => {
|
|
276
|
+
const end = start + part.length;
|
|
277
|
+
if (found.start < end && found.end > start) blocks.push(present[k]);
|
|
278
|
+
start = end + 1;
|
|
279
|
+
});
|
|
280
|
+
const first = present.indexOf(blocks[0]);
|
|
281
|
+
const offset = found.start - texts.slice(0, first).reduce((sum, part) => sum + part.length + 1, 0);
|
|
282
|
+
return { at: index.get(blocks[0]), offset, anchor: { kind: "text", blocks, ...excerptOf(text, found.start, found.end) } };
|
|
283
|
+
}
|
|
284
|
+
// None of its blocks: the words as they are, once in the report, in the innermost block holding them.
|
|
285
|
+
const needle = squash(anchor.quote);
|
|
286
|
+
if (!needle) return null;
|
|
287
|
+
const holding = [];
|
|
288
|
+
units.forEach((unit, at) => { if (squash(unit.text).includes(needle)) holding.push(at); });
|
|
289
|
+
const innermost = holding.filter((at) => !holding.some((other) => other !== at && isInside(units, other, at)));
|
|
290
|
+
const count = innermost.reduce((sum, at) => sum + occurrences(squash(units[at].text), needle), 0);
|
|
291
|
+
if (count !== 1) return null;
|
|
292
|
+
const [at] = innermost;
|
|
293
|
+
const unit = units[at];
|
|
294
|
+
const found = findQuote(unit.text, anchor);
|
|
295
|
+
if (!found || found.unknown) return null;
|
|
296
|
+
return { at, offset: found.start, anchor: { kind: "text", blocks: unit.id ? [unit.id] : [...(anchor.blocks ?? [])], ...excerptOf(unit.text, found.start, found.end) } };
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// The unit right after unit `at` and what it holds (the next in page order not inside it), or null.
|
|
300
|
+
function unitAfter(units, at) {
|
|
301
|
+
for (let next = at + 1; next < units.length; next++) if (!isInside(units, next, at)) return next;
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const occurrences = (hay, needle) => {
|
|
306
|
+
let count = 0;
|
|
307
|
+
for (let at = hay.indexOf(needle); at >= 0; at = hay.indexOf(needle, at + 1)) count++;
|
|
308
|
+
return count;
|
|
309
|
+
};
|
|
310
|
+
// Whether unit `inner` is inside unit `outer` (by their parents).
|
|
311
|
+
const isInside = (units, inner, outer) => {
|
|
312
|
+
for (let at = units[inner].parent; at !== null && at !== undefined; at = units[at]?.parent) if (at === outer) return true;
|
|
313
|
+
return false;
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
const sameAnchor = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* The check (docs/editor.md "Annotations"): each annotation against the report's units (locateAnchor),
|
|
320
|
+
* those whose words or blocks are gone deleted, those found otherwise than they were rewritten to what
|
|
321
|
+
* the report holds now, all in page order. `keep`: the ids of those a page has and the file may not
|
|
322
|
+
* hold yet (its words, a block's id: the commit that writes them is on its way): each stands as it was
|
|
323
|
+
* sent, placed by what is found of it, until the report has its words and all its blocks, and `waiting`
|
|
324
|
+
* in the answer says which still stand so. Returns { items, dropped (those deleted), changed (whether
|
|
325
|
+
* the file is to be written), places (id -> { at, offset }), waiting }.
|
|
326
|
+
*/
|
|
327
|
+
export function checkAnnotations(items, units, { keep = new Set() } = {}) {
|
|
328
|
+
const named = new Set(units.map((unit) => unit.id));
|
|
329
|
+
const placed = [];
|
|
330
|
+
const dropped = [];
|
|
331
|
+
const waiting = new Set();
|
|
332
|
+
let changed = false;
|
|
333
|
+
items.forEach((item, order) => {
|
|
334
|
+
const found = locateAnchor(item.anchor, units);
|
|
335
|
+
if (keep.has(item.id) && (!found || found.unknown || !(item.anchor.blocks ?? []).every((id) => named.has(id)))) {
|
|
336
|
+
waiting.add(item.id);
|
|
337
|
+
placed.push({ item, at: found?.at ?? Infinity, offset: found?.offset ?? 0, order });
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
if (!found) {
|
|
341
|
+
dropped.push(item);
|
|
342
|
+
changed = true;
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
if (found.unknown) {
|
|
346
|
+
placed.push({ item, at: found.at, offset: 0, order });
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
const next = sameAnchor(found.anchor, item.anchor) ? item : { ...item, anchor: found.anchor };
|
|
350
|
+
if (next !== item) changed = true;
|
|
351
|
+
placed.push({ item: next, at: found.at, offset: found.offset, order });
|
|
352
|
+
});
|
|
353
|
+
placed.sort((a, b) => a.at - b.at || a.offset - b.offset || a.order - b.order);
|
|
354
|
+
if (placed.some((entry, index) => entry.order !== index)) changed = true;
|
|
355
|
+
return {
|
|
356
|
+
items: placed.map((entry) => entry.item),
|
|
357
|
+
dropped,
|
|
358
|
+
changed,
|
|
359
|
+
places: new Map(placed.map((entry) => [entry.item.id, { at: entry.at, offset: entry.offset }])),
|
|
360
|
+
waiting,
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// ---------- what the file holds ----------
|
|
365
|
+
|
|
366
|
+
const ID = /^[a-z0-9]{8}$/;
|
|
367
|
+
|
|
368
|
+
/** A new annotation's id: eight letters and digits. */
|
|
369
|
+
export const newAnnotationId = () => randomId(8);
|
|
370
|
+
|
|
371
|
+
const strings = (list) => Array.isArray(list) && list.every((value) => typeof value === "string");
|
|
372
|
+
|
|
373
|
+
/** An anchor as the file keeps it, from what was sent, or null when it is none. */
|
|
374
|
+
export function cleanAnchor(anchor) {
|
|
375
|
+
if (!anchor || (anchor.kind !== "text" && anchor.kind !== "blocks") || !strings(anchor.blocks ?? []) || typeof anchor.quote !== "string") return null;
|
|
376
|
+
const blocks = [...new Set(anchor.blocks ?? [])].filter((id) => BLOCK_ID.test(id));
|
|
377
|
+
const quote = anchor.kind === "text" ? tidyLines(anchor.quote).slice(0, QUOTE_MOST) : tidyLines(anchor.quote).slice(0, BLOCKS_QUOTE_MOST);
|
|
378
|
+
if (anchor.kind === "text" && !squash(quote)) return null;
|
|
379
|
+
return anchor.kind === "text"
|
|
380
|
+
? { kind: "text", blocks, quote, prefix: tidy(anchor.prefix ?? "").slice(-CONTEXT), suffix: tidy(anchor.suffix ?? "").slice(0, CONTEXT) }
|
|
381
|
+
: { kind: "blocks", blocks, quote };
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Whether two anchors say the same for finding them again (their blocks, their quote, and the ends
|
|
386
|
+
* of their context the check looks at), white space aside: the page tells the server of an anchor
|
|
387
|
+
* that followed the reader's edit only when it says something else.
|
|
388
|
+
*/
|
|
389
|
+
export const sameWords = (a, b) => Boolean(a && b) && a.kind === b.kind && (a.blocks ?? []).join() === (b.blocks ?? []).join() && squash(a.quote) === squash(b.quote)
|
|
390
|
+
&& squash(a.prefix).slice(-CONTEXT_KEPT) === squash(b.prefix).slice(-CONTEXT_KEPT) && squash(a.suffix).slice(0, CONTEXT_KEPT) === squash(b.suffix).slice(0, CONTEXT_KEPT);
|
|
391
|
+
|
|
392
|
+
/** An annotation as the file keeps it, from what was sent (`now`: when it is saved), or null when it is none (no id, no anchor, no words). */
|
|
393
|
+
export function cleanItem(item, now = new Date().toISOString()) {
|
|
394
|
+
if (!item || typeof item !== "object" || typeof item.id !== "string" || !ID.test(item.id) || typeof item.text !== "string") return null;
|
|
395
|
+
const anchor = cleanAnchor(item.anchor);
|
|
396
|
+
if (!anchor) return null;
|
|
397
|
+
const text = item.text.replace(/\r\n?/g, "\n").slice(0, TEXT_MOST);
|
|
398
|
+
if (!text.trim()) return null;
|
|
399
|
+
return { id: item.id, created: typeof item.created === "string" ? item.created : now, updated: now, text, anchor };
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/** The annotations of a file's text (annotations.json), those it holds that are not annotations left out. */
|
|
403
|
+
export function readItems(text) {
|
|
404
|
+
let data = null;
|
|
405
|
+
try { data = JSON.parse(text); } catch {}
|
|
406
|
+
if (!data || typeof data !== "object" || !Array.isArray(data.items)) return [];
|
|
407
|
+
const seen = new Set();
|
|
408
|
+
return data.items.filter((item) => {
|
|
409
|
+
const clean = cleanItem(item, item?.updated);
|
|
410
|
+
if (!clean || seen.has(clean.id)) return false;
|
|
411
|
+
seen.add(clean.id);
|
|
412
|
+
return true;
|
|
413
|
+
}).map((item) => cleanItem(item, item.updated));
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/** The file's text for `items` (none: no file, null). */
|
|
417
|
+
export const itemsText = (items) => (items.length === 0 ? null : `${JSON.stringify({ v: VERSION, items }, null, 2)}\n`);
|
|
418
|
+
|
|
419
|
+
// ---------- 复制批注 ----------
|
|
420
|
+
|
|
421
|
+
/** What the Markdown says, in the UI's language (the workbench passes them through t()). */
|
|
422
|
+
export const MARKDOWN_WORDS = {
|
|
423
|
+
head: "以下是我对这份文档的批注,共 {0} 条。请逐条按“建议”修改底稿;每条给出它在文档里的位置、块的 data-block-id 和批注的原文。",
|
|
424
|
+
headOne: "以下是我对这份文档的一条批注。请按“建议”修改底稿;它给出在文档里的位置、块的 data-block-id 和批注的原文。",
|
|
425
|
+
report: "文档",
|
|
426
|
+
source: "底稿",
|
|
427
|
+
block: "块",
|
|
428
|
+
whole: "(整块)",
|
|
429
|
+
noId: "(还没有 id,按原文找)",
|
|
430
|
+
suggestion: "建议",
|
|
431
|
+
body: "正文",
|
|
432
|
+
top: "页首",
|
|
433
|
+
colon: ":",
|
|
434
|
+
comma: ",",
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
const fill = (text, ...values) => text.replace(/\{(\d+)\}/g, (whole, index) => (index < values.length ? String(values[index]) : whole));
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* 复制批注's Markdown for a local Agent: a line saying what it is, the report's title and source path,
|
|
441
|
+
* then each annotation in page order: where it is (`where`: the tab, the headings above it, the
|
|
442
|
+
* disclosure it is in; `top`: before the report's first heading, said 页首, which no tab or heading
|
|
443
|
+
* named 正文 is taken for), its blocks' ids (as the file has them), its quote and the suggestion, each
|
|
444
|
+
* of its lines a paragraph (blank lines in it make no more of them).
|
|
445
|
+
* data: { title, path, items: [{ where: [text], top, blocks: [id], whole, quote, text }] }.
|
|
446
|
+
*/
|
|
447
|
+
export function annotationsMarkdown({ title, path, items }, words = MARKDOWN_WORDS) {
|
|
448
|
+
const w = { ...MARKDOWN_WORDS, ...words };
|
|
449
|
+
const head = items.length === 1 && w.headOne ? w.headOne : fill(w.head, items.length);
|
|
450
|
+
const lines = [head, "", `- ${w.report}${w.colon}${title}`, `- ${w.source}${w.colon}${path}`];
|
|
451
|
+
items.forEach((item, index) => {
|
|
452
|
+
const where = item.where?.length ? item.where.join(" › ") : item.top ? w.top : w.body;
|
|
453
|
+
const ids = item.blocks?.length ? item.blocks.map((id) => `\`data-block-id="${id}"\``).join(w.comma) + (item.whole ? w.whole : "") : w.noId;
|
|
454
|
+
lines.push("", `## ${index + 1}. ${where}`, "", `${w.block}${w.colon}${ids}`, "");
|
|
455
|
+
for (const line of String(item.quote ?? "").split("\n")) lines.push(`> ${line}`);
|
|
456
|
+
const said = String(item.text ?? "").replace(/\r\n?/g, "\n").split("\n").map((line) => line.trim()).filter(Boolean);
|
|
457
|
+
lines.push("", `${w.suggestion}${w.colon}${said[0] ?? ""}`);
|
|
458
|
+
for (const line of said.slice(1)) lines.push("", line);
|
|
459
|
+
});
|
|
460
|
+
return `${lines.join("\n")}\n`;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// ---------- the margin ----------
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Notion's margin: items stacked without overlapping, the active one at its own line, the others
|
|
467
|
+
* pushed up above it and down below it. items: [{ ideal (top), height, marker (a 24px marker, else a
|
|
468
|
+
* card), active }], in page order. Gaps: `markers` between two markers, `cards` next to a card;
|
|
469
|
+
* nothing above `top` and nothing past `bottom` (the page's end: what would pass it goes up, so a
|
|
470
|
+
* card near the end never makes the page longer; the top wins where both cannot hold); `obstacles`
|
|
471
|
+
* ([{ top, bottom }]: the format bar's box where it reaches into the margin) are stepped over, on the
|
|
472
|
+
* side nearer the item's line. Returns the tops, in the order given.
|
|
473
|
+
*/
|
|
474
|
+
export function stackItems(items, { markers = 4, cards = 8, top = 52, bottom = Infinity, obstacles = [] } = {}) {
|
|
475
|
+
const order = items.map((item, index) => ({ ...item, index })).sort((a, b) => a.ideal - b.ideal || a.index - b.index);
|
|
476
|
+
if (order.length === 0) return [];
|
|
477
|
+
const gap = (a, b) => (a.marker && b.marker ? markers : cards);
|
|
478
|
+
let k = order.findIndex((item) => item.active);
|
|
479
|
+
if (k < 0) k = 0;
|
|
480
|
+
order[k].top = order[k].ideal;
|
|
481
|
+
for (let i = k + 1; i < order.length; i++) order[i].top = Math.max(order[i].ideal, order[i - 1].top + order[i - 1].height + gap(order[i - 1], order[i]));
|
|
482
|
+
for (let i = k - 1; i >= 0; i--) order[i].top = Math.min(order[i].ideal, order[i + 1].top - gap(order[i], order[i + 1]) - order[i].height);
|
|
483
|
+
// What would pass the page's end goes up (and what comes before it with it).
|
|
484
|
+
let ceiling = bottom;
|
|
485
|
+
for (let i = order.length - 1; i >= 0; i--) {
|
|
486
|
+
order[i].top = Math.min(order[i].top, ceiling - order[i].height);
|
|
487
|
+
ceiling = order[i].top - (i > 0 ? gap(order[i - 1], order[i]) : 0);
|
|
488
|
+
}
|
|
489
|
+
// What would go above the page's top room goes down instead, and what meets an obstacle goes to its
|
|
490
|
+
// nearer side (above it only where that keeps clear of the item before); what follows goes with it.
|
|
491
|
+
let floor = top;
|
|
492
|
+
for (let i = 0; i < order.length; i++) {
|
|
493
|
+
let at = Math.max(order[i].top, floor);
|
|
494
|
+
for (const box of obstacles) {
|
|
495
|
+
if (!(at < box.bottom && at + order[i].height > box.top)) continue;
|
|
496
|
+
const above = box.top - cards - order[i].height;
|
|
497
|
+
const below = box.bottom + cards;
|
|
498
|
+
at = above >= floor && Math.abs(above - order[i].ideal) < Math.abs(below - order[i].ideal) ? above : below;
|
|
499
|
+
}
|
|
500
|
+
order[i].top = at;
|
|
501
|
+
floor = at + order[i].height + (order[i + 1] ? gap(order[i], order[i + 1]) : 0);
|
|
502
|
+
}
|
|
503
|
+
const tops = new Array(items.length);
|
|
504
|
+
for (const item of order) tops[item.index] = item.top;
|
|
505
|
+
return tops;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* The measures of the cards standing beside the page (notion-lite's editor/comments/margin.js, its
|
|
510
|
+
* layoutCards, 298292 S): how far above its anchor a card stands, the gap under each, how much further
|
|
511
|
+
* down a new one's anchor counts, the room under the last, to scroll it up to.
|
|
512
|
+
*/
|
|
513
|
+
export const CARD = Object.freeze({ above: 18, gap: 10, draft: 14, end: 50 });
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Where the cards stand, given [{ id, top (its anchor's), height, created }] and the id of the one in
|
|
517
|
+
* front (or null). In page order (those level with each other, the one made first first), each
|
|
518
|
+
* CARD.above above its anchor (one nearer the page's top than that stays there), pushed down by the one
|
|
519
|
+
* above it with CARD.gap between them. The one in front, pushed down, comes back beside its anchor: those
|
|
520
|
+
* right before it touching go up with it, all those after it follow. Returns [{ id, top }] in that order.
|
|
521
|
+
*/
|
|
522
|
+
export function cardTops(items, front = null) {
|
|
523
|
+
const order = items.map((item) => ({ ...item })).sort((a, b) => a.top - b.top || (a.created < b.created ? -1 : a.created > b.created ? 1 : 0) || (a.id < b.id ? -1 : 1));
|
|
524
|
+
let floor = 0;
|
|
525
|
+
let moved = 0;
|
|
526
|
+
let at = -1;
|
|
527
|
+
order.forEach((item, index) => {
|
|
528
|
+
if (item.top >= CARD.above) item.top -= CARD.above;
|
|
529
|
+
const top = Math.max(item.top, floor);
|
|
530
|
+
if (item.id === front) {
|
|
531
|
+
moved = top - item.top;
|
|
532
|
+
at = index;
|
|
533
|
+
}
|
|
534
|
+
item.top = top;
|
|
535
|
+
floor = top + item.height + CARD.gap;
|
|
536
|
+
});
|
|
537
|
+
if (moved > 0) {
|
|
538
|
+
let after = order[at];
|
|
539
|
+
after.top -= moved;
|
|
540
|
+
for (let index = at - 1; index >= 0; index--) {
|
|
541
|
+
const item = order[index];
|
|
542
|
+
if (after.top > item.top + item.height + CARD.gap) break;
|
|
543
|
+
item.top -= moved;
|
|
544
|
+
after = item;
|
|
545
|
+
}
|
|
546
|
+
for (let index = at + 1; index < order.length; index++) order[index].top -= moved;
|
|
547
|
+
}
|
|
548
|
+
return order.map(({ id, top }) => ({ id, top }));
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* The numbers of 批注 on the page (docs/editor.md "Annotations"): a marker's size; where the markers
|
|
553
|
+
* stand, from the column's right edge, in its own 64px gutter, 5px right of a block anchor's bar (level
|
|
554
|
+
* with a table's corner + at +2 to +20, which stands under the table); where that bar stands (left of
|
|
555
|
+
* the section bar's line at +12 to +16); the card's width by its words or blocks, in the column, where
|
|
556
|
+
* the margin has no room for cards (those are margin.mjs's: MARGIN.card).
|
|
557
|
+
*/
|
|
558
|
+
export const RAIL = Object.freeze({ marker: 24, markerAt: 14, bar: 7, card: 280 });
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Where a marker stands across a window `width` wide, the column's right edge being `right`: `markerAt`
|
|
562
|
+
* right of it, or at `clear` where that is further right (past a section's strip, for what is in that
|
|
563
|
+
* section), inside the window (at the column's edge, in it, where the gutter is too narrow). The button
|
|
564
|
+
* beside a block stands here too (handle/): it and the marker it becomes are one place.
|
|
565
|
+
*/
|
|
566
|
+
export const markerLeft = (right, width, clear = 0) => Math.max(right - RAIL.marker, Math.min(Math.max(right + RAIL.markerAt, clear), width - RAIL.marker - 2));
|
|
567
|
+
|
|
568
|
+
/** The top of a marker in the middle of `line` ({ top, height }): a block's first line, or several blocks. */
|
|
569
|
+
export const markerTop = (line) => line.top + (line.height - RAIL.marker) / 2;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// What a code block's folds look like, written once: the arrow of a line that folds (the kit's
|
|
2
|
+
// code.js draws it in the reading view, the page editor in its line numbers' column) and the "…"
|
|
3
|
+
// after a line that is folded (the kit's styles/code.css asks for it as `@fold-dots`, which
|
|
4
|
+
// kit-build.mjs fills in; the editor's styles interpolate it). Its colors are the kit's tokens.
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A folding line's arrow (markup; it takes the color of its button), pointing down; folded, it is
|
|
8
|
+
* turned to point at what it folds: a code block's and its lines' -90° (right: they stand left of
|
|
9
|
+
* the code), a heading's 90° (left: it stands right of the words, page/fold/).
|
|
10
|
+
*/
|
|
11
|
+
export const FOLD_ARROW = '<svg viewBox="0 0 12 12" aria-hidden="true"><path d="M3.25 4.5h5.5L6 8z" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"/></svg>';
|
|
12
|
+
|
|
13
|
+
/** The three dots of a folded line's "…" (a CSS image). */
|
|
14
|
+
export const FOLD_DOTS = `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='2'%3E%3Ccircle cx='1' cy='1' r='1' fill='%238e8b86'/%3E%3Ccircle cx='6' cy='1' r='1' fill='%238e8b86'/%3E%3Ccircle cx='11' cy='1' r='1' fill='%238e8b86'/%3E%3C/svg%3E")`;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// The languages of the kit's code blocks: those code.js bundles grammars for, as a code block's
|
|
2
|
+
// data-language names them and its header shows them, and what the code of a block written
|
|
3
|
+
// without one looks like (自动识别). In src/shared, so that what reads it is one: the kit's code.js, a code block
|
|
4
|
+
// pasted from Notion (the page editor's clipboard/import/to-blocks.mjs) and the editor's tests.
|
|
5
|
+
|
|
6
|
+
/** In the order the language menu lists them; id: what data-language holds; words: what finds it. */
|
|
7
|
+
export const LANGUAGES = [
|
|
8
|
+
{ id: 'text', name: '纯文本', words: 'text plain txt 纯文本 chunwenben cwb' },
|
|
9
|
+
{ id: 'bash', name: 'Bash', words: 'bash shell sh zsh shellscript' },
|
|
10
|
+
{ id: 'css', name: 'CSS', words: 'css' },
|
|
11
|
+
{ id: 'html', name: 'HTML', words: 'html htm' },
|
|
12
|
+
{ id: 'javascript', name: 'JavaScript', words: 'javascript js mjs cjs' },
|
|
13
|
+
{ id: 'json', name: 'JSON', words: 'json' },
|
|
14
|
+
{ id: 'jsx', name: 'JSX', words: 'jsx react' },
|
|
15
|
+
{ id: 'markdown', name: 'Markdown', words: 'markdown md' },
|
|
16
|
+
{ id: 'python', name: 'Python', words: 'python py' },
|
|
17
|
+
{ id: 'sql', name: 'SQL', words: 'sql' },
|
|
18
|
+
{ id: 'tsx', name: 'TSX', words: 'tsx react' },
|
|
19
|
+
{ id: 'typescript', name: 'TypeScript', words: 'typescript ts' },
|
|
20
|
+
{ id: 'yaml', name: 'YAML', words: 'yaml yml' },
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
// Other names of those languages, file extensions among them.
|
|
24
|
+
const ALIASES = {
|
|
25
|
+
js: 'javascript', mjs: 'javascript', cjs: 'javascript', ts: 'typescript', mts: 'typescript', cts: 'typescript', py: 'python',
|
|
26
|
+
htm: 'html', sh: 'bash', shell: 'bash', zsh: 'bash', shellscript: 'bash', yml: 'yaml', md: 'markdown',
|
|
27
|
+
txt: 'text', plain: 'text', plaintext: 'text',
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/** A language's id from any of its names (an unknown name as it is, lowercased; "" for none). */
|
|
31
|
+
export const languageId = (name) => {
|
|
32
|
+
const id = String(name ?? '').trim().toLowerCase();
|
|
33
|
+
return ALIASES[id] ?? id;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/** Whether the kit knows a language by this name. */
|
|
37
|
+
export const knownLanguage = (name) => LANGUAGES.some((language) => language.id === languageId(name));
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The language code looks like: one of LANGUAGES but text, or null when it looks like none of them
|
|
41
|
+
* (or is too short to tell). What a code block without a language of its own is highlighted as.
|
|
42
|
+
*/
|
|
43
|
+
export function guessLanguage(text) {
|
|
44
|
+
const code = String(text ?? '').trim();
|
|
45
|
+
if (code.replace(/\s/g, '').length < 6) return null;
|
|
46
|
+
if (/^[[{]/.test(code)) {
|
|
47
|
+
try {
|
|
48
|
+
JSON.parse(code);
|
|
49
|
+
return 'json';
|
|
50
|
+
} catch {}
|
|
51
|
+
}
|
|
52
|
+
if (/^<(!doctype|[a-z][\w-]*)([\s>]|\/>)/i.test(code) && /<\/[a-z][\w-]*>|\/>/i.test(code)) return 'html';
|
|
53
|
+
const script = /\b(const|let|var|function|return|import|export|class|new|await|async|typeof)\b|=>|console\.\w|document\.|\bwindow\./.test(code);
|
|
54
|
+
if (/^\s*(def \w+\s*\(|class \w+(\(.*\))?:\s*$|from [\w.]+ import |import [\w.]+(\s+as \w+)?\s*$|print\(|if __name__ ==|elif\b|@\w+\s*$)/m.test(code) && !/[{};]\s*$/m.test(code)) return 'python';
|
|
55
|
+
if (/^\s*(select\b[\s\S]*\bfrom\b|insert\s+into\b|update\s+\w+\s+set\b|delete\s+from\b|create\s+(table|view|index)\b|with\s+\w+\s+as\s*\()/im.test(code)) return 'sql';
|
|
56
|
+
if (/^\s*(\$ |#!\/|(npm|npx|pnpm|yarn|git|cd|ls|echo|curl|wget|sudo|pip3?|brew|apt(-get)?|docker|kubectl|mkdir|rm|cp|mv|cat|grep|chmod|export)\s)/m.test(code) && !script) return 'bash';
|
|
57
|
+
if (/^\s*[^{};\n]+\{\s*[\w-]+\s*:[^;{}]+;?/m.test(code) && !script) return 'css';
|
|
58
|
+
if (script) {
|
|
59
|
+
// JSX: an element closed, or closing itself (a type's <T> closes nothing).
|
|
60
|
+
const jsx = /<\/[A-Za-z][\w.]*>|<[A-Za-z][\w.]*(\s[^<>]*)?\/>/.test(code);
|
|
61
|
+
// TypeScript: a type declared, a parameter's or a return type, a basic type named, `as const`, an enum.
|
|
62
|
+
const typed = /\b(interface|type)\s+\w+\s*[={<]|\(\s*\w+\??\s*:\s*[\w<[\]|]+|\)\s*:\s*[\w<[\]|]+\s*(=>|\{)|\w\s*:\s*(string|number|boolean|void|unknown|any|never)\b|\bas\s+const\b|\benum\s+\w+/.test(code);
|
|
63
|
+
return typed ? (jsx ? 'tsx' : 'typescript') : jsx ? 'jsx' : 'javascript';
|
|
64
|
+
}
|
|
65
|
+
const lines = code.split('\n').filter((line) => line.trim() && !line.trim().startsWith('#'));
|
|
66
|
+
const keyed = /^\s*(- )?[\w"'.-]+:(\s|$)/;
|
|
67
|
+
if (lines.length > 1 && lines.every((line) => keyed.test(line) || /^\s*- \S/.test(line)) && lines.some((line) => keyed.test(line))) return 'yaml';
|
|
68
|
+
if (/^#{1,6}\s+\S/m.test(code) || /^```/m.test(code) || /\[[^\]\n]+\]\([^)\s]+\)/.test(code) || /\*\*[^*\n]+\*\*/.test(code)) return 'markdown';
|
|
69
|
+
return null;
|
|
70
|
+
}
|