@heycys/gallery 0.1.2 → 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/embed/page.mjs +1 -1
- package/browser/editor/components/file/page.mjs +4 -4
- package/browser/editor/components/heading/index.mjs +7 -6
- package/browser/editor/components/icons.mjs +3 -0
- 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 +6 -2
- package/browser/editor/components/installed/page.mjs +80 -13
- 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 +17 -5
- package/browser/editor/components/table/index.mjs +4 -2
- package/browser/editor/page/after/index.mjs +288 -0
- package/browser/editor/page/align.mjs +91 -0
- 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/hint.mjs +64 -27
- package/browser/editor/page/board/index.mjs +160 -71
- package/browser/editor/page/board/motion.mjs +177 -0
- package/browser/editor/page/board/settings.mjs +4 -3
- package/browser/editor/page/clipboard/index.mjs +10 -3
- package/browser/editor/page/clipboard/own/blocks.mjs +3 -4
- package/browser/editor/page/clipboard/own/describe.mjs +6 -2
- package/browser/editor/page/commit.mjs +2 -2
- package/browser/editor/page/core.mjs +3 -1
- package/browser/editor/page/custom-page.mjs +15 -11
- package/browser/editor/page/editor.mjs +31 -14
- package/browser/editor/page/history.mjs +19 -4
- package/browser/editor/page/insert/index.mjs +20 -22
- package/browser/editor/page/menu.mjs +15 -7
- package/browser/editor/page/page-objects.mjs +3 -7
- package/browser/editor/page/present-links.mjs +5 -4
- package/browser/editor/page/present-shell.mjs +63 -0
- package/browser/editor/page/selection/index.mjs +10 -2
- package/browser/editor/page/table/binding.mjs +87 -0
- package/browser/editor/page/table/icons.mjs +0 -2
- package/browser/editor/page/table/index.mjs +10 -14
- package/browser/editor/page/table/views.mjs +5 -52
- package/browser/editor/page/table/widths.mjs +82 -10
- package/browser/editor/page/typing/index.mjs +44 -12
- package/browser/editor/page/typing/leave.mjs +19 -5
- package/browser/shared/block-packs.mjs +23 -8
- package/browser/shared/component-catalog.mjs +15 -8
- package/browser/shared/component-source.mjs +3 -1
- package/browser/shared/components/heading.mjs +2 -1
- package/browser/shared/components/installed.mjs +1 -1
- package/browser/shared/components/page.mjs +2 -0
- package/browser/shared/components/paragraph.mjs +8 -1
- package/browser/shared/components/table.mjs +1 -0
- package/browser/shared/emoji/line-icons.mjs +37 -0
- package/browser/shared/http.mjs +9 -0
- package/browser/shared/i18n/en.mjs +40 -17
- package/browser/shared/outline.mjs +30 -2
- package/browser/shared/pack-manifest.mjs +12 -1
- package/browser/shared/pages.mjs +169 -57
- package/browser/shared/pinyin.mjs +92 -0
- package/browser/shared/present-step.mjs +17 -0
- package/browser/shared/sidebar-head.mjs +70 -0
- package/browser/shared/web-links.mjs +5 -0
- package/dist/chunk-2OHANJ6Q.mjs +2 -0
- package/dist/{chunk-QOUEFUCH.mjs → chunk-3MBRL2PM.mjs} +1 -1
- package/dist/{chunk-NWR2LT5B.mjs → chunk-4OKWZY5E.mjs} +1 -1
- package/dist/{chunk-RMECZA2K.mjs → chunk-5K44HLTZ.mjs} +1 -1
- package/dist/{chunk-NFMCP2HI.mjs → chunk-5XA2ZBAE.mjs} +2 -2
- package/dist/{chunk-OUUP3WKT.mjs → chunk-67N2QJYT.mjs} +1 -1
- package/dist/chunk-6KBYRA2C.mjs +2 -0
- package/dist/{chunk-SX4LJYT6.mjs → chunk-6N3PX4XX.mjs} +1 -1
- package/dist/{chunk-RFDZXFJF.mjs → chunk-7JDX4E65.mjs} +1 -1
- package/dist/chunk-7M2BQQGZ.mjs +2 -0
- package/dist/{chunk-ZUNVAXLH.mjs → chunk-7OG26PGF.mjs} +1 -1
- package/dist/{chunk-B4P2CM2J.mjs → chunk-AHN3NFKJ.mjs} +1 -1
- package/dist/chunk-ALZ6ZENZ.mjs +3 -0
- package/dist/{chunk-UGWYKHBL.mjs → chunk-AR5D57ZD.mjs} +2 -2
- package/dist/{chunk-W3BGBJQW.mjs → chunk-BFJGHSQN.mjs} +1 -1
- package/dist/{chunk-HLYV7RIH.mjs → chunk-CMA72MAG.mjs} +1 -1
- package/dist/{chunk-D4CKRD3V.mjs → chunk-DAZL73VK.mjs} +2 -2
- package/dist/{chunk-6VTU6KEO.mjs → chunk-DJISHPUL.mjs} +1 -1
- package/dist/{chunk-BPL64HGA.mjs → chunk-EAIFITAV.mjs} +1 -1
- package/dist/chunk-EP25HDAJ.mjs +2 -0
- package/dist/{chunk-6EZ7FNIK.mjs → chunk-F4ZA6JRZ.mjs} +1 -1
- package/dist/{chunk-3KJHLHUO.mjs → chunk-F6HVDZR4.mjs} +1 -1
- package/dist/{chunk-3NJACR4W.mjs → chunk-FDMAXMQA.mjs} +1 -1
- package/dist/chunk-FETSREUN.mjs +5 -0
- package/dist/{chunk-RKPWLGZ3.mjs → chunk-GHOYKMQ3.mjs} +1 -1
- package/dist/chunk-HDWTZ763.mjs +12 -0
- package/dist/{chunk-VTKNEYT3.mjs → chunk-HPOI4ZX7.mjs} +1 -1
- package/dist/{chunk-OW5NWPOJ.mjs → chunk-HXG7EOPJ.mjs} +1 -1
- package/dist/{chunk-V6RIYQZZ.mjs → chunk-ITOH5EGO.mjs} +1 -1
- package/dist/{chunk-ZWPMCK7P.mjs → chunk-IV64FFI4.mjs} +1 -1
- package/dist/chunk-J43Z6LSS.mjs +2 -0
- package/dist/chunk-J5PUIV3Y.mjs +4 -0
- package/dist/{chunk-KTKHRC6H.mjs → chunk-JA7G53PC.mjs} +1 -1
- package/dist/{chunk-NWFBE2YA.mjs → chunk-JLTZF4LA.mjs} +1 -1
- package/dist/{chunk-GY3FAUVM.mjs → chunk-JZT7I2OJ.mjs} +1 -1
- package/dist/{chunk-QKXMPUXC.mjs → chunk-K5XATEOO.mjs} +1 -1
- package/dist/chunk-L2SUIS5S.mjs +2 -0
- package/dist/{chunk-TEZAWDSQ.mjs → chunk-LM4XFQHZ.mjs} +1 -1
- package/dist/{chunk-5ZJA7CXT.mjs → chunk-MN7BZL4R.mjs} +1 -1
- package/dist/chunk-MTYYHM2G.mjs +15 -0
- package/dist/{chunk-HMYTM3GT.mjs → chunk-MXUBKDRO.mjs} +1 -1
- package/dist/{chunk-MHW7ZKOU.mjs → chunk-OEXWRJME.mjs} +1 -1
- package/dist/{chunk-CRJEG7MT.mjs → chunk-OFHXGWOX.mjs} +1 -1
- package/dist/chunk-ORID3AE7.mjs +166 -0
- package/dist/{chunk-32ZUEFZ7.mjs → chunk-PGDE24N5.mjs} +1 -1
- package/dist/{chunk-UNOYVIYR.mjs → chunk-POTA2FV4.mjs} +1 -1
- package/dist/{chunk-N7AZZLGT.mjs → chunk-QE5RG76S.mjs} +18 -17
- package/dist/{chunk-N76HWBA3.mjs → chunk-R2ZDLJYT.mjs} +1 -1
- package/dist/chunk-SWUTTZCN.mjs +2 -0
- package/dist/{chunk-POQSE4C2.mjs → chunk-TR7TWGHB.mjs} +1 -1
- package/dist/chunk-U5XL7D6A.mjs +3 -0
- package/dist/{chunk-PVER7LSC.mjs → chunk-U7NZI6N4.mjs} +2 -2
- package/dist/{chunk-Q47PLKIJ.mjs → chunk-UGWMMEJ5.mjs} +1 -1
- package/dist/chunk-UJQJKNGK.mjs +2 -0
- package/dist/chunk-UYVCQK3H.mjs +22 -0
- package/dist/{chunk-FJYN7RTH.mjs → chunk-VFX2KNHP.mjs} +1 -1
- package/dist/{chunk-UBBRTJ2R.mjs → chunk-VS7JIGJW.mjs} +1 -1
- package/dist/{chunk-NVRNLK25.mjs → chunk-W7665ZEC.mjs} +2 -2
- package/dist/{chunk-NG375ILQ.mjs → chunk-WQDQWCX5.mjs} +1 -1
- package/dist/chunk-YLPSMDIS.mjs +5 -0
- package/dist/{chunk-VXACTLO3.mjs → chunk-YNAWBAYN.mjs} +1 -1
- package/dist/{chunk-ZB4H7ZN4.mjs → chunk-YROX2O22.mjs} +1 -1
- package/dist/{chunk-YQGT4AB2.mjs → chunk-ZDLPUOAG.mjs} +1 -1
- package/dist/chunk-ZQS6H473.mjs +16 -0
- package/dist/{chunk-OJKMINIU.mjs → chunk-ZWWC4KLF.mjs} +15 -15
- package/dist/cli.mjs +1 -1
- package/dist/server.mjs +1 -1
- package/dist/worker.mjs +1 -1
- package/kit/board.css +5 -5
- package/kit/code.js +15 -15
- package/kit/report.css +120 -41
- package/kit/runtime.js +45 -7
- package/kit/tables.js +2 -0
- package/kit/ui.js +2 -0
- package/package.json +1 -1
- package/packs/gallery/chart-view/kit.js +3 -3
- package/packs/gallery/chart-view/writing.md +1 -1
- package/packs/gallery/countdown/component.json +1 -1
- package/packs/gallery/countdown/kit.js +89 -29
- package/packs/gallery/countdown/preview.svg +1 -1
- package/packs/gallery/countdown/style.css +88 -100
- package/packs/gallery/countdown/writing.md +2 -2
- package/packs/gallery/habit/component.json +3 -3
- package/packs/gallery/habit/kit.js +114 -75
- package/packs/gallery/habit/preview.svg +1 -1
- package/packs/gallery/habit/style.css +133 -205
- package/packs/gallery/habit/writing.md +2 -2
- package/packs/gallery/heatmap/component.json +2 -2
- package/packs/gallery/heatmap/kit.js +335 -173
- package/packs/gallery/heatmap/preview.svg +1 -1
- package/packs/gallery/heatmap/style.css +158 -170
- package/packs/gallery/heatmap/writing.md +2 -2
- package/packs/gallery/kanban/kit.js +3 -3
- package/packs/gallery/kanban/writing.md +1 -1
- package/packs/gallery/metric/kit.js +3 -3
- package/packs/gallery/metric/writing.md +1 -1
- package/packs/gallery/note/component.json +3 -3
- package/packs/gallery/note/kit.js +40 -13
- package/packs/gallery/note/preview.svg +1 -1
- package/packs/gallery/note/style.css +51 -30
- package/packs/gallery/note/writing.md +2 -2
- package/packs/gallery/recent/component.json +2 -2
- package/packs/gallery/recent/kit.js +141 -86
- package/packs/gallery/recent/preview.svg +1 -1
- package/packs/gallery/recent/style.css +53 -126
- package/packs/gallery/recent/writing.md +2 -2
- package/packs/gallery/static/component.json +2 -2
- package/packs/gallery/static/preview.svg +1 -1
- package/packs/gallery/static/style.css +99 -66
- package/packs/gallery/static/writing.md +2 -2
- package/packs/gallery/stats/component.json +3 -3
- package/packs/gallery/stats/kit.js +253 -72
- package/packs/gallery/stats/preview.svg +1 -1
- package/packs/gallery/stats/style.css +64 -142
- package/packs/gallery/stats/writing.md +2 -2
- package/packs/gallery/today/component.json +2 -2
- package/packs/gallery/today/kit.js +62 -27
- package/packs/gallery/today/preview.svg +1 -1
- package/packs/gallery/today/style.css +101 -72
- package/packs/gallery/today/writing.md +2 -2
- package/packs/gallery/todos/component.json +1 -1
- package/packs/gallery/todos/kit.js +218 -71
- package/packs/gallery/todos/preview.svg +1 -1
- package/packs/gallery/todos/style.css +170 -223
- package/packs/gallery/todos/writing.md +1 -1
- package/packs/gallery/weather/component.json +2 -2
- package/packs/gallery/weather/kit.js +165 -90
- package/packs/gallery/weather/preview.svg +1 -1
- package/packs/gallery/weather/style.css +100 -218
- package/packs/gallery/weather/writing.md +1 -1
- 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/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 +9 -9
- package/skill/SKILL.md +12 -12
- package/skill/references/building-blocks.md +4 -4
- package/skill/references/pages-and-data.md +13 -9
- package/skill/references/writing-html.md +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-2NRBY6AJ.mjs +0 -2
- package/dist/chunk-35NQ4PLQ.mjs +0 -2
- package/dist/chunk-4AV456RQ.mjs +0 -2
- package/dist/chunk-5XYHDBJ5.mjs +0 -2
- package/dist/chunk-6A53MZYZ.mjs +0 -2
- package/dist/chunk-6EXH3ORZ.mjs +0 -166
- package/dist/chunk-BVEFGE4B.mjs +0 -2
- package/dist/chunk-D4EURAX4.mjs +0 -4
- package/dist/chunk-DQCE7TJY.mjs +0 -5
- package/dist/chunk-FWNRPMCJ.mjs +0 -12
- package/dist/chunk-FWW4CSAZ.mjs +0 -2
- package/dist/chunk-JVHHHGEA.mjs +0 -3
- package/dist/chunk-PZDLJJTJ.mjs +0 -3
- package/dist/chunk-SXHBYZST.mjs +0 -16
- package/dist/chunk-UFNYFFKO.mjs +0 -20
- package/dist/chunk-UKSHDZZ6.mjs +0 -2
- package/dist/chunk-VJPFVNNW.mjs +0 -15
- package/dist/chunk-VS3ZMVGX.mjs +0 -5
- package/web/assets/index-BK2e_07w.js +0 -13
- package/web/assets/index-CWFI83mF.css +0 -1
package/browser/shared/pages.mjs
CHANGED
|
@@ -6,36 +6,49 @@ import { isDeepStrictEqual } from "node:util";
|
|
|
6
6
|
import { escapeMarkup, escapeText } from "./escape.mjs";
|
|
7
7
|
import { writeAtomic } from "./files.mjs";
|
|
8
8
|
import { laidOut } from "./json-layout.mjs";
|
|
9
|
+
import { readStoredHead, withOutlineLock, writeHead } from "./outline.mjs";
|
|
10
|
+
import { newPageId } from "./page-links.mjs";
|
|
11
|
+
import { headOrder, headPage, headWithPage } from "./sidebar-head.mjs";
|
|
9
12
|
import { DOCUMENT_FOLDERS, isSlugName, keptName, layoutOf, listTrash, markerOf, slugPattern, slugTaken } from "./workspace.mjs";
|
|
10
13
|
|
|
11
14
|
// A workspace's custom pages (自定义页: notes/plans/component-pages-plan-2026-11-07.md §5, the spec
|
|
12
15
|
// custom-blocks-spec-2026-11-07.md §5): a page is a folder pages/<slug>/ at the workspace's root, as
|
|
13
|
-
// components/ is, holding page.html (the page an Agent writes: its head, its look,
|
|
14
|
-
// boards, <div class="gallery-board">, of
|
|
15
|
-
// data-x data-y data-w data-h> around one
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
16
|
+
// components/ is, holding page.html (the page an Agent writes, free HTML: its head, its look, its own
|
|
17
|
+
// scripts and frames, and where it wants them one or more boards, <div class="gallery-board">, of
|
|
18
|
+
// cards, each <section class="gallery-card" data-card-id data-x data-y data-w data-h> around one
|
|
19
|
+
// instance of a custom block) and page.json ({ title, icon, defaultCards?, hint? }: pageMetaOf). An Agent
|
|
20
|
+
// makes one (gallery page new), and the workbench's 新建页面 a blank one (blankPageHtml) for an Agent to
|
|
21
|
+
// write; the workbench lists them in the sidebar's head with 新建 and 搜索, in the order the reader drags
|
|
22
|
+
// them to (./sidebar-head.mjs, kept in the outline file), shows one at #@<slug> and renames or trashes
|
|
23
|
+
// it (src/workbench/service.mjs). A page's slug and a document's are one pool (./workspace.mjs
|
|
24
|
+
// slugTaken): no new document takes a page's, nor a new page a document's, and `pages` is a name no new
|
|
25
|
+
// document takes. The blocks' scripts and styles are put in by the server as it shows a page
|
|
26
|
+
// (src/render/page-html.mjs).
|
|
27
|
+
// No page is special by its slug. The default home page (首页, HOME_TITLE, at pages/home, holding a card of
|
|
28
|
+
// each of HOME_CARDS) is a page like any other, made once per workspace by src/editor/home-page.mjs, as
|
|
29
|
+
// the server starts and by gallery init (gallery.json's pages.homeMade says it was: markHomeMade; nothing
|
|
30
|
+
// makes it again), whose page.json says what any page's may: it has the default cards (defaultCards:
|
|
31
|
+
// 恢复默认卡片 in its menu, the note of the default cards it has not got), and its first-open note
|
|
32
|
+
// (hint, until the reader closes it: pageHintClosed).
|
|
33
|
+
// Node's built-ins only, but ./escape.mjs, ./files.mjs, ./json-layout.mjs, ./outline.mjs, ./sidebar-head.mjs
|
|
34
|
+
// and ./workspace.mjs.
|
|
25
35
|
|
|
26
36
|
/** A custom page's two files. */
|
|
27
37
|
export const PAGE_FILES = { html: "page.html", json: "page.json" };
|
|
28
|
-
/** The home page
|
|
38
|
+
/** The slug of the default home page (首页), which src/editor/home-page.mjs makes: a page as any other. */
|
|
29
39
|
export const HOME = "home";
|
|
30
40
|
/** The default home page's title. */
|
|
31
41
|
export const HOME_TITLE = "首页";
|
|
32
42
|
/**
|
|
33
|
-
* The blocks of the default home page's cards (the plan's §5.2
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
43
|
+
* The blocks of the default home page's cards (the plan's §5.2, laid out as the pack Gallery 风格's home page,
|
|
44
|
+
* notes/plans/block-packs-plan-2026-11-09.md §3: 问候与日期, 天气, 倒计时, 习惯打卡, 工作区统计, 我的待办, 编辑热力图,
|
|
45
|
+
* 最近编辑, 便签, 静态卡片), in the order they are placed, each at the first free spot by its size (HOME_SIZES',
|
|
46
|
+
* else its block's default: shared/board-places.mjs freeSpot), a home of 12 x 12 cells, none left empty;
|
|
47
|
+
* 恢复默认卡片 (the page service's restore-defaults) puts back those of them no card of the home page holds.
|
|
37
48
|
*/
|
|
38
|
-
export const HOME_CARDS = Object.freeze(["gallery/today", "gallery/
|
|
49
|
+
export const HOME_CARDS = Object.freeze(["gallery/today", "gallery/weather", "gallery/countdown", "gallery/habit", "gallery/stats", "gallery/todos", "gallery/heatmap", "gallery/recent", "gallery/note", "gallery/static"]);
|
|
50
|
+
/** The default home page's cards that are not their block's default size, [w, h] each. */
|
|
51
|
+
export const HOME_SIZES = Object.freeze({ "gallery/habit": [2, 2], "gallery/todos": [4, 6], "gallery/note": [4, 4] });
|
|
39
52
|
/**
|
|
40
53
|
* The default cards a home page made before the workspace's data came had (the plan's phase 2: 问候与日期
|
|
41
54
|
* and 便签): what a home whose hints say nothing of its cards was told of, so that it is told once of the
|
|
@@ -86,21 +99,51 @@ export async function pageSlugRefused(slug, root) {
|
|
|
86
99
|
return null;
|
|
87
100
|
}
|
|
88
101
|
|
|
102
|
+
/**
|
|
103
|
+
* A slug for a new custom page no name of workspace `root` holds (pageSlugRefused): page- and a random id,
|
|
104
|
+
* as a new document's is doc- and one (the workbench's 新建页面, whose title is typed after it is made).
|
|
105
|
+
*/
|
|
106
|
+
export async function newPageSlug(root, random = undefined) {
|
|
107
|
+
for (;;) {
|
|
108
|
+
const slug = `page-${newPageId(new Set(), random)}`;
|
|
109
|
+
if (!(await pageSlugRefused(slug, root))) return slug;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
89
113
|
const readJson = (file) => fs.readFile(file, "utf8").then((text) => JSON.parse(text.replace(/^/, ""))).catch(() => null);
|
|
90
114
|
|
|
91
|
-
/**
|
|
115
|
+
/**
|
|
116
|
+
* A page.json's fields as a list shows them: { title (the slug when it names none), icon (or null),
|
|
117
|
+
* defaultCards (it says `"defaultCards": true`: the page has Gallery's default cards, HOME_CARDS, which
|
|
118
|
+
* 恢复默认卡片 in its menu puts back where it misses them, and its note tells of those that came after
|
|
119
|
+
* it), hint (`"hint": true`: its first-open note on its cards shows until the reader closes it) }.
|
|
120
|
+
* Any page may say either; the default home page says both.
|
|
121
|
+
*/
|
|
92
122
|
export function pageMetaOf(slug, value) {
|
|
93
123
|
const title = typeof value?.title === "string" && value.title.trim() ? value.title.trim() : slug;
|
|
94
124
|
const icon = typeof value?.icon === "string" && value.icon.trim() ? value.icon.trim() : null;
|
|
95
|
-
return { title, icon };
|
|
125
|
+
return { title, icon, defaultCards: value?.defaultCards === true, hint: value?.hint === true };
|
|
96
126
|
}
|
|
97
127
|
|
|
98
|
-
/** Custom page `slug` as a list shows it: { slug, title, icon }, or null when it is not there. */
|
|
128
|
+
/** Custom page `slug` as a list shows it: { slug, title, icon, defaultCards, hint }, or null when it is not there. */
|
|
99
129
|
export async function readPageMeta(slug, root) {
|
|
100
130
|
if (!pageExists(slug, root)) return null;
|
|
101
131
|
return { slug, ...pageMetaOf(slug, await readJson(pageFiles(slug, root).json)) };
|
|
102
132
|
}
|
|
103
133
|
|
|
134
|
+
/** Custom page `slug`'s meta as its page.json says it now (pageMetaOf), read at once; null when it is not there. */
|
|
135
|
+
export function pageMetaNow(slug, root) {
|
|
136
|
+
if (!pageExists(slug, root)) return null;
|
|
137
|
+
let value = null;
|
|
138
|
+
try {
|
|
139
|
+
value = JSON.parse(readFileSync(pageFiles(slug, root).json, "utf8").replace(/^/, ""));
|
|
140
|
+
} catch {}
|
|
141
|
+
return { slug, ...pageMetaOf(slug, value) };
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** Whether custom page `slug` has the default cards (its page.json's defaultCards): 恢复默认卡片 runs on it. */
|
|
145
|
+
export const pageDefaults = (slug, root) => pageMetaNow(slug, root)?.defaultCards === true;
|
|
146
|
+
|
|
104
147
|
/**
|
|
105
148
|
* What gallery.json says of the custom pages (the spec §2): { order: the sidebar's order of their
|
|
106
149
|
* slugs, homeMade: whether the default home page was made }; nothing said, or a gallery.json that does
|
|
@@ -236,8 +279,9 @@ export function ownLine(text, open, member) {
|
|
|
236
279
|
return start > open && /^[ \t]*$/.test(before) ? before : null;
|
|
237
280
|
}
|
|
238
281
|
|
|
239
|
-
// .gallery/hints.json: {
|
|
240
|
-
// or {} where there is none or it does not read.
|
|
282
|
+
// .gallery/hints.json: { pages: { <slug>: <when its first-open note was closed> }, homeCards: [the default
|
|
283
|
+
// cards the reader knows of] }, or {} where there is none or it does not read. Its `home` (<when>) is what
|
|
284
|
+
// a Gallery said before every page was alike: the note of pages/home closed, the one page that had one.
|
|
241
285
|
function hintsOf(root) {
|
|
242
286
|
try {
|
|
243
287
|
const value = JSON.parse(readFileSync(layoutOf(root).hints, "utf8"));
|
|
@@ -246,19 +290,48 @@ function hintsOf(root) {
|
|
|
246
290
|
return {};
|
|
247
291
|
}
|
|
248
292
|
}
|
|
293
|
+
const closedOf = (hints) => (hints.pages && typeof hints.pages === "object" && !Array.isArray(hints.pages) ? hints.pages : {});
|
|
294
|
+
|
|
295
|
+
/** What .gallery/hints.json says under `key` (undefined where it says nothing, or does not read). */
|
|
296
|
+
export const hintOf = (root, key) => hintsOf(root)[key];
|
|
297
|
+
|
|
298
|
+
/** .gallery/hints.json with `patch`'s keys written, its others kept. */
|
|
299
|
+
export async function writeHints(root, patch) {
|
|
300
|
+
const { hints, gallery } = layoutOf(root);
|
|
301
|
+
await fs.mkdir(gallery, { recursive: true });
|
|
302
|
+
await writeAtomic(hints, `${JSON.stringify({ ...hintsOf(root), ...patch }, null, 2)}\n`);
|
|
303
|
+
}
|
|
249
304
|
|
|
250
305
|
/**
|
|
251
|
-
* Whether the reader closed
|
|
306
|
+
* Whether the reader closed custom page `slug`'s first-open note (the plan's §5.2): once for the workspace,
|
|
252
307
|
* whichever browser or port shows it, kept in .gallery/hints.json (what Gallery keeps of its own, never
|
|
253
308
|
* gallery.json, which is the workspace's settings and wakes every page's watcher as it is written).
|
|
254
309
|
*/
|
|
255
|
-
export
|
|
310
|
+
export function pageHintClosed(root, slug) {
|
|
311
|
+
const hints = hintsOf(root);
|
|
312
|
+
return typeof closedOf(hints)[slug] === "string" || (slug === HOME && typeof hints.home === "string");
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/** Whether custom page `slug`'s first-open note shows: its page.json says `hint`, and the reader has not closed it. */
|
|
316
|
+
export const pageHintShown = (slug, root) => pageMetaNow(slug, root)?.hint === true && !pageHintClosed(root, slug);
|
|
317
|
+
|
|
318
|
+
/** Custom page `slug`'s first-open note closed for good (`at`: when, an ISO time), the file's other notes kept. */
|
|
319
|
+
export async function closePageHint(root, slug, at = new Date().toISOString()) {
|
|
320
|
+
const { hints, gallery } = layoutOf(root);
|
|
321
|
+
await fs.mkdir(gallery, { recursive: true });
|
|
322
|
+
const value = hintsOf(root);
|
|
323
|
+
await writeAtomic(hints, `${JSON.stringify({ ...value, pages: { ...closedOf(value), [slug]: at } }, null, 2)}\n`);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/** The first-open note of pages/home closed (closePageHint's), and whether it is (pageHintClosed's): the older words for them. */
|
|
327
|
+
export const closeHomeHint = (root, at) => closePageHint(root, HOME, at);
|
|
328
|
+
export const homeHintClosed = (root) => pageHintClosed(root, HOME);
|
|
256
329
|
|
|
257
330
|
/**
|
|
258
|
-
* The default cards (of HOME_CARDS) the reader knows of in workspace `root`: those its
|
|
259
|
-
* with, or the reader was told of since (
|
|
260
|
-
* 恢复默认卡片 run), kept in .gallery/hints.json as `homeCards`; FIRST_HOME_CARDS where it
|
|
261
|
-
* cards of a home made before the others came.
|
|
331
|
+
* The default cards (of HOME_CARDS) the reader knows of in workspace `root`: those its pages with the
|
|
332
|
+
* default cards were made with, or the reader was told of since (a page's note of new cards, closed or
|
|
333
|
+
* taken up, and 恢复默认卡片 run), kept in .gallery/hints.json as `homeCards`; FIRST_HOME_CARDS where it
|
|
334
|
+
* says none, the cards of a home page made before the others came.
|
|
262
335
|
*/
|
|
263
336
|
export function homeCardsTold(root) {
|
|
264
337
|
const told = hintsOf(root).homeCards;
|
|
@@ -266,43 +339,65 @@ export function homeCardsTold(root) {
|
|
|
266
339
|
}
|
|
267
340
|
|
|
268
341
|
/**
|
|
269
|
-
* The default cards
|
|
270
|
-
* changed, and is told once that 恢复默认卡片 brings them):
|
|
271
|
-
* (homeCardsTold) and no card of the
|
|
272
|
-
* there is none to tell.
|
|
342
|
+
* The default cards a page's note tells of, on a page with the default cards (pageMetaOf's defaultCards;
|
|
343
|
+
* the plan's 3.4: a page made before them is not changed, and is told once that 恢复默认卡片 brings them):
|
|
344
|
+
* those of HOME_CARDS the reader was not told of (homeCardsTold) and no card of the page holds (`held`: the
|
|
345
|
+
* blocks its cards are). Empty where there is none to tell.
|
|
273
346
|
*/
|
|
274
347
|
export const homeCardsNew = (root, held) => HOME_CARDS.filter((id) => !homeCardsTold(root).includes(id) && !held.includes(id));
|
|
275
348
|
|
|
276
|
-
/** Every default card told of (HOME_CARDS, kept as hints.json's `homeCards`):
|
|
349
|
+
/** Every default card told of (HOME_CARDS, kept as hints.json's `homeCards`): a page's note of new cards says nothing again. */
|
|
277
350
|
export async function tellHomeCards(root) {
|
|
278
351
|
const { hints, gallery } = layoutOf(root);
|
|
279
352
|
await fs.mkdir(gallery, { recursive: true });
|
|
280
353
|
await writeAtomic(hints, `${JSON.stringify({ ...hintsOf(root), homeCards: [...HOME_CARDS] }, null, 2)}\n`);
|
|
281
354
|
}
|
|
282
355
|
|
|
283
|
-
/** The home page's first-open note closed for good (`at`: when, an ISO time), the file's other notes kept. */
|
|
284
|
-
export async function closeHomeHint(root, at = new Date().toISOString()) {
|
|
285
|
-
const { hints, gallery } = layoutOf(root);
|
|
286
|
-
await fs.mkdir(gallery, { recursive: true });
|
|
287
|
-
await writeAtomic(hints, `${JSON.stringify({ ...hintsOf(root), home: at }, null, 2)}\n`);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
356
|
/**
|
|
291
|
-
* Pages in the
|
|
292
|
-
* names, in its order, then the rest by title (then slug). Pure:
|
|
357
|
+
* Pages in the order a page goes by where the reader gave it no place in the sidebar's head (the spec
|
|
358
|
+
* §2): those gallery.json's pages.order names, in its order, then the rest by title (then slug). Pure:
|
|
359
|
+
* `pages` [{ slug, title }].
|
|
293
360
|
*/
|
|
294
361
|
export function inPageOrder(pages, order = []) {
|
|
295
|
-
const rank = (slug) => (
|
|
362
|
+
const rank = (slug) => (order.includes(slug) ? order.indexOf(slug) : Infinity);
|
|
296
363
|
const collator = new Intl.Collator("zh-CN", { numeric: true });
|
|
297
364
|
return [...pages].sort((a, b) => rank(a.slug) - rank(b.slug) || collator.compare(a.title, b.title) || (a.slug < b.slug ? -1 : a.slug > b.slug ? 1 : 0));
|
|
298
365
|
}
|
|
299
366
|
|
|
300
|
-
/**
|
|
367
|
+
/**
|
|
368
|
+
* Pages in the sidebar's order: as the head's rows go (`head`, the stored head: ./sidebar-head.mjs
|
|
369
|
+
* headOrder), those it names not after them in inPageOrder's (`order`: gallery.json's pages.order). Pure.
|
|
370
|
+
*/
|
|
371
|
+
export function inHeadOrder(pages, order = [], head = null) {
|
|
372
|
+
const listed = inPageOrder(pages, order);
|
|
373
|
+
const bySlug = new Map(listed.map((page) => [page.slug, page]));
|
|
374
|
+
return headOrder(head, listed.map(({ slug }) => slug)).map(headPage).filter(Boolean).map((slug) => bySlug.get(slug));
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/** The custom pages of workspace `root`, in the sidebar's order (inHeadOrder): [{ slug, title, icon, defaultCards, hint }]. Folders of pages/ that hold no page.html are passed over. */
|
|
301
378
|
export async function listPages(root) {
|
|
302
379
|
const { customPages: pages } = layoutOf(root);
|
|
303
380
|
const names = await fs.readdir(pages, { withFileTypes: true }).catch(() => []);
|
|
304
381
|
const found = await Promise.all(names.filter((entry) => entry.isDirectory() && isSlugName(entry.name)).map((entry) => readPageMeta(entry.name, root)));
|
|
305
|
-
return
|
|
382
|
+
return inHeadOrder(found.filter(Boolean), pagesSettings(root).order, await readStoredHead(root));
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/** The sidebar's head rows of workspace `root` in their order (./sidebar-head.mjs headOrder): new, search and @<slug> of each of `pages` (listPages'). */
|
|
386
|
+
export async function headOf(root, pages = null) {
|
|
387
|
+
return headOrder(await readStoredHead(root), (pages ?? await listPages(root)).map(({ slug }) => slug));
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Custom page `slug` given its row in the sidebar's head, in the outline file under its lock: right after
|
|
392
|
+
* page `after`'s row, else last (a page made: createPage's). A head that was never stored is stored as
|
|
393
|
+
* the sidebar showed it, so that the page made last stands last.
|
|
394
|
+
*/
|
|
395
|
+
export async function placePageInHead(root, slug, after = null) {
|
|
396
|
+
await withOutlineLock(root, async () => {
|
|
397
|
+
const stored = await readStoredHead(root);
|
|
398
|
+
const shown = stored ? null : await headOf(root, (await listPages(root)).filter((page) => page.slug !== slug));
|
|
399
|
+
await writeHead(root, headWithPage(stored, shown, slug, after));
|
|
400
|
+
});
|
|
306
401
|
}
|
|
307
402
|
|
|
308
403
|
/**
|
|
@@ -322,10 +417,14 @@ export async function pageVersionNow(slug, root) {
|
|
|
322
417
|
|
|
323
418
|
/**
|
|
324
419
|
* The page.html of a new custom page: its title (in `<title>` only: the page draws no big title, its
|
|
325
|
-
* name is the sidebar's, the tab's and the top bar's) and
|
|
326
|
-
*
|
|
420
|
+
* name is the sidebar's, the tab's and the top bar's) and its <main class="gallery-page">, holding one
|
|
421
|
+
* empty board (`main`, the spec §5's structure: gallery page new's), or nothing (`blank`: the workbench's
|
|
422
|
+
* 新建页面, a page an Agent is to write, isBlankPage). `lang`: its page's lang ("zh-CN" by default).
|
|
327
423
|
*/
|
|
328
|
-
export function newPageHtml(slug, title, { lang = "zh-CN" } = {}) {
|
|
424
|
+
export function newPageHtml(slug, title, { lang = "zh-CN", blank = false } = {}) {
|
|
425
|
+
const inside = blank ? "" : `
|
|
426
|
+
<div class="gallery-board" data-board-id="${FIRST_BOARD}">
|
|
427
|
+
</div>`;
|
|
329
428
|
return `<!doctype html>
|
|
330
429
|
<html lang="${escapeMarkup(lang)}">
|
|
331
430
|
<head>
|
|
@@ -338,9 +437,7 @@ export function newPageHtml(slug, title, { lang = "zh-CN" } = {}) {
|
|
|
338
437
|
</style>
|
|
339
438
|
</head>
|
|
340
439
|
<body>
|
|
341
|
-
<main class="gallery-page" data-page-id="${slug}"
|
|
342
|
-
<div class="gallery-board" data-board-id="${FIRST_BOARD}">
|
|
343
|
-
</div>
|
|
440
|
+
<main class="gallery-page" data-page-id="${slug}">${inside}
|
|
344
441
|
</main>
|
|
345
442
|
</body>
|
|
346
443
|
</html>
|
|
@@ -348,18 +445,33 @@ export function newPageHtml(slug, title, { lang = "zh-CN" } = {}) {
|
|
|
348
445
|
}
|
|
349
446
|
|
|
350
447
|
/**
|
|
351
|
-
*
|
|
352
|
-
*
|
|
448
|
+
* Whether page.html `html` is a blank page, one no one has written yet: its <body> holds an empty
|
|
449
|
+
* <main class="gallery-page"> and nothing else (comments and blanks aside), as the workbench's 新建页面
|
|
450
|
+
* writes it (newPageHtml's `blank`). The workbench then shows, in its middle, that an Agent writes it.
|
|
451
|
+
*/
|
|
452
|
+
export function isBlankPage(html) {
|
|
453
|
+
const body = /<body\b[^>]*>([\s\S]*?)<\/body>/i.exec(String(html ?? "").replace(/<!--[\s\S]*?-->/g, ""))?.[1];
|
|
454
|
+
return body !== undefined && /^\s*<main\b[^>]*\bclass\s*=\s*["']?gallery-page["']?[^>]*>\s*<\/main>\s*$/i.test(body);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Make custom page `slug` in workspace `root`: pages/<slug>/ with page.html (newPageHtml: one empty
|
|
459
|
+
* board, or none where `blank`) and page.json ({ title, icon?, defaultCards?, hint? }: pageMetaOf), and its
|
|
460
|
+
* row in the sidebar's head right after page `after`'s, else last (placePageInHead; a head that cannot be
|
|
461
|
+
* written leaves it where a page the head names not goes). Throws (code EEXIST) when pageSlugRefused
|
|
462
|
+
* refuses the slug; resolves to its files.
|
|
353
463
|
*/
|
|
354
|
-
export async function createPage(slug, title, { root, icon = null, lang } = {}) {
|
|
464
|
+
export async function createPage(slug, title, { root, icon = null, lang, blank = false, defaultCards = false, hint = false, after = null } = {}) {
|
|
355
465
|
const refused = await pageSlugRefused(slug, root);
|
|
356
466
|
if (refused) throw Object.assign(new Error(refused), { code: "EEXIST" });
|
|
357
467
|
const files = pageFiles(slug, root);
|
|
358
468
|
await fs.mkdir(layoutOf(root).customPages, { recursive: true });
|
|
359
469
|
await fs.mkdir(files.folder, { recursive: false }); // fails when it was made meanwhile
|
|
360
470
|
const name = title.replace(/\s+/g, " ").trim();
|
|
361
|
-
await fs.writeFile(files.html, newPageHtml(slug, name, { lang }));
|
|
362
|
-
|
|
471
|
+
await fs.writeFile(files.html, newPageHtml(slug, name, { lang, blank }));
|
|
472
|
+
const meta = { title: name, ...(icon ? { icon } : {}), ...(defaultCards ? { defaultCards: true } : {}), ...(hint ? { hint: true } : {}) };
|
|
473
|
+
await fs.writeFile(files.json, `${JSON.stringify(meta, null, 2)}\n`);
|
|
474
|
+
await placePageInHead(root, slug, after).catch(() => {});
|
|
363
475
|
return files;
|
|
364
476
|
}
|
|
365
477
|
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// Pinyin as the "/" menu looks for a block by it (docs/editor.md, "In the menus"; the built-in blocks
|
|
2
|
+
// list their words in registry.mjs: 公式 is gongshi gs). A custom block's words are its manifest's, so
|
|
3
|
+
// that an author writes the pinyin of the whole name there (the check notes a name no word spells:
|
|
4
|
+
// cli/component-check.mjs wantsPinyin); the initials ("djs" for 倒计时, "daojishi") are not asked of
|
|
5
|
+
// anyone: they are made here, from a word that reads as pinyin and from the name itself.
|
|
6
|
+
|
|
7
|
+
// A syllable of pinyin, no tones: an initial or none, then a final. A word that can be read as pinyin
|
|
8
|
+
// is syllables one after another.
|
|
9
|
+
const SYLLABLE = "(?:(?:[zcs]h|[bpmfdtnlgkhjqxrzcsyw])?(?:[iuv]?(?:a(?:i|o|ng?)?|e(?:i|r|ng?)?|o(?:u|ng)?)|i(?:u|ng?)?|u(?:i|n)?|vn?))";
|
|
10
|
+
const ONE_SYLLABLE = new RegExp(`^${SYLLABLE}$`, "i");
|
|
11
|
+
const LONGEST_SYLLABLE = 6; // zhuang
|
|
12
|
+
const HAN = /\p{Script=Han}/u;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The syllables `word` reads as, fewest first, its apostrophes left out as an input method leaves
|
|
16
|
+
* them, or null for a word that is none. The fewest, since single finals read a word as more syllables
|
|
17
|
+
* than an input method composes it of (fenbiao as fen-bi-a-o, composed fen-biao).
|
|
18
|
+
*/
|
|
19
|
+
export function syllablesOf(word) {
|
|
20
|
+
const letters = word.replaceAll("'", "");
|
|
21
|
+
const fewest = [0, ...Array(letters.length).fill(Infinity)];
|
|
22
|
+
const from = Array(letters.length + 1).fill(0);
|
|
23
|
+
for (let end = 1; end <= letters.length; end++) {
|
|
24
|
+
for (let start = Math.max(0, end - LONGEST_SYLLABLE); start < end; start++) {
|
|
25
|
+
if (fewest[start] + 1 < fewest[end] && ONE_SYLLABLE.test(letters.slice(start, end))) {
|
|
26
|
+
fewest[end] = fewest[start] + 1;
|
|
27
|
+
from[end] = start;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (!letters || !Number.isFinite(fewest[letters.length])) return null;
|
|
32
|
+
const syllables = [];
|
|
33
|
+
for (let end = letters.length; end > 0; end = from[end]) syllables.unshift(letters.slice(from[end], end));
|
|
34
|
+
return syllables;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** The fewest syllables of pinyin `word` reads as, or null for a word that is none. */
|
|
38
|
+
export const fewestSyllables = (word) => syllablesOf(word)?.length ?? null;
|
|
39
|
+
|
|
40
|
+
/** The first letters of the syllables of a word of pinyin ("daojishi" is "djs"), or null for a word that is none or one syllable. */
|
|
41
|
+
export function initialsOfWord(word) {
|
|
42
|
+
const syllables = syllablesOf(word.toLowerCase());
|
|
43
|
+
return syllables && syllables.length > 1 ? syllables.map((syllable) => syllable[0]).join("") : null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// The characters that open each letter's run in the pinyin order of the platform's collation (阿 a, 八 b …
|
|
47
|
+
// 帀 z: no run for i, u or v), the classic way to find the first letter of a character's reading without a
|
|
48
|
+
// table. Known only where the platform's collation sorts Chinese by pinyin, which it is asked once.
|
|
49
|
+
const OPENERS = [..."阿八嚓哒妸发旮哈讥咔垃妈拿噢妑七呥仨他屲夕丫帀"];
|
|
50
|
+
const LETTERS = [..."abcdefghjklmnopqrstwxyz"];
|
|
51
|
+
let collator;
|
|
52
|
+
|
|
53
|
+
function sorted() {
|
|
54
|
+
if (collator !== undefined) return collator;
|
|
55
|
+
try {
|
|
56
|
+
const found = new Intl.Collator("zh-CN");
|
|
57
|
+
collator = OPENERS.every((each, at) => at === 0 || found.compare(OPENERS[at - 1], each) < 0) && found.compare("计", "时") < 0 ? found : null;
|
|
58
|
+
} catch {
|
|
59
|
+
collator = null;
|
|
60
|
+
}
|
|
61
|
+
return collator;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** The first letter of a Chinese character's pinyin (its commonest reading), or null. */
|
|
65
|
+
function initialOf(character) {
|
|
66
|
+
const found = sorted();
|
|
67
|
+
if (!found || !HAN.test(character)) return null;
|
|
68
|
+
let letter = null;
|
|
69
|
+
for (let at = 0; at < OPENERS.length && found.compare(character, OPENERS[at]) >= 0; at++) letter = LETTERS[at];
|
|
70
|
+
return letter;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** The initials of a name: a Chinese character's first letter of pinyin, a letter or digit as it is ("倒计时" is "djs"), none where the platform cannot tell. */
|
|
74
|
+
export function initialsOfName(name) {
|
|
75
|
+
let initials = "";
|
|
76
|
+
for (const character of name) {
|
|
77
|
+
const letter = initialOf(character) ?? (/[a-z0-9]/i.test(character) ? character.toLowerCase() : null);
|
|
78
|
+
if (letter) initials += letter;
|
|
79
|
+
}
|
|
80
|
+
return initials.length > 1 ? initials : "";
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* What "/" matches a custom block by (slash-menu matchScore: each word whole, or by its start): its names,
|
|
85
|
+
* its id and the manifest's words, then the initials of the name and of every word that reads as pinyin,
|
|
86
|
+
* so that 倒计时 is found by djs as 公式 is by gs.
|
|
87
|
+
*/
|
|
88
|
+
export function searchWords({ name, id, words }) {
|
|
89
|
+
const given = `${name.zh} ${name.en} ${id} ${words}`.toLowerCase();
|
|
90
|
+
const initials = [initialsOfName(name.zh), ...words.split(/\s+/).filter(Boolean).map(initialsOfWord)].filter(Boolean);
|
|
91
|
+
return [given, ...new Set(initials)].join(" ");
|
|
92
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// 演示视图 (the workbench's, src/workbench/app/features/present/): the controls the page keeps its keys for (a field to
|
|
2
|
+
// type in, an editable text, a block's instance: the reader's keys in them are theirs, Esc alone is the presentation's, unless the
|
|
3
|
+
// control used it), and 上一节 / 下一节, which the presentation does on a page of its own origin and a draft's page does itself
|
|
4
|
+
// (src/editor/page/present-shell.mjs), for the presentation cannot reach into a page of another origin.
|
|
5
|
+
|
|
6
|
+
export const KEEPS_KEYS = 'input:not([type="checkbox"], [type="radio"], [type="button"], [type="submit"], [type="reset"], [type="file"], [type="color"]), textarea, select, [contenteditable]:not([contenteditable="false"]), [data-doc-component]';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The report in window `win` scrolled to the next section (`direction` 1) or the one before (-1): the visible h2 and h1 of its main,
|
|
10
|
+
* placed 24px below the window's top; at the last, the page's end, at the first, its top.
|
|
11
|
+
*/
|
|
12
|
+
export function stepSection(win, direction) {
|
|
13
|
+
const doc = win.document;
|
|
14
|
+
const tops = [...doc.querySelectorAll("main h2, main h1")].filter((node) => node.getClientRects().length).map((node) => node.getBoundingClientRect().top - 24);
|
|
15
|
+
const target = direction > 0 ? tops.find((top) => top > 4) : tops.filter((top) => top < -4).pop();
|
|
16
|
+
win.scrollTo({ top: target === undefined ? (direction > 0 ? doc.documentElement.scrollHeight : 0) : win.scrollY + target, behavior: "smooth" });
|
|
17
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// The sidebar's head rows (docs/workbench.md "The sidebar", **Head**; the user's word of 2026-11-09):
|
|
2
|
+
// 新建, 搜索 and each custom page, one list the reader orders by dragging its rows (no row goes into
|
|
3
|
+
// another, none into the tree, no document among them), kept for the workspace in the outline file
|
|
4
|
+
// (.gallery/outline.json's `head`, which ./outline.mjs keeps as it writes the tree, so that every browser
|
|
5
|
+
// shows the order the reader gave). A row's key: "new" (新建), "search" (搜索), or "@<slug>" for a custom
|
|
6
|
+
// page (its address in the workbench, which no slug holds). Pure: the server's (shared/pages.mjs listPages,
|
|
7
|
+
// the workbench service's head) and the workbench's (its sidebar) alike.
|
|
8
|
+
|
|
9
|
+
/** The key of the head's 新建 row. */
|
|
10
|
+
export const HEAD_NEW = "new";
|
|
11
|
+
/** The key of the head's 搜索 row. */
|
|
12
|
+
export const HEAD_SEARCH = "search";
|
|
13
|
+
/** The key of custom page `slug`'s row: @<slug>. */
|
|
14
|
+
export const pageHeadKey = (slug) => `@${slug}`;
|
|
15
|
+
/** The custom page a head key names, or null (new, search). */
|
|
16
|
+
export const headPage = (key) => (typeof key === "string" && key.startsWith("@") ? key.slice(1) : null);
|
|
17
|
+
/** How many keys a stored head keeps at most (those of pages gone stay, so that one restored goes back to its place). */
|
|
18
|
+
export const MOST_HEAD = 200;
|
|
19
|
+
|
|
20
|
+
const KEY = /^(?:new|search|@[a-z0-9]+(?:-[a-z0-9]+)*)$/;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* `value` as a head to store: an array of keys (new, search, @<slug>), each once, MOST_HEAD at most; null
|
|
24
|
+
* for anything else (not an array, a key that is none, one twice, too many).
|
|
25
|
+
*/
|
|
26
|
+
export function storedHead(value) {
|
|
27
|
+
if (!Array.isArray(value) || value.length > MOST_HEAD) return null;
|
|
28
|
+
if (!value.every((key) => typeof key === "string" && KEY.test(key))) return null;
|
|
29
|
+
return new Set(value).size === value.length ? [...value] : null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The head's rows in their order: the keys `stored` (a head as the outline file keeps it, or null) gives,
|
|
34
|
+
* those of pages that are not there passed over, then what it does not name: 新建 first and 搜索 after it
|
|
35
|
+
* where it names neither (as before any drag), and each page of `pages` (their slugs, in the order a page
|
|
36
|
+
* goes by when the reader gave it none: shared/pages.mjs inPageOrder) after the last row it names, in that
|
|
37
|
+
* order. Always holds new and search once each, and each page of `pages` once.
|
|
38
|
+
*/
|
|
39
|
+
export function headOrder(stored, pages = []) {
|
|
40
|
+
const there = new Set(pages);
|
|
41
|
+
const named = (storedHead(stored) ?? []).filter((key) => key === HEAD_NEW || key === HEAD_SEARCH || there.has(headPage(key)));
|
|
42
|
+
if (!named.includes(HEAD_SEARCH)) named.unshift(HEAD_SEARCH);
|
|
43
|
+
if (!named.includes(HEAD_NEW)) named.splice(named.indexOf(HEAD_SEARCH), 0, HEAD_NEW);
|
|
44
|
+
for (const slug of pages) if (!named.includes(pageHeadKey(slug))) named.push(pageHeadKey(slug));
|
|
45
|
+
return named;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The head with the row `key` moved before the row `before` (null: last), the others as they were: what a
|
|
50
|
+
* drop on the head makes. Unchanged where `key` is not in it or is `before`.
|
|
51
|
+
*/
|
|
52
|
+
export function movedInHead(head, key, before) {
|
|
53
|
+
if (!head.includes(key) || key === before) return [...head];
|
|
54
|
+
const rest = head.filter((one) => one !== key);
|
|
55
|
+
const at = before === null ? rest.length : rest.indexOf(before);
|
|
56
|
+
rest.splice(at < 0 ? rest.length : at, 0, key);
|
|
57
|
+
return rest;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The stored head `stored` (or null, when none is kept yet: `shown`, the head as the sidebar shows it now,
|
|
62
|
+
* stands for it) with page `slug`'s row put right after the row of `after` (a page's slug), else last: a
|
|
63
|
+
* new page's place. Keys of pages gone are kept where they stand.
|
|
64
|
+
*/
|
|
65
|
+
export function headWithPage(stored, shown, slug, after = null) {
|
|
66
|
+
const head = (storedHead(stored) ?? storedHead(shown) ?? [HEAD_NEW, HEAD_SEARCH]).filter((key) => key !== pageHeadKey(slug));
|
|
67
|
+
const at = after ? head.indexOf(pageHeadKey(after)) : -1;
|
|
68
|
+
head.splice(at < 0 ? head.length : at + 1, 0, pageHeadKey(slug));
|
|
69
|
+
return head.slice(-MOST_HEAD);
|
|
70
|
+
}
|
|
@@ -37,6 +37,11 @@ export function isSiteIcon(value) {
|
|
|
37
37
|
*/
|
|
38
38
|
export const WEB_SANDBOX = "allow-scripts allow-popups allow-top-navigation-by-user-activation allow-forms allow-same-origin allow-storage-access-by-user-activation allow-popups-to-escape-sandbox";
|
|
39
39
|
|
|
40
|
+
/** Login/error headings are not document names (also used for browser-provided clipboard titles). */
|
|
41
|
+
export function loginTitle(title) {
|
|
42
|
+
return /(?:^|[|·—–-]\s*)(?:钉钉)?统一身份认证\s*$|^(?:(?:登录|登入|sign[ -]?in|log[ -]?in)(?:$|\s*(?:[|·—–-]|to\b))|(?:401|403)(?:\s|$)|unauthorized|access denied|forbidden|无权访问|访问受限)|(?:[|·—–-]\s*)(?:登录|登入|sign[ -]?in|log[ -]?in)\s*$/i.test(title);
|
|
43
|
+
}
|
|
44
|
+
|
|
40
45
|
const tidy = (value) => (typeof value === "string" ? value.replace(/\s+/g, " ").trim() : "");
|
|
41
46
|
|
|
42
47
|
/**
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
|
|
2
|
+
import{constants as G}from"node:buffer";import E from"node:fs";import{Transform as H}from"node:stream";import{pipeline as P}from"node:stream/promises";import b from"node:zlib";import{refusal as k,said as M}from"../browser/shared/i18n/index.mjs";var A=67324752,Z=33639248,F=101010256,W=101075792,X=117853008,U=4294967295,T=2048;function v(t=new Date){let o=t.getHours()<<11|t.getMinutes()<<5|Math.floor(t.getSeconds()/2),e=Math.max(1980,t.getFullYear())-1980<<9|t.getMonth()+1<<5|t.getDate();return[o,e]}function tt(t){let[o,e]=v(),c=[],h=[],n=0;for(let a of t){let s=Buffer.isBuffer(a.data)?a.data:Buffer.from(a.data??"","utf8"),r=Buffer.from(a.name,"utf8"),u=s.length>64?b.deflateRawSync(s):null,w=u&&u.length<s.length?u:s,L=w===s?0:8,g=b.crc32(s);if(s.length>=U||n>=U)throw new Error("\u538B\u7F29\u5305\u592A\u5927\uFF08\u8D85\u8FC7 4GB\uFF09");let l=Buffer.alloc(30);l.writeUInt32LE(A,0),l.writeUInt16LE(20,4),l.writeUInt16LE(T,6),l.writeUInt16LE(L,8),l.writeUInt16LE(o,10),l.writeUInt16LE(e,12),l.writeUInt32LE(g,14),l.writeUInt32LE(w.length,18),l.writeUInt32LE(s.length,22),l.writeUInt16LE(r.length,26),l.writeUInt16LE(0,28);let d=Buffer.alloc(46);d.writeUInt32LE(Z,0),d.writeUInt16LE(20,4),d.writeUInt16LE(20,6),d.writeUInt16LE(T,8),d.writeUInt16LE(L,10),d.writeUInt16LE(o,12),d.writeUInt16LE(e,14),d.writeUInt32LE(g,16),d.writeUInt32LE(w.length,20),d.writeUInt32LE(s.length,24),d.writeUInt16LE(r.length,28),d.writeUInt32LE(n,42),c.push(l,r,w),h.push(d,r),n+=l.length+r.length+w.length}if(t.length>=65535)throw new Error("\u538B\u7F29\u5305\u91CC\u7684\u6587\u4EF6\u592A\u591A");let i=Buffer.concat(h),f=Buffer.alloc(22);return f.writeUInt32LE(F,0),f.writeUInt16LE(t.length,8),f.writeUInt16LE(t.length,10),f.writeUInt32LE(i.length,12),f.writeUInt32LE(n,16),Buffer.concat([...c,i,f])}var Y=new TextDecoder("utf-8",{fatal:!0}),j=new TextDecoder("gbk");function q(t,o){if(o&T)return t.toString("utf8");try{return Y.decode(t)}catch{return j.decode(t)}}var et=t=>t.length>=4&&t.readUInt32LE(0)===A,m=()=>new Error("ZIP \u6587\u4EF6\u5DF2\u635F\u574F"),I=(t,o)=>Number(t.readBigUInt64LE(o));function N(t,o){let e=Math.min(o,65557),c=t(o-e,e),h=-1;for(let r=c.length-22;r>=0;r-=1)if(c.readUInt32LE(r)===F){h=r;break}if(h<0)throw new Error("\u4E0D\u662F\u6709\u6548\u7684 ZIP \u6587\u4EF6");let n=c.readUInt16LE(h+10),i=c.readUInt32LE(h+12),f=c.readUInt32LE(h+16);if(n===65535||i===U||f===U){let r=t(o-e+h-20,20);if(r.readUInt32LE(0)!==X)throw m();let u=t(I(r,8),56);if(u.readUInt32LE(0)!==W)throw m();n=I(u,32),i=I(u,40),f=I(u,48)}let a=t(f,i),s=[];for(let r=0,u=0;u<n;u+=1){if(a.readUInt32LE(r)!==Z)throw m();let w=a.readUInt16LE(r+8),L=a.readUInt16LE(r+10),g=a.readUInt32LE(r+20),l=a.readUInt32LE(r+24),d=a.readUInt16LE(r+28),D=a.readUInt16LE(r+30),_=a.readUInt16LE(r+32),R=a.readUInt32LE(r+42),B=q(a.subarray(r+46,r+46+d),w),p=a.subarray(r+46+d,r+46+d+D);for(let x=0;x+4<=p.length;x+=4+p.readUInt16LE(x+2)){if(p.readUInt16LE(x)!==1)continue;let z=x+4;l===U&&(l=I(p,z),z+=8),g===U&&(g=I(p,z),z+=8),R===U&&(R=I(p,z))}if(r+=46+d+D+_,!B.endsWith("/")){if(w&1)throw k(M("{0} \u5DF2\u52A0\u5BC6",B));if(L!==0&&L!==8)throw k(M("{0}\uFF1A\u4E0D\u652F\u6301\u7684\u538B\u7F29\u65B9\u5F0F",B));s.push({name:B,method:L,packedSize:g,size:l,local:R})}}return s}var S=t=>k(M("{0}\uFF1A\u5927\u5C0F\u4E0D\u7B26",t.name),{code:"size"});function C(t,o){try{return b.inflateRawSync(t,{maxOutputLength:Math.min(G.MAX_LENGTH,Math.max(1,o.size))})}catch(e){throw e?.code==="ERR_BUFFER_TOO_LARGE"?S(o):e}}function O(t,o){let e=t(o.local,30);if(e.readUInt32LE(0)!==A)throw m();return o.local+30+e.readUInt16LE(26)+e.readUInt16LE(28)}function nt(t){let o=(e,c)=>{if(e<0||e+c>t.length)throw m();return t.subarray(e,e+c)};return N(o,t.length).map(e=>{let c=o(O(o,e),e.packedSize),h=e.method===0?Buffer.from(c):C(c,e);if(h.length!==e.size)throw S(e);return{name:e.name,data:h}})}function rt(t){let o=E.openSync(t,"r"),e=E.fstatSync(o).size,c=(n,i)=>{if(n<0||n+i>e)throw m();let f=Buffer.alloc(i);for(let a=0;a<i;){let s=E.readSync(o,f,a,i-a,n+a);if(s===0)throw m();a+=s}return f},h;try{h=N(c,e)}catch(n){throw E.closeSync(o),n}return{entries:h,read(n){let i=c(O(c,n),n.packedSize),f=n.method===0?i:C(i,n);if(f.length!==n.size)throw S(n);return f},async extract(n,i){let f=O(c,n);if(n.packedSize===0)await E.promises.writeFile(i,"");else{let a=E.createReadStream(t,{start:f,end:f+n.packedSize-1}),s=0,r=new H({transform(u,w,L){s+=u.length,L(s>n.size?S(n):null,u)}});await P(...n.method===0?[a]:[a,b.createInflateRaw()],r,E.createWriteStream(i))}if((await E.promises.stat(i)).size!==n.size)throw S(n)},close:()=>E.closeSync(o)}}export{tt as a,et as b,nt as c,rt as d};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
|
|
2
|
-
import{a as je}from"./chunk-JEUK3ZO7.mjs";import{a as Te,b as Ne,c as Xe,d as Ze,g as Oe,h as et}from"./chunk-PUOQ65NC.mjs";import{g as Qe}from"./chunk-
|
|
2
|
+
import{a as je}from"./chunk-JEUK3ZO7.mjs";import{a as Te,b as Ne,c as Xe,d as Ze,g as Oe,h as et}from"./chunk-PUOQ65NC.mjs";import{g as Qe}from"./chunk-ITOH5EGO.mjs";import{b as Se}from"./chunk-ZQS6H473.mjs";import{p as Ee}from"./chunk-MXUBKDRO.mjs";import{a as le}from"./chunk-HYMEEXKN.mjs";import{a as ve,f as Ye,p as ze}from"./chunk-HDWTZ763.mjs";import T from"node:fs/promises";import he from"node:os";import x from"node:path";import{pathToFileURL as Re}from"node:url";import{instancesOf as ot,isInstance as bt}from"../browser/shared/components/index.mjs";import{ATTRIBUTE as $t,FALLBACK as xt,INSTANCE as de,SLOT as vt,SLOT_PART as tt}from"../browser/shared/components/installed.mjs";import{jsonIn as Et}from"../browser/shared/json-layout.mjs";import{QUERY_ROUTE as St}from"../browser/shared/workspace-query.mjs";import{documentDirectory as jt,documentFiles as Tt,layoutOf as it,listDocumentSlugs as Nt,PACKAGE_MANIFEST as Ot}from"../browser/shared/workspace.mjs";var At="in a browser, under the export's policy",ce=(e=null)=>e?`the instances in ${e}, in a browser under the export's policy`:"the workspace's documents",q="component-check",ae=[360,736,1024],Ae=["light","dark"],Lt=[1024,360],nt=1e4,rt=6e4,se=3e4,Dn=12e4,lt=2e3,Rt=3e3,Dt=60,Mn=15e3,Mt=2,Pt=8,Ct=se/2,_t=/^(?:wasm-)?eval$/,It=new Set(["TargetCloseError","ConnectionClosedError"]),Pn=e=>e.evaluateOnNewDocument(Ft,St);function Ft(e){let t=globalThis.fetch;if(typeof t!="function"||globalThis.__galleryQueries)return;let i={pending:new Map,count:0};globalThis.__galleryQueries=i,globalThis.fetch=function(r,n){let a=t.apply(this,arguments);try{let p=new URL(typeof r=="string"?r:r?.url??String(r),location.href);if(p.pathname===e){let u=++i.count,w=/\/__gallery\/components\/([a-z0-9-]+\/[a-z0-9-]+)\/kit\.js/.exec(new Error().stack??"");i.pending.set(u,{kind:p.searchParams.get("kind"),block:w?w[1]:null,at:Date.now()});let l=()=>{i.pending.delete(u)};Promise.resolve(a).then(l,l)}}catch{}return a}}var oe=e=>String(e?.message??e).split(`
|
|
3
3
|
`)[0],ct=(e,t)=>`<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>${e}</title></head><body><main class="doc-page" data-doc-id="${e}">${t}
|
|
4
4
|
</main></body></html>
|
|
5
5
|
`,Bt=({example:e,template:t})=>`<p>example.html</p>${e}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
|
|
2
|
-
import{a,b,c,d,e,f,g,h,i,j}from"./chunk-
|
|
2
|
+
import{a,b,c,d,e,f,g,h,i,j}from"./chunk-ZQS6H473.mjs";import"./chunk-UMHUSOPJ.mjs";import"./chunk-VFX2KNHP.mjs";import"./chunk-VS7JIGJW.mjs";import"./chunk-HDWTZ763.mjs";import"./chunk-A55HN5OK.mjs";import"./chunk-5L7RYZCL.mjs";export{g as changeLines,c as handedInSource,f as headerChanged,e as inStep,a as naturalize,d as pendingBlockIds,h as readOnlyTexts,j as scriptKept,b as shownSource,i as writingNotes};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
|
|
2
|
-
import{d as m,i as g,k as p}from"./chunk-
|
|
2
|
+
import{d as m,i as g,k as p}from"./chunk-5XA2ZBAE.mjs";import{b as a,f as l,i as c}from"./chunk-4OZWXZE5.mjs";import"./chunk-5L7RYZCL.mjs";import{reportsDirectory as i}from"../browser/shared/paths.mjs";import{joinDefaultTree as b,joinedLine as k}from"../browser/shared/drafts.mjs";var D=5e3;async function v(f){let{positional:s,options:u}=l({options:["--no-browser"],argv:f});if(s.length>1)throw new a("Name one document at most.");let{slug:o=null,block:w=null}=s.length?await c(s[0]):{};console.log(`\u5DE5\u4F5C\u533A\uFF1A${i}`);let e=await g({slug:o,baseline:o!==null});if(e.ok||console.error(e.message),e.reason==="missing"){let{HOME:n,pageExists:d}=await import("../browser/shared/pages.mjs"),{missingPageSaid:E,HOME_NOT_MADE:r}=await import("./chunk-UJQJKNGK.mjs");d(o,i)?console.error(`"${o}" is a custom page, not a document: gallery page open ${o} opens it and gives its address.`):o===n&&await E(o,i)===r&&console.error(r)}if(o!==null&&e.reason!=="missing"){let{roundBegins:n}=await import("./chunk-SWUTTZCN.mjs");await n(o,e.ok?{}:{wait:D})}if(o!==null&&e.reason!=="missing"){let n=k(await b(i,o));n&&console.log(n)}e.ok||process.exit(1);let t=await p(o,e,w);for(let n of t)console.log(n);console.log(await m(t,u))}export{v as run};
|