@heycys/gallery 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD-PARTY-NOTICES.md +2 -2
- package/browser/editor/components/align.mjs +58 -0
- package/browser/editor/components/code/index.mjs +1 -1
- package/browser/editor/components/columns/page.mjs +4 -4
- package/browser/editor/components/embed/index.mjs +2 -2
- package/browser/editor/components/embed/page.mjs +1 -1
- package/browser/editor/components/file/page.mjs +4 -4
- package/browser/editor/components/flowchart/add.mjs +7 -6
- package/browser/editor/components/flowchart/page.mjs +1 -1
- package/browser/editor/components/heading/index.mjs +7 -6
- package/browser/editor/components/icons.mjs +11 -0
- package/browser/editor/components/image/crop.mjs +6 -9
- package/browser/editor/components/image/index.mjs +2 -0
- package/browser/editor/components/image/page.mjs +172 -90
- package/browser/editor/components/installed/index.mjs +15 -4
- package/browser/editor/components/installed/page.mjs +103 -25
- package/browser/editor/components/installed/served.mjs +6 -5
- package/browser/editor/components/instances.mjs +18 -0
- package/browser/editor/components/list/page.mjs +3 -6
- package/browser/editor/components/media/icons.mjs +13 -8
- package/browser/editor/components/media/page.mjs +5 -3
- package/browser/editor/components/media/toolbar.mjs +12 -3
- package/browser/editor/components/paragraph/index.mjs +4 -3
- package/browser/editor/components/registry.mjs +30 -9
- package/browser/editor/components/table/index.mjs +61 -2
- package/browser/editor/components/table/page.mjs +1 -1
- package/browser/editor/page/after/index.mjs +288 -0
- package/browser/editor/page/align.mjs +91 -0
- package/browser/editor/page/annotate/card.mjs +3 -6
- package/browser/editor/page/autosave.mjs +310 -37
- package/browser/editor/page/beside.mjs +5 -6
- package/browser/editor/page/block-menu/index.mjs +6 -3
- package/browser/editor/page/blocks.mjs +3 -1
- package/browser/editor/page/board/client.mjs +57 -0
- package/browser/editor/page/board/hint.mjs +182 -0
- package/browser/editor/page/board/history.mjs +119 -0
- package/browser/editor/page/board/index.mjs +1059 -0
- package/browser/editor/page/board/motion.mjs +177 -0
- package/browser/editor/page/board/settings.mjs +210 -0
- package/browser/editor/page/caret.mjs +1 -1
- package/browser/editor/page/changes/bar.mjs +6 -14
- package/browser/editor/page/changes/index.mjs +2 -2
- package/browser/editor/page/clipboard/import/html.mjs +29 -6
- package/browser/editor/page/clipboard/import/inline.mjs +32 -0
- package/browser/editor/page/clipboard/import/markdown.mjs +58 -13
- package/browser/editor/page/clipboard/import/read.mjs +6 -1
- package/browser/editor/page/clipboard/import/to-blocks.mjs +44 -12
- package/browser/editor/page/clipboard/import/yuque.mjs +622 -0
- package/browser/editor/page/clipboard/index.mjs +133 -15
- package/browser/editor/page/clipboard/own/blocks.mjs +13 -14
- package/browser/editor/page/clipboard/own/chart-keys.mjs +41 -28
- package/browser/editor/page/clipboard/own/describe.mjs +6 -2
- package/browser/editor/page/clipboard/own/selection.mjs +1 -1
- package/browser/editor/page/columns/index.mjs +48 -46
- package/browser/editor/page/commit.mjs +80 -22
- package/browser/editor/page/conflicts.mjs +7 -7
- package/browser/editor/page/core.mjs +34 -16
- package/browser/editor/page/custom-page.mjs +110 -0
- package/browser/editor/page/editor.mjs +71 -17
- package/browser/editor/page/emoji-picker/styles.mjs +7 -12
- package/browser/editor/page/emoji-picker/upload.mjs +2 -2
- package/browser/editor/page/handle/index.mjs +5 -8
- package/browser/editor/page/history.mjs +41 -6
- package/browser/editor/page/insert/index.mjs +20 -22
- package/browser/editor/page/links/index.mjs +5 -3
- package/browser/editor/page/links/pages.mjs +27 -9
- package/browser/editor/page/look.mjs +54 -3
- package/browser/editor/page/margin.mjs +18 -3
- package/browser/editor/page/media-menu/index.mjs +6 -7
- package/browser/editor/page/menu.mjs +33 -14
- package/browser/editor/page/notices.mjs +2 -2
- package/browser/editor/page/page-objects.mjs +9 -2
- package/browser/editor/page/panel.mjs +4 -9
- package/browser/editor/page/present-links.mjs +15 -5
- package/browser/editor/page/present-shell.mjs +63 -0
- package/browser/editor/page/resize/index.mjs +42 -29
- package/browser/editor/page/selection/index.mjs +10 -2
- package/browser/editor/page/served.mjs +14 -0
- package/browser/editor/page/session.mjs +48 -4
- package/browser/editor/page/slash-menu/index.mjs +3 -3
- package/browser/editor/page/table/binding.mjs +87 -0
- package/browser/editor/page/table/cells.mjs +102 -46
- package/browser/editor/page/table/index.mjs +24 -9
- package/browser/editor/page/table/pictures.mjs +299 -0
- package/browser/editor/page/table/views.mjs +103 -0
- package/browser/editor/page/table/widths.mjs +82 -10
- package/browser/editor/page/text-select/index.mjs +26 -12
- package/browser/editor/page/todo-writes.mjs +75 -0
- package/browser/editor/page/typing/index.mjs +97 -15
- package/browser/editor/page/typing/leave.mjs +19 -5
- package/browser/editor/page/ui.mjs +13 -0
- package/browser/shared/block-packs.mjs +419 -0
- package/browser/shared/board-places.mjs +224 -0
- package/browser/shared/card-size.mjs +59 -0
- package/browser/shared/colors.mjs +3 -2
- package/browser/shared/component-catalog.mjs +330 -46
- package/browser/shared/component-source.mjs +39 -0
- package/browser/shared/components/heading.mjs +2 -1
- package/browser/shared/components/index.mjs +12 -3
- package/browser/shared/components/installed.mjs +35 -3
- package/browser/shared/components/page.mjs +20 -8
- package/browser/shared/components/paragraph.mjs +8 -1
- package/browser/shared/components/state.mjs +5 -1
- package/browser/shared/components/table.mjs +1 -0
- package/browser/shared/document-look.mjs +10 -5
- package/browser/shared/drafts.mjs +432 -0
- package/browser/shared/emoji/line-icons.mjs +37 -0
- package/browser/shared/extension-sidebar.mjs +126 -0
- package/browser/shared/extensions.mjs +79 -0
- package/browser/shared/file-table.mjs +101 -0
- package/browser/shared/http.mjs +9 -0
- package/browser/shared/i18n/en.mjs +330 -27
- package/browser/shared/json-layout.mjs +47 -0
- package/browser/shared/net-cache.mjs +133 -0
- package/browser/shared/net-keys.mjs +32 -0
- package/browser/shared/net-policy.mjs +177 -0
- package/browser/shared/outline-shape.mjs +128 -0
- package/browser/shared/outline.mjs +359 -67
- package/browser/shared/pack-manifest.mjs +88 -0
- package/browser/shared/page-address.mjs +6 -3
- package/browser/shared/page-cards.mjs +308 -0
- package/browser/shared/page-links.mjs +69 -6
- package/browser/shared/pages.mjs +500 -0
- package/browser/shared/paths.mjs +6 -0
- package/browser/shared/pinyin.mjs +92 -0
- package/browser/shared/present-step.mjs +17 -0
- package/browser/shared/preview-server.mjs +3 -7
- package/browser/shared/session.mjs +8 -1
- package/browser/shared/shipped-blocks.mjs +299 -0
- package/browser/shared/sidebar-head.mjs +70 -0
- package/browser/shared/table-chart.mjs +33 -1
- package/browser/shared/todos.mjs +83 -0
- package/browser/shared/user-directory.mjs +24 -0
- package/browser/shared/versions.mjs +14 -0
- package/browser/shared/web-links.mjs +139 -0
- package/browser/shared/workspace-columns.mjs +120 -0
- package/browser/shared/workspace-name.mjs +154 -0
- package/browser/shared/workspace-query.mjs +125 -0
- package/browser/shared/workspace-registry.mjs +272 -0
- package/browser/shared/workspace.mjs +171 -20
- package/dist/chunk-2OHANJ6Q.mjs +2 -0
- package/dist/chunk-3MBRL2PM.mjs +16 -0
- package/dist/chunk-4OKWZY5E.mjs +2 -0
- package/dist/chunk-4OZWXZE5.mjs +5 -0
- package/dist/chunk-5K44HLTZ.mjs +2 -0
- package/dist/{chunk-5ZKJ3H4P.mjs → chunk-5XA2ZBAE.mjs} +3 -3
- package/dist/{chunk-4FS7Z7WR.mjs → chunk-67N2QJYT.mjs} +1 -1
- package/dist/chunk-6KBYRA2C.mjs +2 -0
- package/dist/chunk-6N3PX4XX.mjs +8 -0
- package/dist/{chunk-V5JTW2LH.mjs → chunk-6QBHU4DF.mjs} +1 -1
- package/dist/chunk-7JDX4E65.mjs +13 -0
- package/dist/chunk-7M2BQQGZ.mjs +2 -0
- package/dist/chunk-7OG26PGF.mjs +2 -0
- package/dist/chunk-AHN3NFKJ.mjs +3 -0
- package/dist/chunk-ALZ6ZENZ.mjs +3 -0
- package/dist/chunk-AR5D57ZD.mjs +170 -0
- package/dist/{chunk-W3BGBJQW.mjs → chunk-BFJGHSQN.mjs} +1 -1
- package/dist/{chunk-LS4F7JUM.mjs → chunk-BZ5RAF7L.mjs} +1 -1
- package/dist/chunk-CMA72MAG.mjs +2 -0
- package/dist/{chunk-LCTHTZIL.mjs → chunk-DAZL73VK.mjs} +91 -91
- package/dist/{chunk-Y6RLRPG3.mjs → chunk-DJISHPUL.mjs} +1 -1
- package/dist/chunk-DR73Y2UJ.mjs +3 -0
- package/dist/{chunk-FDLXYYG4.mjs → chunk-EAIFITAV.mjs} +1 -1
- package/dist/{chunk-TMYZB6AV.mjs → chunk-EKNHM3P4.mjs} +1 -1
- package/dist/chunk-EP25HDAJ.mjs +2 -0
- package/dist/{chunk-GB5SOYQJ.mjs → chunk-ERLAIBOA.mjs} +2 -2
- package/dist/chunk-EURLTOTZ.mjs +4 -0
- package/dist/chunk-F4ZA6JRZ.mjs +3 -0
- package/dist/chunk-F6HVDZR4.mjs +2 -0
- package/dist/chunk-FDMAXMQA.mjs +2 -0
- package/dist/chunk-FETSREUN.mjs +5 -0
- package/dist/chunk-GHOYKMQ3.mjs +4 -0
- package/dist/{chunk-2B5E4CDJ.mjs → chunk-GPIWQ4X4.mjs} +1 -1
- package/dist/chunk-HDWTZ763.mjs +12 -0
- package/dist/chunk-HPOI4ZX7.mjs +6 -0
- package/dist/{chunk-BGGDRNYQ.mjs → chunk-HXG7EOPJ.mjs} +1 -1
- package/dist/chunk-IA4PSIMD.mjs +2 -0
- package/dist/{chunk-E7LWZRXY.mjs → chunk-ITOH5EGO.mjs} +1 -1
- package/dist/chunk-IV64FFI4.mjs +2 -0
- package/dist/chunk-J43Z6LSS.mjs +2 -0
- package/dist/chunk-J5PUIV3Y.mjs +4 -0
- package/dist/chunk-JA7G53PC.mjs +2 -0
- package/dist/chunk-JEUK3ZO7.mjs +2 -0
- package/dist/chunk-JLTZF4LA.mjs +2 -0
- package/dist/chunk-JZT7I2OJ.mjs +2 -0
- package/dist/chunk-K5XATEOO.mjs +2 -0
- package/dist/chunk-L2SUIS5S.mjs +2 -0
- package/dist/chunk-L7UP52JO.mjs +2 -0
- package/dist/chunk-LM4XFQHZ.mjs +2 -0
- package/dist/chunk-MN7BZL4R.mjs +2 -0
- package/dist/chunk-MTYYHM2G.mjs +15 -0
- package/dist/chunk-MXUBKDRO.mjs +15 -0
- package/dist/chunk-NAMN3RAF.mjs +2 -0
- package/dist/{chunk-SYGN7GLU.mjs → chunk-OEXWRJME.mjs} +1 -1
- package/dist/chunk-OFHXGWOX.mjs +2 -0
- package/dist/chunk-ORID3AE7.mjs +166 -0
- package/dist/chunk-PAREWQGB.mjs +4 -0
- package/dist/chunk-PGDE24N5.mjs +2 -0
- package/dist/chunk-POTA2FV4.mjs +2 -0
- package/dist/chunk-PUOQ65NC.mjs +2 -0
- package/dist/chunk-Q4UEPUWF.mjs +2 -0
- package/dist/chunk-QE5RG76S.mjs +549 -0
- package/dist/chunk-R2ZDLJYT.mjs +10 -0
- package/dist/{chunk-7DTINW6U.mjs → chunk-SQ6Y2ZMA.mjs} +2 -2
- package/dist/chunk-SWUTTZCN.mjs +2 -0
- package/dist/chunk-TANZRINB.mjs +2 -0
- package/dist/chunk-TR7TWGHB.mjs +2 -0
- package/dist/chunk-U5XL7D6A.mjs +3 -0
- package/dist/{chunk-XNROSH2T.mjs → chunk-U7NZI6N4.mjs} +2 -2
- package/dist/chunk-UGWMMEJ5.mjs +15 -0
- package/dist/chunk-UJQJKNGK.mjs +2 -0
- package/dist/chunk-UYVCQK3H.mjs +22 -0
- package/dist/chunk-VFX2KNHP.mjs +4 -0
- package/dist/chunk-VS7JIGJW.mjs +24 -0
- package/dist/chunk-W7665ZEC.mjs +6 -0
- package/dist/chunk-WQDQWCX5.mjs +2 -0
- package/dist/chunk-YI43RG4P.mjs +2 -0
- package/dist/chunk-YLPSMDIS.mjs +5 -0
- package/dist/chunk-YNAWBAYN.mjs +3 -0
- package/dist/chunk-YROX2O22.mjs +2 -0
- package/dist/chunk-ZDLPUOAG.mjs +6 -0
- package/dist/{chunk-IVDLMMBD.mjs → chunk-ZHEHPMBK.mjs} +1 -1
- package/dist/chunk-ZQS6H473.mjs +16 -0
- package/dist/chunk-ZTHICSSF.mjs +2 -0
- package/dist/chunk-ZWWC4KLF.mjs +20 -0
- package/dist/cli.mjs +1 -1
- package/dist/server.mjs +1 -1
- package/dist/{chunk-U6KNPJPR.mjs → update-fetch.mjs} +1 -1
- package/dist/worker.mjs +1 -1
- package/kit/board.css +95 -0
- package/kit/board.js +250 -0
- package/kit/charts.js +5 -71
- package/kit/code.js +17 -17
- package/kit/report.css +335 -18
- package/kit/runtime.js +1638 -125
- package/kit/state.js +10 -1
- package/kit/tables.js +130 -43
- package/kit/ui.js +79 -35
- package/package.json +2 -1
- package/packs/gallery/card/component.json +14 -0
- package/packs/gallery/card/example.html +10 -0
- package/packs/gallery/card/preview.svg +1 -0
- package/packs/gallery/card/style.css +6 -0
- package/packs/gallery/card/template.html +6 -0
- package/packs/gallery/card/writing.md +14 -0
- package/packs/gallery/chart-card/component.json +15 -0
- package/packs/gallery/chart-card/example.html +14 -0
- package/packs/gallery/chart-card/kit.js +130 -0
- package/packs/gallery/chart-card/preview.svg +1 -0
- package/packs/gallery/chart-card/style.css +42 -0
- package/packs/gallery/chart-card/template.html +13 -0
- package/packs/gallery/chart-card/writing.md +20 -0
- package/packs/gallery/chart-view/component.json +20 -0
- package/packs/gallery/chart-view/example.html +13 -0
- package/packs/gallery/chart-view/kit.js +355 -0
- package/packs/gallery/chart-view/preview.svg +1 -0
- package/packs/gallery/chart-view/style.css +94 -0
- package/packs/gallery/chart-view/template.html +3 -0
- package/packs/gallery/chart-view/writing.md +22 -0
- package/packs/gallery/countdown/component.json +18 -0
- package/packs/gallery/countdown/example.html +3 -0
- package/packs/gallery/countdown/kit.js +216 -0
- package/packs/gallery/countdown/preview.svg +1 -0
- package/packs/gallery/countdown/style.css +118 -0
- package/packs/gallery/countdown/template.html +3 -0
- package/packs/gallery/countdown/writing.md +22 -0
- package/packs/gallery/habit/component.json +14 -0
- package/packs/gallery/habit/example.html +3 -0
- package/packs/gallery/habit/kit.js +334 -0
- package/packs/gallery/habit/preview.svg +1 -0
- package/packs/gallery/habit/style.css +174 -0
- package/packs/gallery/habit/template.html +3 -0
- package/packs/gallery/habit/writing.md +21 -0
- package/packs/gallery/heatmap/component.json +18 -0
- package/packs/gallery/heatmap/example.html +3 -0
- package/packs/gallery/heatmap/kit.js +513 -0
- package/packs/gallery/heatmap/preview.svg +1 -0
- package/packs/gallery/heatmap/style.css +189 -0
- package/packs/gallery/heatmap/template.html +3 -0
- package/packs/gallery/heatmap/writing.md +21 -0
- package/packs/gallery/kanban/component.json +18 -0
- package/packs/gallery/kanban/example.html +12 -0
- package/packs/gallery/kanban/kit.js +540 -0
- package/packs/gallery/kanban/preview.svg +1 -0
- package/packs/gallery/kanban/style.css +212 -0
- package/packs/gallery/kanban/template.html +3 -0
- package/packs/gallery/kanban/writing.md +20 -0
- package/packs/gallery/metric/component.json +22 -0
- package/packs/gallery/metric/example.html +15 -0
- package/packs/gallery/metric/kit.js +248 -0
- package/packs/gallery/metric/preview.svg +1 -0
- package/packs/gallery/metric/style.css +92 -0
- package/packs/gallery/metric/template.html +3 -0
- package/packs/gallery/metric/writing.md +23 -0
- package/packs/gallery/note/component.json +14 -0
- package/packs/gallery/note/example.html +3 -0
- package/packs/gallery/note/kit.js +129 -0
- package/packs/gallery/note/preview.svg +1 -0
- package/packs/gallery/note/style.css +97 -0
- package/packs/gallery/note/template.html +3 -0
- package/packs/gallery/note/writing.md +18 -0
- package/packs/gallery/pack.json +8 -0
- package/packs/gallery/recent/component.json +13 -0
- package/packs/gallery/recent/example.html +1 -0
- package/packs/gallery/recent/kit.js +293 -0
- package/packs/gallery/recent/preview.svg +1 -0
- package/packs/gallery/recent/style.css +85 -0
- package/packs/gallery/recent/template.html +1 -0
- package/packs/gallery/recent/writing.md +15 -0
- package/packs/gallery/static/component.json +13 -0
- package/packs/gallery/static/example.html +11 -0
- package/packs/gallery/static/preview.svg +1 -0
- package/packs/gallery/static/style.css +171 -0
- package/packs/gallery/static/template.html +1 -0
- package/packs/gallery/static/writing.md +18 -0
- package/packs/gallery/stats/component.json +13 -0
- package/packs/gallery/stats/example.html +1 -0
- package/packs/gallery/stats/kit.js +347 -0
- package/packs/gallery/stats/preview.svg +1 -0
- package/packs/gallery/stats/style.css +73 -0
- package/packs/gallery/stats/template.html +1 -0
- package/packs/gallery/stats/writing.md +11 -0
- package/packs/gallery/today/component.json +12 -0
- package/packs/gallery/today/example.html +1 -0
- package/packs/gallery/today/kit.js +220 -0
- package/packs/gallery/today/preview.svg +1 -0
- package/packs/gallery/today/style.css +149 -0
- package/packs/gallery/today/template.html +1 -0
- package/packs/gallery/today/writing.md +14 -0
- package/packs/gallery/todos/component.json +19 -0
- package/packs/gallery/todos/example.html +3 -0
- package/packs/gallery/todos/kit.js +489 -0
- package/packs/gallery/todos/preview.svg +1 -0
- package/packs/gallery/todos/style.css +214 -0
- package/packs/gallery/todos/template.html +3 -0
- package/packs/gallery/todos/writing.md +30 -0
- package/packs/gallery/weather/component.json +19 -0
- package/packs/gallery/weather/example.html +3 -0
- package/packs/gallery/weather/kit.js +387 -0
- package/packs/gallery/weather/preview.svg +1 -0
- package/packs/gallery/weather/style.css +140 -0
- package/packs/gallery/weather/template.html +3 -0
- package/packs/gallery/weather/writing.md +26 -0
- package/packs/gallery-soft/countdown/component.json +18 -0
- package/packs/gallery-soft/countdown/example.html +3 -0
- package/packs/gallery-soft/countdown/kit.js +206 -0
- package/packs/gallery-soft/countdown/preview.svg +1 -0
- package/packs/gallery-soft/countdown/style.css +211 -0
- package/packs/gallery-soft/countdown/template.html +3 -0
- package/packs/gallery-soft/countdown/writing.md +24 -0
- package/packs/gallery-soft/habit/component.json +14 -0
- package/packs/gallery-soft/habit/example.html +3 -0
- package/packs/gallery-soft/habit/kit.js +366 -0
- package/packs/gallery-soft/habit/preview.svg +1 -0
- package/packs/gallery-soft/habit/style.css +251 -0
- package/packs/gallery-soft/habit/template.html +3 -0
- package/packs/gallery-soft/habit/writing.md +23 -0
- package/packs/gallery-soft/heatmap/component.json +18 -0
- package/packs/gallery-soft/heatmap/example.html +3 -0
- package/packs/gallery-soft/heatmap/kit.js +498 -0
- package/packs/gallery-soft/heatmap/preview.svg +1 -0
- package/packs/gallery-soft/heatmap/style.css +181 -0
- package/packs/gallery-soft/heatmap/template.html +3 -0
- package/packs/gallery-soft/heatmap/writing.md +23 -0
- package/packs/gallery-soft/note/component.json +14 -0
- package/packs/gallery-soft/note/example.html +3 -0
- package/packs/gallery-soft/note/kit.js +162 -0
- package/packs/gallery-soft/note/preview.svg +1 -0
- package/packs/gallery-soft/note/style.css +148 -0
- package/packs/gallery-soft/note/template.html +3 -0
- package/packs/gallery-soft/note/writing.md +20 -0
- package/packs/gallery-soft/pack.json +8 -0
- package/packs/gallery-soft/recent/component.json +13 -0
- package/packs/gallery-soft/recent/example.html +1 -0
- package/packs/gallery-soft/recent/kit.js +335 -0
- package/packs/gallery-soft/recent/preview.svg +1 -0
- package/packs/gallery-soft/recent/style.css +160 -0
- package/packs/gallery-soft/recent/template.html +1 -0
- package/packs/gallery-soft/recent/writing.md +17 -0
- package/packs/gallery-soft/static/component.json +13 -0
- package/packs/gallery-soft/static/example.html +12 -0
- package/packs/gallery-soft/static/preview.svg +1 -0
- package/packs/gallery-soft/static/style.css +186 -0
- package/packs/gallery-soft/static/template.html +1 -0
- package/packs/gallery-soft/static/writing.md +20 -0
- package/packs/gallery-soft/stats/component.json +13 -0
- package/packs/gallery-soft/stats/example.html +1 -0
- package/packs/gallery-soft/stats/kit.js +341 -0
- package/packs/gallery-soft/stats/preview.svg +1 -0
- package/packs/gallery-soft/stats/style.css +119 -0
- package/packs/gallery-soft/stats/template.html +1 -0
- package/packs/gallery-soft/stats/writing.md +13 -0
- package/packs/gallery-soft/today/component.json +12 -0
- package/packs/gallery-soft/today/example.html +1 -0
- package/packs/gallery-soft/today/kit.js +222 -0
- package/packs/gallery-soft/today/preview.svg +1 -0
- package/packs/gallery-soft/today/style.css +178 -0
- package/packs/gallery-soft/today/template.html +1 -0
- package/packs/gallery-soft/today/writing.md +16 -0
- package/packs/gallery-soft/todos/component.json +19 -0
- package/packs/gallery-soft/todos/example.html +3 -0
- package/packs/gallery-soft/todos/kit.js +527 -0
- package/packs/gallery-soft/todos/preview.svg +1 -0
- package/packs/gallery-soft/todos/style.css +212 -0
- package/packs/gallery-soft/todos/template.html +3 -0
- package/packs/gallery-soft/todos/writing.md +32 -0
- package/packs/gallery-soft/weather/component.json +19 -0
- package/packs/gallery-soft/weather/example.html +3 -0
- package/packs/gallery-soft/weather/kit.js +411 -0
- package/packs/gallery-soft/weather/preview.svg +1 -0
- package/packs/gallery-soft/weather/style.css +185 -0
- package/packs/gallery-soft/weather/template.html +3 -0
- package/packs/gallery-soft/weather/writing.md +28 -0
- package/release.json +12 -10
- package/sdk/doc-kit.d.ts +396 -5
- package/sdk/doc-state.d.ts +2 -0
- package/skill/SKILL.md +56 -23
- package/skill/references/block-script.md +140 -0
- package/skill/references/building-blocks.md +257 -0
- package/skill/references/extensions.md +59 -0
- package/skill/references/pages-and-data.md +225 -0
- package/skill/references/writing-html.md +8 -4
- package/skill/sdk/doc-kit.d.ts +396 -5
- package/skill/sdk/doc-state.d.ts +2 -0
- package/web/assets/index-BM_K-Auu.css +1 -0
- package/web/assets/index-DRslOBiv.js +15 -0
- package/web/index.html +2 -2
- package/dist/chunk-3HIRPVLU.mjs +0 -2
- package/dist/chunk-5MHMDLZD.mjs +0 -4
- package/dist/chunk-64K7IPLO.mjs +0 -255
- package/dist/chunk-6QXGZM36.mjs +0 -8
- package/dist/chunk-6RGJOMJP.mjs +0 -16
- package/dist/chunk-AJ73XJF3.mjs +0 -2
- package/dist/chunk-AUZGSZJH.mjs +0 -13
- package/dist/chunk-BFE45AKL.mjs +0 -2
- package/dist/chunk-BXO2ZY5P.mjs +0 -2
- package/dist/chunk-CEH4MRCC.mjs +0 -2
- package/dist/chunk-CY2FNNAB.mjs +0 -16
- package/dist/chunk-DFUDV4LX.mjs +0 -2
- package/dist/chunk-DKXG4XDG.mjs +0 -2
- package/dist/chunk-EZQ34M3F.mjs +0 -124
- package/dist/chunk-EZY3WC6Z.mjs +0 -15
- package/dist/chunk-FUKQNOQS.mjs +0 -9
- package/dist/chunk-JPOSLGOC.mjs +0 -6
- package/dist/chunk-JVHHHGEA.mjs +0 -3
- package/dist/chunk-L3QKH4OK.mjs +0 -26
- package/dist/chunk-LAE5NQ4B.mjs +0 -2
- package/dist/chunk-LEF6DRCK.mjs +0 -59
- package/dist/chunk-NO5NJCHO.mjs +0 -2
- package/dist/chunk-NQPVAU63.mjs +0 -2
- package/dist/chunk-NSKUTQ5J.mjs +0 -5
- package/dist/chunk-O35FIXRB.mjs +0 -2
- package/dist/chunk-P2CAZPDP.mjs +0 -3
- package/dist/chunk-PL6GHLGD.mjs +0 -15
- package/dist/chunk-QJIR2BLP.mjs +0 -6
- package/dist/chunk-QUPLVPB2.mjs +0 -7
- package/dist/chunk-R7BNENLY.mjs +0 -4
- package/dist/chunk-S6O4UHLC.mjs +0 -2
- package/dist/chunk-SGJWQKEI.mjs +0 -2
- package/dist/chunk-TX6JH7TR.mjs +0 -2
- package/dist/chunk-TYK6VNAB.mjs +0 -10
- package/dist/chunk-UALRNVSE.mjs +0 -4
- package/dist/chunk-V3HXVQEM.mjs +0 -2
- package/dist/chunk-V5VXUJKG.mjs +0 -2
- package/dist/chunk-VBXMADMP.mjs +0 -2
- package/dist/chunk-VNV55RUA.mjs +0 -2
- package/dist/chunk-VPD2PS35.mjs +0 -2
- package/dist/chunk-W4VKN3GF.mjs +0 -7
- package/dist/chunk-W5BXXPDJ.mjs +0 -3
- package/dist/chunk-XUNHRCOG.mjs +0 -6
- package/skill/references/building-components.md +0 -367
- package/web/assets/index-Bh74DfsV.css +0 -1
- package/web/assets/index-UW0RyFFt.js +0 -13
package/kit/runtime.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
var define_COMPONENT_FLOWS_default = [".doc-page", ".doc-section", ".doc-summary", ".doc-panel", ".doc-callout", ".doc-details-content", ".doc-dialog-content", "[data-doc-sheet]", ".doc-column", "[data-doc-slot]"];
|
|
5
5
|
|
|
6
6
|
// <define:__COMPONENT_RUNTIME__>
|
|
7
|
-
var define_COMPONENT_RUNTIME_default = [{ id: "page", match: "main.doc-page", runtime: { generated: [".doc-display", "script[data-doc-state]"], root: { attrs: ["data-doc-ready", "data-doc-drawn", "data-doc-controls"] }, state: { html: ["data-doc-theme", "data-doc-
|
|
7
|
+
var define_COMPONENT_RUNTIME_default = [{ id: "page", match: "main.doc-page", runtime: { generated: [".doc-display", "script[data-doc-state]"], root: { attrs: ["data-doc-ready", "data-doc-drawn", "data-doc-controls", "data-doc-effective-theme", "data-doc-platform"] }, state: { html: ["data-doc-theme", "data-doc-font", "data-doc-size", "data-doc-spacing", "data-doc-measure", "data-doc-width"] }, internal: ["doc-display*", "data-doc-export-copy", "data-theme", "doc-export-id", "doc-reveal", "doc-kit-error", "doc-net-consent*", "data-doc-snapshot", "data-doc-net-narrow", "data-at", "data-x", "data-y", "data-w", "data-h", "data-columns"] } }, { id: "text", runtime: { classes: { ".doc-range": ["doc-range"], ".doc-long-run": ["doc-long-run"] } } }, { id: "mention", runtime: { attrs: { "a.doc-link-mention": ["data-doc-gone"] } } }, { id: "paragraph", match: "p" }, { id: "heading", match: "h1, h2, h3, h4" }, { id: "list", match: "ul, ol", runtime: { attrs: { "ol.doc-flow": ["data-doc-flow-key", "data-doc-flow-recount"] }, generated: ["br.doc-item-line"] } }, { id: "quote", match: "blockquote" }, { id: "code", match: ".doc-code", runtime: { generated: [".doc-code-fold", ".doc-code-range", ".doc-code-tools"], internal: ["doc-code-lines", "doc-code-line*", "doc-code-content", "doc-code-toolbar", "doc-code-language", "doc-code-separator", "doc-code-copy*", "doc-code-wrap*", "data-line-number"] } }, { id: "divider", match: "hr" }, { id: "math", match: ".doc-math-inline, .doc-math-block", runtime: { generated: [".doc-math-break", ".doc-math-joiner"], classes: { ".doc-math-tie": ["doc-math-tie"], ".doc-math-skip": ["doc-math-skip"] } } }, { id: "section", match: "section.doc-section" }, { id: "highlight", match: ".doc-panel, .doc-summary" }, { id: "callout", match: ".doc-callout" }, { id: "details", match: "details.doc-details" }, { id: "dialog", match: "dialog.doc-dialog", runtime: { attrs: { "dialog.doc-dialog": ["data-doc-dialog-ready", "open", "aria-label"], ".doc-dialog-content": ["tabindex"] }, root: { classes: ["doc-dialog-open", "doc-dialog-gutter"] }, internal: ["doc-dialog-in", "doc-dialog-fade"] } }, { id: "sheets", match: "[data-doc-sheets]", runtime: { state: { "[data-doc-sheets]": ["data-active-sheet"], "[data-sheet-tab]": ["aria-selected", "tabindex", "is-active"], "[data-doc-sheet]": ["hidden", "aria-hidden"] }, internal: ["doc-sheets"] } }, { id: "table", match: "table.doc-table", runtime: { generated: ["colgroup[data-doc-columns]", ".doc-scrollbars"], attrs: { "table.doc-table": ["data-doc-sortable-ready", "data-doc-filled"], ".doc-table-wrap": ["data-doc-min-width", "data-doc-layout", "data-doc-whole"], "th, td": ["data-column-kind", "data-column-wrap", "data-run-wrap", "data-doc-edge"] }, classes: { "table.doc-table": ["doc-table--auto"] }, internal: ["doc-code-run", "doc-table-sort-button", "doc-scrollbar*", "data-doc-sort-arrow", "data-active", "data-drag", "data-x", "data-y", "data-more"] } }, { id: "columns", match: ".doc-columns" }, { id: "figure", match: "figure" }, { id: "chart", match: "[data-doc-chart]", runtime: { attrs: { "[data-doc-chart]": ["data-doc-layout"] }, classes: { "[data-doc-chart]": ["doc-chart"] }, internal: ["doc-chart-message", "data-missing"] } }, { id: "image", match: "figure.doc-image", runtime: { generated: ["dialog.doc-zoom"], attrs: { "img[data-doc-zoom]": ["data-doc-zoom", "tabindex", "role", "aria-haspopup", "aria-label"] }, root: { classes: ["doc-zoom-open", "doc-zoom-gutter", "doc-zoom-hover"] }, internal: ["doc-zoom-*"] } }, { id: "file", match: "figure.doc-file" }, { id: "bookmark", match: "figure.doc-bookmark" }, { id: "embed", match: "figure.doc-embed", runtime: { attrs: { "iframe.doc-embed-frame": ["data-doc-blob"] } } }, { id: "diff", match: ".doc-diff", runtime: { generated: [".doc-diff-body", ".doc-diff-stats"], internal: ["doc-diff-added", "doc-diff-removed"] } }, { id: "icon", match: ".doc-icon", runtime: { internal: ["data-doc-tab-icon"] } }, { id: "installed", match: "div[data-doc-component], section[data-doc-component]", runtime: { generated: [".doc-component-note", ".doc-component-data"], attrs: { "[data-doc-fallback]": ["data-doc-fallback"], "[data-doc-fallback-control]": ["data-doc-fallback-control", "inert"] }, internal: ["data-doc-package", "doc-component-more", "doc-component-one", "doc-component-line", "doc-component-short", "doc-dragging"] } }, { id: "state", match: "[data-doc-bind], [data-doc-show]", runtime: { generated: [".doc-choice"], attrs: { "[data-doc-show]": ["hidden"] }, state: { "button[data-doc-bind]": ["aria-pressed"] }, internal: ["doc-choice-*"] } }];
|
|
8
8
|
|
|
9
9
|
// src/render/kit/runtime/bindings.js
|
|
10
10
|
var global = globalThis;
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
let state = null;
|
|
27
27
|
const later = /* @__PURE__ */ new Map();
|
|
28
28
|
const listeners = /* @__PURE__ */ new Set();
|
|
29
|
-
function
|
|
29
|
+
function open2() {
|
|
30
30
|
if (state) return state;
|
|
31
31
|
if (!global.DocState) throw new Error("State bindings require /kit/state.js to be loaded.");
|
|
32
32
|
const defaults = {};
|
|
@@ -49,11 +49,11 @@
|
|
|
49
49
|
});
|
|
50
50
|
return state;
|
|
51
51
|
}
|
|
52
|
-
const known = (key) => later.has(key) || Object.prototype.hasOwnProperty.call(
|
|
52
|
+
const known = (key) => later.has(key) || Object.prototype.hasOwnProperty.call(open2().snapshot(), key);
|
|
53
53
|
const store = {
|
|
54
54
|
get(key) {
|
|
55
55
|
if (later.has(key)) return later.get(key);
|
|
56
|
-
return
|
|
56
|
+
return open2().get(key, "");
|
|
57
57
|
},
|
|
58
58
|
set(key, value) {
|
|
59
59
|
if (!known(key)) later.set(key, value);
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
for (const listener of listeners) listener(key);
|
|
63
63
|
return;
|
|
64
64
|
}
|
|
65
|
-
if (JSON.stringify(
|
|
65
|
+
if (JSON.stringify(open2().get(key)) !== JSON.stringify(value)) open2().set(key, value);
|
|
66
66
|
},
|
|
67
67
|
/** Calls listener(key) when a key changes; returns what stops it. */
|
|
68
68
|
subscribe(listener) {
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
const key = element.getAttribute("data-doc-bind").trim();
|
|
76
76
|
if (!key) return null;
|
|
77
77
|
if (!known(key)) later.set(key, initial(element) ?? "");
|
|
78
|
-
const
|
|
78
|
+
const show2 = () => {
|
|
79
79
|
const value = store.get(key);
|
|
80
80
|
if (element.localName === "details") {
|
|
81
81
|
if (element.open !== Boolean(value)) element.open = Boolean(value);
|
|
@@ -99,25 +99,286 @@
|
|
|
99
99
|
};
|
|
100
100
|
const event = element.localName === "details" ? "toggle" : element.localName === "button" ? "click" : element.localName === "select" || element.type === "checkbox" || element.type === "radio" ? "change" : "input";
|
|
101
101
|
element.addEventListener(event, write, { signal });
|
|
102
|
-
const stop = store.subscribe((changed) => changed === key &&
|
|
103
|
-
|
|
102
|
+
const stop = store.subscribe((changed) => changed === key && show2());
|
|
103
|
+
show2();
|
|
104
104
|
return { destroy: stop };
|
|
105
105
|
}
|
|
106
106
|
function bindShow(element) {
|
|
107
107
|
const { key, value } = showOf(element);
|
|
108
108
|
if (!key) return null;
|
|
109
|
-
const
|
|
109
|
+
const show2 = () => {
|
|
110
110
|
const chosen = store.get(key);
|
|
111
111
|
const hidden = chosen !== "" && chosen !== null && chosen !== void 0 && String(chosen) !== value;
|
|
112
112
|
if (element.hidden !== hidden) element.hidden = hidden;
|
|
113
113
|
};
|
|
114
|
-
const stop = store.subscribe((changed) => changed === key &&
|
|
115
|
-
|
|
114
|
+
const stop = store.subscribe((changed) => changed === key && show2());
|
|
115
|
+
show2();
|
|
116
116
|
return { destroy: stop };
|
|
117
117
|
}
|
|
118
118
|
return { store, bindControl, bindShow, CONTROLS };
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
+
// src/render/kit/runtime/choice.js
|
|
122
|
+
var MENU = "doc-choice";
|
|
123
|
+
var CHECK = '<svg class="doc-choice-check" viewBox="0 0 16 16" aria-hidden="true"><path d="m3.5 8.5 3 3 6-7"/></svg>';
|
|
124
|
+
var GAP = 4;
|
|
125
|
+
var EDGE = 8;
|
|
126
|
+
var LEAST_HEIGHT = 96;
|
|
127
|
+
var TYPING = 700;
|
|
128
|
+
var open = null;
|
|
129
|
+
function rowsOf(options) {
|
|
130
|
+
const rows = [];
|
|
131
|
+
for (const entry of Array.isArray(options) ? options : []) {
|
|
132
|
+
if (Array.isArray(entry)) rows.push({ value: String(entry[0]), label: String(entry[1] ?? entry[0]) });
|
|
133
|
+
else if (entry !== null && typeof entry === "object" && "group" in entry) rows.push({ group: String(entry.group) });
|
|
134
|
+
else if (entry !== null && typeof entry === "object") rows.push({ value: String(entry.value), label: String(entry.label ?? entry.value), disabled: Boolean(entry.disabled) });
|
|
135
|
+
else rows.push({ value: String(entry), label: String(entry) });
|
|
136
|
+
}
|
|
137
|
+
return rows;
|
|
138
|
+
}
|
|
139
|
+
var choosable = (row) => row.value !== void 0 && !row.disabled;
|
|
140
|
+
function show(anchor, rows, { current = -1, signal = null, label = "" } = {}) {
|
|
141
|
+
open?.finish(null);
|
|
142
|
+
const doc = anchor.ownerDocument;
|
|
143
|
+
const view = doc.defaultView;
|
|
144
|
+
const menu = doc.createElement("div");
|
|
145
|
+
menu.className = MENU;
|
|
146
|
+
menu.setAttribute("role", "listbox");
|
|
147
|
+
if (label) menu.setAttribute("aria-label", label);
|
|
148
|
+
const nodes = rows.map((row, index) => {
|
|
149
|
+
const node = doc.createElement("div");
|
|
150
|
+
if (row.group !== void 0) {
|
|
151
|
+
node.className = "doc-choice-group";
|
|
152
|
+
node.setAttribute("role", "presentation");
|
|
153
|
+
node.textContent = row.group;
|
|
154
|
+
} else {
|
|
155
|
+
node.className = "doc-choice-row";
|
|
156
|
+
node.setAttribute("role", "option");
|
|
157
|
+
node.setAttribute("aria-selected", String(index === current));
|
|
158
|
+
if (row.disabled) node.setAttribute("aria-disabled", "true");
|
|
159
|
+
const words = doc.createElement("span");
|
|
160
|
+
words.className = "doc-choice-label";
|
|
161
|
+
words.textContent = row.label;
|
|
162
|
+
node.append(words);
|
|
163
|
+
if (index === current) node.insertAdjacentHTML("beforeend", CHECK);
|
|
164
|
+
}
|
|
165
|
+
menu.append(node);
|
|
166
|
+
return node;
|
|
167
|
+
});
|
|
168
|
+
const first = () => rows.findIndex(choosable);
|
|
169
|
+
let active = current >= 0 && choosable(rows[current]) ? current : first();
|
|
170
|
+
const light = () => nodes.forEach((node, index) => node.classList.toggle("is-active", index === active));
|
|
171
|
+
const reveal2 = () => {
|
|
172
|
+
const node = nodes[active];
|
|
173
|
+
if (!node) return;
|
|
174
|
+
if (node.offsetTop < menu.scrollTop) menu.scrollTop = node.offsetTop - 4;
|
|
175
|
+
else if (node.offsetTop + node.offsetHeight > menu.scrollTop + menu.clientHeight) menu.scrollTop = node.offsetTop + node.offsetHeight - menu.clientHeight + 4;
|
|
176
|
+
};
|
|
177
|
+
const move = (to) => {
|
|
178
|
+
if (to < 0 || to >= rows.length || !choosable(rows[to])) return;
|
|
179
|
+
active = to;
|
|
180
|
+
light();
|
|
181
|
+
reveal2();
|
|
182
|
+
};
|
|
183
|
+
const step = (from, by) => {
|
|
184
|
+
for (let at = from + by; at >= 0 && at < rows.length; at += by) if (choosable(rows[at])) return at;
|
|
185
|
+
return from;
|
|
186
|
+
};
|
|
187
|
+
const place = () => {
|
|
188
|
+
const box = anchor.getBoundingClientRect();
|
|
189
|
+
const root = doc.documentElement;
|
|
190
|
+
const width = root.clientWidth || view.innerWidth;
|
|
191
|
+
const height = view.innerHeight;
|
|
192
|
+
menu.style.minWidth = `${Math.round(box.width)}px`;
|
|
193
|
+
menu.style.maxHeight = "";
|
|
194
|
+
menu.style.left = "0px";
|
|
195
|
+
menu.style.top = "0px";
|
|
196
|
+
const size = menu.getBoundingClientRect();
|
|
197
|
+
const below = height - box.bottom - GAP - EDGE;
|
|
198
|
+
const above = box.top - GAP - EDGE;
|
|
199
|
+
const up = size.height > below && above > below;
|
|
200
|
+
const room = Math.max(LEAST_HEIGHT, up ? above : below);
|
|
201
|
+
menu.style.maxHeight = `${Math.floor(room)}px`;
|
|
202
|
+
const tall = Math.min(size.height, room);
|
|
203
|
+
const rtl = view.getComputedStyle(anchor).direction === "rtl";
|
|
204
|
+
const left = rtl ? box.right - size.width : box.left;
|
|
205
|
+
menu.style.left = `${Math.round(Math.max(EDGE, Math.min(left, width - size.width - EDGE)))}px`;
|
|
206
|
+
menu.style.top = `${Math.round(up ? box.top - GAP - tall : box.bottom + GAP)}px`;
|
|
207
|
+
};
|
|
208
|
+
return new Promise((resolve) => {
|
|
209
|
+
const controller = new AbortController();
|
|
210
|
+
const { signal: own } = controller;
|
|
211
|
+
let typed = "";
|
|
212
|
+
let typedAt = 0;
|
|
213
|
+
let done = false;
|
|
214
|
+
const watcher = new view.MutationObserver((records) => {
|
|
215
|
+
if (!anchor.isConnected || anchor.localName === "select" && records.some((record) => anchor.contains(record.target))) finish2(null);
|
|
216
|
+
});
|
|
217
|
+
function finish2(row, refocus = true) {
|
|
218
|
+
if (done) return;
|
|
219
|
+
done = true;
|
|
220
|
+
if (open?.finish === finish2) open = null;
|
|
221
|
+
controller.abort();
|
|
222
|
+
watcher.disconnect();
|
|
223
|
+
try {
|
|
224
|
+
menu.hidePopover?.();
|
|
225
|
+
} catch {
|
|
226
|
+
}
|
|
227
|
+
menu.remove();
|
|
228
|
+
if (refocus && anchor.isConnected) anchor.focus({ preventScroll: true });
|
|
229
|
+
resolve(row);
|
|
230
|
+
}
|
|
231
|
+
open = { finish: finish2, anchor };
|
|
232
|
+
signal?.addEventListener("abort", () => finish2(null, false), { once: true, signal: own });
|
|
233
|
+
if (signal?.aborted) return finish2(null, false);
|
|
234
|
+
(anchor.closest?.("dialog[open]") ?? doc.body).append(menu);
|
|
235
|
+
menu.setAttribute("popover", "manual");
|
|
236
|
+
try {
|
|
237
|
+
menu.showPopover();
|
|
238
|
+
} catch {
|
|
239
|
+
menu.removeAttribute("popover");
|
|
240
|
+
}
|
|
241
|
+
light();
|
|
242
|
+
place();
|
|
243
|
+
reveal2();
|
|
244
|
+
const inside = (target) => target instanceof view.Node && menu.contains(target);
|
|
245
|
+
view.addEventListener("pointerdown", (event) => {
|
|
246
|
+
if (!inside(event.target) && !(event.target instanceof view.Node && anchor.contains(event.target))) finish2(null, false);
|
|
247
|
+
}, { capture: true, signal: own });
|
|
248
|
+
view.addEventListener("scroll", (event) => {
|
|
249
|
+
if (!inside(event.target)) finish2(null, false);
|
|
250
|
+
}, { capture: true, signal: own });
|
|
251
|
+
view.addEventListener("resize", () => finish2(null, false), { signal: own });
|
|
252
|
+
view.addEventListener("blur", () => finish2(null, false), { signal: own });
|
|
253
|
+
watcher.observe(doc.documentElement, { childList: true, subtree: true });
|
|
254
|
+
view.addEventListener("keydown", (event) => {
|
|
255
|
+
if (event.isComposing || event.keyCode === 229) return;
|
|
256
|
+
const take = () => {
|
|
257
|
+
event.preventDefault();
|
|
258
|
+
event.stopImmediatePropagation();
|
|
259
|
+
};
|
|
260
|
+
const key = event.key;
|
|
261
|
+
if (event.repeat && (key === "Enter" || key === " ")) take();
|
|
262
|
+
else if (key === "Escape") {
|
|
263
|
+
take();
|
|
264
|
+
finish2(null);
|
|
265
|
+
} else if (key === "Tab") {
|
|
266
|
+
finish2(null, false);
|
|
267
|
+
} else if (key === "ArrowDown" || key === "ArrowUp") {
|
|
268
|
+
take();
|
|
269
|
+
if (event.altKey) finish2(choosable(rows[active] ?? {}) ? rows[active] : null);
|
|
270
|
+
else move(step(active, key === "ArrowDown" ? 1 : -1));
|
|
271
|
+
} else if (key === "Home" || key === "End") {
|
|
272
|
+
take();
|
|
273
|
+
move(key === "Home" ? first() : rows.length - 1 - [...rows].reverse().findIndex(choosable));
|
|
274
|
+
} else if (key === "PageDown" || key === "PageUp") {
|
|
275
|
+
take();
|
|
276
|
+
const page = Math.max(1, Math.floor(menu.clientHeight / 28) - 1);
|
|
277
|
+
let to = active;
|
|
278
|
+
for (let count = 0; count < page; count++) to = step(to, key === "PageDown" ? 1 : -1);
|
|
279
|
+
move(to);
|
|
280
|
+
} else if (key === "Enter" || key === " " && typed === "") {
|
|
281
|
+
take();
|
|
282
|
+
if (choosable(rows[active] ?? {})) finish2(rows[active]);
|
|
283
|
+
} else if (key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
|
|
284
|
+
take();
|
|
285
|
+
typed = Date.now() - typedAt > TYPING ? key.toLowerCase() : typed + key.toLowerCase();
|
|
286
|
+
typedAt = Date.now();
|
|
287
|
+
const same = [...typed].every((letter) => letter === typed[0]);
|
|
288
|
+
const at = (from) => rows.findIndex((row, index) => index >= from && choosable(row) && row.label.trim().toLowerCase().startsWith(same ? typed[0] : typed));
|
|
289
|
+
const found = same && typed.length > 1 ? at(active + 1) >= 0 ? at(active + 1) : at(0) : at(0);
|
|
290
|
+
if (found >= 0) move(found);
|
|
291
|
+
setTimeout(() => {
|
|
292
|
+
if (Date.now() - typedAt >= TYPING) typed = "";
|
|
293
|
+
}, TYPING + 20);
|
|
294
|
+
}
|
|
295
|
+
}, { capture: true, signal: own });
|
|
296
|
+
menu.addEventListener("pointermove", (event) => {
|
|
297
|
+
const node = event.target instanceof view.Element ? event.target.closest(".doc-choice-row") : null;
|
|
298
|
+
const at = node ? nodes.indexOf(node) : -1;
|
|
299
|
+
if (at >= 0 && at !== active && choosable(rows[at])) {
|
|
300
|
+
active = at;
|
|
301
|
+
light();
|
|
302
|
+
}
|
|
303
|
+
}, { signal: own });
|
|
304
|
+
menu.addEventListener("pointerdown", (event) => {
|
|
305
|
+
event.preventDefault();
|
|
306
|
+
event.stopPropagation();
|
|
307
|
+
}, { signal: own });
|
|
308
|
+
menu.addEventListener("click", (event) => {
|
|
309
|
+
event.preventDefault();
|
|
310
|
+
event.stopPropagation();
|
|
311
|
+
const node = event.target instanceof view.Element ? event.target.closest(".doc-choice-row") : null;
|
|
312
|
+
const at = node ? nodes.indexOf(node) : -1;
|
|
313
|
+
if (at >= 0 && choosable(rows[at])) finish2(rows[at]);
|
|
314
|
+
}, { signal: own });
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
async function chooseIn(select) {
|
|
318
|
+
const rows = [];
|
|
319
|
+
const current = { at: -1 };
|
|
320
|
+
const walk = (parent, disabled) => {
|
|
321
|
+
for (const child of parent.children) {
|
|
322
|
+
if (child.localName === "optgroup") {
|
|
323
|
+
if (child.label) rows.push({ group: child.label });
|
|
324
|
+
walk(child, disabled || child.disabled);
|
|
325
|
+
} else if (child.localName === "option" && !child.hidden) {
|
|
326
|
+
if (child.selected) current.at = rows.length;
|
|
327
|
+
rows.push({ value: child.value, label: child.label || child.textContent.trim(), disabled: disabled || child.disabled, option: child });
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
walk(select, false);
|
|
332
|
+
const row = await show(select, rows, { current: current.at, label: select.getAttribute("aria-label") ?? "" });
|
|
333
|
+
if (!row?.option || !select.isConnected || row.option.index === select.selectedIndex) return;
|
|
334
|
+
select.selectedIndex = row.option.index;
|
|
335
|
+
const view = select.ownerDocument.defaultView;
|
|
336
|
+
select.dispatchEvent(new view.Event("input", { bubbles: true, composed: true }));
|
|
337
|
+
select.dispatchEvent(new view.Event("change", { bubbles: true }));
|
|
338
|
+
}
|
|
339
|
+
async function choose(anchor, { options, value = null, label = "", signal } = {}) {
|
|
340
|
+
if (anchor?.nodeType !== 1) throw new Error("DocKit.choose: the first argument is the element the menu opens under");
|
|
341
|
+
if (open?.anchor === anchor) {
|
|
342
|
+
open.finish(null);
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
const rows = rowsOf(options);
|
|
346
|
+
const current = value === null || value === void 0 ? -1 : rows.findIndex((row2) => row2.value === String(value));
|
|
347
|
+
const row = await show(anchor, rows, { current, signal, label });
|
|
348
|
+
return row?.value ?? null;
|
|
349
|
+
}
|
|
350
|
+
var popup = (select) => {
|
|
351
|
+
if (!(select instanceof select.ownerDocument.defaultView.HTMLSelectElement)) return false;
|
|
352
|
+
if (select.multiple || Number(select.getAttribute("size")) > 1 || select.disabled) return false;
|
|
353
|
+
return !select.closest("fieldset:disabled");
|
|
354
|
+
};
|
|
355
|
+
var selectAt = (event, view) => {
|
|
356
|
+
const node = event.target instanceof view.Element ? event.target.closest("select") : null;
|
|
357
|
+
return node && popup(node) ? node : null;
|
|
358
|
+
};
|
|
359
|
+
function startChoices(doc) {
|
|
360
|
+
const view = doc.defaultView;
|
|
361
|
+
view.addEventListener("mousedown", (event) => {
|
|
362
|
+
if (event.button !== 0 || event.ctrlKey) return;
|
|
363
|
+
const select = selectAt(event, view);
|
|
364
|
+
if (!select) return;
|
|
365
|
+
event.preventDefault();
|
|
366
|
+
select.focus({ preventScroll: true, focusVisible: false });
|
|
367
|
+
if (open?.anchor === select) open.finish(null);
|
|
368
|
+
else void chooseIn(select);
|
|
369
|
+
}, true);
|
|
370
|
+
view.addEventListener("keydown", (event) => {
|
|
371
|
+
if (event.isComposing || event.keyCode === 229 || event.defaultPrevented) return;
|
|
372
|
+
const select = selectAt(event, view);
|
|
373
|
+
if (!select || open) return;
|
|
374
|
+
const opens = event.key === " " || event.key === "Enter" || event.key === "F4" || event.key === "ArrowDown" || event.key === "ArrowUp";
|
|
375
|
+
if (!opens || event.ctrlKey || event.metaKey || event.shiftKey) return;
|
|
376
|
+
event.preventDefault();
|
|
377
|
+
event.stopImmediatePropagation();
|
|
378
|
+
if (!event.repeat) void chooseIn(select);
|
|
379
|
+
}, true);
|
|
380
|
+
}
|
|
381
|
+
|
|
121
382
|
// src/render/kit/runtime/embeds.js
|
|
122
383
|
var sources = /* @__PURE__ */ new Map();
|
|
123
384
|
function showEmbed(figure) {
|
|
@@ -215,9 +476,9 @@
|
|
|
215
476
|
|
|
216
477
|
// src/render/kit/words.js
|
|
217
478
|
var RUNTIME = {
|
|
218
|
-
"component-missing": { zh: "\
|
|
219
|
-
"component-broken": { zh: "\
|
|
220
|
-
"component-silent": { zh: "\
|
|
479
|
+
"component-missing": { zh: "\u81EA\u5B9A\u4E49\u5757 {0} \u4E0D\u5728\u8FD9\u4E2A\u5DE5\u4F5C\u533A\u91CC\uFF0C\u8FD9\u91CC\u53EA\u663E\u793A\u5B83\u7684\u5185\u5BB9\u3002", en: "The custom block {0} is not in this workspace: only what it holds is shown." },
|
|
480
|
+
"component-broken": { zh: "\u81EA\u5B9A\u4E49\u5757 {0} \u6CA1\u6709\u52A0\u8F7D\uFF0C\u8FD9\u91CC\u53EA\u663E\u793A\u5B83\u7684\u5185\u5BB9\u3002\u539F\u56E0\uFF1A{1}", en: "The custom block {0} did not load: only what it holds is shown. Why: {1}" },
|
|
481
|
+
"component-silent": { zh: "\u81EA\u5B9A\u4E49\u5757 {0} \u7684\u811A\u672C\u6CA1\u6709\u542F\u52A8\u5B83\uFF0C\u8FD9\u91CC\u53EA\u663E\u793A\u5B83\u7684\u5185\u5BB9\uFF1A\u770B\u63A7\u5236\u53F0\u91CC\u7684\u9519\u8BEF\u3002", en: "The script of the custom block {0} did not start it: only what it holds is shown. See the console for the error." },
|
|
221
482
|
"value-true": { zh: "\u662F", en: "Yes" },
|
|
222
483
|
"value-false": { zh: "\u5426", en: "No" },
|
|
223
484
|
"value-empty": { zh: "\uFF08\u7A7A\uFF09", en: "(empty)" },
|
|
@@ -230,7 +491,17 @@
|
|
|
230
491
|
"open-image": { zh: "\u653E\u5927\u67E5\u770B\u56FE\u7247", en: "View the image larger" },
|
|
231
492
|
"open-image-named": { zh: "\u653E\u5927\u67E5\u770B\uFF1A{0}", en: "View larger: {0}" },
|
|
232
493
|
"close": { zh: "\u5173\u95ED", en: "Close" },
|
|
233
|
-
"flowchart": FLOW_LABEL
|
|
494
|
+
"flowchart": FLOW_LABEL,
|
|
495
|
+
// net.js: a block whose fetch waits for the reader's consent, its bar's line and its button.
|
|
496
|
+
"net-why": { zh: "\u8FD9\u4E2A\u5757\u8981\u8054\u7F51\u624D\u80FD\u663E\u793A\u5185\u5BB9", en: "This block needs the internet to show its content" },
|
|
497
|
+
// On a card a reader reads: what letting it online brings, never the maintainers' 块 (a block's manifest may say its own: card.consent).
|
|
498
|
+
"net-card-why": { zh: "\u5141\u8BB8\u8054\u7F51\u4E4B\u540E\u663E\u793A\u5185\u5BB9", en: "Allow internet access to show this" },
|
|
499
|
+
"net-allow": { zh: "\u5141\u8BB8\u8BBF\u95EE {0}", en: "Allow {0}" },
|
|
500
|
+
"net-allow-many": { zh: "\u5141\u8BB8\u8BBF\u95EE {0} \u7B49 {1} \u4E2A\u7F51\u7AD9", en: "Allow {0} and others ({1} sites)" },
|
|
501
|
+
// On a card of a custom page: the button's words alone, and a line under the why saying whose the data is.
|
|
502
|
+
"net-allow-short": { zh: "\u5141\u8BB8\u8BBF\u95EE", en: "Allow" },
|
|
503
|
+
"net-from": { zh: "\u6570\u636E\u6765\u81EA {0}", en: "From {0}" },
|
|
504
|
+
"net-from-many": { zh: "\u6570\u636E\u6765\u81EA {0} \u7B49 {1} \u4E2A\u7F51\u7AD9", en: "From {0} and others ({1} sites)" }
|
|
234
505
|
};
|
|
235
506
|
var UI_LANGUAGE = "data-ge-language";
|
|
236
507
|
function kitLanguage(root = globalThis.document?.documentElement) {
|
|
@@ -242,7 +513,7 @@
|
|
|
242
513
|
const entry = table2[key];
|
|
243
514
|
if (!entry) throw new Error(`The kit has no word "${key}" here (src/render/kit/words.js).`);
|
|
244
515
|
const text = entry[language] ?? entry.zh;
|
|
245
|
-
return values.length === 0 ? text : text.replace(/\{(\d+)\}/g, (
|
|
516
|
+
return values.length === 0 ? text : text.replace(/\{(\d+)\}/g, (whole2, index) => index < values.length ? String(values[index]) : whole2);
|
|
246
517
|
}
|
|
247
518
|
var sayer = (table2) => (key, ...values) => wordIn(table2, kitLanguage(), key, ...values);
|
|
248
519
|
var sayRuntime = /* @__PURE__ */ sayer(RUNTIME);
|
|
@@ -438,8 +709,8 @@
|
|
|
438
709
|
}
|
|
439
710
|
return { pieces, widest: Math.max(0, ...pieces.filter((piece) => !piece.space).map((piece) => piece.width)) };
|
|
440
711
|
};
|
|
441
|
-
const
|
|
442
|
-
return { pieces: collect(true).pieces, widest:
|
|
712
|
+
const whole2 = collect(false);
|
|
713
|
+
return { pieces: collect(true).pieces, widest: whole2.widest };
|
|
443
714
|
}
|
|
444
715
|
function contentOf(elements) {
|
|
445
716
|
const blocks = [];
|
|
@@ -489,8 +760,8 @@
|
|
|
489
760
|
const [first] = blocks;
|
|
490
761
|
if (short || first?.tagName !== "P") return { nodes: ownNodes(item2), style, line: lineOf(style), content: blocks, short };
|
|
491
762
|
const look = getComputedStyle(first);
|
|
492
|
-
const
|
|
493
|
-
return { nodes: [...first.childNodes], style:
|
|
763
|
+
const whole2 = first.children.length === 1 && first.textContent === first.firstElementChild.textContent ? getComputedStyle(first.firstElementChild) : look;
|
|
764
|
+
return { nodes: [...first.childNodes], style: whole2, line: lineOf(look), content: blocks.slice(1), short };
|
|
494
765
|
}
|
|
495
766
|
function stepShape(item2) {
|
|
496
767
|
const style = getComputedStyle(item2);
|
|
@@ -592,6 +863,125 @@
|
|
|
592
863
|
}
|
|
593
864
|
var FLOWCHART = `ol.${FLOW}`;
|
|
594
865
|
|
|
866
|
+
// src/render/kit/runtime/gestures.js
|
|
867
|
+
var listen = (target, type, run, signal, options = {}) => target.addEventListener(type, run, { ...options, signal });
|
|
868
|
+
var DRAGGING = "doc-dragging";
|
|
869
|
+
function fieldIn(field, { commit, signal } = {}) {
|
|
870
|
+
if (typeof commit !== "function") throw new Error("DocKit.input: commit(value) is a function");
|
|
871
|
+
let committed = field.value;
|
|
872
|
+
let composing = false;
|
|
873
|
+
let leftComposing = false;
|
|
874
|
+
const done = () => {
|
|
875
|
+
if (composing || field.value === committed) return;
|
|
876
|
+
committed = field.value;
|
|
877
|
+
commit(committed);
|
|
878
|
+
};
|
|
879
|
+
listen(field, "compositionstart", () => {
|
|
880
|
+
composing = true;
|
|
881
|
+
}, signal);
|
|
882
|
+
listen(field, "compositionend", () => {
|
|
883
|
+
composing = false;
|
|
884
|
+
if (leftComposing) {
|
|
885
|
+
leftComposing = false;
|
|
886
|
+
done();
|
|
887
|
+
}
|
|
888
|
+
}, signal);
|
|
889
|
+
listen(field, "keydown", (event) => {
|
|
890
|
+
if (composing || event.isComposing || event.keyCode === 229) return;
|
|
891
|
+
if (event.key === "Enter" && field.localName !== "select" && (field.localName !== "textarea" || event.ctrlKey || event.metaKey)) {
|
|
892
|
+
event.preventDefault();
|
|
893
|
+
done();
|
|
894
|
+
} else if (event.key === "Escape") {
|
|
895
|
+
event.preventDefault();
|
|
896
|
+
event.stopPropagation();
|
|
897
|
+
field.value = committed;
|
|
898
|
+
field.blur();
|
|
899
|
+
}
|
|
900
|
+
}, signal);
|
|
901
|
+
listen(field, "blur", () => {
|
|
902
|
+
if (composing) leftComposing = true;
|
|
903
|
+
else done();
|
|
904
|
+
}, signal);
|
|
905
|
+
if (field.localName === "select") listen(field, "change", done, signal);
|
|
906
|
+
return Object.freeze({
|
|
907
|
+
/**
|
|
908
|
+
* The value the file holds now (drawn from a part): shown, unless the reader is typing another in
|
|
909
|
+
* the field, whose words stay; either way it is what is committed against.
|
|
910
|
+
*/
|
|
911
|
+
set(value) {
|
|
912
|
+
const typing = field.ownerDocument.activeElement === field && field.value !== committed;
|
|
913
|
+
committed = String(value);
|
|
914
|
+
if (!typing) field.value = committed;
|
|
915
|
+
},
|
|
916
|
+
/** The value committed last, or set. */
|
|
917
|
+
get value() {
|
|
918
|
+
return committed;
|
|
919
|
+
}
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
function dragIn(area, { items, handle = null, threshold = 4, enabled = () => true, marker = null, over, drop, signal } = {}) {
|
|
923
|
+
if (typeof items !== "string" || typeof over !== "function" || typeof drop !== "function") throw new Error("DocKit.drag: items (a selector), over(x, y, item) and drop(item, spot) are given");
|
|
924
|
+
const view = area.ownerDocument.defaultView;
|
|
925
|
+
let drag = null;
|
|
926
|
+
const end = () => {
|
|
927
|
+
drag?.item.classList.remove(DRAGGING);
|
|
928
|
+
marker?.remove();
|
|
929
|
+
drag = null;
|
|
930
|
+
};
|
|
931
|
+
const noClick = () => {
|
|
932
|
+
const swallow = (event) => {
|
|
933
|
+
event.preventDefault();
|
|
934
|
+
event.stopPropagation();
|
|
935
|
+
};
|
|
936
|
+
view.addEventListener("click", swallow, { capture: true, once: true });
|
|
937
|
+
view.setTimeout(() => view.removeEventListener("click", swallow, { capture: true }), 0);
|
|
938
|
+
};
|
|
939
|
+
listen(area, "pointerdown", (event) => {
|
|
940
|
+
const at = event.target instanceof view.Element ? event.target : null;
|
|
941
|
+
const item2 = at?.closest(items);
|
|
942
|
+
if (!item2 || !area.contains(item2) || event.button !== 0 || handle && !at.closest(handle) || !enabled()) return;
|
|
943
|
+
drag = { item: item2, x: event.clientX, y: event.clientY, pointer: event.pointerId, moving: false };
|
|
944
|
+
item2.setPointerCapture?.(event.pointerId);
|
|
945
|
+
}, signal);
|
|
946
|
+
listen(area, "pointermove", (event) => {
|
|
947
|
+
if (!drag || event.pointerId !== drag.pointer) return;
|
|
948
|
+
if (!drag.moving && Math.hypot(event.clientX - drag.x, event.clientY - drag.y) < threshold) return;
|
|
949
|
+
drag.moving = true;
|
|
950
|
+
drag.item.classList.add(DRAGGING);
|
|
951
|
+
const spot = over(event.clientX, event.clientY, drag.item);
|
|
952
|
+
if (spot && marker) spot.into.insertBefore(marker, spot.before ?? null);
|
|
953
|
+
else marker?.remove();
|
|
954
|
+
}, signal);
|
|
955
|
+
listen(area, "pointerup", (event) => {
|
|
956
|
+
if (!drag || event.pointerId !== drag.pointer) return;
|
|
957
|
+
const { item: item2, moving } = drag;
|
|
958
|
+
const spot = moving ? over(event.clientX, event.clientY, item2) : null;
|
|
959
|
+
end();
|
|
960
|
+
if (!moving) return;
|
|
961
|
+
noClick();
|
|
962
|
+
if (spot) drop(item2, spot);
|
|
963
|
+
}, signal);
|
|
964
|
+
listen(area, "pointercancel", end, signal);
|
|
965
|
+
listen(area, "lostpointercapture", (event) => {
|
|
966
|
+
if (drag && event.pointerId === drag.pointer) end();
|
|
967
|
+
}, signal);
|
|
968
|
+
listen(view, "keydown", (event) => {
|
|
969
|
+
if (!drag || event.key !== "Escape") return;
|
|
970
|
+
event.preventDefault();
|
|
971
|
+
event.stopPropagation();
|
|
972
|
+
end();
|
|
973
|
+
}, signal, { capture: true });
|
|
974
|
+
signal?.addEventListener("abort", end, { once: true });
|
|
975
|
+
return Object.freeze({
|
|
976
|
+
/** Give up a drag going on, as Escape does: nothing dropped. */
|
|
977
|
+
cancel: end,
|
|
978
|
+
/** Whether an item is being dragged: past the threshold, not yet released. */
|
|
979
|
+
get dragging() {
|
|
980
|
+
return Boolean(drag?.moving);
|
|
981
|
+
}
|
|
982
|
+
});
|
|
983
|
+
}
|
|
984
|
+
|
|
595
985
|
// src/shared/components/installed.mjs
|
|
596
986
|
var ATTRIBUTE = "data-doc-component";
|
|
597
987
|
var PACKAGE_ID = /^[a-z0-9][a-z0-9-]*\/[a-z0-9][a-z0-9-]*$/;
|
|
@@ -607,8 +997,15 @@
|
|
|
607
997
|
if (edge.matches(INSTANCE)) return owner ?? edge;
|
|
608
998
|
return owner !== null && edgeAround(edge) === owner ? null : owner;
|
|
609
999
|
}
|
|
1000
|
+
function heldWithin(element) {
|
|
1001
|
+
if (!element.matches(REGION)) return heldBy(element);
|
|
1002
|
+
const owner = heldBy(element);
|
|
1003
|
+
if (element.matches(INSTANCE)) return owner ?? element;
|
|
1004
|
+
return owner !== null && edgeAround(element) === owner ? null : owner;
|
|
1005
|
+
}
|
|
610
1006
|
var opensDocument = (node) => node.matches(SLOT_PART) && heldBy(node) !== null && edgeAround(node) === heldBy(node);
|
|
611
1007
|
var componentAt = (node) => node?.nodeType === 1 && heldBy(node) !== null && !opensDocument(node);
|
|
1008
|
+
var slotsIn = (instance) => [...instance.querySelectorAll(SLOT_PART)].filter((slot) => edgeAround(slot) === instance);
|
|
612
1009
|
var FALLBACK = "data-doc-fallback";
|
|
613
1010
|
var CONTROLS2 = "input, select, textarea, button";
|
|
614
1011
|
var CONTROL_MARK = "data-doc-fallback-control";
|
|
@@ -624,16 +1021,718 @@
|
|
|
624
1021
|
var SCHEMA = "data-doc-schema";
|
|
625
1022
|
var schemaAhead = (value, schema = 1) => value !== null && value !== void 0 && !(String(value).trim() !== "" && Number(value) <= schema);
|
|
626
1023
|
|
|
1024
|
+
// src/shared/card-size.mjs
|
|
1025
|
+
var PAGE2 = "main.gallery-page";
|
|
1026
|
+
var BOARD = ".gallery-board";
|
|
1027
|
+
var CARD = ".gallery-card";
|
|
1028
|
+
var CARD_ID = "data-card-id";
|
|
1029
|
+
var MOST = Object.freeze({ w: 12, h: 24 });
|
|
1030
|
+
var DEFAULT = Object.freeze({ x: 0, y: 0, w: 4, h: 2 });
|
|
1031
|
+
var whole = (value, fallback) => {
|
|
1032
|
+
const number2 = Number.parseInt(value ?? "", 10);
|
|
1033
|
+
return Number.isFinite(number2) ? number2 : fallback;
|
|
1034
|
+
};
|
|
1035
|
+
function cellsOf(card) {
|
|
1036
|
+
const w = Math.min(MOST.w, Math.max(1, whole(card.dataset.w, DEFAULT.w)));
|
|
1037
|
+
const h = Math.min(MOST.h, Math.max(1, whole(card.dataset.h, DEFAULT.h)));
|
|
1038
|
+
const x = Math.min(MOST.w - w, Math.max(0, whole(card.dataset.x, DEFAULT.x)));
|
|
1039
|
+
const y = Math.max(0, whole(card.dataset.y, DEFAULT.y));
|
|
1040
|
+
return { x, y, w, h };
|
|
1041
|
+
}
|
|
1042
|
+
function drawnCells(card) {
|
|
1043
|
+
const { w, h } = cellsOf(card);
|
|
1044
|
+
const columns = Number(
|
|
1045
|
+
/** @type {HTMLElement | null} */
|
|
1046
|
+
card.closest(BOARD)?.dataset.columns
|
|
1047
|
+
) || MOST.w;
|
|
1048
|
+
const drawn2 = Number.parseInt(card.style?.getPropertyValue?.("--gallery-h") ?? "", 10);
|
|
1049
|
+
return { w: Math.min(w, columns), h: Number.isFinite(drawn2) ? Math.min(MOST.h, Math.max(1, drawn2)) : h };
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
// src/shared/colors.mjs
|
|
1053
|
+
var COLORS = [
|
|
1054
|
+
{ name: "gray", label: "\u7070\u8272", text: ["#6e6e73", "#a1a1a6"], fill: ["#f0efed", "#383836"], mark: ["#e0dfdd", "#454542"] },
|
|
1055
|
+
{ name: "brown", label: "\u68D5\u8272", text: ["#9f765a", "#ba856f"], fill: ["#f5ede9", "#45362d"], mark: ["#efdbce", "#534034"] },
|
|
1056
|
+
{ name: "orange", label: "\u6A59\u8272", text: ["#d27b2d", "#c77d48"], fill: ["#fbebde", "#53361f"], mark: ["#fbddc5", "#654025"] },
|
|
1057
|
+
{ name: "yellow", label: "\u9EC4\u8272", text: ["#cb9434", "#ca9849"], fill: ["#f9f3dc", "#504425"], mark: ["#f8eab6", "#614f26"] },
|
|
1058
|
+
{ name: "green", label: "\u7EFF\u8272", text: ["#50946e", "#529e72"], fill: ["#e8f1ec", "#263d30"], mark: ["#cfead9", "#2c4b3a"] },
|
|
1059
|
+
{ name: "blue", label: "\u84DD\u8272", text: ["#387dc9", "#5e87c9"], fill: ["#e5f2fc", "#233850"], mark: ["#cde5fb", "#294564"] },
|
|
1060
|
+
{ name: "purple", label: "\u7D2B\u8272", text: ["#9a6bb4", "#9d68d3"], fill: ["#f3ebf9", "#3c2d47"], mark: ["#ebdaf6", "#4b3859"] },
|
|
1061
|
+
{ name: "pink", label: "\u7C89\u8272", text: ["#c14c8a", "#d15796"], fill: ["#fae9f1", "#4e2b3c"], mark: ["#f8d7e6", "#5d3548"] },
|
|
1062
|
+
{ name: "red", label: "\u7EA2\u8272", text: ["#cf5148", "#df5452"], fill: ["#fce9e7", "#502c29"], mark: ["#fed7d1", "#663632"] }
|
|
1063
|
+
];
|
|
1064
|
+
var COLOR_NAMES = COLORS.map(({ name }) => name);
|
|
1065
|
+
|
|
1066
|
+
// src/shared/component-source.mjs
|
|
1067
|
+
var SOURCE_ATTRIBUTES = ["data-checked", "rowspan", "colspan", "data-sort-status", "data-sort-type", "data-sort-key", "data-sort-default", "data-sort-ignore", "data-sort-value", "data-sort-rank"];
|
|
1068
|
+
var LOOK_CLASSES = /* @__PURE__ */ new Set([
|
|
1069
|
+
...COLOR_NAMES.flatMap((name) => [`doc-text-${name}`, `doc-highlight-${name}`]),
|
|
1070
|
+
// table.mjs's CELL_ALIGN_CLASSES, CELL_VALIGN_CLASSES and CELL_BOLD_CLASS, written out: an import of that
|
|
1071
|
+
// file would bring its description, prose and all, into the kit's runtime (tests/unit/installed.mjs
|
|
1072
|
+
// holds the two lists together).
|
|
1073
|
+
"doc-align-left",
|
|
1074
|
+
"doc-align-center",
|
|
1075
|
+
"doc-align-right",
|
|
1076
|
+
"doc-valign-top",
|
|
1077
|
+
"doc-valign-middle",
|
|
1078
|
+
"doc-valign-bottom",
|
|
1079
|
+
"doc-bold",
|
|
1080
|
+
// A paragraph's or a heading's indent (the editor's components/align.mjs INDENTS; its alignment is a cell's classes above).
|
|
1081
|
+
...Array.from({ length: 8 }, (_, index) => `doc-indent-${index + 1}`)
|
|
1082
|
+
]);
|
|
1083
|
+
function lookChanged(before, after) {
|
|
1084
|
+
const looks = (value) => [...new Set(String(value ?? "").split(/\s+/).filter((name) => LOOK_CLASSES.has(name)))].sort().join(" ");
|
|
1085
|
+
return looks(before) !== looks(after);
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
// src/shared/json-layout.mjs
|
|
1089
|
+
var isValue = (value) => value === null || typeof value !== "object";
|
|
1090
|
+
var isFlat = (value) => Object.values(value).every((each) => isValue(each) || Array.isArray(each) && each.every(isValue));
|
|
1091
|
+
function laidOut(value, indent) {
|
|
1092
|
+
if (typeof value?.toJSON === "function") return laidOut(value.toJSON(), indent);
|
|
1093
|
+
if (isValue(value)) return JSON.stringify(value) ?? "null";
|
|
1094
|
+
const list2 = Array.isArray(value);
|
|
1095
|
+
const entries = Object.entries(value).map(([key, each]) => [key, typeof each?.toJSON === "function" ? each.toJSON() : each]).filter(([, each]) => list2 || each !== void 0 && typeof each !== "function");
|
|
1096
|
+
const items = entries.map(([key, each]) => `${list2 ? "" : `${JSON.stringify(key)}: `}${laidOut(each, `${indent} `)}`);
|
|
1097
|
+
if (items.length === 0) return list2 ? "[]" : "{}";
|
|
1098
|
+
if (isFlat(Object.fromEntries(entries))) return list2 ? `[${items.join(", ")}]` : `{ ${items.join(", ")} }`;
|
|
1099
|
+
return `${list2 ? "[" : "{"}
|
|
1100
|
+
${items.map((item2) => `${indent} ${item2}`).join(",\n")}
|
|
1101
|
+
${indent}${list2 ? "]" : "}"}`;
|
|
1102
|
+
}
|
|
1103
|
+
function jsonIn(text, value) {
|
|
1104
|
+
const start = text.length - text.trimStart().length;
|
|
1105
|
+
const end = text.trimEnd().length;
|
|
1106
|
+
const indent = text.slice(text.lastIndexOf("\n", start) + 1, start);
|
|
1107
|
+
const json = text.slice(start, end).includes("\n") ? laidOut(value, indent) : JSON.stringify(value) ?? "null";
|
|
1108
|
+
return text.slice(0, start) + json.replaceAll("</", "<\\/").replaceAll("<!--", "\\u003c!--") + text.slice(end);
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
// src/shared/inline-spacing.mjs
|
|
1112
|
+
var UNITS = /* @__PURE__ */ new Set([..."\u4E2A\u4E07\u4EBF\u5343\u767E\u5341\u5143\u89D2\u5206\u5398\u6BDB\u500D\u5E74\u6708\u65E5\u53F7\u65F6\u70B9\u79D2\u5929\u5468\u5C81\u4EBA\u4F4D\u540D\u6B21\u5BB6\u6761\u9879\u79CD\u53F0\u53EA\u4EF6\u7BC7\u9875\u5F20\u5957\u4EFD\u7EC4\u6279\u671F\u5C4A\u4EE3\u7EA7\u5C42\u8F6E\u6B65\u7C73\u514B\u65A4\u5428\u5EA6\u91CC\u516C\u6BEB\u5FAE\u5BF8\u5C3A\u4E24\u5347\u6237\u6240\u5EA7\u680B\u8F86\u67B6\u8258\u672C\u90E8\u7AE0\u8282\u573A\u5C40\u9996\u53E5\u5B57\u884C\u5217\u904D\u56DE\u756A\u6210"]);
|
|
1113
|
+
var ZWSP = String.fromCharCode(8203);
|
|
1114
|
+
var WORD = /[\p{L}\p{N}]/u;
|
|
1115
|
+
var ITEM = "code, .doc-math-inline, .katex";
|
|
1116
|
+
var LINE = /^(P|LI|H[1-6]|TD|TH|DT|DD|DIV|SECTION|ARTICLE|ASIDE|HEADER|FOOTER|MAIN|NAV|FIGURE|FIGCAPTION|CAPTION|SUMMARY|DETAILS|BLOCKQUOTE|UL|OL|TABLE|THEAD|TBODY|TR|PRE|BR|HR|DIALOG|BODY|BUTTON|svg)$/;
|
|
1117
|
+
var emptyFormula = (element) => element.matches(".doc-math-inline") && (element.getAttribute("data-ge-empty") === "formula" || !element.textContent.replace(/\\[()]/g, "").trim());
|
|
1118
|
+
var isInlineItem = (node) => node?.nodeType === 1 && node.matches(ITEM) && !emptyFormula(node);
|
|
1119
|
+
function inlineItems(root) {
|
|
1120
|
+
const items = root.nodeType === 1 && root.matches(ITEM) ? [root, ...root.querySelectorAll(ITEM)] : [...root.querySelectorAll(ITEM)];
|
|
1121
|
+
return items.filter((item2) => isInlineItem(item2) && !item2.parentElement?.closest(".doc-math-inline, .katex, .katex-display, code"));
|
|
1122
|
+
}
|
|
1123
|
+
function endOf(node, after) {
|
|
1124
|
+
if (node.nodeType === 3) {
|
|
1125
|
+
const characters = [...node.data.replaceAll(ZWSP, "")];
|
|
1126
|
+
return characters.length === 0 ? void 0 : after ? characters[0] : characters.at(-1);
|
|
1127
|
+
}
|
|
1128
|
+
if (node.nodeType !== 1) return void 0;
|
|
1129
|
+
if (LINE.test(node.tagName)) return null;
|
|
1130
|
+
if (node.matches(ITEM)) return emptyFormula(node) ? void 0 : true;
|
|
1131
|
+
if (node.hasAttribute("data-ge-empty")) return void 0;
|
|
1132
|
+
const children = [...node.childNodes];
|
|
1133
|
+
for (const child of after ? children : children.reverse()) {
|
|
1134
|
+
const found = endOf(child, after);
|
|
1135
|
+
if (found !== void 0) return found;
|
|
1136
|
+
}
|
|
1137
|
+
return void 0;
|
|
1138
|
+
}
|
|
1139
|
+
function sideOf(node, after) {
|
|
1140
|
+
for (let at = node; at; ) {
|
|
1141
|
+
const next = after ? at.nextSibling : at.previousSibling;
|
|
1142
|
+
if (!next) {
|
|
1143
|
+
at = at.parentElement;
|
|
1144
|
+
if (!at || LINE.test(at.tagName) || at.hasAttribute("contenteditable")) return null;
|
|
1145
|
+
continue;
|
|
1146
|
+
}
|
|
1147
|
+
const found = endOf(next, after);
|
|
1148
|
+
if (found !== void 0) return found;
|
|
1149
|
+
at = next;
|
|
1150
|
+
}
|
|
1151
|
+
return null;
|
|
1152
|
+
}
|
|
1153
|
+
function spaceAround(element) {
|
|
1154
|
+
const put = { before: null, after: null };
|
|
1155
|
+
for (const after of [false, true]) {
|
|
1156
|
+
const side = sideOf(element, after);
|
|
1157
|
+
if (side !== true && !(typeof side === "string" && WORD.test(side))) continue;
|
|
1158
|
+
const space = element.ownerDocument.createTextNode(" ");
|
|
1159
|
+
if (after) element.after(space);
|
|
1160
|
+
else element.before(space);
|
|
1161
|
+
put[after ? "after" : "before"] = space;
|
|
1162
|
+
}
|
|
1163
|
+
return put;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
// src/shared/number-reading.mjs
|
|
1167
|
+
var missingValues = /* @__PURE__ */ new Set(["", "-", "\u2014", "\u2013", "\u2212", "n/a", "na", "null"]);
|
|
1168
|
+
function isMissingValue(raw) {
|
|
1169
|
+
return missingValues.has(raw.toLowerCase());
|
|
1170
|
+
}
|
|
1171
|
+
var QUALIFIER = String.raw`(?:约|大约|近|超过|不足|≈|~|<=?|>=?|≤|≥|±)?`;
|
|
1172
|
+
var AMOUNT = String.raw`[$¥€£₩₹]?\s*((?:\d{1,3}(?:[,\s\u00a0\u2009]\d{3})+|\d{1,4}(?:,\d{4})+|\d+)(?:\.\d*)?(?:e[+-]?\d+)?|\.\d+)`;
|
|
1173
|
+
var UNIT = String.raw`((?:[%‰x×]|[A-Za-zµμ\u4e00-\u9fff°℃]+(?:\/[A-Za-zµμ\u4e00-\u9fff°℃·]+)?)?)`;
|
|
1174
|
+
var UNIT_SCALES = { \u5343: 1e3, \u4E07: 1e4, \u4EBF: 1e8 };
|
|
1175
|
+
var SCALE = UNIT_SCALES;
|
|
1176
|
+
var SINGLE = new RegExp(`^${QUALIFIER}\\s*([+-]?)\\s*${AMOUNT}\\s*${UNIT}$`, "i");
|
|
1177
|
+
var RANGE = new RegExp(`^([+-]?)\\s*${AMOUNT}\\s*${UNIT}\\s*(?:-|~|\u81F3|\u5230)\\s*[+-]?\\s*${AMOUNT}\\s*${UNIT}$`, "i");
|
|
1178
|
+
function numberReading(raw) {
|
|
1179
|
+
let text = raw.normalize("NFKC").trim().replace(/[−–—]/g, "-");
|
|
1180
|
+
const accounting = /^\((.+)\)$/.exec(text);
|
|
1181
|
+
if (accounting) text = accounting[1].trim();
|
|
1182
|
+
const single = SINGLE.exec(text);
|
|
1183
|
+
const match = single ?? RANGE.exec(text);
|
|
1184
|
+
if (!match) return null;
|
|
1185
|
+
const value = Number(`${match[1]}${match[2].replace(/[,\s\u00a0\u2009]/g, "")}`);
|
|
1186
|
+
const written = accounting ? -value : value;
|
|
1187
|
+
const unit = match[3] ?? "";
|
|
1188
|
+
const scaled = written * (SCALE[unit[0]] ?? 1);
|
|
1189
|
+
if (!Number.isFinite(scaled)) return null;
|
|
1190
|
+
return single ? { value: scaled, written, unit } : { value: scaled, written, unit, range: true };
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
// src/shared/table-chart.mjs
|
|
1194
|
+
var CHART_DATA = "data-doc-chart-data";
|
|
1195
|
+
var CHART_SOURCE = "data-doc-chart-source";
|
|
1196
|
+
var VIEW_FROM = "data-doc-from";
|
|
1197
|
+
var TABLE_READERS = [CHART_DATA, VIEW_FROM];
|
|
1198
|
+
var CHART_KEY = /^[A-Za-z][\w-]{0,31}$/;
|
|
1199
|
+
var FORMULA = /\\\(([\s\S]*?)\\\)|\\\[([\s\S]*?)\\\]|\$\$([\s\S]*?)\$\$/g;
|
|
1200
|
+
var cellWords = (text) => text.replace(FORMULA, (_, inline, display, dollars) => inline ?? display ?? dollars).replaceAll(ZWSP, "").replace(/\s+/g, " ").trim();
|
|
1201
|
+
var TEX = 'annotation[encoding="application/x-tex"]';
|
|
1202
|
+
function cellText(node) {
|
|
1203
|
+
if (node.nodeType === 3) return (
|
|
1204
|
+
/** @type {Text} */
|
|
1205
|
+
node.data
|
|
1206
|
+
);
|
|
1207
|
+
if (node.nodeType !== 1) return "";
|
|
1208
|
+
const element = (
|
|
1209
|
+
/** @type {Element} */
|
|
1210
|
+
node
|
|
1211
|
+
);
|
|
1212
|
+
if (element.hasAttribute("data-ge-empty")) return "";
|
|
1213
|
+
const tex = element.classList.contains("katex") ? element.querySelector(TEX) : null;
|
|
1214
|
+
if (tex) return tex.textContent ?? "";
|
|
1215
|
+
let text = "";
|
|
1216
|
+
for (const child of element.childNodes) text += cellText(child);
|
|
1217
|
+
return text;
|
|
1218
|
+
}
|
|
1219
|
+
var WORD_TYPES = /* @__PURE__ */ new Set(["text", "date"]);
|
|
1220
|
+
function cellValue(cell, type = null) {
|
|
1221
|
+
if (!cell) return null;
|
|
1222
|
+
const raw = cell.sort ?? cell.words;
|
|
1223
|
+
if (isMissingValue(raw)) return null;
|
|
1224
|
+
if (WORD_TYPES.has(type)) return cell.words;
|
|
1225
|
+
const reading = numberReading(raw);
|
|
1226
|
+
return reading && !reading.range ? reading.value : cell.words;
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
// src/shared/net-policy.mjs
|
|
1230
|
+
var NET = "net:";
|
|
1231
|
+
var netHostsOf = (needs) => Array.isArray(needs) ? needs.filter((need) => typeof need === "string" && need.startsWith(NET)).map((need) => need.slice(NET.length)) : [];
|
|
1232
|
+
|
|
1233
|
+
// src/render/kit/runtime/net.js
|
|
1234
|
+
var CONSENT_BAR = "doc-net-consent";
|
|
1235
|
+
function createNet({ restart, instances, describe }) {
|
|
1236
|
+
const global2 = globalThis;
|
|
1237
|
+
const refused = /* @__PURE__ */ new Map();
|
|
1238
|
+
const bars = /* @__PURE__ */ new Map();
|
|
1239
|
+
let consents = null;
|
|
1240
|
+
let snapshot;
|
|
1241
|
+
const embedded2 = () => {
|
|
1242
|
+
if (snapshot !== void 0) return snapshot;
|
|
1243
|
+
try {
|
|
1244
|
+
snapshot = JSON.parse(document.querySelector("script[data-doc-snapshot]")?.textContent ?? "null");
|
|
1245
|
+
} catch {
|
|
1246
|
+
snapshot = null;
|
|
1247
|
+
}
|
|
1248
|
+
return snapshot;
|
|
1249
|
+
};
|
|
1250
|
+
const failure = (code, message, fields = {}) => Object.assign(new Error(message), { code, ...fields });
|
|
1251
|
+
const read = (data, as) => {
|
|
1252
|
+
if (as === "text") return typeof data === "string" ? data : JSON.stringify(data);
|
|
1253
|
+
if (typeof data !== "string") return data;
|
|
1254
|
+
try {
|
|
1255
|
+
return JSON.parse(data);
|
|
1256
|
+
} catch {
|
|
1257
|
+
return data;
|
|
1258
|
+
}
|
|
1259
|
+
};
|
|
1260
|
+
const ownSlug = () => document.querySelector(".doc-page")?.dataset.docId || null;
|
|
1261
|
+
const NARROW = 240;
|
|
1262
|
+
const fit = (bar) => {
|
|
1263
|
+
const card = bar.parentElement;
|
|
1264
|
+
if (!card?.classList.contains("gallery-card")) return;
|
|
1265
|
+
const style = global2.getComputedStyle(card);
|
|
1266
|
+
const inner = card.clientWidth - (parseFloat(style.paddingLeft) || 0) - (parseFloat(style.paddingRight) || 0);
|
|
1267
|
+
bar.toggleAttribute("data-doc-net-narrow", inner > 0 && inner < NARROW);
|
|
1268
|
+
};
|
|
1269
|
+
global2.addEventListener("doc-layout-change", () => {
|
|
1270
|
+
for (const bar of bars.values()) if (bar.isConnected) fit(bar);
|
|
1271
|
+
});
|
|
1272
|
+
const pageSlug = () => /^\/pages\/([a-z0-9-]+)\/?$/.exec(location.pathname)?.[1] ?? null;
|
|
1273
|
+
function clear(host) {
|
|
1274
|
+
refused.delete(host);
|
|
1275
|
+
bars.get(host)?.remove();
|
|
1276
|
+
bars.delete(host);
|
|
1277
|
+
}
|
|
1278
|
+
function ask(id, hosts) {
|
|
1279
|
+
const asked = new CustomEvent("doc-net-consent", { cancelable: true, detail: { block: id, hosts } });
|
|
1280
|
+
if (global2.dispatchEvent(asked)) {
|
|
1281
|
+
const page = pageSlug();
|
|
1282
|
+
const slug = ownSlug();
|
|
1283
|
+
global2.open(`${location.origin}/${page ? `#@${page}` : slug ? `#${slug}` : ""}`, "_blank", "noopener");
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
function showConsent(host, id, hosts) {
|
|
1287
|
+
refused.set(host, { id, hosts });
|
|
1288
|
+
let bar = bars.get(host);
|
|
1289
|
+
if (!bar?.isConnected) {
|
|
1290
|
+
bar = document.createElement("div");
|
|
1291
|
+
bar.className = CONSENT_BAR;
|
|
1292
|
+
bar.setAttribute("data-doc-dev", "");
|
|
1293
|
+
bar.setAttribute("contenteditable", "false");
|
|
1294
|
+
bar.setAttribute("role", "group");
|
|
1295
|
+
const why = document.createElement("span");
|
|
1296
|
+
why.className = `${CONSENT_BAR}-why`;
|
|
1297
|
+
const from = document.createElement("span");
|
|
1298
|
+
from.className = `${CONSENT_BAR}-from`;
|
|
1299
|
+
const words = document.createElement("span");
|
|
1300
|
+
words.className = `${CONSENT_BAR}-words`;
|
|
1301
|
+
words.append(why, from);
|
|
1302
|
+
const button2 = document.createElement("button");
|
|
1303
|
+
button2.type = "button";
|
|
1304
|
+
button2.className = `${CONSENT_BAR}-allow`;
|
|
1305
|
+
button2.addEventListener("click", (event) => {
|
|
1306
|
+
event.preventDefault();
|
|
1307
|
+
event.stopPropagation();
|
|
1308
|
+
const waiting = refused.get(host);
|
|
1309
|
+
if (waiting) ask(waiting.id, waiting.hosts);
|
|
1310
|
+
});
|
|
1311
|
+
bar.append(words, button2);
|
|
1312
|
+
host.after(bar);
|
|
1313
|
+
bars.set(host, bar);
|
|
1314
|
+
}
|
|
1315
|
+
const [first, ...others] = hosts;
|
|
1316
|
+
const onCard = host.parentElement?.classList.contains("gallery-card") === true;
|
|
1317
|
+
const own = describe(id)?.consent?.[kitLanguage()];
|
|
1318
|
+
const reason = onCard ? typeof own === "string" && own ? own : sayRuntime("net-card-why") : sayRuntime("net-why");
|
|
1319
|
+
bar.querySelector(`.${CONSENT_BAR}-why`).textContent = reason;
|
|
1320
|
+
fit(bar);
|
|
1321
|
+
const button = bar.querySelector(`.${CONSENT_BAR}-allow`);
|
|
1322
|
+
const long2 = document.createElement("span");
|
|
1323
|
+
long2.className = `${CONSENT_BAR}-long`;
|
|
1324
|
+
long2.textContent = others.length > 0 ? sayRuntime("net-allow-many", first, hosts.length) : sayRuntime("net-allow", first);
|
|
1325
|
+
const short = document.createElement("span");
|
|
1326
|
+
short.className = `${CONSENT_BAR}-short`;
|
|
1327
|
+
short.textContent = sayRuntime("net-allow-short");
|
|
1328
|
+
button.replaceChildren(long2, short);
|
|
1329
|
+
button.setAttribute("aria-label", long2.textContent);
|
|
1330
|
+
const site = (name) => name.split(".").slice(-2).join(".");
|
|
1331
|
+
const shared = hosts.every((name) => site(name) === site(first)) ? site(first) : null;
|
|
1332
|
+
bar.querySelector(`.${CONSENT_BAR}-from`).textContent = shared ? sayRuntime("net-from", shared) : others.length > 0 ? sayRuntime("net-from-many", first, hosts.length) : sayRuntime("net-from", first);
|
|
1333
|
+
button.title = hosts.join("\n");
|
|
1334
|
+
bar.setAttribute("aria-label", reason);
|
|
1335
|
+
}
|
|
1336
|
+
global2.addEventListener("doc-settings-changed", (event) => {
|
|
1337
|
+
const told = event.detail?.net;
|
|
1338
|
+
if (!Array.isArray(told)) return;
|
|
1339
|
+
const before = consents;
|
|
1340
|
+
consents = new Set(told);
|
|
1341
|
+
for (const [host, def] of instances()) {
|
|
1342
|
+
const hosts = netHostsOf(describe(def.id)?.needs);
|
|
1343
|
+
if (hosts.length === 0) continue;
|
|
1344
|
+
const pair = (name) => `${def.id}@${name}`;
|
|
1345
|
+
const changed = before !== null && hosts.some((name) => before.has(pair(name)) !== consents.has(pair(name)));
|
|
1346
|
+
const waiting = refused.get(host);
|
|
1347
|
+
if (changed || waiting && waiting.hosts.every((name) => consents.has(pair(name)))) {
|
|
1348
|
+
clear(host);
|
|
1349
|
+
restart(host);
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
});
|
|
1353
|
+
return {
|
|
1354
|
+
/** The context.fetch of the instance of `def` on `host`, at `place` (context.place). */
|
|
1355
|
+
fetchFor: (def, host, place) => async (url, options = {}) => {
|
|
1356
|
+
const as = options?.as ?? "json";
|
|
1357
|
+
if (as !== "json" && as !== "text") throw failure("url", `context.fetch: as is "json" or "text", not ${JSON.stringify(as)}`);
|
|
1358
|
+
if (place === "export") {
|
|
1359
|
+
let name2;
|
|
1360
|
+
try {
|
|
1361
|
+
const address = new URL(url);
|
|
1362
|
+
address.hash = "";
|
|
1363
|
+
name2 = address.href;
|
|
1364
|
+
} catch {
|
|
1365
|
+
throw failure("url", `context.fetch: ${url} is not an absolute address`);
|
|
1366
|
+
}
|
|
1367
|
+
const kept = embedded2()?.net?.[name2];
|
|
1368
|
+
if (!kept) throw failure("offline", `an exported file reaches no network, and holds no answer for ${name2}`);
|
|
1369
|
+
return { data: read(kept.data, as), at: kept.at, cached: true };
|
|
1370
|
+
}
|
|
1371
|
+
let asked = null;
|
|
1372
|
+
const ask2 = { block: def.id, url, as, ...place === "document" && ownSlug() ? { doc: ownSlug() } : {} };
|
|
1373
|
+
global2.dispatchEvent(new CustomEvent("doc-net-fetch", { cancelable: true, detail: { ask: ask2, answer: (promise) => {
|
|
1374
|
+
asked = promise;
|
|
1375
|
+
} } }));
|
|
1376
|
+
if (!asked) throw failure("offline", "no server shows this page: nothing reaches the network for it");
|
|
1377
|
+
let answer;
|
|
1378
|
+
try {
|
|
1379
|
+
answer = await asked;
|
|
1380
|
+
} catch (error) {
|
|
1381
|
+
throw failure("offline", `the server did not answer: ${error?.message ?? error}`);
|
|
1382
|
+
}
|
|
1383
|
+
if (answer?.ok) {
|
|
1384
|
+
if (refused.has(host)) clear(host);
|
|
1385
|
+
return { data: answer.data, at: answer.at, cached: Boolean(answer.cached) };
|
|
1386
|
+
}
|
|
1387
|
+
const { code = "offline", why, hosts, host: name, status } = answer ?? {};
|
|
1388
|
+
if (code === "consent" && Array.isArray(hosts) && host.isConnected) showConsent(host, def.id, hosts);
|
|
1389
|
+
throw failure(code, `${def.id}: ${url}: ${code}${why ? ` (${why})` : ""}`, { ...hosts ? { hosts } : {}, ...name ? { host: name } : {}, ...status ? { status } : {} });
|
|
1390
|
+
},
|
|
1391
|
+
forget: clear
|
|
1392
|
+
};
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
// src/shared/page-links.mjs
|
|
1396
|
+
var DOC_SLUG = /^doc-([a-z][a-z0-9]{7})$/;
|
|
1397
|
+
function hashId(slug) {
|
|
1398
|
+
let one = 3735928559;
|
|
1399
|
+
let two = 1103547991;
|
|
1400
|
+
for (let at = 0; at < slug.length; at++) {
|
|
1401
|
+
one = Math.imul(one ^ slug.charCodeAt(at), 2654435761);
|
|
1402
|
+
two = Math.imul(two ^ slug.charCodeAt(at), 1597334677);
|
|
1403
|
+
}
|
|
1404
|
+
one = Math.imul(one ^ one >>> 16, 2246822507) ^ Math.imul(two ^ two >>> 13, 3266489909);
|
|
1405
|
+
two = Math.imul(two ^ two >>> 16, 2246822507) ^ Math.imul(one ^ one >>> 13, 3266489909);
|
|
1406
|
+
const hash = (two >>> 0) % 2 ** 21 * 2 ** 32 + (one >>> 0);
|
|
1407
|
+
return String.fromCharCode(97 + hash % 26) + Math.floor(hash / 26).toString(36).padStart(7, "0").slice(-7);
|
|
1408
|
+
}
|
|
1409
|
+
var pageId = (slug) => DOC_SLUG.exec(slug)?.[1] ?? hashId(slug);
|
|
1410
|
+
var earlierId = (slug) => DOC_SLUG.test(slug) ? hashId(slug) : null;
|
|
1411
|
+
var ID_FIRST = "abcdefghijklmnopqrstuvwxyz";
|
|
1412
|
+
var ID_REST = `${ID_FIRST}0123456789`;
|
|
1413
|
+
function pageOfLink(links, value) {
|
|
1414
|
+
if (links.has(value)) return value;
|
|
1415
|
+
const id = value.slice(value.lastIndexOf("-") + 1);
|
|
1416
|
+
for (const slug of links.keys()) if (pageId(slug) === id) return slug;
|
|
1417
|
+
for (const slug of links.keys()) if (earlierId(slug) === id) return slug;
|
|
1418
|
+
return null;
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
// src/shared/page-address.mjs
|
|
1422
|
+
var SLUG = "[a-z0-9]+(?:-[a-z0-9]+)*";
|
|
1423
|
+
var FILE = "(?:doc|report)\\.html";
|
|
1424
|
+
var IN_FILE = new RegExp(`^\\.\\./(${SLUG})/${FILE}(?:#(.*))?$`);
|
|
1425
|
+
var PAGE3 = new RegExp(`^/generated/(${SLUG})\\.html$`);
|
|
1426
|
+
var OWN_FILE = new RegExp(`^/(${SLUG})/${FILE}$`);
|
|
1427
|
+
var LOOPBACK = /* @__PURE__ */ new Set(["127.0.0.1", "localhost"]);
|
|
1428
|
+
var decoded = (text) => {
|
|
1429
|
+
try {
|
|
1430
|
+
return decodeURIComponent(text);
|
|
1431
|
+
} catch {
|
|
1432
|
+
return text;
|
|
1433
|
+
}
|
|
1434
|
+
};
|
|
1435
|
+
function ownAddress(text) {
|
|
1436
|
+
try {
|
|
1437
|
+
const url = new URL(text, "http://127.0.0.1");
|
|
1438
|
+
return /^https?:$/.test(url.protocol) && LOOPBACK.has(url.hostname) && /^(?:https?:|\/)/i.test(text) ? url : null;
|
|
1439
|
+
} catch {
|
|
1440
|
+
return null;
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
function hashAddress(hash, links = null) {
|
|
1444
|
+
const at = hash.indexOf("/");
|
|
1445
|
+
const name = at < 0 ? hash : hash.slice(0, at);
|
|
1446
|
+
const block = at < 0 ? null : hash.slice(at + 1) || null;
|
|
1447
|
+
const slug = links && pageOfLink(links, name);
|
|
1448
|
+
return slug ? { slug, block } : null;
|
|
1449
|
+
}
|
|
1450
|
+
function pageAddress(text, links = null) {
|
|
1451
|
+
const address = String(text ?? "").trim();
|
|
1452
|
+
const known = (slug, block) => !links || links.has(slug) ? { slug, block: block || null } : null;
|
|
1453
|
+
const inFile = IN_FILE.exec(address);
|
|
1454
|
+
if (inFile) return known(inFile[1], decoded(inFile[2] ?? ""));
|
|
1455
|
+
const url = ownAddress(address);
|
|
1456
|
+
if (!url) return null;
|
|
1457
|
+
const path = PAGE3.exec(url.pathname) ?? OWN_FILE.exec(url.pathname);
|
|
1458
|
+
if (path) return known(path[1], decoded(url.hash.slice(1)));
|
|
1459
|
+
return url.pathname === "/" && url.hash.length > 1 ? hashAddress(decoded(url.hash.slice(1)), links) : null;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
// src/render/kit/runtime/table-reading.js
|
|
1463
|
+
var cellReading = (cell) => ({ words: cellWords(cellText(cell)), sort: cell.getAttribute("data-sort-value")?.trim() ?? null });
|
|
1464
|
+
var spans = (row) => Boolean(row) && [...row.cells].some((cell) => cell.rowSpan !== 1 || cell.colSpan !== 1);
|
|
1465
|
+
function readTable(table2, { order = (rows) => rows, cell = cellReading } = {}) {
|
|
1466
|
+
const head = table2.tHead?.rows[0] ?? null;
|
|
1467
|
+
const body = [...table2.tBodies].flatMap((section) => [...section.rows]);
|
|
1468
|
+
const header = head ?? (body[0] && body[0].cells.length > 0 && [...body[0].cells].every((each) => each.localName === "th") ? body[0] : null);
|
|
1469
|
+
const ordered = order(body.filter((row) => row !== header));
|
|
1470
|
+
const first = header ?? ordered[0] ?? null;
|
|
1471
|
+
const rows = header ? ordered : ordered.slice(1);
|
|
1472
|
+
const read = (row) => [...row.cells].map(cell);
|
|
1473
|
+
const named = first ? read(first) : [];
|
|
1474
|
+
return {
|
|
1475
|
+
table: table2,
|
|
1476
|
+
header,
|
|
1477
|
+
first,
|
|
1478
|
+
rows,
|
|
1479
|
+
names: named.map(({ words }) => words),
|
|
1480
|
+
types: first ? [...first.cells].map((each) => each.getAttribute("data-sort-type")) : [],
|
|
1481
|
+
cells: rows.map(read),
|
|
1482
|
+
merged: [first, ...rows].some(spans)
|
|
1483
|
+
};
|
|
1484
|
+
}
|
|
1485
|
+
function linksOf(row, own) {
|
|
1486
|
+
return [...row.querySelectorAll("a[href]")].flatMap((link) => {
|
|
1487
|
+
const href = link.getAttribute("href").trim();
|
|
1488
|
+
const place = href.startsWith("#") && href.length > 1 ? own ? { slug: own, block: decoded(href.slice(1)) } : null : pageAddress(href);
|
|
1489
|
+
return place ? [{ slug: place.slug, title: cellWords(cellText(link)), block: place.block ?? null }] : [];
|
|
1490
|
+
});
|
|
1491
|
+
}
|
|
1492
|
+
function rowOf(reading, at, own) {
|
|
1493
|
+
const values = {};
|
|
1494
|
+
reading.names.forEach((name, index) => {
|
|
1495
|
+
values[name] = cellValue(reading.cells[at][index], reading.types[index] ?? null);
|
|
1496
|
+
});
|
|
1497
|
+
return Object.freeze({ el: reading.rows[at], values: Object.freeze(values), links: Object.freeze(linksOf(reading.rows[at], own)) });
|
|
1498
|
+
}
|
|
1499
|
+
var rowsOf2 = (reading, own = null) => reading.rows.map((_, at) => rowOf(reading, at, own));
|
|
1500
|
+
var SOURCES = `.doc-table-wrap[${CHART_SOURCE}]`;
|
|
1501
|
+
var READERS = TABLE_READERS.map((name) => `[${name}]`).join(", ");
|
|
1502
|
+
var WATCHED = [CHART_SOURCE, ...TABLE_READERS, "data-sort-value", "data-sort-type", "rowspan", "colspan", "aria-sort", "href"];
|
|
1503
|
+
function createKeyedTables(doc = globalThis.document) {
|
|
1504
|
+
const followers = /* @__PURE__ */ new Set();
|
|
1505
|
+
const kept = /* @__PURE__ */ new Map();
|
|
1506
|
+
let cells = /* @__PURE__ */ new WeakMap();
|
|
1507
|
+
let rowsKept = /* @__PURE__ */ new WeakMap();
|
|
1508
|
+
let observer = null;
|
|
1509
|
+
const frameOf = (key) => key === null || key === void 0 ? null : [...doc.querySelectorAll(SOURCES)].find((wrap) => wrap.getAttribute(CHART_SOURCE) === key && !wrap.closest("[data-doc-dev]")) ?? null;
|
|
1510
|
+
const fileOrder = /* @__PURE__ */ new WeakMap();
|
|
1511
|
+
const inFileOrder = (table2) => (rows) => {
|
|
1512
|
+
const sorted = [...table2.tHead?.rows[0]?.cells ?? []].some((cell) => /^(?:ascending|descending)$/.test(cell.getAttribute("aria-sort") ?? ""));
|
|
1513
|
+
if (!sorted) {
|
|
1514
|
+
rows.forEach((row, index) => fileOrder.set(row, index));
|
|
1515
|
+
return rows;
|
|
1516
|
+
}
|
|
1517
|
+
const place = (row) => fileOrder.get(row) ?? rows.length + rows.indexOf(row);
|
|
1518
|
+
return [...rows].sort((a, b) => place(a) - place(b));
|
|
1519
|
+
};
|
|
1520
|
+
const cellOf = (cell) => {
|
|
1521
|
+
if (!observer) return cellReading(cell);
|
|
1522
|
+
if (!cells.has(cell)) cells.set(cell, cellReading(cell));
|
|
1523
|
+
return cells.get(cell);
|
|
1524
|
+
};
|
|
1525
|
+
function touched(records) {
|
|
1526
|
+
const keys = /* @__PURE__ */ new Set();
|
|
1527
|
+
let readers = false;
|
|
1528
|
+
const keysIn = (node) => {
|
|
1529
|
+
if (node.nodeType !== 1) return;
|
|
1530
|
+
for (const frame of [...node.matches(SOURCES) ? [node] : [], ...node.querySelectorAll(SOURCES)]) keys.add(frame.getAttribute(CHART_SOURCE));
|
|
1531
|
+
if (node.matches(READERS) || node.querySelector(READERS)) readers = true;
|
|
1532
|
+
};
|
|
1533
|
+
for (const record of records) {
|
|
1534
|
+
if (record.type === "attributes" && record.attributeName === CHART_SOURCE) {
|
|
1535
|
+
keys.add(record.oldValue);
|
|
1536
|
+
keys.add(record.target.getAttribute(CHART_SOURCE));
|
|
1537
|
+
continue;
|
|
1538
|
+
}
|
|
1539
|
+
if (record.type === "attributes" && TABLE_READERS.includes(record.attributeName)) {
|
|
1540
|
+
readers = true;
|
|
1541
|
+
continue;
|
|
1542
|
+
}
|
|
1543
|
+
const target = record.target.nodeType === 1 ? record.target : record.target.parentElement;
|
|
1544
|
+
const frame = target?.closest(SOURCES);
|
|
1545
|
+
if (frame) keys.add(frame.getAttribute(CHART_SOURCE));
|
|
1546
|
+
const cell = target?.closest("td, th");
|
|
1547
|
+
if (cell) cells.delete(cell);
|
|
1548
|
+
const row = target?.closest("tr");
|
|
1549
|
+
if (row) rowsKept.delete(row);
|
|
1550
|
+
for (const node of [...record.addedNodes, ...record.removedNodes]) keysIn(node);
|
|
1551
|
+
}
|
|
1552
|
+
keys.delete(null);
|
|
1553
|
+
return { keys, readers };
|
|
1554
|
+
}
|
|
1555
|
+
function heard(records) {
|
|
1556
|
+
if (!doc.defaultView || records.length === 0) return;
|
|
1557
|
+
const { keys, readers } = touched(records);
|
|
1558
|
+
if (keys.size === 0 && !readers) return;
|
|
1559
|
+
for (const key of keys) kept.delete(key);
|
|
1560
|
+
for (const follower of [...followers]) {
|
|
1561
|
+
if (!followers.has(follower)) continue;
|
|
1562
|
+
const key = follower.keyOf() ?? null;
|
|
1563
|
+
if (key === follower.key && !keys.has(key)) continue;
|
|
1564
|
+
follower.key = key;
|
|
1565
|
+
follower.heard();
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
const flush = () => observer && heard(observer.takeRecords());
|
|
1569
|
+
function keptOf(key) {
|
|
1570
|
+
flush();
|
|
1571
|
+
if (kept.has(key)) return kept.get(key);
|
|
1572
|
+
const frame = frameOf(key);
|
|
1573
|
+
const table2 = frame?.querySelector("table") ?? null;
|
|
1574
|
+
const entry = { frame, reading: table2 ? readTable(table2, { order: inFileOrder(table2), cell: cellOf }) : null, rows: /* @__PURE__ */ new Map(), signature: null };
|
|
1575
|
+
if (observer) kept.set(key, entry);
|
|
1576
|
+
return entry;
|
|
1577
|
+
}
|
|
1578
|
+
const serials = /* @__PURE__ */ new WeakMap();
|
|
1579
|
+
let serial = 0;
|
|
1580
|
+
const serialOf = (el) => serials.get(el) ?? (serials.set(el, ++serial), serial);
|
|
1581
|
+
function rowKept(reading, at, own, header) {
|
|
1582
|
+
const el = reading.rows[at];
|
|
1583
|
+
const was = observer ? rowsKept.get(el) : null;
|
|
1584
|
+
if (was && was.header === header && was.own === own) return was;
|
|
1585
|
+
const row = rowOf(reading, at, own);
|
|
1586
|
+
const entry = { header, own, row, sign: null };
|
|
1587
|
+
if (observer) rowsKept.set(el, entry);
|
|
1588
|
+
return entry;
|
|
1589
|
+
}
|
|
1590
|
+
function rowsKeptOf(key, own) {
|
|
1591
|
+
const entry = keptOf(key);
|
|
1592
|
+
if (!entry.reading) return null;
|
|
1593
|
+
if (!entry.rows.has(own)) {
|
|
1594
|
+
const header = JSON.stringify([entry.reading.names, entry.reading.types]);
|
|
1595
|
+
entry.rows.set(own, entry.reading.rows.map((_, at) => rowKept(entry.reading, at, own, header)));
|
|
1596
|
+
}
|
|
1597
|
+
return entry.rows.get(own);
|
|
1598
|
+
}
|
|
1599
|
+
return Object.freeze({
|
|
1600
|
+
frameOf,
|
|
1601
|
+
reading: (key) => keptOf(key).reading,
|
|
1602
|
+
rows: (key, own = null) => rowsKeptOf(key, own)?.map(({ row }) => row) ?? null,
|
|
1603
|
+
signature(key, own = null) {
|
|
1604
|
+
const entry = keptOf(key);
|
|
1605
|
+
if (!entry.reading) return "null";
|
|
1606
|
+
if (entry.signature === null) {
|
|
1607
|
+
const rows = rowsKeptOf(key, own).map((kept2) => {
|
|
1608
|
+
kept2.sign ??= JSON.stringify([serialOf(kept2.row.el), kept2.row.values, kept2.row.links]);
|
|
1609
|
+
return kept2.sign;
|
|
1610
|
+
});
|
|
1611
|
+
entry.signature = `${JSON.stringify([entry.reading.names, entry.reading.merged])}${rows.join(",")}`;
|
|
1612
|
+
}
|
|
1613
|
+
return entry.signature;
|
|
1614
|
+
},
|
|
1615
|
+
follow(keyOf, heardIt) {
|
|
1616
|
+
const follower = { keyOf, heard: heardIt, key: keyOf() ?? null };
|
|
1617
|
+
followers.add(follower);
|
|
1618
|
+
if (!observer) {
|
|
1619
|
+
observer = new MutationObserver(heard);
|
|
1620
|
+
observer.observe(doc.documentElement, { childList: true, subtree: true, characterData: true, attributes: true, attributeOldValue: true, attributeFilter: WATCHED });
|
|
1621
|
+
}
|
|
1622
|
+
return () => {
|
|
1623
|
+
followers.delete(follower);
|
|
1624
|
+
if (followers.size > 0 || !observer) return;
|
|
1625
|
+
observer.disconnect();
|
|
1626
|
+
observer = null;
|
|
1627
|
+
kept.clear();
|
|
1628
|
+
cells = /* @__PURE__ */ new WeakMap();
|
|
1629
|
+
rowsKept = /* @__PURE__ */ new WeakMap();
|
|
1630
|
+
};
|
|
1631
|
+
}
|
|
1632
|
+
});
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
// src/render/kit/runtime/rows.js
|
|
1636
|
+
var TEXT = 3;
|
|
1637
|
+
var blankBefore = (node) => {
|
|
1638
|
+
const blank2 = node?.previousSibling;
|
|
1639
|
+
return blank2?.nodeType === TEXT && !blank2.data.trim() ? blank2 : null;
|
|
1640
|
+
};
|
|
1641
|
+
var blankAtEnd = (section) => {
|
|
1642
|
+
const last = section.lastChild;
|
|
1643
|
+
return last?.nodeType === TEXT && !last.data.trim() ? last : null;
|
|
1644
|
+
};
|
|
1645
|
+
var tableOf = (part) => part?.localName === "table" ? part : part?.querySelector?.("table") ?? null;
|
|
1646
|
+
function namedIn(columns, values) {
|
|
1647
|
+
const unknown = Object.keys(values ?? {}).filter((name) => !columns.includes(name));
|
|
1648
|
+
if (unknown.length > 0) throw new Error(`no column ${unknown.map((name) => `"${name}"`).join(", ")} in the table: its columns are ${columns.map((name) => `"${name}"`).join(", ") || "none"}`);
|
|
1649
|
+
return values ?? {};
|
|
1650
|
+
}
|
|
1651
|
+
function rowSet(table2, edit, own = null) {
|
|
1652
|
+
const found = readTable(table2);
|
|
1653
|
+
if (found.merged) return null;
|
|
1654
|
+
const columns = Object.freeze([...found.names]);
|
|
1655
|
+
const rows = Object.freeze(rowsOf2(found, own));
|
|
1656
|
+
const placeOf = (row) => rows.includes(row) && row.el.parentNode && table2.contains(row.el) ? [...table2.rows].indexOf(row.el) : -1;
|
|
1657
|
+
const named = (values) => namedIn(columns, values);
|
|
1658
|
+
const setCells = (row, values) => {
|
|
1659
|
+
columns.forEach((name, index) => {
|
|
1660
|
+
if (!Object.hasOwn(values, name)) return;
|
|
1661
|
+
while (row.cells.length <= index) row.append(row.ownerDocument.createElement("td"));
|
|
1662
|
+
row.cells[index].textContent = String(values[name] ?? "");
|
|
1663
|
+
});
|
|
1664
|
+
};
|
|
1665
|
+
const put = (nodes, next, section) => {
|
|
1666
|
+
const at = next ? blankBefore(next) ?? next : blankAtEnd(section);
|
|
1667
|
+
for (const node of nodes) if (node) (next?.parentNode ?? section).insertBefore(node, at);
|
|
1668
|
+
};
|
|
1669
|
+
const after = (row, skipped) => {
|
|
1670
|
+
let next = row.nextElementSibling;
|
|
1671
|
+
while (next && (next === skipped || next.localName !== "tr")) next = next.nextElementSibling;
|
|
1672
|
+
return next;
|
|
1673
|
+
};
|
|
1674
|
+
return Object.freeze({
|
|
1675
|
+
columns,
|
|
1676
|
+
rows,
|
|
1677
|
+
add(values, at = {}) {
|
|
1678
|
+
const given = named(values);
|
|
1679
|
+
const place = at?.after ? placeOf(at.after) : null;
|
|
1680
|
+
if (place === -1) return false;
|
|
1681
|
+
return edit((draft) => {
|
|
1682
|
+
const all = [...draft.rows];
|
|
1683
|
+
const previous = place === null ? null : all[place];
|
|
1684
|
+
const section = previous?.parentNode ?? draft.tBodies[draft.tBodies.length - 1] ?? draft.createTBody();
|
|
1685
|
+
const model = readTable(draft).rows[0] ?? null;
|
|
1686
|
+
const row = draft.ownerDocument.createElement("tr");
|
|
1687
|
+
columns.forEach((name, index) => {
|
|
1688
|
+
const like = model?.cells[index];
|
|
1689
|
+
const cell = draft.ownerDocument.createElement(like?.localName === "th" ? "th" : "td");
|
|
1690
|
+
if (like?.hasAttribute("scope")) cell.setAttribute("scope", like.getAttribute("scope"));
|
|
1691
|
+
cell.textContent = String(given[name] ?? "");
|
|
1692
|
+
row.append(cell);
|
|
1693
|
+
});
|
|
1694
|
+
const blank2 = blankBefore(previous ?? model ?? section.lastElementChild);
|
|
1695
|
+
put([blank2 ? draft.ownerDocument.createTextNode(blank2.data) : null, row], previous ? after(previous, null) : null, section);
|
|
1696
|
+
});
|
|
1697
|
+
},
|
|
1698
|
+
move(row, to = {}) {
|
|
1699
|
+
const from = placeOf(row);
|
|
1700
|
+
const target = to?.before ?? to?.after ?? null;
|
|
1701
|
+
const there = target ? placeOf(target) : null;
|
|
1702
|
+
const values = to?.values ? named(to.values) : null;
|
|
1703
|
+
if (from === -1 || there === -1) return false;
|
|
1704
|
+
return edit((draft) => {
|
|
1705
|
+
const all = [...draft.rows];
|
|
1706
|
+
const moved = all[from];
|
|
1707
|
+
if (values) setCells(moved, values);
|
|
1708
|
+
if (there === null || there === from) return;
|
|
1709
|
+
const nodes = [blankBefore(moved), moved];
|
|
1710
|
+
if (to.before) put(nodes, all[there], all[there].parentNode);
|
|
1711
|
+
else put(nodes, after(all[there], moved), all[there].parentNode);
|
|
1712
|
+
});
|
|
1713
|
+
},
|
|
1714
|
+
remove(row) {
|
|
1715
|
+
const from = placeOf(row);
|
|
1716
|
+
if (from === -1) return false;
|
|
1717
|
+
return edit((draft) => {
|
|
1718
|
+
const gone = [...draft.rows][from];
|
|
1719
|
+
blankBefore(gone)?.remove();
|
|
1720
|
+
gone.remove();
|
|
1721
|
+
});
|
|
1722
|
+
}
|
|
1723
|
+
});
|
|
1724
|
+
}
|
|
1725
|
+
|
|
627
1726
|
// src/render/kit/runtime/shown-data.js
|
|
628
1727
|
var DEPTH = 3;
|
|
629
1728
|
var ITEMS = 20;
|
|
630
1729
|
var COLUMNS = 8;
|
|
631
|
-
var
|
|
632
|
-
var
|
|
1730
|
+
var TEXT2 = 200;
|
|
1731
|
+
var MOST2 = 400;
|
|
633
1732
|
var SHORT = 20;
|
|
634
1733
|
var isObject = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
635
|
-
var
|
|
636
|
-
var cut = (text) => text.length >
|
|
1734
|
+
var isValue2 = (value) => value === null || typeof value !== "object";
|
|
1735
|
+
var cut = (text) => text.length > TEXT2 ? `${text.slice(0, TEXT2)}\u2026` : text;
|
|
637
1736
|
var sizeOf = (value) => Array.isArray(value) ? value.length : Object.keys(value).length;
|
|
638
1737
|
function made(doc, tag, text = null, className = null) {
|
|
639
1738
|
const node = doc.createElement(tag);
|
|
@@ -649,7 +1748,7 @@
|
|
|
649
1748
|
}
|
|
650
1749
|
function drawn(doc, value, depth, left) {
|
|
651
1750
|
left.values--;
|
|
652
|
-
if (
|
|
1751
|
+
if (isValue2(value)) return doc.createTextNode(scalar(value));
|
|
653
1752
|
if (sizeOf(value) === 0) return doc.createTextNode(sayRuntime("value-empty"));
|
|
654
1753
|
if (depth >= DEPTH || left.values <= 0) return doc.createTextNode(sayRuntime("value-deeper", String(sizeOf(value))));
|
|
655
1754
|
if (Array.isArray(value) && value.every(isObject)) return table(doc, value, depth, left);
|
|
@@ -690,7 +1789,7 @@
|
|
|
690
1789
|
return node;
|
|
691
1790
|
}
|
|
692
1791
|
function list(doc, items, depth, left) {
|
|
693
|
-
const node = made(doc, "ul", null, depth > 0 && items.every(
|
|
1792
|
+
const node = made(doc, "ul", null, depth > 0 && items.every(isValue2) ? DATA_LINE : null);
|
|
694
1793
|
let shown2 = 0;
|
|
695
1794
|
for (const value of items.slice(0, ITEMS)) {
|
|
696
1795
|
if (left.values <= 0) break;
|
|
@@ -719,7 +1818,7 @@
|
|
|
719
1818
|
const text = script.textContent.trim();
|
|
720
1819
|
let root;
|
|
721
1820
|
try {
|
|
722
|
-
root = text === "" ? doc.createTextNode(sayRuntime("value-empty")) : drawn(doc, JSON.parse(text), 0, { values:
|
|
1821
|
+
root = text === "" ? doc.createTextNode(sayRuntime("value-empty")) : drawn(doc, JSON.parse(text), 0, { values: MOST2 });
|
|
723
1822
|
} catch {
|
|
724
1823
|
root = doc.createTextNode(writing ? sayRuntime("not-json", cut(text)) : cut(text));
|
|
725
1824
|
}
|
|
@@ -732,12 +1831,162 @@
|
|
|
732
1831
|
return root;
|
|
733
1832
|
}
|
|
734
1833
|
|
|
1834
|
+
// src/shared/workspace-query.mjs
|
|
1835
|
+
var QUERY_KINDS = Object.freeze(["todos", "recent", "stats", "activity", "table"]);
|
|
1836
|
+
var FACT_KINDS = Object.freeze(["todos", "recent", "stats", "activity", "table"]);
|
|
1837
|
+
var QUERY_CODES = Object.freeze(["kind", "options", "unsupported", "missing", "offline", "failed"]);
|
|
1838
|
+
var QUERY_LIMITS = Object.freeze({ todos: { default: 200, most: 1e3 }, recent: { default: 10, most: 50 }, activity: { default: 365, most: 371 }, table: { default: 200, most: 1e3 } });
|
|
1839
|
+
var SNAPSHOT_LIMITS = Object.freeze({ todos: 200, recent: 50, activity: 371, tables: 20, rows: 1e3 });
|
|
1840
|
+
var TODO_EVENT = "doc-todo-set";
|
|
1841
|
+
var TODO_CODES = Object.freeze(["ref", "changed", "ambiguous", "locked", "missing", "busy", "offline", "failed"]);
|
|
1842
|
+
var SLUG2 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
1843
|
+
var BLOCK = /^[A-Za-z0-9_-]{1,64}$/;
|
|
1844
|
+
var VERSION = /^[a-f0-9]{16}$/;
|
|
1845
|
+
function todoRef(ref) {
|
|
1846
|
+
if (!ref || typeof ref !== "object" || Array.isArray(ref)) return null;
|
|
1847
|
+
const { slug, block = null, text, path, nth, version = null } = ref;
|
|
1848
|
+
if (typeof slug !== "string" || !SLUG2.test(slug) || block !== null && (typeof block !== "string" || !BLOCK.test(block))) return null;
|
|
1849
|
+
if (typeof text !== "string" || text.length > 4e3 || !Array.isArray(path) || path.length > 6 || !path.every((step) => typeof step === "string" && step.length <= 4e3)) return null;
|
|
1850
|
+
if (!Number.isInteger(nth) || nth < 0 || version !== null && (typeof version !== "string" || !VERSION.test(version))) return null;
|
|
1851
|
+
return { slug, block, text, path: [...path], nth, version };
|
|
1852
|
+
}
|
|
1853
|
+
var WORKSPACE_GLOBAL = "__galleryWorkspace";
|
|
1854
|
+
var OPEN_EVENT = "doc-open-request";
|
|
1855
|
+
function queryOptions(kind, options) {
|
|
1856
|
+
const given = options ?? {};
|
|
1857
|
+
if (typeof given !== "object" || Array.isArray(given)) return { problem: "its options are an object" };
|
|
1858
|
+
const count = (name, { default: fallback, most }) => {
|
|
1859
|
+
const value = given[name];
|
|
1860
|
+
if (value === void 0) return fallback;
|
|
1861
|
+
if (!Number.isInteger(value) || value < 1) throw new Error(`${name} is a whole number from 1`);
|
|
1862
|
+
return Math.min(value, most);
|
|
1863
|
+
};
|
|
1864
|
+
try {
|
|
1865
|
+
if (kind === "todos") {
|
|
1866
|
+
if (given.done !== void 0 && typeof given.done !== "boolean") return { problem: "done is true or false" };
|
|
1867
|
+
if (given.slugs !== void 0 && !(Array.isArray(given.slugs) && given.slugs.every((slug) => typeof slug === "string"))) return { problem: "slugs is a list of documents' slugs" };
|
|
1868
|
+
return { options: { done: given.done, slugs: given.slugs ?? null, limit: count("limit", QUERY_LIMITS.todos) } };
|
|
1869
|
+
}
|
|
1870
|
+
if (kind === "recent") return { options: { limit: count("limit", QUERY_LIMITS.recent) } };
|
|
1871
|
+
if (kind === "table") {
|
|
1872
|
+
if (typeof given.slug !== "string" || !SLUG2.test(given.slug)) return { problem: "slug is a document's slug" };
|
|
1873
|
+
if (typeof given.key !== "string" || !CHART_KEY.test(given.key)) return { problem: "key is a table's key (data-doc-chart-source)" };
|
|
1874
|
+
const where = given.where ?? {};
|
|
1875
|
+
if (typeof where !== "object" || Array.isArray(where) || !Object.values(where).every((value) => typeof value === "string")) return { problem: "where maps each column to the words its cells are to hold" };
|
|
1876
|
+
return { options: { slug: given.slug, key: given.key, where: { ...where }, limit: count("limit", QUERY_LIMITS.table) } };
|
|
1877
|
+
}
|
|
1878
|
+
if (kind === "activity") return { options: { days: count("days", QUERY_LIMITS.activity) } };
|
|
1879
|
+
return { options: {} };
|
|
1880
|
+
} catch (error) {
|
|
1881
|
+
return { problem: error.message };
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
// src/render/kit/runtime/workspace.js
|
|
1886
|
+
var ASKED = /* @__PURE__ */ new Set(["kind", "options", "unsupported", "missing"]);
|
|
1887
|
+
var SLUG3 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
1888
|
+
var BLOCK2 = /^[A-Za-z0-9_-]{1,64}$/;
|
|
1889
|
+
var embedded;
|
|
1890
|
+
var snapshotOf = () => {
|
|
1891
|
+
if (embedded !== void 0) return embedded;
|
|
1892
|
+
const tag = document.querySelector("script[data-doc-snapshot]");
|
|
1893
|
+
try {
|
|
1894
|
+
const value = JSON.parse(tag?.textContent ?? "null");
|
|
1895
|
+
embedded = value && typeof value === "object" ? { value, at: tag.getAttribute("data-at") ?? "" } : null;
|
|
1896
|
+
} catch {
|
|
1897
|
+
embedded = null;
|
|
1898
|
+
}
|
|
1899
|
+
return embedded;
|
|
1900
|
+
};
|
|
1901
|
+
function fromSnapshot(kind, used) {
|
|
1902
|
+
const value = snapshotOf()?.value;
|
|
1903
|
+
if (!value) return void 0;
|
|
1904
|
+
if (kind === "todos") {
|
|
1905
|
+
if (!Array.isArray(value.todos)) return void 0;
|
|
1906
|
+
return value.todos.filter((todo) => (used.done === void 0 || todo.done === used.done) && (!used.slugs || used.slugs.includes(todo.slug))).slice(0, used.limit);
|
|
1907
|
+
}
|
|
1908
|
+
if (kind === "recent") return Array.isArray(value.recent) ? value.recent.slice(0, used.limit) : void 0;
|
|
1909
|
+
if (kind === "stats") return value.stats && typeof value.stats === "object" ? value.stats : void 0;
|
|
1910
|
+
if (kind === "activity") return Array.isArray(value.activity) ? value.activity.slice(-used.days) : void 0;
|
|
1911
|
+
const table2 = value.tables?.[`${used.slug}#${used.key}`];
|
|
1912
|
+
if (!table2 || !Array.isArray(table2.columns) || !Array.isArray(table2.rows)) return void 0;
|
|
1913
|
+
const tidy = (text) => String(text).replace(/\s+/g, " ").trim();
|
|
1914
|
+
const words = (value2) => value2 === null || value2 === void 0 ? "" : tidy(value2);
|
|
1915
|
+
const rows = table2.rows.filter((row) => Object.entries(used.where).every(([name, wanted]) => (row.words ? tidy(row.words[name] ?? "") : words(row.values?.[name])) === tidy(wanted)));
|
|
1916
|
+
return { columns: table2.columns, rows: rows.slice(0, used.limit).map(({ values, links }) => ({ values, links })), total: rows.length };
|
|
1917
|
+
}
|
|
1918
|
+
function workspaceOf({ id, place, kinds }) {
|
|
1919
|
+
const refused = (message, code) => Promise.reject(Object.assign(new Error(`${id}: ${message}`), { code }));
|
|
1920
|
+
const own = () => document.querySelector(".doc-page")?.dataset.docId || null;
|
|
1921
|
+
const member = {
|
|
1922
|
+
query(kind, options = {}) {
|
|
1923
|
+
if (!QUERY_KINDS.includes(kind)) return refused(`workspace.query knows no kind "${kind}": todos, recent, stats, activity or table`, "kind");
|
|
1924
|
+
kinds.add(kind);
|
|
1925
|
+
if (place === "export") {
|
|
1926
|
+
const { problem, options: used } = queryOptions(kind, options);
|
|
1927
|
+
if (problem) return refused(`${kind}: ${problem}`, "options");
|
|
1928
|
+
const data = fromSnapshot(kind, used);
|
|
1929
|
+
if (data === void 0) return refused("an exported file has no workspace to read, and its export kept none of this: open it in Gallery", "offline");
|
|
1930
|
+
return Promise.resolve({ data, at: snapshotOf()?.at ?? "" });
|
|
1931
|
+
}
|
|
1932
|
+
const route = globalThis[WORKSPACE_GLOBAL];
|
|
1933
|
+
if (typeof route !== "string") return refused("an exported file has no workspace to read: open it in Gallery", "offline");
|
|
1934
|
+
let given;
|
|
1935
|
+
try {
|
|
1936
|
+
given = JSON.stringify(options ?? {});
|
|
1937
|
+
} catch {
|
|
1938
|
+
return refused("its options are no JSON", "options");
|
|
1939
|
+
}
|
|
1940
|
+
const doc = kind === "table" && place === "document" ? own() : null;
|
|
1941
|
+
const address = `${route}?kind=${encodeURIComponent(kind)}&options=${encodeURIComponent(given)}${doc ? `&doc=${encodeURIComponent(doc)}` : ""}`;
|
|
1942
|
+
return fetch(address, { cache: "no-store", credentials: "same-origin" }).then(
|
|
1943
|
+
(response) => response.json().then((answer) => {
|
|
1944
|
+
if (answer?.ok) return { data: answer.data, at: answer.at };
|
|
1945
|
+
const message = typeof answer?.message === "string" ? answer.message : `the server answered ${response.status}`;
|
|
1946
|
+
return ASKED.has(answer?.reason) ? refused(message, answer.reason) : refused(`the workspace could not be read: ${message}`, "failed");
|
|
1947
|
+
}, () => refused(`the workspace could not be read: the server answered ${response.status}`, "failed")),
|
|
1948
|
+
() => refused("the server that showed this page does not answer", "offline")
|
|
1949
|
+
);
|
|
1950
|
+
},
|
|
1951
|
+
open(target) {
|
|
1952
|
+
if (place === "export") return;
|
|
1953
|
+
const page = typeof target?.page === "string" ? target.page : null;
|
|
1954
|
+
const slug = typeof target?.slug === "string" ? target.slug : null;
|
|
1955
|
+
const block = typeof target?.block === "string" && target.block ? target.block : null;
|
|
1956
|
+
if (!(page ? SLUG3.test(page) : slug && SLUG3.test(slug)) || block !== null && !BLOCK2.test(block)) throw new Error(`${id}: workspace.open is given { slug, block? } of a document or { page } of a custom page`);
|
|
1957
|
+
const detail = page ? { page } : { slug, block };
|
|
1958
|
+
const asked = new CustomEvent(OPEN_EVENT, { cancelable: true, detail });
|
|
1959
|
+
if (!globalThis.dispatchEvent(asked)) return;
|
|
1960
|
+
globalThis.location.assign(page ? `/pages/${page}` : `/generated/${slug}.html${block ? `#${encodeURIComponent(block)}` : ""}`);
|
|
1961
|
+
}
|
|
1962
|
+
};
|
|
1963
|
+
if (place !== "export") {
|
|
1964
|
+
member.setTodo = (ref, done) => {
|
|
1965
|
+
const given = todoRef(ref);
|
|
1966
|
+
if (!given || typeof done !== "boolean") return refused(`workspace.setTodo is given a to-do's ref as query("todos") gave it, and true or false`, "ref");
|
|
1967
|
+
let answer = null;
|
|
1968
|
+
const asked = new CustomEvent(TODO_EVENT, { cancelable: true, detail: { ask: { slug: given.slug, ref: given, done }, answer: (promise) => {
|
|
1969
|
+
answer = promise;
|
|
1970
|
+
} } });
|
|
1971
|
+
globalThis.dispatchEvent(asked);
|
|
1972
|
+
if (!asked.defaultPrevented || !answer) return refused("nothing on this page writes the workspace: open it in Gallery's workbench", "offline");
|
|
1973
|
+
return Promise.resolve(answer).then((result) => {
|
|
1974
|
+
if (result?.ok) return result.changed === true;
|
|
1975
|
+
const code = TODO_CODES.includes(result?.reason) ? result.reason : "failed";
|
|
1976
|
+
return refused(typeof result?.message === "string" ? result.message : `the to-do could not be written (${result?.reason ?? "no answer"})`, code);
|
|
1977
|
+
}, () => refused("the server that showed this page does not answer", "offline"));
|
|
1978
|
+
};
|
|
1979
|
+
}
|
|
1980
|
+
return Object.freeze(member);
|
|
1981
|
+
}
|
|
1982
|
+
|
|
735
1983
|
// src/render/kit/runtime/kernel.js
|
|
736
1984
|
function createKit({ descriptions }) {
|
|
737
1985
|
const global2 = globalThis;
|
|
738
1986
|
const defs = /* @__PURE__ */ new Map();
|
|
739
1987
|
const instances = /* @__PURE__ */ new Map();
|
|
740
1988
|
const counters = { mounted: 0, destroyed: 0, failed: 0 };
|
|
1989
|
+
const tables = createKeyedTables();
|
|
741
1990
|
const preview = () => !document.querySelector('meta[name="generator"][content="Gallery"], meta[name="generator"][content="HTML Report Studio"], meta[name="doc-export-id"]');
|
|
742
1991
|
const writing = () => preview() && !new URLSearchParams(location.search).has("present");
|
|
743
1992
|
const selectorOf = (def) => def.selector ?? descriptions.get(def.id)?.match;
|
|
@@ -766,17 +2015,21 @@
|
|
|
766
2015
|
instance.note = null;
|
|
767
2016
|
}
|
|
768
2017
|
const queued = /* @__PURE__ */ new Map();
|
|
2018
|
+
const toHear = /* @__PURE__ */ new Map();
|
|
769
2019
|
let frame = 0;
|
|
770
2020
|
let asked = 0;
|
|
771
2021
|
function runFrame() {
|
|
772
2022
|
frame = 0;
|
|
2023
|
+
const told = [...toHear];
|
|
2024
|
+
toHear.clear();
|
|
2025
|
+
for (const [host, records] of told) tell(host, "source", records);
|
|
773
2026
|
const work = [...queued];
|
|
774
2027
|
queued.clear();
|
|
775
2028
|
for (const [host, run] of work) {
|
|
776
2029
|
const instance = instances.get(host);
|
|
777
2030
|
if (!instance) continue;
|
|
778
2031
|
try {
|
|
779
|
-
run
|
|
2032
|
+
guarded(instance, host, run, "drew in a frame");
|
|
780
2033
|
clearNote(instance);
|
|
781
2034
|
} catch (error) {
|
|
782
2035
|
report(instance.def, host, error);
|
|
@@ -785,10 +2038,58 @@
|
|
|
785
2038
|
asked = queued.size > 0 ? asked + 1 : 0;
|
|
786
2039
|
settle();
|
|
787
2040
|
}
|
|
2041
|
+
const ask = () => {
|
|
2042
|
+
if (!frame) frame = requestAnimationFrame(runFrame);
|
|
2043
|
+
};
|
|
788
2044
|
function schedule(host, run) {
|
|
789
2045
|
if (instances.get(host)?.failed) return;
|
|
790
2046
|
queued.set(host, run);
|
|
791
|
-
|
|
2047
|
+
ask();
|
|
2048
|
+
}
|
|
2049
|
+
function hearLater(host, records) {
|
|
2050
|
+
const pending = toHear.get(host);
|
|
2051
|
+
if (pending) pending.push(...records);
|
|
2052
|
+
else toHear.set(host, records);
|
|
2053
|
+
ask();
|
|
2054
|
+
}
|
|
2055
|
+
const GUARD = { childList: true, subtree: true, characterData: true, characterDataOldValue: true, attributes: true, attributeOldValue: true };
|
|
2056
|
+
function guarded(instance, host, run, when) {
|
|
2057
|
+
const slots = ofPackage(instance.def) ? slotsIn(host) : [];
|
|
2058
|
+
if (slots.length === 0) return run();
|
|
2059
|
+
const guard = new MutationObserver(() => {
|
|
2060
|
+
});
|
|
2061
|
+
guard.observe(host, GUARD);
|
|
2062
|
+
let result;
|
|
2063
|
+
let failure = null;
|
|
2064
|
+
try {
|
|
2065
|
+
result = run();
|
|
2066
|
+
} catch (error) {
|
|
2067
|
+
failure = error;
|
|
2068
|
+
}
|
|
2069
|
+
const records = guard.takeRecords();
|
|
2070
|
+
guard.disconnect();
|
|
2071
|
+
const touches = (slot2) => records.some((record) => slot2.contains(record.target) || record.type === "childList" && [...record.addedNodes, ...record.removedNodes].some((node) => node === slot2 || node.contains?.(slot2)));
|
|
2072
|
+
const slot = slots.find(touches);
|
|
2073
|
+
if (!slot) {
|
|
2074
|
+
if (failure) throw failure;
|
|
2075
|
+
return result;
|
|
2076
|
+
}
|
|
2077
|
+
putBack(records);
|
|
2078
|
+
throw Object.assign(new Error(`it wrote in its slot "${slot.getAttribute(SLOT)}" as it ${when}, which is put back: a slot holds the document's blocks, the reader's; read it with context.part, and draw outside it`), { made: result });
|
|
2079
|
+
}
|
|
2080
|
+
function putBack(records) {
|
|
2081
|
+
for (const record of [...records].reverse()) {
|
|
2082
|
+
const { target } = record;
|
|
2083
|
+
if (record.type === "characterData") target.data = record.oldValue ?? "";
|
|
2084
|
+
else if (record.type === "attributes") {
|
|
2085
|
+
if (record.oldValue === null) target.removeAttributeNS(record.attributeNamespace, record.attributeName);
|
|
2086
|
+
else target.setAttributeNS(record.attributeNamespace, record.attributeName, record.oldValue);
|
|
2087
|
+
} else {
|
|
2088
|
+
for (const node of record.addedNodes) if (node.parentNode === target) target.removeChild(node);
|
|
2089
|
+
const next = record.nextSibling?.parentNode === target ? record.nextSibling : null;
|
|
2090
|
+
for (const node of record.removedNodes) target.insertBefore(node, next);
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
792
2093
|
}
|
|
793
2094
|
const ENDLESS = 30;
|
|
794
2095
|
let drawn2 = false;
|
|
@@ -815,7 +2116,7 @@
|
|
|
815
2116
|
const instance = instances.get(host);
|
|
816
2117
|
if (!instance?.handle?.update) return;
|
|
817
2118
|
try {
|
|
818
|
-
instance.handle.update(reason, detail, options);
|
|
2119
|
+
guarded(instance, host, () => instance.handle.update(reason, detail, options), `heard ${reason}`);
|
|
819
2120
|
} catch (error) {
|
|
820
2121
|
report(instance.def, host, error);
|
|
821
2122
|
}
|
|
@@ -841,30 +2142,107 @@
|
|
|
841
2142
|
global2.addEventListener("resize", () => tellAll("viewport"));
|
|
842
2143
|
document.fonts?.ready.then(() => tellAll("fonts"));
|
|
843
2144
|
document.fonts?.addEventListener?.("loadingdone", (event) => tellAll("fonts", [...event.fontfaces ?? []]));
|
|
2145
|
+
global2.addEventListener("doc-workspace-change", (event) => listening("data").forEach(([host, instance]) => {
|
|
2146
|
+
if (instance.kinds?.has(event.detail)) tell(host, "data", event.detail);
|
|
2147
|
+
}));
|
|
2148
|
+
let clockTimer = 0;
|
|
2149
|
+
let today = null;
|
|
2150
|
+
function armClock() {
|
|
2151
|
+
if (clockTimer || listening("clock").length === 0) return;
|
|
2152
|
+
const now = /* @__PURE__ */ new Date();
|
|
2153
|
+
today ??= now.toDateString();
|
|
2154
|
+
clockTimer = global2.setTimeout(tick, 6e4 - (now.getSeconds() * 1e3 + now.getMilliseconds()) + 5);
|
|
2155
|
+
}
|
|
2156
|
+
function tick() {
|
|
2157
|
+
clockTimer = 0;
|
|
2158
|
+
const day = (/* @__PURE__ */ new Date()).toDateString();
|
|
2159
|
+
const detail = day === today ? "minute" : "day";
|
|
2160
|
+
today = day;
|
|
2161
|
+
tellAll("clock", detail);
|
|
2162
|
+
armClock();
|
|
2163
|
+
}
|
|
844
2164
|
const ownedBy = (node, host) => node.parentElement.closest(INSTANCE) === host && heldBy(node) === host;
|
|
845
2165
|
const partsIn = (host, at, edit = null) => [...host.querySelectorAll(at)].filter((node) => !node.matches(INSTANCE) && ownedBy(node, host) && edit === "flow" === node.matches(SLOT_PART));
|
|
846
|
-
const
|
|
2166
|
+
const placeOf = (host) => host.closest(PAGE2) ? "page" : preview() ? "document" : "export";
|
|
2167
|
+
const HASHED_OUT = /^(?:data-block-id|data-ge-.*|contenteditable|spellcheck|data-doc-fallback.*|inert)$/;
|
|
2168
|
+
const hashes = /* @__PURE__ */ new WeakMap();
|
|
2169
|
+
function markupHash(def, host) {
|
|
2170
|
+
if (hashes.has(host)) return hashes.get(host);
|
|
2171
|
+
const copy = host.cloneNode(true);
|
|
2172
|
+
try {
|
|
2173
|
+
def.dehydrate?.(copy);
|
|
2174
|
+
} catch {
|
|
2175
|
+
}
|
|
2176
|
+
takeRuntime(descriptions.get(def.id), copy);
|
|
2177
|
+
for (const { at, edit } of Object.values(descriptions.get(def.id)?.parts ?? {})) {
|
|
2178
|
+
if (edit === "text" || edit === "data" || edit === "flow") partsIn(copy, at, edit).forEach((node) => node.replaceChildren());
|
|
2179
|
+
}
|
|
2180
|
+
const attributes = (node) => [...node.attributes].filter(({ name }) => !HASHED_OUT.test(name)).map(({ name, value }) => ` ${name}="${value}"`).sort().join("");
|
|
2181
|
+
const shape = (node) => `<${node.localName}${attributes(node)}>${[...node.children].filter((child) => !child.matches(`[data-doc-dev], .${NOTE}, .${DATA_SHOWN}`)).map(shape).join("")}`;
|
|
2182
|
+
let hash = 2166136261;
|
|
2183
|
+
for (const char of shape(copy)) hash = Math.imul(hash ^ char.codePointAt(0), 16777619);
|
|
2184
|
+
const made2 = (hash >>> 0).toString(36);
|
|
2185
|
+
hashes.set(host, made2);
|
|
2186
|
+
return made2;
|
|
2187
|
+
}
|
|
2188
|
+
function stateName(def, host) {
|
|
2189
|
+
const card = placeOf(host) === "page" ? host.closest(CARD)?.getAttribute(CARD_ID) : null;
|
|
2190
|
+
if (card) return { id: `${def.id}:${card}` };
|
|
2191
|
+
const hashed = () => {
|
|
2192
|
+
const hash = markupHash(def, host);
|
|
2193
|
+
const alike = hostsIn(document, selectorOf(def)).filter((other) => !outsidePage(other) && !inOther(def, other) && markupHash(def, other) === hash);
|
|
2194
|
+
return `${def.id}:${hash}:${Math.max(0, alike.indexOf(host))}`;
|
|
2195
|
+
};
|
|
2196
|
+
const block = host.getAttribute("data-block-id");
|
|
2197
|
+
return block ? { id: `${def.id}:${block}`, formerId: hashed() } : { id: hashed() };
|
|
2198
|
+
}
|
|
2199
|
+
const ownSlug = () => document.querySelector(".doc-page")?.dataset.docId || null;
|
|
847
2200
|
const canEdit = (def, host) => editable && instances.get(host)?.failed === false && !schemaAhead(host.getAttribute(SCHEMA), descriptions.get(def.id)?.schema);
|
|
848
2201
|
const partNamed = (def, name) => {
|
|
849
2202
|
const part = descriptions.get(def.id)?.parts?.[name];
|
|
850
2203
|
if (!part) throw new Error(`no part "${name}" in ${def.id}'s manifest`);
|
|
851
2204
|
return part;
|
|
852
2205
|
};
|
|
853
|
-
|
|
854
|
-
part
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
2206
|
+
function packageContext(def, host, instance) {
|
|
2207
|
+
const part = (name) => partsIn(host, partNamed(def, name).at, partNamed(def, name).edit)[0] ?? null;
|
|
2208
|
+
const place = placeOf(host);
|
|
2209
|
+
const needs = descriptions.get(def.id)?.needs ?? [];
|
|
2210
|
+
const ended = () => instances.get(host) !== instance || instance.failed;
|
|
2211
|
+
const timers = /* @__PURE__ */ new Map();
|
|
2212
|
+
const timer = (set, clear2, run, ms, once) => {
|
|
2213
|
+
if (typeof run !== "function") throw new Error(`${def.id}: a timer runs a function`);
|
|
2214
|
+
const { signal } = instance.controller;
|
|
2215
|
+
if (signal.aborted) return 0;
|
|
2216
|
+
if (!timers.armed) {
|
|
2217
|
+
timers.armed = true;
|
|
2218
|
+
signal.addEventListener("abort", () => {
|
|
2219
|
+
for (const [id2, clearIt] of timers) clearIt.call(global2, id2);
|
|
2220
|
+
timers.clear();
|
|
2221
|
+
}, { once: true });
|
|
2222
|
+
}
|
|
2223
|
+
const id = set.call(global2, () => {
|
|
2224
|
+
if (once) timers.delete(id);
|
|
2225
|
+
if (ended()) return;
|
|
2226
|
+
try {
|
|
2227
|
+
guarded(instance, host, run, "ran a timer");
|
|
2228
|
+
} catch (error) {
|
|
2229
|
+
report(def, host, error);
|
|
2230
|
+
}
|
|
2231
|
+
}, ms);
|
|
2232
|
+
timers.set(id, clear2);
|
|
2233
|
+
return id;
|
|
2234
|
+
};
|
|
2235
|
+
const edit = (names, change) => {
|
|
858
2236
|
if (!canEdit(def, host)) return false;
|
|
859
2237
|
const several = Array.isArray(names);
|
|
860
2238
|
const parts = (several ? names : [names]).map((name) => {
|
|
861
|
-
const { at, edit } = partNamed(def, name);
|
|
862
|
-
if (
|
|
863
|
-
return { name, part: partsIn(host, at,
|
|
2239
|
+
const { at, edit: edit2 } = partNamed(def, name);
|
|
2240
|
+
if (edit2 !== "data") throw new Error(`the part "${name}" of ${def.id} is not edited as data`);
|
|
2241
|
+
return { name, part: partsIn(host, at, edit2)[0] };
|
|
864
2242
|
});
|
|
865
|
-
const apart = parts.find(({ part }, index) => parts.some((other, at) => at !== index &&
|
|
2243
|
+
const apart = parts.find(({ part: part2 }, index) => parts.some((other, at) => at !== index && part2 && other.part && (part2 === other.part || other.part.contains(part2))));
|
|
866
2244
|
if (apart) throw new Error(`the part "${apart.name}" of ${def.id} is in another this edit names, or is it: name the one around it`);
|
|
867
|
-
if (parts.length === 0 || parts.some(({ part }) => !
|
|
2245
|
+
if (parts.length === 0 || parts.some(({ part: part2 }) => !part2)) return false;
|
|
868
2246
|
const run = (drafts) => {
|
|
869
2247
|
try {
|
|
870
2248
|
if (typeof change(several ? drafts : drafts[names])?.then === "function") throw new Error(`a change of ${several ? names.map((name) => `"${name}"`).join(", ") : `"${names}"`} runs at once: context.edit does not wait for it`);
|
|
@@ -875,8 +2253,158 @@
|
|
|
875
2253
|
}
|
|
876
2254
|
};
|
|
877
2255
|
return !host.dispatchEvent(new CustomEvent("doc-component-edit", { bubbles: true, cancelable: true, detail: { parts, run } }));
|
|
2256
|
+
};
|
|
2257
|
+
return {
|
|
2258
|
+
part,
|
|
2259
|
+
state: ({ version, defaults, transientKeys }) => global2.DocState.getOrCreate({ ...stateName(def, host), version, defaults, transientKeys }),
|
|
2260
|
+
canEdit: () => canEdit(def, host),
|
|
2261
|
+
edit,
|
|
2262
|
+
// A part's JSON, parsed (JSON's null too, as any value it holds); undefined where there is nothing
|
|
2263
|
+
// to read, which no JSON is: an optional part the instance does not hold, and one that holds no
|
|
2264
|
+
// JSON, which fails the instance (context.fail), as its data cannot be read.
|
|
2265
|
+
readJSON(name) {
|
|
2266
|
+
const node = part(name);
|
|
2267
|
+
if (!node) return void 0;
|
|
2268
|
+
try {
|
|
2269
|
+
return JSON.parse(node.textContent ?? "");
|
|
2270
|
+
} catch (error) {
|
|
2271
|
+
report(def, host, new Error(`its part "${name}" holds no JSON: ${error.message}`));
|
|
2272
|
+
return void 0;
|
|
2273
|
+
}
|
|
2274
|
+
},
|
|
2275
|
+
// An edit of a part of JSON (a script of data): `change` is handed what it holds, parsed, and changes
|
|
2276
|
+
// it or returns what is to stand there instead; written back as it was laid out (json-layout.mjs
|
|
2277
|
+
// jsonIn), and not at all where it holds what it held.
|
|
2278
|
+
editJSON(name, change) {
|
|
2279
|
+
if (typeof name !== "string") throw new Error(`${def.id}: context.editJSON names one part`);
|
|
2280
|
+
return edit(name, (script) => {
|
|
2281
|
+
const text = script.textContent ?? "";
|
|
2282
|
+
let data;
|
|
2283
|
+
try {
|
|
2284
|
+
data = JSON.parse(text);
|
|
2285
|
+
} catch (error) {
|
|
2286
|
+
throw new Error(`its part "${name}" holds no JSON: ${error.message}`);
|
|
2287
|
+
}
|
|
2288
|
+
const result = change(data);
|
|
2289
|
+
if (typeof result?.then === "function") throw new Error(`a change of "${name}" runs at once: context.editJSON does not wait for it`);
|
|
2290
|
+
const next = result === void 0 ? data : result;
|
|
2291
|
+
if (JSON.stringify(next) !== JSON.stringify(JSON.parse(text))) script.textContent = jsonIn(text, next);
|
|
2292
|
+
});
|
|
2293
|
+
},
|
|
2294
|
+
// The rows of the table a part is or holds (rows.js), each write of them one edit of that part.
|
|
2295
|
+
rows(name) {
|
|
2296
|
+
const table2 = tableOf(part(name));
|
|
2297
|
+
if (!table2) return null;
|
|
2298
|
+
return rowSet(table2, (change) => edit(name, (draft) => {
|
|
2299
|
+
const drafted = tableOf(draft);
|
|
2300
|
+
if (!drafted) throw new Error(`its part "${name}" holds no table`);
|
|
2301
|
+
change(drafted);
|
|
2302
|
+
}), ownSlug());
|
|
2303
|
+
},
|
|
2304
|
+
// The table of the document this instance is a view of (a block whose needs hold "tables": VIEW_FROM
|
|
2305
|
+
// names its key), read now: its rows as context.rows gives them, and what changes it, each asked of
|
|
2306
|
+
// the page editor (tableView).
|
|
2307
|
+
table: () => tableView(def, host, instance, place),
|
|
2308
|
+
interval: (run, ms) => timer(global2.setInterval, global2.clearInterval, run, ms, false),
|
|
2309
|
+
timeout: (run, ms) => timer(global2.setTimeout, global2.clearTimeout, run, ms, true),
|
|
2310
|
+
// A listener that goes as the instance ends, or as the signal of its own options aborts.
|
|
2311
|
+
listen(target, type, run, options = {}) {
|
|
2312
|
+
const given = typeof options === "boolean" ? { capture: options } : { ...options ?? {} };
|
|
2313
|
+
const own = given.signal;
|
|
2314
|
+
if (own?.aborted || instance.controller.signal.aborted) return;
|
|
2315
|
+
target.addEventListener(type, run, { ...given, signal: instance.controller.signal });
|
|
2316
|
+
own?.addEventListener("abort", () => target.removeEventListener(type, run, { capture: Boolean(given.capture) }), { once: true });
|
|
2317
|
+
},
|
|
2318
|
+
place,
|
|
2319
|
+
// A block whose needs name a host of the net reaches it through the server (net.js), nothing else.
|
|
2320
|
+
...netHostsOf(descriptions.get(def.id)?.needs).length > 0 ? { fetch: net.fetchFor(def, host, place) } : {},
|
|
2321
|
+
// Its card's size on a custom page, in the grid's cells (what the board draws it at, never the raw
|
|
2322
|
+
// attributes: card-size.mjs drawnCells) and in pixels, what its card holds inside its padding; null
|
|
2323
|
+
// anywhere else. The page says when it changes: `layout`.
|
|
2324
|
+
get size() {
|
|
2325
|
+
const card = place === "page" ? host.closest(CARD) : null;
|
|
2326
|
+
if (!card) return null;
|
|
2327
|
+
const style = global2.getComputedStyle(card);
|
|
2328
|
+
const inner = (size, ...sides) => Math.max(0, Math.round(size - sides.reduce((sum, side) => sum + (parseFloat(style[side]) || 0), 0)));
|
|
2329
|
+
return { ...drawnCells(card), width: inner(card.clientWidth, "paddingLeft", "paddingRight"), height: inner(card.clientHeight, "paddingTop", "paddingBottom") };
|
|
2330
|
+
},
|
|
2331
|
+
// What it reads of the workspace, where its manifest's needs say "workspace" (workspace.js), and none elsewhere.
|
|
2332
|
+
...needs.includes("workspace") ? { workspace: workspaceOf({ id: def.id, place, kinds: instance.kinds = /* @__PURE__ */ new Set() }) } : {}
|
|
2333
|
+
};
|
|
2334
|
+
}
|
|
2335
|
+
const tablesTold = /* @__PURE__ */ new Set();
|
|
2336
|
+
const readsTables = (def) => descriptions.get(def.id)?.needs?.includes("tables") ?? false;
|
|
2337
|
+
function following(def, host, instance) {
|
|
2338
|
+
if (instance.view) return instance.view;
|
|
2339
|
+
const signature = () => {
|
|
2340
|
+
const key = host.getAttribute(VIEW_FROM);
|
|
2341
|
+
return key ? tables.signature(key, ownSlug()) : "none";
|
|
2342
|
+
};
|
|
2343
|
+
const view = { listeners: /* @__PURE__ */ new Set(), told: signature() };
|
|
2344
|
+
instance.view = view;
|
|
2345
|
+
const unfollow = tables.follow(() => host.getAttribute(VIEW_FROM), () => {
|
|
2346
|
+
if (instances.get(host) !== instance || instance.failed) return;
|
|
2347
|
+
const now = signature();
|
|
2348
|
+
if (now === view.told) return;
|
|
2349
|
+
view.told = now;
|
|
2350
|
+
for (const listener of [...view.listeners]) {
|
|
2351
|
+
try {
|
|
2352
|
+
guarded(instance, host, listener, "heard its table");
|
|
2353
|
+
} catch (error) {
|
|
2354
|
+
report(def, host, error);
|
|
2355
|
+
return;
|
|
2356
|
+
}
|
|
2357
|
+
}
|
|
2358
|
+
if (def.on?.includes("data")) tell(host, "data", "table");
|
|
2359
|
+
});
|
|
2360
|
+
instance.controller.signal.addEventListener("abort", unfollow, { once: true });
|
|
2361
|
+
return view;
|
|
2362
|
+
}
|
|
2363
|
+
function tableView(def, host, instance, place) {
|
|
2364
|
+
if (!readsTables(def)) {
|
|
2365
|
+
if (!tablesTold.has(def.id)) console.error(`[DocKit] ${def.id}: context.table() reads a table for a block whose manifest's needs hold "tables"`);
|
|
2366
|
+
tablesTold.add(def.id);
|
|
2367
|
+
return null;
|
|
878
2368
|
}
|
|
879
|
-
|
|
2369
|
+
const key = host.getAttribute(VIEW_FROM);
|
|
2370
|
+
const reading = place === "page" || !key ? null : tables.reading(key);
|
|
2371
|
+
if (!reading || reading.merged) return null;
|
|
2372
|
+
const { table: table2 } = reading;
|
|
2373
|
+
const columns = Object.freeze([...reading.names]);
|
|
2374
|
+
const rows = Object.freeze([...tables.rows(key, ownSlug())]);
|
|
2375
|
+
const live2 = (row) => rows.includes(row) && table2.isConnected && table2.contains(row.el);
|
|
2376
|
+
const cellsOf2 = (values) => Object.entries(namedIn(columns, values)).map(([name, text]) => [columns.lastIndexOf(name), String(text ?? "")]);
|
|
2377
|
+
const ask2 = (detail) => place === "document" && canEdit(def, host) && !host.dispatchEvent(new CustomEvent("doc-table-intent", { bubbles: true, cancelable: true, detail: { table: table2, ...detail } }));
|
|
2378
|
+
return Object.freeze({
|
|
2379
|
+
columns,
|
|
2380
|
+
rows,
|
|
2381
|
+
canEdit: () => ask2({ op: "check" }),
|
|
2382
|
+
set(row, column, text) {
|
|
2383
|
+
const cells = cellsOf2({ [column]: text });
|
|
2384
|
+
return live2(row) && ask2({ op: "set", row: row.el, cells });
|
|
2385
|
+
},
|
|
2386
|
+
add(values, at = {}) {
|
|
2387
|
+
const cells = cellsOf2(values);
|
|
2388
|
+
if (at?.after && !live2(at.after)) return false;
|
|
2389
|
+
return ask2({ op: "add", after: at?.after?.el ?? null, cells });
|
|
2390
|
+
},
|
|
2391
|
+
move(row, to = {}) {
|
|
2392
|
+
const cells = to?.values ? cellsOf2(to.values) : [];
|
|
2393
|
+
const target = to?.before ?? to?.after ?? null;
|
|
2394
|
+
if (!live2(row) || target && !live2(target)) return false;
|
|
2395
|
+
return ask2({ op: "move", row: row.el, before: to?.before?.el ?? null, after: to?.before ? null : to?.after?.el ?? null, cells });
|
|
2396
|
+
},
|
|
2397
|
+
remove: (row) => live2(row) && ask2({ op: "remove", row: row.el }),
|
|
2398
|
+
subscribe(listener) {
|
|
2399
|
+
if (typeof listener !== "function") throw new Error(`${def.id}: context.table().subscribe takes a function`);
|
|
2400
|
+
if (instances.get(host) !== instance || instance.controller.signal.aborted) return () => {
|
|
2401
|
+
};
|
|
2402
|
+
const { listeners } = following(def, host, instance);
|
|
2403
|
+
listeners.add(listener);
|
|
2404
|
+
return () => void listeners.delete(listener);
|
|
2405
|
+
}
|
|
2406
|
+
});
|
|
2407
|
+
}
|
|
880
2408
|
function takeRuntime(description, root) {
|
|
881
2409
|
const { generated = [], attrs = {} } = description?.runtime ?? {};
|
|
882
2410
|
const own = (selector) => hostsIn(root, selector).filter((node) => node === root || heldBy(node) === root);
|
|
@@ -905,6 +2433,7 @@
|
|
|
905
2433
|
if (instance.failed) return;
|
|
906
2434
|
instance.failed = true;
|
|
907
2435
|
queued.delete(host);
|
|
2436
|
+
toHear.delete(host);
|
|
908
2437
|
resize.unobserve(host);
|
|
909
2438
|
instance.controller.abort();
|
|
910
2439
|
const { handle } = instance;
|
|
@@ -930,16 +2459,17 @@
|
|
|
930
2459
|
host,
|
|
931
2460
|
signal: controller.signal,
|
|
932
2461
|
frame: (run) => schedule(host, run),
|
|
933
|
-
fail: (error) => report(def, host, error)
|
|
934
|
-
...packaged ? packageContext(def, host) : {}
|
|
2462
|
+
fail: (error) => report(def, host, error)
|
|
935
2463
|
};
|
|
2464
|
+
if (packaged) Object.defineProperties(context2, Object.getOwnPropertyDescriptors(packageContext(def, host, instance)));
|
|
936
2465
|
instance.context = context2;
|
|
937
2466
|
let failure = null;
|
|
938
2467
|
let made2 = null;
|
|
939
2468
|
try {
|
|
940
|
-
made2 = make(context2);
|
|
2469
|
+
made2 = make(context2, (run) => guarded(instance, host, run, "mounted"));
|
|
941
2470
|
} catch (error) {
|
|
942
2471
|
failure = error;
|
|
2472
|
+
if (error?.made && typeof error.made.then !== "function") instance.handle = error.made;
|
|
943
2473
|
}
|
|
944
2474
|
if (packaged && (failure || instance.failed)) {
|
|
945
2475
|
const failedAsItRan = instance.failed;
|
|
@@ -957,6 +2487,9 @@
|
|
|
957
2487
|
}
|
|
958
2488
|
counters.mounted += 1;
|
|
959
2489
|
if (def.on?.includes("resize")) resize.observe(host);
|
|
2490
|
+
if (def.on?.includes("source")) watchSource();
|
|
2491
|
+
if (def.on?.includes("clock")) armClock();
|
|
2492
|
+
if (packaged && def.on?.includes("data") && readsTables(def)) following(def, host, instance);
|
|
960
2493
|
return instance.handle;
|
|
961
2494
|
}
|
|
962
2495
|
function whenMade(promise, instance, host, context2) {
|
|
@@ -973,16 +2506,18 @@
|
|
|
973
2506
|
}
|
|
974
2507
|
function mount(def, host) {
|
|
975
2508
|
if (instances.has(host)) return instances.get(host).handle;
|
|
976
|
-
return keep(def, host, (context2) => {
|
|
2509
|
+
return keep(def, host, (context2, guard) => {
|
|
977
2510
|
if (ofPackage(def)) clear(def, host);
|
|
978
|
-
return def.mount(host, context2);
|
|
2511
|
+
return guard(() => def.mount(host, context2));
|
|
979
2512
|
});
|
|
980
2513
|
}
|
|
981
2514
|
function destroy(host) {
|
|
982
2515
|
const instance = instances.get(host);
|
|
983
2516
|
if (!instance) return;
|
|
2517
|
+
net.forget(host);
|
|
984
2518
|
instances.delete(host);
|
|
985
2519
|
queued.delete(host);
|
|
2520
|
+
toHear.delete(host);
|
|
986
2521
|
counters.destroyed += 1;
|
|
987
2522
|
resize.unobserve(host);
|
|
988
2523
|
instance.controller.abort();
|
|
@@ -993,6 +2528,13 @@
|
|
|
993
2528
|
report(instance.def, host, error);
|
|
994
2529
|
}
|
|
995
2530
|
}
|
|
2531
|
+
function restart(host) {
|
|
2532
|
+
const instance = instances.get(host);
|
|
2533
|
+
if (!instance) return;
|
|
2534
|
+
destroy(host);
|
|
2535
|
+
if (host.isConnected) mount(instance.def, host);
|
|
2536
|
+
}
|
|
2537
|
+
const net = createNet({ restart, instances: () => [...instances].map(([host, { def }]) => [host, def]), describe: (id) => descriptions.get(id) });
|
|
996
2538
|
const hostsIn = (root, selector) => [...root.matches?.(selector) ? [root] : [], ...root.querySelectorAll?.(selector) ?? []];
|
|
997
2539
|
const outsidePage = (node) => Boolean(node.closest?.("[data-doc-dev]"));
|
|
998
2540
|
const inOther = (def, host) => host.matches(INSTANCE) && host.getAttribute(ATTRIBUTE) !== def.id || (heldBy(host)?.getAttribute(ATTRIBUTE) ?? def.id) !== def.id;
|
|
@@ -1079,6 +2621,12 @@
|
|
|
1079
2621
|
if (!host.matches(INSTANCE)) return true;
|
|
1080
2622
|
return target === host || componentAt(target) && heldBy(target) === host;
|
|
1081
2623
|
};
|
|
2624
|
+
function ofTheFile(host, target, record) {
|
|
2625
|
+
const region = record.type === "attributes" ? heldBy(target) : heldWithin(target);
|
|
2626
|
+
if (region === null || region === host) return true;
|
|
2627
|
+
return sourceParts(region, region.getAttribute(ATTRIBUTE)).some((part) => part.contains(target));
|
|
2628
|
+
}
|
|
2629
|
+
const ofSource = (record) => record.attributeName === "class" ? lookChanged(record.oldValue, record.target.getAttribute("class")) : SOURCE_ATTRIBUTES.includes(record.attributeName);
|
|
1082
2630
|
function changes(records, options) {
|
|
1083
2631
|
if (!global2.document?.defaultView) return;
|
|
1084
2632
|
const changed = [];
|
|
@@ -1086,19 +2634,24 @@
|
|
|
1086
2634
|
const sourced = options?.quiet ? [] : listening("source");
|
|
1087
2635
|
const written = [];
|
|
1088
2636
|
let removed = false;
|
|
1089
|
-
|
|
2637
|
+
let later = null;
|
|
1090
2638
|
for (const record of records) {
|
|
2639
|
+
const attribute = record.type === "attributes" ? record.attributeName : null;
|
|
2640
|
+
const reveals = attribute !== null && REVEALS.includes(attribute);
|
|
2641
|
+
if (attribute !== null && !reveals && (sourced.length === 0 || !ofSource(record))) continue;
|
|
1091
2642
|
const target = record.target.nodeType === 1 ? record.target : record.target.parentElement;
|
|
1092
2643
|
if (!target || outsidePage(target)) continue;
|
|
1093
|
-
if (sourced.length > 0 &&
|
|
2644
|
+
if (sourced.length > 0 && !reveals) written.push([target, record]);
|
|
1094
2645
|
if (owned && ownedHere(target)) continue;
|
|
1095
|
-
if (
|
|
1096
|
-
revealed.add(target);
|
|
2646
|
+
if (attribute !== null) {
|
|
2647
|
+
if (reveals) revealed.add(target);
|
|
1097
2648
|
continue;
|
|
1098
2649
|
}
|
|
1099
2650
|
if (record.removedNodes.length > 0) removed = true;
|
|
1100
2651
|
for (const node of record.addedNodes) {
|
|
1101
|
-
if (node.nodeType !== 1 || !node.isConnected || outsidePage(node)
|
|
2652
|
+
if (node.nodeType !== 1 || !node.isConnected || outsidePage(node)) continue;
|
|
2653
|
+
later ??= [...defs.values()].filter((def) => def.started && def.added !== false).map(selectorOf).concat(INSTANCE).join(", ");
|
|
2654
|
+
if (!(node.matches(later) || node.querySelector(later))) continue;
|
|
1102
2655
|
scan(node, null, { later: true });
|
|
1103
2656
|
fallback(node);
|
|
1104
2657
|
}
|
|
@@ -1114,9 +2667,10 @@
|
|
|
1114
2667
|
for (const host of hosts) if (heard.get(host).length > 0) tell(host, "content", heard.get(host), options);
|
|
1115
2668
|
}
|
|
1116
2669
|
for (const [host, { def }] of sourced) {
|
|
2670
|
+
if (!instances.has(host) || written.length === 0) continue;
|
|
1117
2671
|
const parts = sourceParts(host, def.id);
|
|
1118
|
-
const heard = written.filter(([target]) => parts.some((part) => part.contains(target))).map(([, record]) => record);
|
|
1119
|
-
if (heard.length > 0)
|
|
2672
|
+
const heard = written.filter(([target, record]) => parts.some((part) => part.contains(target)) && ofTheFile(host, target, record)).map(([, record]) => record);
|
|
2673
|
+
if (heard.length > 0) hearLater(host, heard);
|
|
1120
2674
|
}
|
|
1121
2675
|
for (const [host] of listening("reveal")) {
|
|
1122
2676
|
for (const target of revealed) if (target.contains(host)) {
|
|
@@ -1125,8 +2679,16 @@
|
|
|
1125
2679
|
}
|
|
1126
2680
|
}
|
|
1127
2681
|
}
|
|
2682
|
+
const REVEALS = ["hidden", "open"];
|
|
2683
|
+
const WATCHED2 = { childList: true, subtree: true, characterData: true, attributes: true, attributeFilter: REVEALS };
|
|
1128
2684
|
const observer = new MutationObserver((records) => changes(records));
|
|
1129
|
-
observer.observe(document.documentElement,
|
|
2685
|
+
observer.observe(document.documentElement, WATCHED2);
|
|
2686
|
+
let watchingSource = false;
|
|
2687
|
+
function watchSource() {
|
|
2688
|
+
if (watchingSource) return;
|
|
2689
|
+
watchingSource = true;
|
|
2690
|
+
observer.observe(document.documentElement, { ...WATCHED2, attributeOldValue: true, attributeFilter: [...REVEALS, ...SOURCE_ATTRIBUTES, "class"] });
|
|
2691
|
+
}
|
|
1130
2692
|
function quietly(change) {
|
|
1131
2693
|
changes(observer.takeRecords());
|
|
1132
2694
|
try {
|
|
@@ -1178,7 +2740,9 @@
|
|
|
1178
2740
|
},
|
|
1179
2741
|
quietly,
|
|
1180
2742
|
dehydrate,
|
|
1181
|
-
/** The
|
|
2743
|
+
/** The tables of the page a key names, for the kit's charts drawn from a table and its views (table-reading.js createKeyedTables): the kit's own, no document's. */
|
|
2744
|
+
tables,
|
|
2745
|
+
/** The component on `host` makes its `example` of an edit, as gallery block check asks it. Whether it has one. */
|
|
1182
2746
|
example(host) {
|
|
1183
2747
|
const instance = instances.get(host);
|
|
1184
2748
|
if (!instance?.def.example) return false;
|
|
@@ -1256,7 +2820,7 @@
|
|
|
1256
2820
|
}
|
|
1257
2821
|
|
|
1258
2822
|
// src/render/kit/runtime/reveal.js
|
|
1259
|
-
var
|
|
2823
|
+
var CARD2 = "dialog.doc-dialog";
|
|
1260
2824
|
var shown = (panel) => {
|
|
1261
2825
|
const area = panel.parentElement;
|
|
1262
2826
|
const key = panel.getAttribute("data-doc-sheet");
|
|
@@ -1264,7 +2828,7 @@
|
|
|
1264
2828
|
if (panel.hidden) [...area.querySelectorAll("[data-sheet-tab]")].find((tab) => tab.getAttribute("data-sheet-tab") === key)?.click();
|
|
1265
2829
|
};
|
|
1266
2830
|
function reveal(target) {
|
|
1267
|
-
for (const card of [...document.querySelectorAll(`${
|
|
2831
|
+
for (const card of [...document.querySelectorAll(`${CARD2}[open]`)].reverse()) {
|
|
1268
2832
|
if (card.contains(target)) continue;
|
|
1269
2833
|
if (globalThis.DocDialogs) globalThis.DocDialogs.close(card, "outside");
|
|
1270
2834
|
else card.close();
|
|
@@ -1273,7 +2837,7 @@
|
|
|
1273
2837
|
for (let node = target; node; node = node.parentElement) around.unshift(node);
|
|
1274
2838
|
for (const node of around) {
|
|
1275
2839
|
if (node.hasAttribute("data-doc-sheet") && node.hidden && node.parentElement?.matches("[data-doc-sheets]")) shown(node);
|
|
1276
|
-
else if (node.matches(`${
|
|
2840
|
+
else if (node.matches(`${CARD2}:not([open])`)) {
|
|
1277
2841
|
if (globalThis.DocDialogs) globalThis.DocDialogs.open(node);
|
|
1278
2842
|
else node.showModal();
|
|
1279
2843
|
} else if (node !== target && node.localName === "details" && !node.open) node.open = true;
|
|
@@ -1299,18 +2863,18 @@
|
|
|
1299
2863
|
reveal(target);
|
|
1300
2864
|
target.scrollIntoView({ block: "center" });
|
|
1301
2865
|
};
|
|
1302
|
-
let order = [...doc.querySelectorAll(`${
|
|
2866
|
+
let order = [...doc.querySelectorAll(`${CARD2}[open]`)];
|
|
1303
2867
|
new win.MutationObserver((records) => {
|
|
1304
2868
|
for (const { target } of records) {
|
|
1305
|
-
if (!target.matches?.(
|
|
2869
|
+
if (!target.matches?.(CARD2)) continue;
|
|
1306
2870
|
order = order.filter((card) => card !== target);
|
|
1307
2871
|
if (target.open) order.push(target);
|
|
1308
2872
|
}
|
|
1309
2873
|
}).observe(root, { subtree: true, attributes: true, attributeFilter: ["open"] });
|
|
1310
2874
|
const contentOf2 = (card) => card.querySelector(".doc-dialog-content");
|
|
1311
2875
|
const cards = () => {
|
|
1312
|
-
const
|
|
1313
|
-
return [...order.filter((card) => card.open), ...
|
|
2876
|
+
const open2 = [...doc.querySelectorAll(`${CARD2}[open]`)];
|
|
2877
|
+
return [...order.filter((card) => card.open), ...open2.filter((card) => !order.includes(card))].filter((card) => card.id).map((card) => ({ id: card.id, top: contentOf2(card)?.scrollTop ?? 0 }));
|
|
1314
2878
|
};
|
|
1315
2879
|
let putting = 0;
|
|
1316
2880
|
let seen = win.location.hash;
|
|
@@ -1343,7 +2907,7 @@
|
|
|
1343
2907
|
});
|
|
1344
2908
|
for (const { id } of kept) {
|
|
1345
2909
|
const card = doc.getElementById(id);
|
|
1346
|
-
if (!card?.matches(`${
|
|
2910
|
+
if (!card?.matches(`${CARD2}:not([open])`)) continue;
|
|
1347
2911
|
if (globalThis.DocDialogs) globalThis.DocDialogs.open(card);
|
|
1348
2912
|
else card.showModal();
|
|
1349
2913
|
}
|
|
@@ -1398,69 +2962,14 @@
|
|
|
1398
2962
|
observer.observe(root, { attributes: true, attributeFilter: ["data-doc-drawn"] });
|
|
1399
2963
|
}
|
|
1400
2964
|
|
|
1401
|
-
// src/shared/inline-spacing.mjs
|
|
1402
|
-
var UNITS = /* @__PURE__ */ new Set([..."\u4E2A\u4E07\u4EBF\u5343\u767E\u5341\u5143\u89D2\u5206\u5398\u6BDB\u500D\u5E74\u6708\u65E5\u53F7\u65F6\u70B9\u79D2\u5929\u5468\u5C81\u4EBA\u4F4D\u540D\u6B21\u5BB6\u6761\u9879\u79CD\u53F0\u53EA\u4EF6\u7BC7\u9875\u5F20\u5957\u4EFD\u7EC4\u6279\u671F\u5C4A\u4EE3\u7EA7\u5C42\u8F6E\u6B65\u7C73\u514B\u65A4\u5428\u5EA6\u91CC\u516C\u6BEB\u5FAE\u5BF8\u5C3A\u4E24\u5347\u6237\u6240\u5EA7\u680B\u8F86\u67B6\u8258\u672C\u90E8\u7AE0\u8282\u573A\u5C40\u9996\u53E5\u5B57\u884C\u5217\u904D\u56DE\u756A\u6210"]);
|
|
1403
|
-
var ZWSP = String.fromCharCode(8203);
|
|
1404
|
-
var WORD = /[\p{L}\p{N}]/u;
|
|
1405
|
-
var ITEM = "code, .doc-math-inline, .katex";
|
|
1406
|
-
var LINE = /^(P|LI|H[1-6]|TD|TH|DT|DD|DIV|SECTION|ARTICLE|ASIDE|HEADER|FOOTER|MAIN|NAV|FIGURE|FIGCAPTION|CAPTION|SUMMARY|DETAILS|BLOCKQUOTE|UL|OL|TABLE|THEAD|TBODY|TR|PRE|BR|HR|DIALOG|BODY|BUTTON|svg)$/;
|
|
1407
|
-
var emptyFormula = (element) => element.matches(".doc-math-inline") && (element.getAttribute("data-ge-empty") === "formula" || !element.textContent.replace(/\\[()]/g, "").trim());
|
|
1408
|
-
var isInlineItem = (node) => node?.nodeType === 1 && node.matches(ITEM) && !emptyFormula(node);
|
|
1409
|
-
function inlineItems(root) {
|
|
1410
|
-
const items = root.nodeType === 1 && root.matches(ITEM) ? [root, ...root.querySelectorAll(ITEM)] : [...root.querySelectorAll(ITEM)];
|
|
1411
|
-
return items.filter((item2) => isInlineItem(item2) && !item2.parentElement?.closest(".doc-math-inline, .katex, .katex-display, code"));
|
|
1412
|
-
}
|
|
1413
|
-
function endOf(node, after) {
|
|
1414
|
-
if (node.nodeType === 3) {
|
|
1415
|
-
const characters = [...node.data.replaceAll(ZWSP, "")];
|
|
1416
|
-
return characters.length === 0 ? void 0 : after ? characters[0] : characters.at(-1);
|
|
1417
|
-
}
|
|
1418
|
-
if (node.nodeType !== 1) return void 0;
|
|
1419
|
-
if (LINE.test(node.tagName)) return null;
|
|
1420
|
-
if (node.matches(ITEM)) return emptyFormula(node) ? void 0 : true;
|
|
1421
|
-
if (node.hasAttribute("data-ge-empty")) return void 0;
|
|
1422
|
-
const children = [...node.childNodes];
|
|
1423
|
-
for (const child of after ? children : children.reverse()) {
|
|
1424
|
-
const found = endOf(child, after);
|
|
1425
|
-
if (found !== void 0) return found;
|
|
1426
|
-
}
|
|
1427
|
-
return void 0;
|
|
1428
|
-
}
|
|
1429
|
-
function sideOf(node, after) {
|
|
1430
|
-
for (let at = node; at; ) {
|
|
1431
|
-
const next = after ? at.nextSibling : at.previousSibling;
|
|
1432
|
-
if (!next) {
|
|
1433
|
-
at = at.parentElement;
|
|
1434
|
-
if (!at || LINE.test(at.tagName) || at.hasAttribute("contenteditable")) return null;
|
|
1435
|
-
continue;
|
|
1436
|
-
}
|
|
1437
|
-
const found = endOf(next, after);
|
|
1438
|
-
if (found !== void 0) return found;
|
|
1439
|
-
at = next;
|
|
1440
|
-
}
|
|
1441
|
-
return null;
|
|
1442
|
-
}
|
|
1443
|
-
function spaceAround(element) {
|
|
1444
|
-
const put = { before: null, after: null };
|
|
1445
|
-
for (const after of [false, true]) {
|
|
1446
|
-
const side = sideOf(element, after);
|
|
1447
|
-
if (side !== true && !(typeof side === "string" && WORD.test(side))) continue;
|
|
1448
|
-
const space = element.ownerDocument.createTextNode(" ");
|
|
1449
|
-
if (after) element.after(space);
|
|
1450
|
-
else element.before(space);
|
|
1451
|
-
put[after ? "after" : "before"] = space;
|
|
1452
|
-
}
|
|
1453
|
-
return put;
|
|
1454
|
-
}
|
|
1455
|
-
|
|
1456
2965
|
// src/render/kit/runtime/spacing.js
|
|
1457
2966
|
var inert = (element) => element.closest("pre, svg, [contenteditable], [data-doc-dev], script, style, textarea") || element.matches(INSTANCE) || componentAt(element);
|
|
1458
2967
|
var NUMBER = String.raw`\d(?:[\d.,]*\d)?(?:%|[A-Za-z]{1,3})?`;
|
|
1459
2968
|
var DASH = "[\u2013\u2014~\uFF5E]";
|
|
1460
2969
|
var CLOSING = new RegExp(String.raw`^(?:${DASH}${NUMBER})?[,。、;:!?)」』》】〉〕”’,.;:!?)\]]*`);
|
|
1461
|
-
var
|
|
2970
|
+
var RANGE2 = new RegExp(`${NUMBER} ?${DASH} ?${NUMBER}`);
|
|
1462
2971
|
var OWN_TEXT = "code, kbd, samp, .katex, .doc-range, .doc-long-run, option";
|
|
1463
|
-
var
|
|
2972
|
+
var TEX2 = /\\[()[\]]|\$\$/;
|
|
1464
2973
|
var WRAPPER = /^(STRONG|B|EM|I|U|S|MARK|SPAN|A|SUB|SUP|SMALL)$/;
|
|
1465
2974
|
function tieClosing(formula) {
|
|
1466
2975
|
let at = formula;
|
|
@@ -1498,7 +3007,7 @@
|
|
|
1498
3007
|
function holdRanges(text) {
|
|
1499
3008
|
const held = [];
|
|
1500
3009
|
for (let rest = text; rest; ) {
|
|
1501
|
-
const found =
|
|
3010
|
+
const found = RANGE2.exec(rest.data);
|
|
1502
3011
|
if (!found) break;
|
|
1503
3012
|
const range = found.index > 0 ? rest.splitText(found.index) : rest;
|
|
1504
3013
|
rest = range.data.length > found[0].length ? range.splitText(found[0].length) : null;
|
|
@@ -1533,10 +3042,10 @@
|
|
|
1533
3042
|
}
|
|
1534
3043
|
function looked(text) {
|
|
1535
3044
|
const parent = text.parentElement;
|
|
1536
|
-
return Boolean(parent?.closest("main")) && !
|
|
3045
|
+
return Boolean(parent?.closest("main")) && !TEX2.test(text.data) && !inert(parent) && !parent.closest(OWN_TEXT) && !(text.data.includes("$") && parent.closest("[data-doc-math-dollar]"));
|
|
1537
3046
|
}
|
|
1538
3047
|
function holdIn(root) {
|
|
1539
|
-
for (const text of textsIn(root)) if (
|
|
3048
|
+
for (const text of textsIn(root)) if (RANGE2.test(text.data) && looked(text)) holdRanges(text);
|
|
1540
3049
|
for (const text of textsIn(root)) if (holdsLongRun(text.data) && looked(text)) holdRuns(text);
|
|
1541
3050
|
for (const code of [...root.matches("code") ? [root] : [], ...root.querySelectorAll("code")]) {
|
|
1542
3051
|
if (code.closest("main") && !inert(code) && !code.parentElement?.closest(`${OWN_TEXT}, td, th`) && holdsLongRun(code.textContent)) breaking(code);
|
|
@@ -1764,13 +3273,16 @@
|
|
|
1764
3273
|
|
|
1765
3274
|
// src/render/kit/runtime/index.js
|
|
1766
3275
|
if (!globalThis.DocKit) {
|
|
3276
|
+
const platform = globalThis.navigator?.userAgentData?.platform || globalThis.navigator?.platform || "";
|
|
3277
|
+
if (/mac|iphone|ipad/i.test(platform)) document.documentElement.setAttribute("data-doc-platform", "mac");
|
|
3278
|
+
else document.documentElement.removeAttribute("data-doc-platform");
|
|
1767
3279
|
const kit = createKit({ descriptions: new Map(define_COMPONENT_RUNTIME_default.map((component) => [component.id, component])) });
|
|
1768
3280
|
const { store, bindControl, bindShow, CONTROLS: CONTROLS3 } = createBindings();
|
|
1769
3281
|
kit.component({ id: "bind", selector: CONTROLS3, mount: (element, context2) => bindControl(element, context2) });
|
|
1770
3282
|
kit.component({ id: "show", selector: "[data-doc-show]", mount: (element) => bindShow(element) });
|
|
1771
3283
|
kit.component({ id: "embed", mount: (figure) => showEmbed(figure), dehydrate: (figure) => dehydrateEmbed(figure) });
|
|
1772
3284
|
kit.component({ id: "flowchart", selector: FLOWCHART, on: ["resize", "fonts", "content", "layout"], mount: (list2, context2) => startFlowchart(list2, context2), dehydrate: (list2) => dehydrateFlowchart(list2) });
|
|
1773
|
-
globalThis.DocKit = Object.freeze({ ...kit, bindings: store, flows: define_COMPONENT_FLOWS_default, reveal });
|
|
3285
|
+
globalThis.DocKit = Object.freeze({ ...kit, bindings: store, flows: define_COMPONENT_FLOWS_default, reveal, input: fieldIn, drag: dragIn, choose });
|
|
1774
3286
|
globalThis.ReportKit = globalThis.DocKit;
|
|
1775
3287
|
globalThis.DocKit.component({ id: "range", selector: ".doc-range", added: false, mount: () => null, dehydrate: untie });
|
|
1776
3288
|
globalThis.DocKit.component({ id: "long-run", selector: ".doc-long-run", added: false, mount: () => null, dehydrate: untie });
|
|
@@ -1778,5 +3290,6 @@
|
|
|
1778
3290
|
startZoom(document);
|
|
1779
3291
|
globalThis.DocKit.component({ id: "zoom", selector: ZOOM_PICTURES, on: ["resize", "reveal"], mount: (img, context2) => watchZoom(img, context2) });
|
|
1780
3292
|
startBlockLinks(document);
|
|
3293
|
+
startChoices(document);
|
|
1781
3294
|
}
|
|
1782
3295
|
})();
|