@heycys/gallery 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD-PARTY-NOTICES.md +1 -1
- package/browser/editor/page/annotate/index.mjs +3 -2
- package/browser/editor/page/board/index.mjs +2 -1
- package/browser/editor/page/board/settings.mjs +2 -1
- package/browser/editor/page/core.mjs +3 -2
- package/browser/editor/page/custom-page.mjs +4 -3
- package/browser/editor/page/editor.mjs +13 -7
- package/browser/editor/page/emoji-picker/support.mjs +3 -2
- package/browser/editor/page/links/index.mjs +1 -12
- package/browser/editor/page/links/pages.mjs +3 -2
- package/browser/editor/page/outline/folds.mjs +3 -0
- package/browser/editor/page/post.mjs +2 -1
- package/browser/editor/page/present-links.mjs +4 -3
- package/browser/editor/page/present-shell.mjs +3 -58
- package/browser/editor/page/session.mjs +3 -37
- package/browser/editor/page/storage.mjs +5 -5
- package/browser/shared/component-catalog.mjs +2 -2
- package/browser/shared/drafts.mjs +26 -51
- package/browser/shared/emoji/icon-value.mjs +2 -1
- package/browser/shared/extension-manifest.mjs +90 -0
- package/browser/shared/extensions.mjs +26 -16
- package/browser/shared/http.mjs +1 -1
- package/browser/shared/i18n/en.mjs +46 -15
- package/browser/shared/media.mjs +2 -1
- package/browser/shared/outline.mjs +11 -51
- package/browser/shared/page-address.mjs +8 -15
- package/browser/shared/paths.mjs +2 -1
- package/browser/shared/preferences.mjs +3 -1
- package/browser/shared/preview-server.mjs +51 -63
- package/browser/shared/service-location.mjs +18 -0
- package/browser/shared/session.mjs +3 -6
- package/browser/shared/workspace-address.mjs +22 -0
- package/browser/shared/workspace-columns.mjs +1 -2
- package/browser/shared/workspace-registry.mjs +6 -40
- package/browser/shared/workspace.mjs +3 -6
- package/browser/shared/writing-preferences.mjs +6 -4
- package/dist/{chunk-5MEXZ2UF.mjs → chunk-225ALKYI.mjs} +1 -1
- package/dist/{chunk-7N2LPG33.mjs → chunk-2HS7ZBPU.mjs} +1 -1
- package/dist/chunk-3F57LEN5.mjs +2 -0
- package/dist/{chunk-MKTX5PGV.mjs → chunk-43B75J5T.mjs} +1 -1
- package/dist/{chunk-VKSRM7EY.mjs → chunk-4B2TB5K2.mjs} +1 -1
- package/dist/{chunk-LV24RY2E.mjs → chunk-4K5KC6V2.mjs} +1 -1
- package/dist/chunk-5GK7HS62.mjs +2 -0
- package/dist/chunk-6GV3CBB2.mjs +2 -0
- package/dist/{chunk-TOE6DPLH.mjs → chunk-6NLXUKAY.mjs} +1 -1
- package/dist/{chunk-ZCP7BTOZ.mjs → chunk-6QBHU4DF.mjs} +1 -1
- package/dist/{chunk-QXVNUASA.mjs → chunk-6QWQXHAV.mjs} +1 -1
- package/dist/chunk-6XD6U3QA.mjs +5 -0
- package/dist/{chunk-DKR7LFIY.mjs → chunk-6Y3HYOBM.mjs} +1 -1
- package/dist/{chunk-36FIRJIF.mjs → chunk-742D2WWJ.mjs} +2 -2
- package/dist/{chunk-7M7UPWU6.mjs → chunk-7EFHNQ5B.mjs} +1 -1
- package/dist/{chunk-2GKGEVMR.mjs → chunk-7UZUQQ7Q.mjs} +25 -24
- package/dist/{chunk-VPVOAJ7X.mjs → chunk-AGDILNWB.mjs} +1 -1
- package/dist/{chunk-5IIH335D.mjs → chunk-ALZ6ZENZ.mjs} +1 -1
- package/dist/{chunk-G4YP7GVC.mjs → chunk-BFJGHSQN.mjs} +1 -1
- package/dist/{chunk-AMDGVDNV.mjs → chunk-BQNTTFPL.mjs} +1 -1
- package/dist/chunk-BX5AKINW.mjs +15 -0
- package/dist/{chunk-PAFSFVYB.mjs → chunk-BYNPEUDS.mjs} +1 -1
- package/dist/{chunk-74RPP2M2.mjs → chunk-C564NU2H.mjs} +1 -1
- package/dist/{chunk-DH6GMDNN.mjs → chunk-CRDG6EF2.mjs} +1 -1
- package/dist/{chunk-7XDYK3UC.mjs → chunk-E7656LR7.mjs} +1 -1
- package/dist/{chunk-KFZBYDIS.mjs → chunk-ECZBLQKK.mjs} +1 -1
- package/dist/{chunk-ZEY2RLBT.mjs → chunk-ERLAIBOA.mjs} +2 -2
- package/dist/{chunk-YFJU3O7G.mjs → chunk-FJLM7YE7.mjs} +1 -1
- package/dist/{chunk-AFGUR7SY.mjs → chunk-FNCCVGKX.mjs} +1 -1
- package/dist/{chunk-VNUWREXU.mjs → chunk-FOJ3K5Z3.mjs} +1 -1
- package/dist/{chunk-WCWYNFDF.mjs → chunk-FQ72LZHB.mjs} +1 -1
- package/dist/chunk-G7N7YFVD.mjs +2 -0
- package/dist/chunk-GIRXJBGC.mjs +2 -0
- package/dist/{chunk-VA3KAQZD.mjs → chunk-GKOBB6DH.mjs} +1 -1
- package/dist/chunk-GMJD7ID3.mjs +2 -0
- package/dist/chunk-GQJMVSSN.mjs +2 -0
- package/dist/{chunk-QZ35UAB4.mjs → chunk-GRAXKKG4.mjs} +1 -1
- package/dist/{chunk-SAHS56QM.mjs → chunk-HX4DLE3J.mjs} +1 -1
- package/dist/{chunk-2RKIHJI2.mjs → chunk-HYMEEXKN.mjs} +1 -1
- package/dist/{chunk-QK3VISCA.mjs → chunk-IA4PSIMD.mjs} +1 -1
- package/dist/chunk-IS7N3N6Q.mjs +168 -0
- package/dist/{chunk-CZ5KJSGK.mjs → chunk-JJNHKGTD.mjs} +1 -1
- package/dist/chunk-JPG2LBQM.mjs +11 -0
- package/dist/chunk-JYK5WJPM.mjs +2 -0
- package/dist/{chunk-LE44MD3O.mjs → chunk-KLQP46Y3.mjs} +1 -1
- package/dist/chunk-L55NOXBE.mjs +4 -0
- package/dist/{chunk-FXQBADMN.mjs → chunk-LCB6MARS.mjs} +1 -1
- package/dist/{chunk-SOD23RGL.mjs → chunk-LJLVCU6W.mjs} +8 -8
- package/dist/{chunk-NAGMRVW4.mjs → chunk-LKX55H76.mjs} +1 -1
- package/dist/chunk-LMUZQK5O.mjs +2 -0
- package/dist/{chunk-CG3UHDKH.mjs → chunk-M4NRDYI5.mjs} +1 -1
- package/dist/{chunk-HM4E43VM.mjs → chunk-MAFIGVXY.mjs} +1 -1
- package/dist/chunk-NLDF35P5.mjs +2 -0
- package/dist/{chunk-3OFXMN6N.mjs → chunk-NMF3IPYA.mjs} +1 -1
- package/dist/chunk-ONKC4BCC.mjs +2 -0
- package/dist/{chunk-CPS4SRPF.mjs → chunk-OU6ZZVBX.mjs} +2 -2
- package/dist/{chunk-NWRZXELO.mjs → chunk-PAREWQGB.mjs} +1 -1
- package/dist/{chunk-BYSF5UMM.mjs → chunk-PKVK6WFC.mjs} +2 -2
- package/dist/{chunk-4AMTKWDO.mjs → chunk-PUOQ65NC.mjs} +1 -1
- package/dist/{chunk-L7W624FD.mjs → chunk-QJAVCTY7.mjs} +1 -1
- package/dist/{chunk-6MPKCH3P.mjs → chunk-QNECWMGR.mjs} +1 -1
- package/dist/{chunk-HBAUKKQH.mjs → chunk-QP7BOHE4.mjs} +1 -1
- package/dist/chunk-QVGOPHOF.mjs +2 -0
- package/dist/{chunk-NFABH3QW.mjs → chunk-RRKJMHNX.mjs} +2 -2
- package/dist/chunk-S3SX3COT.mjs +20 -0
- package/dist/chunk-SQ3FQCCN.mjs +8 -0
- package/dist/{chunk-ZO7SFB2E.mjs → chunk-SQ6Y2ZMA.mjs} +2 -2
- package/dist/{chunk-3A5I2GJK.mjs → chunk-T4Y2ZSVX.mjs} +1 -1
- package/dist/{chunk-VG5JEIUQ.mjs → chunk-TKWEX4FD.mjs} +2 -2
- package/dist/{chunk-CCSGFCLZ.mjs → chunk-U3SSPL4K.mjs} +1 -1
- package/dist/{chunk-DHB7UZ7F.mjs → chunk-U5XL7D6A.mjs} +1 -1
- package/dist/{chunk-JXLSHVJ2.mjs → chunk-UMHUSOPJ.mjs} +1 -1
- package/dist/chunk-UTF7GBQU.mjs +4 -0
- package/dist/chunk-UTMAY3WK.mjs +2 -0
- package/dist/{chunk-S2Y7VI4H.mjs → chunk-V4ZHRALW.mjs} +2 -2
- package/dist/{chunk-GWOYMENX.mjs → chunk-V6XZ4VIR.mjs} +1 -1
- package/dist/{chunk-WTEGUPFG.mjs → chunk-VRPVVMRB.mjs} +1 -1
- package/dist/{chunk-XKOHV4H6.mjs → chunk-W5NPH5UA.mjs} +1 -1
- package/dist/{chunk-VGTMLQWZ.mjs → chunk-WD4U6XXT.mjs} +1 -1
- package/dist/{chunk-4DNHHJSL.mjs → chunk-XBNFXWAW.mjs} +1 -1
- package/dist/chunk-XZV72SQ4.mjs +2 -0
- package/dist/{chunk-QJ3TFJLQ.mjs → chunk-Y34NR5JL.mjs} +1 -1
- package/dist/{chunk-YBB5LWZK.mjs → chunk-YFJB534W.mjs} +1 -1
- package/dist/{chunk-V5JRSGZF.mjs → chunk-YN37ZDLW.mjs} +1 -1
- package/dist/chunk-Z6OKLRHC.mjs +2 -0
- package/dist/chunk-ZLS2FRS6.mjs +3 -0
- package/dist/{chunk-JI6T3A4Y.mjs → chunk-ZMHUDYLV.mjs} +1 -1
- package/dist/{chunk-KH24LWAT.mjs → chunk-ZTHICSSF.mjs} +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/server.mjs +1 -1
- package/dist/worker.mjs +1 -1
- package/kit/math.js +1 -1
- package/kit/runtime.js +13 -2
- package/kit/state.js +2 -0
- package/kit/ui.js +5 -1
- package/package.json +1 -1
- package/release.json +7 -7
- package/skill/SKILL.md +13 -13
- package/skill/references/building-blocks.md +1 -1
- package/skill/references/extensions.md +45 -9
- package/web/assets/index-D8P8uhDW.js +15 -0
- package/web/assets/{index-xP0uw3a0.css → index-FLb9jCfl.css} +1 -1
- package/web/index.html +2 -2
- package/dist/chunk-46ACXOU5.mjs +0 -2
- package/dist/chunk-5DPABPBI.mjs +0 -2
- package/dist/chunk-5L26JUYA.mjs +0 -2
- package/dist/chunk-AEMVZYZQ.mjs +0 -166
- package/dist/chunk-ASAXY2DJ.mjs +0 -2
- package/dist/chunk-DAMVDXR3.mjs +0 -2
- package/dist/chunk-DLFZJJEE.mjs +0 -2
- package/dist/chunk-EKNHM3P4.mjs +0 -2
- package/dist/chunk-FCK6NXON.mjs +0 -3
- package/dist/chunk-FX42XU6J.mjs +0 -2
- package/dist/chunk-HATA2W7X.mjs +0 -2
- package/dist/chunk-JJNRIFND.mjs +0 -8
- package/dist/chunk-JL6R4FG4.mjs +0 -4
- package/dist/chunk-KUILYI7H.mjs +0 -4
- package/dist/chunk-NIW7F7LU.mjs +0 -4
- package/dist/chunk-OU3S466R.mjs +0 -20
- package/dist/chunk-QCEATQC4.mjs +0 -2
- package/dist/chunk-TDWJKOLN.mjs +0 -2
- package/dist/chunk-UGO5N3EI.mjs +0 -15
- package/dist/chunk-XMKHCUI6.mjs +0 -15
- package/dist/chunk-XQRUG4G3.mjs +0 -2
- package/dist/chunk-YPPJVDQI.mjs +0 -2
- package/dist/chunk-ZANMKAWS.mjs +0 -2
- package/web/assets/index-BHC5ZOMh.js +0 -15
- /package/dist/{chunk-N3DSBH5S.mjs → chunk-A55HN5OK.mjs} +0 -0
- /package/dist/{chunk-KNZJT4ET.mjs → chunk-QAIHRH3I.mjs} +0 -0
- /package/dist/{chunk-ZW2A6GBW.mjs → chunk-QR6A54KJ.mjs} +0 -0
- /package/dist/{chunk-74UW7QSL.mjs → chunk-UH4SIXTR.mjs} +0 -0
- /package/dist/{chunk-EKGYYOSP.mjs → chunk-W7XHE4CT.mjs} +0 -0
- /package/dist/{chunk-5MMN3N5J.mjs → chunk-YEY3RSFQ.mjs} +0 -0
|
@@ -6,7 +6,7 @@ sidebar's \u9ED8\u8BA4\u6587\u6863 (GALLERY_DEFAULT_WORKSPACE names another fold
|
|
|
6
6
|
whole address, as a user hands one over (http://127.0.0.1:4317/#\u5468\u62A5-k3xv9q2a, a block's id after a / or not): the
|
|
7
7
|
words in a link are a label, and a title changed since leaves the address good.`,a={init:`Usage: gallery init [<dir>] [--from <old reports dir>] [--name "<name>"]
|
|
8
8
|
Makes a workspace: <dir> (else the workspace found as every command finds it) with its gallery.json
|
|
9
|
-
|
|
9
|
+
only (never over a gallery.json that is there); the home workspace also gets its application folders. Prints \u5DE5\u4F5C\u533A\uFF1A<abs>\uFF08\u65B0\u5EFA or \u5DF2\u6709\uFF09.
|
|
10
10
|
--name writes the workspace's name in its gallery.json (the project's: what the sidebar and gallery
|
|
11
11
|
workspaces call it; else its folder's), said as \u540D\u5B57\uFF1A<name>; gallery workspaces --name changes it.
|
|
12
12
|
The workspace goes on this machine's registry, as every command's does (gallery workspaces).
|
|
@@ -15,7 +15,7 @@ holding report.html or doc.html) into the workspace: every document whose slug i
|
|
|
15
15
|
others listed as skipped), its preferences.md when the workspace has none, the sidebar's order, the
|
|
16
16
|
\u5199\u4F5C\u504F\u597D page, the custom emoji and the documents' recent versions. The old folder is only read:
|
|
17
17
|
nothing there is changed, moved or deleted.
|
|
18
|
-
|
|
18
|
+
Only the default workspace gets its home page (\u9996\u9875, pages/home/: Gallery's today and note cards),
|
|
19
19
|
as a server's first start gives it, said in a line; once made, nothing makes it again.
|
|
20
20
|
Exits 1 when the workspace cannot be written or --from names no folder; 2 for a name that is empty,
|
|
21
21
|
over 80 characters or more than one line.`,new:`Usage: gallery new <slug> "<title>" ["<description>"] [--under <document>] [--after <document> | --first] [--no-preview] [--no-browser]
|
|
@@ -25,13 +25,13 @@ in the sidebar's tree: under --under's document, last (first with --first), or r
|
|
|
25
25
|
(at that one's level); neither, at the top level, last. A document is named there by its slug, link
|
|
26
26
|
or address (gallery help says how), and must be there, not in the trash; the \u5199\u4F5C\u504F\u597D page holds none.
|
|
27
27
|
Then says where it went (Placed it \u2026), where it wrote (the workspace), where the user's writing preferences are (\u5199\u4F5C\u504F\u597D,
|
|
28
|
-
<
|
|
29
|
-
the next steps (the first: send the user the address now), and last starts
|
|
28
|
+
<home>/preferences.md, to read first: made from Gallery's default when there are none yet) and
|
|
29
|
+
the next steps (the first: send the user the address now), and last starts the one Gallery
|
|
30
30
|
server (or uses the one running: it runs on after this command), opens the default browser at the
|
|
31
31
|
document and prints the address to give the user, as gallery open does. In a workspace other than the
|
|
32
32
|
default one, the document also joins the default workspace's sidebar (when there is one), in its
|
|
33
33
|
workspace's column: a line says where, \u9ED8\u8BA4\u5DE5\u4F5C\u533A\uFF08\u2026\uFF09\u7684\u4FA7\u8FB9\u680F\uFF1A\u5DF2\u52A0\u8FDB\u2026; it is a display only, the file stays in
|
|
34
|
-
its own workspace.
|
|
34
|
+
its own workspace. --no-preview (or
|
|
35
35
|
GALLERY_NO_PREVIEW=1) leaves the server alone; --no-browser (or GALLERY_NO_BROWSER=1) opens no
|
|
36
36
|
browser. Editing needs Chrome or Edge.
|
|
37
37
|
A title or a description that starts with "-" and a letter would be read as an option: put "--"
|
|
@@ -54,7 +54,7 @@ Put "--" before a title that starts with "-" and a letter.
|
|
|
54
54
|
Exits 1 when the file is not there, cannot be read, or gallery new would refuse the slug; 2 for a
|
|
55
55
|
kind it does not take.`,open:`Usage: gallery open [<slug>] [--no-browser]
|
|
56
56
|
Starts this workspace's Gallery server (or uses the one running: it runs on after this command, its
|
|
57
|
-
log in <
|
|
57
|
+
log in <data>/logs/server.log), waits until it answers, and opens the default browser
|
|
58
58
|
at the workbench, or at the document <slug>, at its block when an address names one (--no-browser,
|
|
59
59
|
or GALLERY_NO_BROWSER=1, opens none).
|
|
60
60
|
${t}
|
|
@@ -63,7 +63,7 @@ the address to give the user. With a slug in a workspace other than the default
|
|
|
63
63
|
them says the document joined the default workspace's sidebar (as gallery new's does). Editing needs Chrome or Edge: open the address there.
|
|
64
64
|
With a slug and no qa baseline yet, it first keeps one of the document as it is now, so that the
|
|
65
65
|
first gallery qa after the changes pictures what changed.
|
|
66
|
-
Exits 1 when there is no such document, no server answers, or the
|
|
66
|
+
Exits 1 when there is no such document, no server answers, or the shared Gallery server takes the
|
|
67
67
|
request and gives no answer (a second server is never started beside it).`,serve:`Usage: gallery serve [--port <n>]
|
|
68
68
|
Runs this workspace's Gallery server in the foreground until Ctrl+C (gallery open runs one in the
|
|
69
69
|
background instead). Prints the address once it answers. --port picks the port (else the last one
|
|
@@ -83,7 +83,7 @@ Exits 1 when a document fails, unless --allow-failures.`,export:`Usage: gallery
|
|
|
83
83
|
gallery export --all [--allow-failures]
|
|
84
84
|
Hands each named document in: its doc.html (report.html in an older document) written as its
|
|
85
85
|
preview shows it, natural HTML as the kit's markup and every block given an id (through the
|
|
86
|
-
|
|
86
|
+
shared Gallery server while one runs); then checks it and writes one standalone offline file per
|
|
87
87
|
passing document, <workspace>/exports/<slug>.html. A document the quick checks fail is not handed in.
|
|
88
88
|
${t}
|
|
89
89
|
It says first, once, what the preview wrote when the reader edited a document and the \u6279\u6CE8 it deleted;
|
|
@@ -119,7 +119,7 @@ with --no-export or --blocks names an id the document has not, else 0. A warning
|
|
|
119
119
|
gallery list [<words>...] --all
|
|
120
120
|
The workspace's documents, for an Agent to find the one the user means: each one's slug and title,
|
|
121
121
|
its description, where it is in the sidebar's tree when it is under another (\u4F4D\u7F6E\uFF1Athe documents above
|
|
122
|
-
it, from the top), its address (\u5730\u5740\uFF1A/#<link>, after the port of the
|
|
122
|
+
it, from the top), its address (\u5730\u5740\uFF1A/#<link>, after the port of the shared Gallery server), when its file
|
|
123
123
|
was last written and where that file is, the one edited last first.
|
|
124
124
|
With words, only those whose title, description or slug holds any of them (case alike, Chinese found
|
|
125
125
|
inside words), the best first, then those whose text holds them, each with its first place there
|
|
@@ -145,13 +145,13 @@ Exits 1 when --tree names a document that is not there, 2 one in the trash.`,wor
|
|
|
145
145
|
gallery workspaces --name "<name>"
|
|
146
146
|
gallery workspaces --forget <path>
|
|
147
147
|
The workspaces of this machine: every workspace a gallery command or a Gallery server has worked in
|
|
148
|
-
|
|
148
|
+
is registered in a file of the user's (GALLERY_DATA_DIR,
|
|
149
149
|
else %LOCALAPPDATA%\\gallery\\workspaces.json on Windows, ~/Library/Application Support/gallery on macOS,
|
|
150
150
|
$XDG_STATE_HOME/gallery or ~/.local/state/gallery elsewhere). Lists them, the current one first (*),
|
|
151
151
|
then the one edited last first: each one's name (its gallery.json's, else its folder's; the folder
|
|
152
152
|
above it, or its own path, after the name when two are called alike), its id (ws- and six hex
|
|
153
153
|
digits), its path (\u8DEF\u5F84\uFF1A), how many documents it has and when one was last edited (\u6587\u6863\uFF1A), and its
|
|
154
|
-
|
|
154
|
+
one shared service address printed above the list (\u670D\u52A1\uFF1A); one whose folder or gallery.json is gone is marked \u4E0D\u5728\u4E86
|
|
155
155
|
and stays registered (a drive may come back).
|
|
156
156
|
--scan registers the workspaces in <folder> and below it, 6 levels down at most (not in node_modules,
|
|
157
157
|
.git, a dot folder or the recycle bin): the Documents folder when none is named. --name names the
|
|
@@ -204,9 +204,11 @@ remove moves it to the trash, which the workbench's \u8BBE\u7F6E \u203A \u56DE\u
|
|
|
204
204
|
Each is written through the workspace's running server when there is one (an open workbench shows it
|
|
205
205
|
at once), else here.
|
|
206
206
|
Exits 1 when a link, a column or an entry named is not there or the server refuses it; 2 for an
|
|
207
|
-
address that is not http or https, an empty name, or two places at once.`,extension:`Usage: gallery extension new <id> "<title>"
|
|
207
|
+
address that is not http or https, an empty name, or two places at once.`,extension:`Usage: gallery extension new <id> "<title>"
|
|
208
208
|
gallery extension list
|
|
209
209
|
gallery extension check <id>
|
|
210
|
+
gallery extension install <folder | .zip>
|
|
211
|
+
gallery extension remove <id>
|
|
210
212
|
An extension (\u6269\u5C55) gives the sidebar a column of entries of its own, beside \u6587\u6863: a folder
|
|
211
213
|
<workspace>/extensions/<id>/ whose sidebar.json lists them (a title, an optional icon, and entries each with
|
|
212
214
|
an id, a title, an optional address (http or https), an optional icon and optional children). The workbench
|
|
@@ -214,13 +216,12 @@ reads the file again within a second of every change; a click on an entry with a
|
|
|
214
216
|
the sidebar (as a web link's), one without opens and closes what is under it. The user may drag the column to
|
|
215
217
|
another place, rename it and reorder its root entries; title/order edits write back to sidebar.json.
|
|
216
218
|
A file that does not read shows the column with one row, \u6761\u76EE\u8BFB\u4E0D\u51FA\u6765\uFF1A<why>.
|
|
217
|
-
new creates an empty sidebar.json in the
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
Every sidebar reads the default workspace's extensions
|
|
221
|
-
takes precedence in that project; an empty folder does not. No files are copied or moved automatically.
|
|
219
|
+
new creates an empty sidebar.json in the default workspace. Project-local extensions are not read.
|
|
220
|
+
install <folder | .zip> validates and replaces an extension; remove <id> removes it.
|
|
221
|
+
list prints capabilities and AGENT.md paths. Executable extensions require user confirmation in Settings > Extensions.
|
|
222
|
+
Every sidebar reads only the default workspace's extensions. No files are copied or moved automatically.
|
|
222
223
|
list prints the visible extensions, their source paths, titles and entry counts, or why they show none.
|
|
223
|
-
check <id> resolves the same
|
|
224
|
+
check <id> resolves the same default-workspace source as the sidebar and prints what the sidebar will show:
|
|
224
225
|
the column, then each entry with its id, title and address, one under another indented; notes (an icon that
|
|
225
226
|
is no emoji and no icon of the \u56FE\u6807 tab, which is left out) follow. Writes nothing.
|
|
226
227
|
Exits 0 when the file reads; 1 when the extension is not there, has no sidebar.json or its file does not
|
|
@@ -332,7 +333,7 @@ Exits 2 for an id no block can have.
|
|
|
332
333
|
try makes what a reader does on an instance in a document, with the pointer and the keys, and says
|
|
333
334
|
what it wrote. It makes it on a scratch copy of the document (<workspace>/.gallery/try/try-<8 hex>/,
|
|
334
335
|
gone at the end, whatever came of it): doc.html is not written, and no page of the user's shows the trial;
|
|
335
|
-
--keep makes it on the document itself and leaves what it wrote. It starts the
|
|
336
|
+
--keep makes it on the document itself and leaves what it wrote. It starts the shared Gallery server (or
|
|
336
337
|
uses the one running), as gallery open does, and opens the copy's page alone, editable, in Chrome or
|
|
337
338
|
Edge, headless, in a profile of its own, and waits until the server has told the page of the writes
|
|
338
339
|
made before it (a custom block changed), which load it again. Each selector is the first element of the
|
|
@@ -406,7 +407,7 @@ Documents and custom pages share one set of slugs: neither takes the other's, no
|
|
|
406
407
|
The home page (\u9996\u9875) is pages/home, a page as any.
|
|
407
408
|
new makes one: page.html with its title (in <title>: a page draws no big title) and one empty board (data-board-id="main"), and
|
|
408
409
|
page.json with the title; it goes last in the sidebar's head. The server puts in the scripts and styles
|
|
409
|
-
of the blocks its cards hold. Says where it wrote and what to write next, and with the
|
|
410
|
+
of the blocks its cards hold. Says where it wrote and what to write next, and with the shared Gallery server
|
|
410
411
|
running ends with the \u4EA4\u7ED9\u7528\u6237 line gallery open has: the page's whole address, to send the user at once
|
|
411
412
|
(without one, gallery page open <slug> --no-browser gives it).
|
|
412
413
|
Exits 1 when the slug is taken (a document's, a page's, the trash's) or kept (exports, components, pages,
|
|
@@ -415,7 +416,7 @@ its own cards; gallery open --no-browser starts one), gallery page open, add, tr
|
|
|
415
416
|
so in place of "no such page".
|
|
416
417
|
list says the workspace's custom pages in the sidebar's order (the order the user dragged them to, then
|
|
417
418
|
gallery.json's pages.order, then by title): each one's slug, icon and title, its address (\u5730\u5740\uFF1A, the whole address with
|
|
418
|
-
the
|
|
419
|
+
the shared Gallery server running, else /#@<slug>, after the port of a server) and where its page.html is;
|
|
419
420
|
in a workspace with no page whose home page is not made yet, only that the home page waits for the server.
|
|
420
421
|
open starts this workspace's Gallery server (or uses the one running), as gallery open does, and opens
|
|
421
422
|
the default browser at the page in the workbench (--no-browser, or GALLERY_NO_BROWSER=1, opens none).
|
|
@@ -448,7 +449,7 @@ gallery block try's gestures (--press, --drag \u2026 --to, --key, --type, --sele
|
|
|
448
449
|
the first element of the instance it finds (gallery block --help says each). It makes them on a scratch
|
|
449
450
|
copy of the page (<workspace>/.gallery/try/try-<8 hex>/, gone at the end, whatever came of it):
|
|
450
451
|
page.html is not written, and no page of the user's shows the trial; --keep makes them on the page itself
|
|
451
|
-
and leaves what they wrote. It starts the
|
|
452
|
+
and leaves what they wrote. It starts the shared Gallery server (or uses the one running) and opens the
|
|
452
453
|
copy's page alone (/pages/<slug>), editable, in Chrome or Edge, headless, in a profile of its own. A
|
|
453
454
|
write is what the page's board sends the page service, as the user's gestures go: once each is
|
|
454
455
|
answered, a Gesture line (Step N with --steps) and a Wrote line say each data part of the card's
|
|
@@ -486,7 +487,7 @@ the last check that found nothing saw it (or, before any, since the version the
|
|
|
486
487
|
its last write): cards added, removed, moved (to another board too), resized, their data parts changed
|
|
487
488
|
(with the lines), a card's own markup, the page's own HTML; each change the page wrote since, a gesture
|
|
488
489
|
of the user's there (not gallery page add's), ends "(the user's, on the page)": leave it as it is. Then
|
|
489
|
-
the page itself, a scratch copy of it on the
|
|
490
|
+
the page itself, a scratch copy of it on the shared Gallery server (started
|
|
490
491
|
or used, as gallery page open does), in Chrome or Edge at 1280, 1920 and 600px wide (a narrow board: fewer
|
|
491
492
|
columns of the same 64px cells), light and dark: a card whose content does not fit it, a card drawn out of its board, the page
|
|
492
493
|
wider than the window, a block that failed, a picture that does not load, what the console says; each
|
|
@@ -523,7 +524,7 @@ Gallery: documents written as HTML, edited in the browser, exported as one offli
|
|
|
523
524
|
gallery import <file> [<slug> ["<title>"]] documents made of a file (Markdown, HTML, Word, PDF\u2026)
|
|
524
525
|
gallery open [<slug>] [--no-browser] start or reuse the server and open the browser
|
|
525
526
|
gallery serve [--port <n>] run the server in the foreground
|
|
526
|
-
gallery stop stop the
|
|
527
|
+
gallery stop stop the shared Gallery server
|
|
527
528
|
gallery check [<slug>...] check documents (none named: all)
|
|
528
529
|
gallery export <slug>... | --all write <workspace>/exports/<slug>.html
|
|
529
530
|
gallery qa <slug>... [--blocks a,b] [--tiles] look at exports in Chrome or Edge
|
|
@@ -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}from"./chunk-
|
|
2
|
+
import{a}from"./chunk-MAFIGVXY.mjs";import"./chunk-742D2WWJ.mjs";import"./chunk-5L7RYZCL.mjs";export{a as convertPuppeteerChannelToBrowsersChannel};
|
|
@@ -1,3 +1,3 @@
|
|
|
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 q,b as B}from"./chunk-
|
|
2
|
+
import{a as q,b as B}from"./chunk-IA4PSIMD.mjs";import{b as C}from"./chunk-ZTHICSSF.mjs";import x from"node:fs/promises";import W from"node:path";import{MENTION as L}from"../browser/shared/components/mention.mjs";import{writeAtomic as R}from"../browser/shared/files.mjs";import{reportLines as U}from"../browser/shared/search.mjs";import{countWords as Q}from"../browser/shared/words.mjs";import{FACT_KINDS as V,QUERY_KINDS as Y,SNAPSHOT_LIMITS as y,queryOptions as G}from"../browser/shared/workspace-query.mjs";import{documentDirectory as M,documentFiles as T,layoutOf as X,listDocumentSlugs as _,listTrash as Z}from"../browser/shared/workspace.mjs";var ut=f=>c=>f.readTaken(c,{wait:0}),z=({todos:f})=>{let c=new Map,g=d=>JSON.stringify([d.text,d.path]);for(let d of f)c.set(g(d),(c.get(g(d))??0)+1);return f.some(d=>!d.block&&c.get(g(d))>1)},tt=(f,c)=>({hash:B(f),words:Q(c),todos:q(c)});function et(f){let c=new Date(f);return c.setHours(0,0,0,0),c.setDate(c.getDate()-(c.getDay()+6)%7),c.getTime()}function mt({root:f,read:c,draw:g=u=>u,activity:d=null,now:I=()=>new Date}){let u=new Map,m=new Map,b=t=>x.stat(t).then(({mtimeMs:e})=>e,()=>null);async function J(t,e=null){let o=T(M(t,f)),[a,n]=await Promise.all([b(o.html),b(o.json)]);if(a===null)return null;let s=e??await c(t);if(!s)return null;let r={};try{r=JSON.parse(await x.readFile(o.json,"utf8"))??{}}catch{}let{title:i,icon:h}=r,w={slug:t,title:typeof i=="string"&&i.trim()?i:t,icon:typeof h=="string"&&h?h:null,edited:Math.round(a),...tt(s.source,s.text)};return u.set(t,{html:a,json:n,facts:w,held:s.held===!0}),m.has(t)||m.set(t,w),w}async function O(t){let e=u.get(t);if(e&&!e.held){let o=T(M(t,f)),[a,n]=await Promise.all([b(o.html),b(o.json)]);if(a===e.html&&n===e.json)return e.facts}return J(t)}async function S(){let t=await _(f);for(let e of u.keys())t.includes(e)||u.delete(e);for(let e of m.keys())t.includes(e)||m.delete(e);return(await Promise.all(t.map(e=>O(e).catch(()=>null)))).filter(Boolean)}let P={async todos({done:t,slugs:e,limit:o}){let a=(await S()).filter(s=>!e||e.includes(s.slug)).sort((s,r)=>r.edited-s.edited||s.slug.localeCompare(r.slug)),n=[];for(let{slug:s,title:r,icon:i,todos:h,hash:w}of a)for(let l of h)if(!(t!==void 0&&l.done!==t)){if(n.length>=o)return n;n.push({ref:{slug:s,block:l.block,text:l.text,path:l.path,nth:l.nth,version:w},text:l.text,done:l.done,slug:s,title:r,icon:i,path:l.path})}return n},async recent({limit:t}){return(await S()).sort((e,o)=>o.edited-e.edited||e.slug.localeCompare(o.slug)).slice(0,t).map(({slug:e,title:o,icon:a,edited:n})=>({slug:e,title:o,icon:a,edited:new Date(n).toISOString()}))},async stats(){let t=await S(),e=et(I()),o=t.flatMap(a=>a.todos);return{documents:t.length,todos:{done:o.filter(a=>a.done).length,total:o.length},words:t.reduce((a,n)=>a+n.words,0),editedThisWeek:t.filter(a=>a.edited>=e).length}},async activity({days:t}){return d?(await d.load(),await $,d.days(t)):[]},async table({slug:t,key:e,where:o,limit:a},{words:n=!1}={}){let s=await O(t).catch(()=>null),r=u.get(t);if(!s||!r)return k(404,"missing",`no document "${t}"`);if(r.tables??=new Map,!r.tables.has(e)){let l=await c(t);if(!l)return k(404,"missing",`no document "${t}"`);r.tables.set(e,C(l.text,e,t))}let i=r.tables.get(e);if(i.error==="missing")return k(404,"missing",`"${t}" holds no table whose frame carries data-doc-chart-source="${e}"`);if(i.error)return k(422,"missing",`the table "${e}" of "${t}" has merged cells, which no view reads: write each value in its own cell`);let h=Object.keys(o).filter(l=>!i.columns.includes(l));if(h.length>0)return k(400,"options",`table: the table "${e}" of "${t}" has no column ${h.map(l=>JSON.stringify(l)).join(", ")} (its columns: ${i.columns.map(l=>JSON.stringify(l)).join(", ")})`);let w=i.rows.filter(l=>Object.entries(o).every(([D,v])=>l.words[D]===v.replace(/\s+/g," ").trim()));return{columns:[...i.columns],rows:w.slice(0,a).map(({values:l,links:D,words:v})=>({values:{...l},links:D.map(K=>({...K})),...n?{words:{...v}}:{}})),total:w.length}}},k=(t,e,o)=>{throw Object.assign(new Error(o),{refusal:[t,{ok:!1,reason:e,message:o}]})},p=new Map,j=t=>W.join(X(f).gallery,"cache","workspace",`${t}.json`),A=async t=>{if(!p.has(t)){let e=[];try{let o=JSON.parse(await x.readFile(j(t),"utf8"));Array.isArray(o?.tables)&&(e=o.tables.filter(a=>typeof a=="string").slice(-y.tables))}catch{}p.has(t)||p.set(t,e)}return p.get(t)},N=Promise.resolve(),H=async(t,e)=>{let o=await A(t);if(o.at(-1)===e)return;let a=[...o.filter(n=>n!==e),e].slice(-y.tables);p.set(t,a),N=N.then(async()=>{await x.mkdir(W.dirname(j(t)),{recursive:!0}),await R(j(t),`${JSON.stringify({tables:p.get(t)})}
|
|
3
3
|
`)}).catch(()=>{})},F=/^[a-z0-9]+(?:-[a-z0-9]+)*$/,$=Promise.resolve(),E={facts:O,all:S,async lines(t,e){let o=u.get(t);if(!await O(t))return null;let n=u.get(t);if(n!==o||!n.lines||n.lines.titles!==null&&n.lines.titles!==e){let s=await c(t);if(!s)return null;n.lines={titles:s.text.includes(L)?e:null,value:U(g(s.text,t))}}return n.lines.value},async query(t,e,{doc:o=null}={}){if(!Y.includes(t))return[400,{ok:!1,reason:"kind",message:`no kind "${t}": todos, recent, stats, activity or table`}];let{problem:a,options:n}=G(t,e);if(a)return[400,{ok:!1,reason:"options",message:`${t}: ${a}`}];let s;try{s=await P[t](n)}catch(r){if(r.refusal)return r.refusal;throw r}return t==="table"&&typeof o=="string"&&F.test(o)&&await H(o,`${n.slug}#${n.key}`),[200,{ok:!0,kind:t,data:s,at:new Date(I()).toISOString()}]},async snapshot(t){let e=async(n,s)=>{let[r,i]=await E.query(n,s);return r===200?i.data:null},o={todos:await e("todos",{limit:y.todos}),recent:await e("recent",{limit:y.recent}),stats:await e("stats"),activity:await e("activity",{days:y.activity})},a={};for(let n of F.test(t)?await A(t):[]){let[s,r]=n.split("#"),i=await P.table({slug:s,key:r,where:{},limit:y.rows},{words:!0}).catch(()=>null);i&&(a[n]=i)}return Object.keys(a).length>0&&(o.tables=a),Object.fromEntries(Object.entries(o).filter(([,n])=>n!==null))},stored:()=>N,async changed(t,{source:e=null,text:o=null,by:a="agent"}={}){let n=m.get(t)??u.get(t)?.facts??null;u.delete(t);let s=e===null?null:await J(t,{source:e,text:o??e}).catch(()=>null);s?m.set(t,s):m.delete(t);let r=new Set;if(!!n!=!!s)for(let i of["todos","recent","stats","table"])r.add(i);return n&&s&&n.hash!==s.hash&&r.add("table"),n&&s&&n.hash!==s.hash&&(z(n)||z(s))&&r.add("todos"),n&&s&&((n.title!==s.title||JSON.stringify(n.todos)!==JSON.stringify(s.todos))&&r.add("todos"),(n.title!==s.title||n.icon!==s.icon||n.edited!==s.edited)&&r.add("recent"),(n.words!==s.words||n.todos.length!==s.todos.length||n.todos.filter(i=>i.done).length!==s.todos.filter(i=>i.done).length||n.edited!==s.edited)&&r.add("stats")),!n&&s&&r.add("recent"),d&&s&&(await d.load(),await $,d.record(t,{hash:s.hash,words:s.words,mtime:s.edited,by:a})&&r.add("activity")),V.filter(i=>r.has(i))},start(){return d?($=(async()=>{await d.load();let t=await _(f),e=(await Promise.all(t.map(async a=>({slug:a,mtime:await b(T(M(a,f)).html)})))).filter(({mtime:a})=>a!==null),o=(await Z(f).catch(()=>[])).map(a=>a.slug);return d.catchUp(e.map(({slug:a,mtime:n})=>({slug:a,mtime:Math.round(n)})),O,{kept:o})})().catch(()=>0),$):Promise.resolve(0)},forget(t){u.delete(t),m.delete(t)}};return E}export{ut as a,mt as b};
|
|
@@ -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{f as A}from"./chunk-DHB7UZ7F.mjs";import{a as w,c as U}from"./chunk-2RKIHJI2.mjs";import he from"node:fs";import $e from"node:path";import{reportsDirectory as we}from"../browser/shared/paths.mjs";import{assetFile as be,assetProblem as ge,embedFile as ke}from"../browser/shared/media.mjs";import{attr as H,hasClass as xe,walk as ye}from"../browser/shared/html-tree.mjs";import _ from"node:fs";import ie from"node:path";import{attr as ae,hasClass as ce,walk as fe}from"../browser/shared/html-tree.mjs";import{MEDIA_ROUTES as le,mediaTypeOf as de,mediaUrl as ue}from"../browser/shared/media.mjs";import{documentDirectory as pe}from"../browser/shared/workspace.mjs";function k(e,n,o){let s=null;return fe(e,t=>{!s&&t.tagName===n&&ce(t,o)&&(s=t)}),s}function N(e,n){let o=ie.join(e,n);return _.statSync(o,{throwIfNoEntry:!1})?.isFile()?`data:${de(n)};base64,${_.readFileSync(o).toString("base64")}`:null}function me(e,{attribute:n,route:o,slug:s,mode:t,reportsDirectory:r}){if(!le[o](e))return null;if(t==="preview")return`${n}="${ue(o,s,e)}" data-ge-${n}="${e}"`;let a=N(pe(s,r),e);return a&&`${n}="${a}"`}function x(e,n,{attribute:o,route:s,slug:t,mode:r,reportsDirectory:a}){let i=n.map(f=>({place:f.sourceCodeLocation?.attrs?.[o],value:ae(f,o)})).filter(({place:f})=>f).sort((f,d)=>f.place.startOffset-d.place.startOffset),c=[],l=0;for(let{place:f,value:d}of i){let u=me(d,{attribute:o,route:s,slug:t,mode:r,reportsDirectory:a});u===null||f.startOffset<l||(c.push(e.slice(l,f.startOffset),u),l=f.endOffset)}return c.push(e.slice(l)),c.join("")}function D(e){let n=[];return ye(e,o=>{let s=o.tagName==="figure"&&xe(o,"doc-embed")?k(o,"iframe","doc-embed-frame"):null;s&&n.push(s)}),n}function bt(e,{slug:n,mode:o="export",reportsDirectory:s=we}){return e.includes("doc-embed")?x(e,D(w(e)),{attribute:"src",route:"embed",slug:n,mode:o,reportsDirectory:s}):e}var I=(e,n=w(e))=>D(n).map(o=>o.sourceCodeLocation.startOffset);function gt({html:e,directory:n,tree:o=w(e)}){let s=[];for(let t of D(o)){let r=`line ${t.sourceCodeLocation.startLine}`,a=H(t,"src")??"",i=H(t,"sandbox"),c=/^https:\/\/[^\s"]+$/.test(a),l=!c&&!/^[a-z][a-z0-9+.-]*:/i.test(a)&&!be(a)?ge(a):null;l?s.push(`${r}: an embed's frame (${a.slice(0,80)}): ${l} (an HTML or PDF file; or a web page, https://\u2026)`):!c&&!ke(a)?s.push(`${r}: an embed's frame (${a.slice(0,80)}) shows a web page (https://\u2026, never http) or an HTML or PDF file of the document's folder (assets/<file>)`):!c&&!he.existsSync($e.join(n,a))?s.push(`${r}: the embed's file ${a} is not in the document's folder`):(c||/\.html?$/i.test(a))&&i===void 0?s.push(`${r}: an embed's frame (${a.slice(0,80)}) is sandboxed: sandbox="allow-scripts allow-popups \u2026"`):!c&&/\.html?$/i.test(a)&&/\ballow-same-origin\b/.test(i)?s.push(`${r}: an embedded HTML file (${a}) keeps its own origin: its sandbox has no allow-same-origin`):!c&&/\.pdf$/i.test(a)&&i!==void 0&&s.push(`${r}: an embedded PDF (${a}) is sandboxed, and a sandboxed frame shows no PDF: take its sandbox attribute off`)}return[...new Set(s)]}import Oe from"node:fs";import Se from"node:path";import{reportsDirectory as ve}from"../browser/shared/paths.mjs";import{assetFile as Fe,assetProblem as Le}from"../browser/shared/media.mjs";import{attr as z,hasClass as Ee,walk as Ce}from"../browser/shared/html-tree.mjs";function F(e,n=w(e)){let o=[];return Ce(n,s=>{s.tagName==="figure"&&Ee(s,"doc-file")&&o.push({node:s,link:k(s,"a","doc-file-link")})}),o}function Et(e,{slug:n,mode:o="export",reportsDirectory:s=ve}){if(!e.includes("doc-file"))return e;let t=F(e).flatMap(({link:r})=>r?[r]:[]);return x(e,t,{attribute:"href",route:"file",slug:n,mode:o,reportsDirectory:s})}function Ct({html:e,directory:n,tree:o=w(e)}){let s=[];for(let{link:t}of F(e,o)){if(!t)continue;let r=`line ${t.sourceCodeLocation?.startLine}`,a=z(t,"href")??"";Fe(a)?Oe.existsSync(Se.join(n,a))||s.push(`${r}: the file block's file ${a} is not in the document's folder`):s.push(`${r}: a file block's file (${a.slice(0,80)}): ${Le(a)} (<a class="doc-file-link" href="assets/<file>" download="<name>">)`),z(t,"download")||s.push(`${r}: a file block's link (${a.slice(0,80)}) says the name to save it as: download="<name>"`)}return[...new Set(s)]}import Ne from"node:fs";import De from"node:path";import{reportsDirectory as Re}from"../browser/shared/paths.mjs";import{assetProblem as W,imageFile as K}from"../browser/shared/media.mjs";import{attr as R,hasClass as Me,walk as M}from"../browser/shared/html-tree.mjs";var je={"doc-image":"image","doc-bookmark":"bookmark"},Te={image:"an image's picture",bookmark:"a bookmark's icon or cover"},Pe=/doc-(?:image|bookmark|link-mention-icon)/;function G(e){let n=[];return M(e,o=>{let s=o.tagName==="figure"&&(R(o,"class")??"").split(/\s+/).map(t=>je[t]).find(Boolean);s&&n.push({node:o,kind:s})}),n}function L(e,n=w(e)){let o=new Map,s=(t,r,a)=>{let i=t.sourceCodeLocation;i&&!o.has(i.startOffset)&&o.set(i.startOffset,{at:i.startOffset,line:i.startLine,node:t,what:r,kind:a,mention:a==="mention"})};for(let{node:t,kind:r}of G(n))M(t,a=>a.tagName==="img"&&s(a,Te[r],r));return M(n,t=>t.tagName==="img"&&Me(t,"doc-link-mention-icon")&&s(t,"a link's icon","mention")),[...o.values()].sort((t,r)=>t.at-r.at)}function Ut(e,{slug:n,mode:o="export",reportsDirectory:s=Re}){return Pe.test(e)?x(e,L(e).map(({node:t})=>t),{attribute:"src",route:"asset",slug:n,mode:o,reportsDirectory:s}):e}function At({html:e,directory:n,tree:o=w(e)}){let s=[];for(let{line:t,node:r,what:a,mention:i}of L(e,o)){let c=R(r,"src");i&&!K(c)?s.push(`line ${t}: a link's icon (${(c??"").slice(0,80)}): ${W(c,{picture:!0})}; or write an empty <span class="doc-link-mention-icon"></span>`):c===void 0?s.push(`line ${t}: ${a} has no src: <img src="assets/<file>" alt="\u2026">`):K(c)?Ne.existsSync(De.join(n,c))||s.push(`line ${t}: ${a} ${c} is not in the document's folder`):s.push(`line ${t}: ${a} (${c.slice(0,80)}): ${W(c,{picture:!0})}`)}for(let{node:t,kind:r}of G(o)){let a=r==="bookmark"?k(t,"a","doc-bookmark-card"):null,i=a&&R(a,"href");a&&!/^https?:\/\/[^\s"]+$/.test(i??"")&&s.push(`line ${a.sourceCodeLocation?.startLine}: a bookmark's link (${(i??"").slice(0,80)}) is a web address: <a class="doc-bookmark-card" href="https://\u2026">`)}return[...new Set(s)]}import ee from"node:fs";import te from"node:path";import{escapeAttribute as S}from"../browser/shared/escape.mjs";import{attr as y,hasClass as Be,walk as Ue}from"../browser/shared/html-tree.mjs";import{cssReferences as q}from"../browser/shared/css-references.mjs";import{assetFile as Ae,assetProblem as _e,imageFile as He,mediaUrl as Ie,referencedFile as v}from"../browser/shared/media.mjs";import{reportsDirectory as ze}from"../browser/shared/paths.mjs";import{documentDirectory as We}from"../browser/shared/workspace.mjs";var Y=/^\s*(?:\.\/)?assets\//i,J=1e6;function Ke(e){let n=[],o=0;for(;o<e.length;){for(;o<e.length&&/[\s,]/.test(e[o]);)o++;if(o>=e.length)break;let s=o;for(;s<e.length&&!/\s/.test(e[s]);)s++;let t=e.slice(o,s),r="";if(t.endsWith(","))t=t.replace(/,+$/,""),o=s;else{let i=s;for(let c=0;i<e.length&&(e[i]!==","||c>0);i++)e[i]==="("?c++:e[i]===")"&&c--;r=e.slice(s,i).trim(),o=i+1}let a=r.split(/\s+/).find(i=>/^\d*\.?\d+[wx]$/i.test(i));n.push({url:t,descriptor:r,size:a?parseFloat(a):1,wide:/w$/i.test(a??"")})}return n}function Ge(e){let n=e.filter(o=>o.wide);return(n.length>0?n:e).reduce((o,s)=>!o||s.size>o.size?s:o,null)}var qe=new Set(["body","table","thead","tbody","tfoot","tr","td","th"]);function T(e,n,o=s=>Y.test(s)){let s=[],t=r=>{o(r.value,r.node)&&s.push({...r,value:r.value.trim(),written:r.css?.written})};return Ue(n,r=>{let a=r.sourceCodeLocation;if(a){for(let{name:i,value:c,prefix:l}of r.attrs){let f=l?`${l}:${i}`:i,d=a.attrs?.[f],u={node:r,how:i,key:f,place:d,line:d?.startLine??a.startLine};if(i==="src"||i==="href"||i==="poster"||i==="data"&&r.tagName==="object"||i==="background"&&qe.has(r.tagName))t({...u,value:c});else if(i==="srcset"){let p=Ke(c),g=Ge(p.filter(b=>Y.test(b.url)));p.forEach((b,m)=>t({...u,value:b.url,candidates:p,index:m,largest:b===g}))}else if(i==="style")for(let p of q(c))t({...u,value:p.value,css:p})}if(r.tagName==="style")for(let i of r.childNodes){if(i.nodeName!=="#text"||!i.sourceCodeLocation)continue;let{startOffset:c,endOffset:l}=i.sourceCodeLocation;for(let f of q(e.slice(c,l)))t({node:r,how:"css",value:f.value,line:U(e,c+f.index),css:{...f,offset:c}})}}}),s}function se(e,n){let o=new Map;for(let{at:s,kind:t}of L(e,n))o.set(s,{attribute:"src",owner:"block",icon:t!=="image"});for(let{link:s}of F(e,n))s&&o.set(s.sourceCodeLocation.startOffset,{attribute:"href",owner:"block"});for(let s of I(e,n))o.set(s,{attribute:"src",owner:"block"});for(let s of A(e))o.set(s,{attribute:"src",owner:"icon"});return o}var oe=(e,n)=>{let o=e.get(n.node.sourceCodeLocation.startOffset);return o?.attribute===n.how?o:null},Ye=new Set(["img","input","video","audio","source","track"]),Q="an export holds no stylesheet of the folder (the addresses in one are read from its own place): put its rules in the page's <style>",V=e=>(y(e,"rel")??"").toLowerCase().split(/\s+/),j=/\.html?$/i,Je={html:'src="assets/<file>.html" sandbox="allow-scripts"',pdf:'src="assets/<file>.pdf"'},P=e=>`<figure class="doc-embed doc-embed--file"><iframe class="doc-embed-frame" ${Je[e]}></iframe><figcaption></figcaption></figure>`,X=`its frame with no sandbox (a sandboxed one shows no PDF): ${P("pdf")}`,Z='show a picture with <img src="assets/<file>">, a file to save with a link, <a href="assets/<file>" download="<name>">';function B({node:e,how:n,css:o,value:s}){let t=e.tagName;if(n==="style"||n==="css")return o.kind==="import"?{not:Q}:{use:"shown"};if(n==="srcset"&&(t==="img"||t==="source")||n==="poster"&&t==="video"||n==="src"&&Ye.has(t)||n==="background")return{use:"shown"};if(n==="src"&&t==="iframe"){let r=v(s)??"";return j.test(r)?{use:"frame"}:/\.pdf$/i.test(r)?{not:`a PDF shows in an embed block alone (the kit hands its file to the browser's PDF viewer, in the preview and in an export): make it one, ${X}`}:{not:`a frame shows a page of the folder (an HTML file), not this file, which the preview would hand out for saving: ${Z}`}}if(n==="href"&&(t==="a"||t==="area"))return{use:"link"};if(n==="href"&&(t==="image"||t==="link"&&V(e).some(r=>r.endsWith("icon"))))return{use:"shown"};if(t==="object"||t==="embed"){let r=v(s)??"";return{not:`an export's policy loads no plugin content (<object>, <embed>): ${/\.pdf$/i.test(r)?`show a PDF in an embed block, ${X}`:j.test(r)?`show a page in an embed block, ${P("html")}`:Z}`}}return t==="script"?{not:"an export runs the page's own scripts alone: put the code in the page's <script>"}:t==="link"&&V(e).includes("stylesheet")?{not:Q}:{not:"an export holds a file of the folder as a picture, a font, a video or audio, a link or a frame, not there"}}var E=e=>e.startsWith("assets/")&&Ae(e),Qe=e=>_e(e)??`the folder is assets/, in lowercase: write it so (assets/${e.slice(7)})`,ne=(e,n,o)=>n==="link"&&j.test(o)&&y(e.node,"download")===void 0,Ve=(e,n)=>e==="frame"?"embed":e==="shown"&&He(n)?"asset":"file",Xe=(e,n)=>!!ee.statSync(te.join(e,n),{throwIfNoEntry:!1})?.isFile(),O=({node:e,how:n,value:o,written:s})=>({srcset:`<${e.tagName} srcset="\u2026 ${o} \u2026">`,style:`${s} in the style of <${e.tagName}>`,css:`${s} in <style>`})[n]??`<${e.tagName} ${n}="${o}">`,Ze=e=>{for(let n=e.parentNode;n;n=n.parentNode)if(n.tagName&&Be(n,"doc-icon"))return!0;return!1},et=e=>e.length>1?`${e.slice(0,-1).join(", ")} and ${e.at(-1)}`:`${e[0]}`;function tt(e,n){let o=new Map;for(let{file:a,line:i,owned:c}of e){let l=o.get(a)??o.set(a,{lines:[],owned:!1}).get(a);c?l.owned=!0:l.lines.push(i)}let s=0,t=[];for(let[a,{lines:i,owned:c}]of o){let l=c?i.length:i.length-1;if(l<1)continue;let f=l*Math.ceil(ee.statSync(te.join(n,a)).size/3)*4;s+=f;let d=i.length===1?"once":i.length===2?"twice":`${i.length} times`;t.push({bytes:f,said:`${a} ${d}${c?" besides a media block's or the icon's":""} (line${new Set(i).size>1?"s":""} ${et([...new Set(i)])})`})}if(s<=J)return[];let r=t.sort((a,i)=>i.bytes-a.bytes).map(({said:a})=>a).join(", ");return[`files embedded more than once make an export ${s.toLocaleString("en-US")} bytes bigger, over the ${J.toLocaleString("en-US")} bytes the copies outside the media blocks may add: ${r}; show each fewer times (a picture, a link or a frame holds a copy of its own each time it is written), or, for a CSS background (url() in a <style> or a style attribute), name it once in the page's <style> (--picture: url(assets/<file>)) and write var(--picture) where it shows`]}function re({html:e,directory:n,tree:o}){let s=se(e,o),t=[],r=[],a=[];for(let i of T(e,o)){let{line:c}=i,l=oe(s,i),f=v(i.value),d=f!==null&&Xe(n,f);if(d&&!E(f)&&a.push({file:f,line:c}),l?.owner==="block"){d&&E(f)&&r.push({file:f,line:c,owned:!0,icon:!!l.icon});continue}if(d||t.push(l?`line ${c}: the icon's image ${i.value} is not in the document's folder`:`line ${c}: ${O(i)} names a file that is not in the document's folder`),l){d&&r.push({file:f,line:c,owned:!0,icon:!0});continue}let{use:u,not:p}=B(i);p&&t.push(`line ${c}: ${O(i)}: ${p}`),!(!u||!d)&&(E(f)?ne(i,u,f)?t.push(`line ${c}: ${O(i)} opens an HTML file, which an export cannot (a browser opens no page from a data: address): show it in an embed block, ${P("html")}, or give the link download="<name>" to hand it out as a file`):i.node.tagName==="img"&&i.how==="src"&&Ze(i.node)?t.push(`line ${c}: ${O(i)} is in an icon (.doc-icon) written as an icon is not read (its picker, the browser tab's icon): write it <div class="doc-icon"><img src="assets/<file>" alt=""></div>, in double quotes and with no other class`):(i.how!=="srcset"||i.largest)&&r.push({file:f,line:c}):t.push(`line ${c}: ${O(i)}: ${Qe(f)}`))}return{failures:t,embedded:r,unserved:a}}function ts({html:e,directory:n,tree:o=w(e)}){let{failures:s,embedded:t}=re({html:e,directory:n,tree:o});return[...new Set([...s,...tt(t,n)])]}function ss({html:e,directory:n,tree:o=w(e)}){let{embedded:s,unserved:t}=re({html:e,directory:n,tree:o});return{embedded:s.map(({file:r,line:a,icon:i=!1})=>({file:r,line:a,icon:i})),unserved:t}}function st(e,{slug:n,mode:o,directory:s}){let{use:t}=B(e),r=v(e.value);if(!t||!r||!E(r)||ne(e,t,r))return null;let a=/#.*$/.exec(e.value)?.[0]??"";if(o==="preview")return`${Ie(Ve(t,r),n,r)}${a}`;let i=N(s,r);return i&&`${i}${a}`}function ot(e,n,{mode:o,shown:s}){let[t]=n,{node:r,how:a,key:i}=t,c=(m,h="")=>({start:e.startOffset,end:e.endOffset,text:`${i}="${S(m)}"${h}`}),l=o==="preview"?` data-ge-${a}="${S(y(r,a)??"")}"`:"",d=(o==="preview"?[`data-ge-${a}`,`data-rs-${a}`].map(m=>r.sourceCodeLocation.attrs?.[m]).filter(Boolean):[]).map(m=>({start:m.startOffset,end:m.endOffset,text:""}));if(a==="srcset"){if(o==="export"){let h=n.find(C=>C.largest),$=h&&s(h);return $?[c(`${$} ${h.candidates[h.index].descriptor}`.trim())]:[]}let m=new Map(n.map(h=>[h.index,s(h)]));return[...m.values()].some(Boolean)?[c(t.candidates.map((h,$)=>[m.get($)??h.url,h.descriptor].filter(Boolean).join(" ")).join(", "),l),...d]:[]}if(a==="style"){let m=y(r,"style"),h=n.map($=>({...$.css,address:s($)})).filter($=>$.address).sort(($,C)=>C.start-$.start);for(let $ of h)m=`${m.slice(0,$.start)}${$.address}${m.slice($.end)}`;return h.length>0?[c(m)]:[]}let u=s(t);if(!u)return[];if(o==="preview"||B(t).use!=="link")return[c(u,l),...d];let p=v(t.value).slice(7),g=y(r,"download");if(g===void 0)return[c(u,` download="${S(p)}"`)];let b=r.sourceCodeLocation.attrs?.download;return[c(u),...g===""&&b?[{start:b.startOffset,end:b.endOffset,text:`download="${S(p)}"`}]:[]]}function nt(e,n){let o=[],s=0;for(let{start:t,end:r,text:a}of[...n].sort((i,c)=>i.start-c.start))t<s||(o.push(e.slice(s,t),a),s=r);return o.push(e.slice(s)),o.join("")}var os=(e,n,o=w(e))=>T(e,o,n);function ns(e,n){let o=[],s=new Map;for(let t of e){let r=n(t);typeof r=="string"&&(t.how==="css"?o.push({start:t.css.offset+t.css.start,end:t.css.offset+t.css.end,text:r}):t.place&&s.set(t.place,[...s.get(t.place)??[],{...t,address:r}]))}for(let[t,r]of s){let[{node:a,how:i,key:c,candidates:l}]=r,f=r[0].address;if(i==="srcset"){let d=new Map(r.map(u=>[u.index,u.address]));f=l.map((u,p)=>[d.get(p)??u.url,u.descriptor].filter(Boolean).join(" ")).join(", ")}else if(i==="style"){f=y(a,"style");for(let{css:d,address:u}of[...r].sort((p,g)=>g.css.start-p.css.start))f=`${f.slice(0,d.start)}${u}${f.slice(d.end)}`}o.push({start:t.startOffset,end:t.endOffset,text:`${c}="${S(f)}"`})}return o}function rs(e,{slug:n,mode:o="export",reportsDirectory:s=ze}){if(!/assets\//i.test(e.replace(/\sdata-ge-(?:src|href|icon)="[^"]*"/g,"")))return e;let t=w(e),r=se(e,t),a=We(n,s),i=f=>st(f,{slug:n,mode:o,directory:a}),c=[],l=new Map;for(let f of T(e,t))if(!oe(r,f))if(f.how==="css"){let d=i(f),u=f.css.offset;d&&c.push({start:u+f.css.start,end:u+f.css.end,text:d})}else f.place&&l.set(f.place,[...l.get(f.place)??[],f]);for(let[f,d]of l)c.push(...ot(f,d,{mode:o,shown:i}));return nt(e,c)}export{bt as a,gt as b,Et as c,Ct as d,Ut as e,At as f,ts as g,ss as h,nt as i,os as j,ns as k,rs as l};
|
|
2
|
+
import{f as A}from"./chunk-U5XL7D6A.mjs";import{a as w,c as U}from"./chunk-HYMEEXKN.mjs";import he from"node:fs";import $e from"node:path";import{reportsDirectory as we}from"../browser/shared/paths.mjs";import{assetFile as be,assetProblem as ge,embedFile as ke}from"../browser/shared/media.mjs";import{attr as H,hasClass as xe,walk as ye}from"../browser/shared/html-tree.mjs";import _ from"node:fs";import ie from"node:path";import{attr as ae,hasClass as ce,walk as fe}from"../browser/shared/html-tree.mjs";import{MEDIA_ROUTES as le,mediaTypeOf as de,mediaUrl as ue}from"../browser/shared/media.mjs";import{documentDirectory as pe}from"../browser/shared/workspace.mjs";function k(e,n,o){let s=null;return fe(e,t=>{!s&&t.tagName===n&&ce(t,o)&&(s=t)}),s}function N(e,n){let o=ie.join(e,n);return _.statSync(o,{throwIfNoEntry:!1})?.isFile()?`data:${de(n)};base64,${_.readFileSync(o).toString("base64")}`:null}function me(e,{attribute:n,route:o,slug:s,mode:t,reportsDirectory:r}){if(!le[o](e))return null;if(t==="preview")return`${n}="${ue(o,s,e)}" data-ge-${n}="${e}"`;let a=N(pe(s,r),e);return a&&`${n}="${a}"`}function x(e,n,{attribute:o,route:s,slug:t,mode:r,reportsDirectory:a}){let i=n.map(f=>({place:f.sourceCodeLocation?.attrs?.[o],value:ae(f,o)})).filter(({place:f})=>f).sort((f,d)=>f.place.startOffset-d.place.startOffset),c=[],l=0;for(let{place:f,value:d}of i){let u=me(d,{attribute:o,route:s,slug:t,mode:r,reportsDirectory:a});u===null||f.startOffset<l||(c.push(e.slice(l,f.startOffset),u),l=f.endOffset)}return c.push(e.slice(l)),c.join("")}function D(e){let n=[];return ye(e,o=>{let s=o.tagName==="figure"&&xe(o,"doc-embed")?k(o,"iframe","doc-embed-frame"):null;s&&n.push(s)}),n}function bt(e,{slug:n,mode:o="export",reportsDirectory:s=we}){return e.includes("doc-embed")?x(e,D(w(e)),{attribute:"src",route:"embed",slug:n,mode:o,reportsDirectory:s}):e}var I=(e,n=w(e))=>D(n).map(o=>o.sourceCodeLocation.startOffset);function gt({html:e,directory:n,tree:o=w(e)}){let s=[];for(let t of D(o)){let r=`line ${t.sourceCodeLocation.startLine}`,a=H(t,"src")??"",i=H(t,"sandbox"),c=/^https:\/\/[^\s"]+$/.test(a),l=!c&&!/^[a-z][a-z0-9+.-]*:/i.test(a)&&!be(a)?ge(a):null;l?s.push(`${r}: an embed's frame (${a.slice(0,80)}): ${l} (an HTML or PDF file; or a web page, https://\u2026)`):!c&&!ke(a)?s.push(`${r}: an embed's frame (${a.slice(0,80)}) shows a web page (https://\u2026, never http) or an HTML or PDF file of the document's folder (assets/<file>)`):!c&&!he.existsSync($e.join(n,a))?s.push(`${r}: the embed's file ${a} is not in the document's folder`):(c||/\.html?$/i.test(a))&&i===void 0?s.push(`${r}: an embed's frame (${a.slice(0,80)}) is sandboxed: sandbox="allow-scripts allow-popups \u2026"`):!c&&/\.html?$/i.test(a)&&/\ballow-same-origin\b/.test(i)?s.push(`${r}: an embedded HTML file (${a}) keeps its own origin: its sandbox has no allow-same-origin`):!c&&/\.pdf$/i.test(a)&&i!==void 0&&s.push(`${r}: an embedded PDF (${a}) is sandboxed, and a sandboxed frame shows no PDF: take its sandbox attribute off`)}return[...new Set(s)]}import Oe from"node:fs";import Se from"node:path";import{reportsDirectory as ve}from"../browser/shared/paths.mjs";import{assetFile as Fe,assetProblem as Le}from"../browser/shared/media.mjs";import{attr as z,hasClass as Ee,walk as Ce}from"../browser/shared/html-tree.mjs";function F(e,n=w(e)){let o=[];return Ce(n,s=>{s.tagName==="figure"&&Ee(s,"doc-file")&&o.push({node:s,link:k(s,"a","doc-file-link")})}),o}function Et(e,{slug:n,mode:o="export",reportsDirectory:s=ve}){if(!e.includes("doc-file"))return e;let t=F(e).flatMap(({link:r})=>r?[r]:[]);return x(e,t,{attribute:"href",route:"file",slug:n,mode:o,reportsDirectory:s})}function Ct({html:e,directory:n,tree:o=w(e)}){let s=[];for(let{link:t}of F(e,o)){if(!t)continue;let r=`line ${t.sourceCodeLocation?.startLine}`,a=z(t,"href")??"";Fe(a)?Oe.existsSync(Se.join(n,a))||s.push(`${r}: the file block's file ${a} is not in the document's folder`):s.push(`${r}: a file block's file (${a.slice(0,80)}): ${Le(a)} (<a class="doc-file-link" href="assets/<file>" download="<name>">)`),z(t,"download")||s.push(`${r}: a file block's link (${a.slice(0,80)}) says the name to save it as: download="<name>"`)}return[...new Set(s)]}import Ne from"node:fs";import De from"node:path";import{reportsDirectory as Re}from"../browser/shared/paths.mjs";import{assetProblem as W,imageFile as K}from"../browser/shared/media.mjs";import{attr as R,hasClass as Me,walk as M}from"../browser/shared/html-tree.mjs";var je={"doc-image":"image","doc-bookmark":"bookmark"},Te={image:"an image's picture",bookmark:"a bookmark's icon or cover"},Pe=/doc-(?:image|bookmark|link-mention-icon)/;function G(e){let n=[];return M(e,o=>{let s=o.tagName==="figure"&&(R(o,"class")??"").split(/\s+/).map(t=>je[t]).find(Boolean);s&&n.push({node:o,kind:s})}),n}function L(e,n=w(e)){let o=new Map,s=(t,r,a)=>{let i=t.sourceCodeLocation;i&&!o.has(i.startOffset)&&o.set(i.startOffset,{at:i.startOffset,line:i.startLine,node:t,what:r,kind:a,mention:a==="mention"})};for(let{node:t,kind:r}of G(n))M(t,a=>a.tagName==="img"&&s(a,Te[r],r));return M(n,t=>t.tagName==="img"&&Me(t,"doc-link-mention-icon")&&s(t,"a link's icon","mention")),[...o.values()].sort((t,r)=>t.at-r.at)}function Ut(e,{slug:n,mode:o="export",reportsDirectory:s=Re}){return Pe.test(e)?x(e,L(e).map(({node:t})=>t),{attribute:"src",route:"asset",slug:n,mode:o,reportsDirectory:s}):e}function At({html:e,directory:n,tree:o=w(e)}){let s=[];for(let{line:t,node:r,what:a,mention:i}of L(e,o)){let c=R(r,"src");i&&!K(c)?s.push(`line ${t}: a link's icon (${(c??"").slice(0,80)}): ${W(c,{picture:!0})}; or write an empty <span class="doc-link-mention-icon"></span>`):c===void 0?s.push(`line ${t}: ${a} has no src: <img src="assets/<file>" alt="\u2026">`):K(c)?Ne.existsSync(De.join(n,c))||s.push(`line ${t}: ${a} ${c} is not in the document's folder`):s.push(`line ${t}: ${a} (${c.slice(0,80)}): ${W(c,{picture:!0})}`)}for(let{node:t,kind:r}of G(o)){let a=r==="bookmark"?k(t,"a","doc-bookmark-card"):null,i=a&&R(a,"href");a&&!/^https?:\/\/[^\s"]+$/.test(i??"")&&s.push(`line ${a.sourceCodeLocation?.startLine}: a bookmark's link (${(i??"").slice(0,80)}) is a web address: <a class="doc-bookmark-card" href="https://\u2026">`)}return[...new Set(s)]}import ee from"node:fs";import te from"node:path";import{escapeAttribute as S}from"../browser/shared/escape.mjs";import{attr as y,hasClass as Be,walk as Ue}from"../browser/shared/html-tree.mjs";import{cssReferences as q}from"../browser/shared/css-references.mjs";import{assetFile as Ae,assetProblem as _e,imageFile as He,mediaUrl as Ie,referencedFile as v}from"../browser/shared/media.mjs";import{reportsDirectory as ze}from"../browser/shared/paths.mjs";import{documentDirectory as We}from"../browser/shared/workspace.mjs";var Y=/^\s*(?:\.\/)?assets\//i,J=1e6;function Ke(e){let n=[],o=0;for(;o<e.length;){for(;o<e.length&&/[\s,]/.test(e[o]);)o++;if(o>=e.length)break;let s=o;for(;s<e.length&&!/\s/.test(e[s]);)s++;let t=e.slice(o,s),r="";if(t.endsWith(","))t=t.replace(/,+$/,""),o=s;else{let i=s;for(let c=0;i<e.length&&(e[i]!==","||c>0);i++)e[i]==="("?c++:e[i]===")"&&c--;r=e.slice(s,i).trim(),o=i+1}let a=r.split(/\s+/).find(i=>/^\d*\.?\d+[wx]$/i.test(i));n.push({url:t,descriptor:r,size:a?parseFloat(a):1,wide:/w$/i.test(a??"")})}return n}function Ge(e){let n=e.filter(o=>o.wide);return(n.length>0?n:e).reduce((o,s)=>!o||s.size>o.size?s:o,null)}var qe=new Set(["body","table","thead","tbody","tfoot","tr","td","th"]);function T(e,n,o=s=>Y.test(s)){let s=[],t=r=>{o(r.value,r.node)&&s.push({...r,value:r.value.trim(),written:r.css?.written})};return Ue(n,r=>{let a=r.sourceCodeLocation;if(a){for(let{name:i,value:c,prefix:l}of r.attrs){let f=l?`${l}:${i}`:i,d=a.attrs?.[f],u={node:r,how:i,key:f,place:d,line:d?.startLine??a.startLine};if(i==="src"||i==="href"||i==="poster"||i==="data"&&r.tagName==="object"||i==="background"&&qe.has(r.tagName))t({...u,value:c});else if(i==="srcset"){let p=Ke(c),g=Ge(p.filter(b=>Y.test(b.url)));p.forEach((b,m)=>t({...u,value:b.url,candidates:p,index:m,largest:b===g}))}else if(i==="style")for(let p of q(c))t({...u,value:p.value,css:p})}if(r.tagName==="style")for(let i of r.childNodes){if(i.nodeName!=="#text"||!i.sourceCodeLocation)continue;let{startOffset:c,endOffset:l}=i.sourceCodeLocation;for(let f of q(e.slice(c,l)))t({node:r,how:"css",value:f.value,line:U(e,c+f.index),css:{...f,offset:c}})}}}),s}function se(e,n){let o=new Map;for(let{at:s,kind:t}of L(e,n))o.set(s,{attribute:"src",owner:"block",icon:t!=="image"});for(let{link:s}of F(e,n))s&&o.set(s.sourceCodeLocation.startOffset,{attribute:"href",owner:"block"});for(let s of I(e,n))o.set(s,{attribute:"src",owner:"block"});for(let s of A(e))o.set(s,{attribute:"src",owner:"icon"});return o}var oe=(e,n)=>{let o=e.get(n.node.sourceCodeLocation.startOffset);return o?.attribute===n.how?o:null},Ye=new Set(["img","input","video","audio","source","track"]),Q="an export holds no stylesheet of the folder (the addresses in one are read from its own place): put its rules in the page's <style>",V=e=>(y(e,"rel")??"").toLowerCase().split(/\s+/),j=/\.html?$/i,Je={html:'src="assets/<file>.html" sandbox="allow-scripts"',pdf:'src="assets/<file>.pdf"'},P=e=>`<figure class="doc-embed doc-embed--file"><iframe class="doc-embed-frame" ${Je[e]}></iframe><figcaption></figcaption></figure>`,X=`its frame with no sandbox (a sandboxed one shows no PDF): ${P("pdf")}`,Z='show a picture with <img src="assets/<file>">, a file to save with a link, <a href="assets/<file>" download="<name>">';function B({node:e,how:n,css:o,value:s}){let t=e.tagName;if(n==="style"||n==="css")return o.kind==="import"?{not:Q}:{use:"shown"};if(n==="srcset"&&(t==="img"||t==="source")||n==="poster"&&t==="video"||n==="src"&&Ye.has(t)||n==="background")return{use:"shown"};if(n==="src"&&t==="iframe"){let r=v(s)??"";return j.test(r)?{use:"frame"}:/\.pdf$/i.test(r)?{not:`a PDF shows in an embed block alone (the kit hands its file to the browser's PDF viewer, in the preview and in an export): make it one, ${X}`}:{not:`a frame shows a page of the folder (an HTML file), not this file, which the preview would hand out for saving: ${Z}`}}if(n==="href"&&(t==="a"||t==="area"))return{use:"link"};if(n==="href"&&(t==="image"||t==="link"&&V(e).some(r=>r.endsWith("icon"))))return{use:"shown"};if(t==="object"||t==="embed"){let r=v(s)??"";return{not:`an export's policy loads no plugin content (<object>, <embed>): ${/\.pdf$/i.test(r)?`show a PDF in an embed block, ${X}`:j.test(r)?`show a page in an embed block, ${P("html")}`:Z}`}}return t==="script"?{not:"an export runs the page's own scripts alone: put the code in the page's <script>"}:t==="link"&&V(e).includes("stylesheet")?{not:Q}:{not:"an export holds a file of the folder as a picture, a font, a video or audio, a link or a frame, not there"}}var E=e=>e.startsWith("assets/")&&Ae(e),Qe=e=>_e(e)??`the folder is assets/, in lowercase: write it so (assets/${e.slice(7)})`,ne=(e,n,o)=>n==="link"&&j.test(o)&&y(e.node,"download")===void 0,Ve=(e,n)=>e==="frame"?"embed":e==="shown"&&He(n)?"asset":"file",Xe=(e,n)=>!!ee.statSync(te.join(e,n),{throwIfNoEntry:!1})?.isFile(),O=({node:e,how:n,value:o,written:s})=>({srcset:`<${e.tagName} srcset="\u2026 ${o} \u2026">`,style:`${s} in the style of <${e.tagName}>`,css:`${s} in <style>`})[n]??`<${e.tagName} ${n}="${o}">`,Ze=e=>{for(let n=e.parentNode;n;n=n.parentNode)if(n.tagName&&Be(n,"doc-icon"))return!0;return!1},et=e=>e.length>1?`${e.slice(0,-1).join(", ")} and ${e.at(-1)}`:`${e[0]}`;function tt(e,n){let o=new Map;for(let{file:a,line:i,owned:c}of e){let l=o.get(a)??o.set(a,{lines:[],owned:!1}).get(a);c?l.owned=!0:l.lines.push(i)}let s=0,t=[];for(let[a,{lines:i,owned:c}]of o){let l=c?i.length:i.length-1;if(l<1)continue;let f=l*Math.ceil(ee.statSync(te.join(n,a)).size/3)*4;s+=f;let d=i.length===1?"once":i.length===2?"twice":`${i.length} times`;t.push({bytes:f,said:`${a} ${d}${c?" besides a media block's or the icon's":""} (line${new Set(i).size>1?"s":""} ${et([...new Set(i)])})`})}if(s<=J)return[];let r=t.sort((a,i)=>i.bytes-a.bytes).map(({said:a})=>a).join(", ");return[`files embedded more than once make an export ${s.toLocaleString("en-US")} bytes bigger, over the ${J.toLocaleString("en-US")} bytes the copies outside the media blocks may add: ${r}; show each fewer times (a picture, a link or a frame holds a copy of its own each time it is written), or, for a CSS background (url() in a <style> or a style attribute), name it once in the page's <style> (--picture: url(assets/<file>)) and write var(--picture) where it shows`]}function re({html:e,directory:n,tree:o}){let s=se(e,o),t=[],r=[],a=[];for(let i of T(e,o)){let{line:c}=i,l=oe(s,i),f=v(i.value),d=f!==null&&Xe(n,f);if(d&&!E(f)&&a.push({file:f,line:c}),l?.owner==="block"){d&&E(f)&&r.push({file:f,line:c,owned:!0,icon:!!l.icon});continue}if(d||t.push(l?`line ${c}: the icon's image ${i.value} is not in the document's folder`:`line ${c}: ${O(i)} names a file that is not in the document's folder`),l){d&&r.push({file:f,line:c,owned:!0,icon:!0});continue}let{use:u,not:p}=B(i);p&&t.push(`line ${c}: ${O(i)}: ${p}`),!(!u||!d)&&(E(f)?ne(i,u,f)?t.push(`line ${c}: ${O(i)} opens an HTML file, which an export cannot (a browser opens no page from a data: address): show it in an embed block, ${P("html")}, or give the link download="<name>" to hand it out as a file`):i.node.tagName==="img"&&i.how==="src"&&Ze(i.node)?t.push(`line ${c}: ${O(i)} is in an icon (.doc-icon) written as an icon is not read (its picker, the browser tab's icon): write it <div class="doc-icon"><img src="assets/<file>" alt=""></div>, in double quotes and with no other class`):(i.how!=="srcset"||i.largest)&&r.push({file:f,line:c}):t.push(`line ${c}: ${O(i)}: ${Qe(f)}`))}return{failures:t,embedded:r,unserved:a}}function ts({html:e,directory:n,tree:o=w(e)}){let{failures:s,embedded:t}=re({html:e,directory:n,tree:o});return[...new Set([...s,...tt(t,n)])]}function ss({html:e,directory:n,tree:o=w(e)}){let{embedded:s,unserved:t}=re({html:e,directory:n,tree:o});return{embedded:s.map(({file:r,line:a,icon:i=!1})=>({file:r,line:a,icon:i})),unserved:t}}function st(e,{slug:n,mode:o,directory:s}){let{use:t}=B(e),r=v(e.value);if(!t||!r||!E(r)||ne(e,t,r))return null;let a=/#.*$/.exec(e.value)?.[0]??"";if(o==="preview")return`${Ie(Ve(t,r),n,r)}${a}`;let i=N(s,r);return i&&`${i}${a}`}function ot(e,n,{mode:o,shown:s}){let[t]=n,{node:r,how:a,key:i}=t,c=(m,h="")=>({start:e.startOffset,end:e.endOffset,text:`${i}="${S(m)}"${h}`}),l=o==="preview"?` data-ge-${a}="${S(y(r,a)??"")}"`:"",d=(o==="preview"?[`data-ge-${a}`,`data-rs-${a}`].map(m=>r.sourceCodeLocation.attrs?.[m]).filter(Boolean):[]).map(m=>({start:m.startOffset,end:m.endOffset,text:""}));if(a==="srcset"){if(o==="export"){let h=n.find(C=>C.largest),$=h&&s(h);return $?[c(`${$} ${h.candidates[h.index].descriptor}`.trim())]:[]}let m=new Map(n.map(h=>[h.index,s(h)]));return[...m.values()].some(Boolean)?[c(t.candidates.map((h,$)=>[m.get($)??h.url,h.descriptor].filter(Boolean).join(" ")).join(", "),l),...d]:[]}if(a==="style"){let m=y(r,"style"),h=n.map($=>({...$.css,address:s($)})).filter($=>$.address).sort(($,C)=>C.start-$.start);for(let $ of h)m=`${m.slice(0,$.start)}${$.address}${m.slice($.end)}`;return h.length>0?[c(m)]:[]}let u=s(t);if(!u)return[];if(o==="preview"||B(t).use!=="link")return[c(u,l),...d];let p=v(t.value).slice(7),g=y(r,"download");if(g===void 0)return[c(u,` download="${S(p)}"`)];let b=r.sourceCodeLocation.attrs?.download;return[c(u),...g===""&&b?[{start:b.startOffset,end:b.endOffset,text:`download="${S(p)}"`}]:[]]}function nt(e,n){let o=[],s=0;for(let{start:t,end:r,text:a}of[...n].sort((i,c)=>i.start-c.start))t<s||(o.push(e.slice(s,t),a),s=r);return o.push(e.slice(s)),o.join("")}var os=(e,n,o=w(e))=>T(e,o,n);function ns(e,n){let o=[],s=new Map;for(let t of e){let r=n(t);typeof r=="string"&&(t.how==="css"?o.push({start:t.css.offset+t.css.start,end:t.css.offset+t.css.end,text:r}):t.place&&s.set(t.place,[...s.get(t.place)??[],{...t,address:r}]))}for(let[t,r]of s){let[{node:a,how:i,key:c,candidates:l}]=r,f=r[0].address;if(i==="srcset"){let d=new Map(r.map(u=>[u.index,u.address]));f=l.map((u,p)=>[d.get(p)??u.url,u.descriptor].filter(Boolean).join(" ")).join(", ")}else if(i==="style"){f=y(a,"style");for(let{css:d,address:u}of[...r].sort((p,g)=>g.css.start-p.css.start))f=`${f.slice(0,d.start)}${u}${f.slice(d.end)}`}o.push({start:t.startOffset,end:t.endOffset,text:`${c}="${S(f)}"`})}return o}function rs(e,{slug:n,mode:o="export",reportsDirectory:s=ze}){if(!/assets\//i.test(e.replace(/\sdata-ge-(?:src|href|icon)="[^"]*"/g,"")))return e;let t=w(e),r=se(e,t),a=We(n,s),i=f=>st(f,{slug:n,mode:o,directory:a}),c=[],l=new Map;for(let f of T(e,t))if(!oe(r,f))if(f.how==="css"){let d=i(f),u=f.css.offset;d&&c.push({start:u+f.css.start,end:u+f.css.end,text:d})}else f.place&&l.set(f.place,[...l.get(f.place)??[],f]);for(let[f,d]of l)c.push(...ot(f,d,{mode:o,shown:i}));return nt(e,c)}export{bt as a,gt as b,Et as c,Ct as d,Ut as e,At as f,ts as g,ss as h,nt as i,os as j,ns as k,rs as l};
|
|
@@ -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 a,e as b,f as c,g as d}from"./chunk-
|
|
2
|
+
import{d as a,e as b,f as c,g as d}from"./chunk-W5NPH5UA.mjs";import"./chunk-ECZBLQKK.mjs";import"./chunk-E7656LR7.mjs";import"./chunk-TKWEX4FD.mjs";import"./chunk-A55HN5OK.mjs";import"./chunk-5L7RYZCL.mjs";export{a as commitEdits,c as revertedParts,d as revertedTexts,b as revertedUnits};
|
|
@@ -0,0 +1,15 @@
|
|
|
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 we,b as q,c as X,f as be,g as L,h as ke,i as Q,l as ye,m as xe}from"./chunk-HX4DLE3J.mjs";import{a as gt}from"./chunk-ZTHICSSF.mjs";import{b as le,c as $t,e as K,f as de,i as fe,j as he,m as ue,n as pe,o as me,p as ge,q as $e,r as wt}from"./chunk-FJLM7YE7.mjs";import{a as pt}from"./chunk-PAREWQGB.mjs";import{a as te,b as ee,c as oe,d as se,e as ne,f as ie,g as ae,h as re,l as ce}from"./chunk-BFJGHSQN.mjs";import{b as mt,c as Yt,d as qt,e as Xt,g as Qt}from"./chunk-U5XL7D6A.mjs";import{a as w,b as Vt,c as Zt}from"./chunk-HYMEEXKN.mjs";import{g as T,j as Kt,l as Gt,m as Jt}from"./chunk-TKWEX4FD.mjs";import{existsSync as bo,readFileSync as ki,readdirSync as yi}from"node:fs";import S from"node:fs/promises";import N from"node:path";function Se(t){if(!t||!Array.isArray(t.lines))throw new Error("diff: lines must be an array.");t.lines.forEach(e=>{if(!e||!["added","removed","unchanged"].includes(e.type)||typeof e.content!="string"||/[\r\n]/.test(e.content))throw new Error("diff: each line needs a valid type and single-line content.");if(e.lineNumber!=null&&(!Number.isInteger(e.lineNumber)||e.lineNumber<1))throw new Error("diff: lineNumber must be a positive integer.")})}import{BODY as kt,isInstance as Wo}from"../browser/shared/components/index.mjs";import{ATTRIBUTE as Bo}from"../browser/shared/components/installed.mjs";import{attr as F,elementsOf as Ne,hasClass as Ho,walk as yt}from"../browser/shared/html-tree.mjs";import{CHART_DATA as Ko,CHART_KEY as Go,CHART_SOURCE as z,VIEW_FROM as tt,cellWords as Jo,rowsReading as ve,tableRows as Vo}from"../browser/shared/table-chart.mjs";var Zo=t=>t.tagName==="script"&&(F(t,"type")??"").trim().toLowerCase()==="application/json",Oe=t=>t.nodeName==="#text"?t.value:(t.childNodes??[]).map(Oe).join("");function Yo(t){let e=t;for(;e&&e.tagName!=="figure";)e=e.parentNode;let s=e?Ne(e).find(o=>/^h[2-4]$/.test(o.tagName)):null;return s?Jo(Oe(s)):""}function Ee(t,e,s=w(t)){let o=[];return yt(s,n=>{let i=e(n);if(i===void 0||!n.sourceCodeLocation)return;let a=n.childNodes.find(Zo);o.push({type:i,line:n.sourceCodeLocation.startLine,text:a?a.childNodes.map(c=>c.value??"").join(""):null,source:F(n,Ko),tag:n.tagName,holder:n.parentNode?.tagName,title:Yo(n)})},kt),o}var qo=t=>t.tagName==="ol"&&F(t,"data-doc-chart")==="flow",et=(t,e)=>Ee(t,s=>qo(s)?void 0:F(s,"data-doc-chart"),e),Xo=t=>Ee(t,e=>Ho(e,"doc-diff")?"diff":void 0);function G(t){let e=new Map;return yt(t,s=>{let o=F(s,z);if(o===void 0||!s.sourceCodeLocation)return;(e.get(o)??e.set(o,[]).get(o)).push({line:s.sourceCodeLocation.startLine,offset:s.sourceCodeLocation.startOffset,table:Ne(s).find(i=>i.tagName==="table")??null})},{...kt,inTemplates:!1}),e}function xt(t,e){let s=e.get(t)??[];if(s.length===0)return{error:`no table's frame carries ${z}="${t}", so the chart has nothing to draw: put the table back, or delete the card`};if(s.length>1)return{error:`${s.length} tables carry ${z}="${t}" (lines ${s.map(({line:c})=>c).join(", ")}): a key names one table (the chart draws the first); take it off the copies`};let[{line:o,table:n}]=s;if(!n)return{error:`the frame carrying ${z}="${t}" (line ${o}) holds no table`};let i=gt(n),a=Vo(i);return a.error?{error:`its table (line ${o}) ${a.error}`}:{...a,line:o,cells:i}}function St(t){let e=[t,...L(t).filter(({files:n})=>n.includes("kit.js")).map(n=>Q(n,"kit.js")??"")].join(`
|
|
3
|
+
`),s=new Set([...e.matchAll(/DocCharts\.define\(\s*(["'`])([a-z][a-z0-9-]*)\1/g)].map(n=>n[2])),o=new Set([...e.matchAll(/DocCharts\.define\(\s*(["'`])([^"'`\n]*)\1/g)].map(n=>n[2]).filter(n=>!s.has(n)));return{defined:s,misnamed:o}}function Nt(t){let e=w(t),s=[],{defined:o,misnamed:n}=St(t),i=null;for(let{type:a,line:c,text:l,source:r,tag:d,holder:f}of et(t,e)){let h=`data-doc-chart="${a}" (line ${c})`;if(d==="table"){s.push(f==="figure"?`${h} is on a table inside a <figure>: the chart's card is a figure of its own, so write the table outside it, its <caption> the chart's title`:`${h} is on a table the tools leave as written (inside a whole block, an element with a class of the document's own, a cell): a chart is drawn from a table outside one`);continue}if(n.has(a)){s.push(`${h}: the document's script defines "${a}" with DocCharts.define, which refuses that name: a chart type's name is lowercase letters, digits and hyphens, a letter first ("interval", "ci-plot"); rename it in both places`);continue}if(!o.has(a)){s.push(`${h}: the document's script does not define "${a}": define it once in the document's <script> with DocCharts.define("${a}", ({ host, data, tokens, width, height }) => { \u2026 }) (references/writing-html.md, "Figures and charts")`);continue}if(r!==void 0){if(l!==null){s.push(`${h}: a chart drawn from a table takes its data from the table: take its <script type="application/json"> out`);continue}let u=xt(r,i??=G(e));u.error&&s.push(`${h}: ${u.error}`);continue}if(l===null){s.push(`${h} needs its data in a <script type="application/json"> child`);continue}try{JSON.parse(l)}catch(u){s.push(`${h}: its data is not valid JSON (${u.message})`)}}s.push(...Le(e,i??=G(e)).failures);for(let{line:a,text:c}of Xo(t)){if(c===null)continue;let l=`.doc-diff (line ${a})`;try{Se(JSON.parse(c))}catch(r){s.push(`${l}: ${r instanceof SyntaxError?`its options are not valid JSON (${r.message})`:r.message}`)}}return s}function Te(t,{written:e=t}={}){let s=w(t),o=[],{defined:n}=St(t),i=null,a=null;for(let{type:c,line:l,text:r,source:d,title:f,tag:h}of et(t,s)){if(d===void 0||h==="table"||r!==null||!n.has(c))continue;let u=`data-doc-chart="${c}" (line ${l})`;if(!f){a??=new Set(e===t?[]:et(e).map(k=>k.source).filter(k=>k!==void 0));let b=e!==t&&!a.has(d);o.push(`${u}: this chart card has no title: ${b?"write a <caption> on its table (the one with data-doc-chart), which becomes the card's h3":"write an h3 in the card's figure, before the chart"}`)}let m=xt(d,i??=G(s));if(m.error)continue;let{blank:p,twice:g}=ve(m.cells,m.data);p&&o.push(`${u}: its table's header (line ${m.line}) has a cell with no words, so that column's values are keyed "" in data: write the column's name there`),g.length>0&&o.push(`${u}: its table's header (line ${m.line}) names ${g.map(b=>`"${b}"`).join(", ")} twice, so data keeps the later column's value under it: give each column a name of its own`)}return o.push(...Le(s,i??=G(s)).notes),o}var bt=500;function Le(t,e){let s=[],o=[],n=T().packages;return yt(t,i=>{let a=F(i,tt);if(a===void 0||!i.sourceCodeLocation)return;let c=F(i,Bo),l=`${c??i.tagName} (line ${i.sourceCodeLocation.startLine})`;if(!Wo(i))return void s.push(`<${i.tagName}> (line ${i.sourceCodeLocation.startLine}) carries ${tt}="${a}", which only a view of a table carries: an instance of a custom block (<div data-doc-component="<scope>/<name>">) whose block's needs hold "tables"; take it off`);if(!Go.test(a))return void s.push(`${l}: ${tt}="${a}" is no key: a letter, then letters, digits, "_" or "-", 32 at most, as the table's frame writes it in ${z}`);let r=e.get(a)??[];if(r.length===0)return void s.push(`${l}: no table's frame carries ${z}="${a}", so the view has no table to read: put the table back, or delete the view`);if(r.length>1)return void s.push(`${l}: ${r.length} tables carry ${z}="${a}" (lines ${r.map(({line:g})=>g).join(", ")}): a key names one table (the view reads the first); take it off the copies`);let[{line:d,offset:f,table:h}]=r;if(!h)return void s.push(`${l}: the frame carrying ${z}="${a}" (line ${d}) holds no table`);i.sourceCodeLocation.startOffset<f&&o.push(`${l} stands before the table it reads (${z}="${a}", line ${d}): it works there, but each block's writing.md writes the table first and the view after it, as its example does: move the view below the table, unless the document is meant to open on it`);let u=n.get(c)?.needs;u&&!u.includes("tables")&&o.push(`${l} carries ${tt}="${a}", but its block's needs hold no "tables", so it reads no table: add "tables" to needs in its component.json, or take the key off`);let m=gt(h);m.merged&&o.push(`${l}: its table (line ${d}) has merged cells, which no view reads, so the view shows nothing of it: write each value in its own cell`);let p=m.names?m.rows.length:Math.max(0,m.rows.length-1);p>bt&&o.push(`${l}: its table (line ${d}) has ${p} rows: every view of a table reads it again as it is typed in, and past ${bt} rows that slows typing in it; split it, or keep what a view shows to ${bt} rows`)},kt),{failures:s,notes:o}}function Ae(t){let e=w(t),s=[],o=[],{defined:n}=St(t),i=null,a=(c,l)=>`${c} ${l}${c===1?"":"s"}`;for(let{type:c,line:l,text:r,source:d,tag:f}of et(t,e)){if(d===void 0||f==="table"||r!==null||!n.has(c))continue;let h=xt(d,i??=G(e));if(h.error)continue;let{rows:u,columns:m,foot:p,extra:g}=ve(h.cells,h.data),b=`data-doc-chart="${c}" (line ${l})`,k=[a(u,"row")];for(let{name:x,numbers:v,words:E,empty:H}of m){let R=v+E+H,Y=v===R&&R>0?"numbers":E===R&&R>0?"words":[v&&a(v,"number"),E&&`${E} as words`,H&&`${H} empty (null)`].filter(Boolean).join(", ")||"no rows";k.push(`"${x}": ${Y}`),v>0&&E>0&&o.push(`${b}: its table's column "${x}" (line ${h.line}) reads as numbers in ${a(v,"row")} and as words in ${E}: write each of its cells as one number (an empty cell, "\u2014" or "n/a" for none: null in data), or, for a column of words, data-sort-type="text" on its header cell`)}p>0&&o.push(`${b}: its table's <tfoot> (line ${h.line}) holds ${a(p,"row")} the chart leaves out, and a table with a <tfoot> has no table tools in the preview: keep a total out of a table you chart and say it in the text`),g>0&&o.push(`${b}: ${a(g,"row")} of its table (line ${h.line}) ${g===1?"has":"have"} cells past the header, which the chart does not read: give each column a header cell`),s.push(`${c} (line ${l}) reads its table (line ${h.line}): ${k.join("; ")}`)}return{readings:s,notes:o}}import{BODY as xi,componentOf as Si,matchesNode as ko}from"../browser/shared/components/index.mjs";import{FLOW as Ni}from"../browser/shared/components/list.mjs";import{attr as O,elementsOf as yo,walk as M}from"../browser/shared/html-tree.mjs";import{GLYPH_SETS as vi,ICON_COLORS as xo,glyphOf as Oi,glyphValue as Ei,iconKind as Pt,iconMarkup as Ti,iconValueOf as Li}from"../browser/shared/emoji/icon-value.mjs";import Qo from"node:vm";import{LINE_START as nt,lineStart as ts}from"../browser/shared/code-lines.mjs";import{BODY as De,COMPONENTS as es,FLOWS as os,instanceSlots as ss,instancesOf as ns,isInstance as D,isSlot as _e,matchesNode as P,ownSlots as is,partOf as Tt,vocabulary as as}from"../browser/shared/components/index.mjs";import{ATTRIBUTE as C,INSTANCE as rs,PACKAGE_ID as it,SCHEMA as vt,SLOT as I,schemaAhead as cs}from"../browser/shared/components/installed.mjs";import{packageScript as ls}from"../browser/shared/export-wrap.mjs";import{asDocName as ds,kitNamespace as fs}from"../browser/shared/old-names.mjs";import{shortSheets as hs}from"../browser/shared/components/sheets.mjs";import{attr as y,curlyQuoted as us,hasClass as ps,walk as J}from"../browser/shared/html-tree.mjs";var{authoring:st,runtime:Ce}=as(),ms="input, select, textarea, button, details, table",at=t=>t.sourceCodeLocation?.startLine,$=t=>at(t)?` (line ${at(t)})`:"";function ze(t){let e=(o,n)=>{let i=Array.from({length:n.length+1},(a,c)=>c);for(let a=1;a<=o.length;a++){let c=i[0];i[0]=a;for(let l=1;l<=n.length;l++){let r=i[l];i[l]=Math.min(i[l]+1,i[l-1]+1,c+(o[a-1]===n[l-1]?0:1)),c=r}}return i[n.length]},[s]=[...st.keys()].filter(o=>o.startsWith(t.slice(0,7))).map(o=>[o,e(t,o)]).sort((o,n)=>o[1]-n[1]);return s&&s[1]<=3?` (${s[0]}?)`:""}function gs(t,e,s){let{part:o,property:n,min:i}=t.shares,a=new RegExp(`(?:^|;)\\s*${n}\\s*:\\s*([^;]*)`),c=s.map(f=>a.exec(y(f,"style")??"")?.[1].trim()??null),l=c.filter(f=>f!==null);if(l.length===0)return[];let r=`${t.id}${$(e)}`;return l.length<c.length?[`${r}: ${n} on ${l.length} of its ${c.length} ${o}: write it on every one of them, or on none (equal widths)`]:l.map(Number).some(f=>!Number.isFinite(f)||f<i-1e-9||f>1)?[`${r}: ${n} is a share of the row, a number from ${Math.round(i*1e3)/1e3} to 1 (${l.join(", ")})`]:[]}var ot={"doc-dialog-header":'a detail card has no header: its content region (<div class="doc-dialog-content">) stands alone in its panel',"doc-dialog-title":"a detail card's title is an ordinary heading (<h3>), first in its content region","doc-dialog-close":"a detail card has no close button: Esc and a press outside it close it","data-doc-dialog-close":"a detail card has no close button: Esc and a press outside it close it","doc-section-header":"a section's title is a plain heading (<h2>) with an ordinary paragraph below it for the line that says what the section is: no <div> goes around them","doc-grid":'a card row is now columns: <div class="doc-columns"> holding one <div class="doc-column"> per card',"doc-grid-3":'a card row is now columns: <div class="doc-columns"> holding three <div class="doc-column">',"doc-lede":`write the line under the title as a paragraph of the header (an ordinary <p>), or as small text, <p class="doc-note"): the header's lines read as the body's paragraphs`,"doc-source":`write the line under the title as a plain paragraph of the header (an ordinary <p>), or as small text (<p class="doc-note">): the header's lines read as the body's paragraphs`,"doc-prose":"write the text straight in its flow (the page, a Sheet panel, a section, a panel, a column\u2026): it reads the same there","doc-prose-h1":"write an h1","doc-prose-h2":"write an h2","doc-prose-h3":"write an h3","doc-prose-h4":"write an h4","doc-state-grid":'put the groups side by side in columns (<div class="doc-columns">)',"doc-state-group":"write the group's title as a heading and its controls as blocks of their own in a column","doc-state-status":'write the line as small text, <p class="doc-note">',"doc-code-block":'a code block is <div class="doc-code"> holding its title (<div class="doc-code-title">) and the <pre><code>',"doc-code-card":'a code block is <div class="doc-code"> holding its title and its <pre>; a diff is <div class="doc-diff">',"doc-code-header":'write the title as <div class="doc-code-title">: the kit draws the rest of the header',"data-doc-diff":'a diff is <div class="doc-diff"> holding its title and its options as JSON (sdk/doc-code.d.ts)',"data-doc-diff-stats":"the kit shows a diff's counts in its header: remove it","doc-code--wrap":"a code block wraps its long lines by itself: remove it (doc-code--nowrap scrolls them instead)"},$s={[nt]:'write it on its <div class="doc-code">',"data-start":`write ${nt} on its <div class="doc-code">`,"data-line-numbers":'write it on its <div class="doc-code">',"data-folded-lines":'write it on its <div class="doc-code">',"data-title":'write the title in its <div class="doc-code-title">',"data-wrap":'for long lines that scroll, write class="doc-code doc-code--nowrap" on its <div class="doc-code">'};function ws(t){let e=[],s=t.tagName==="pre"?t.parentNode:t.tagName==="code"&&t.parentNode?.tagName==="pre"?t.parentNode.parentNode:null;if(s?.tagName&&P(s,".doc-code"))for(let[n,i]of Object.entries($s))y(t,n)!==void 0&&e.push(`${n}${$(t)} on the <${t.tagName}> of a code block does nothing: ${i}`);let o=t.tagName==="div"&&P(t,".doc-code")?y(t,nt):void 0;return o!==void 0&&ts(o)===null&&e.push(`${nt}="${o}"${$(t)}: the number of a code block's first line is a whole number from 1`),e}var Ie=os.join(", "),bs=t=>P(t.parentNode,Ie)||t.parentNode?.tagName==="div"&&!y(t.parentNode,"class")&&P(t.parentNode.parentNode,Ie);function ks(t,e){let s=[];J(e,n=>s.push(...us(t,n)));let o=n=>n.replace(/=(\s*)[“”]/,'=$1"').replace(/[“”]$/,'"');return s.map(({written:n,line:i},a)=>a===0?`line ${i}: attribute ${n} uses curly quotes (U+201C/U+201D), which HTML reads as part of the value: write straight quotes, ${o(n)}; an editor keeping a file's \u201C\u2026\u201D style may change them`:`line ${i}: attribute ${n} uses curly quotes too: write ${o(n)}`)}var je={details:"write a plain <details> without the class (its <summary>, then what it holds): the export makes it the kit's"},ys="write a <section> of no attribute straight in it for each tab, starting with its heading (<h2>\u2013<h4>), the tab's name, the rest its blocks, and nothing else: the export makes the kit's tabs",xs='a bookmark written the short way is a paragraph in a flow holding only <a class="doc-bookmark" href="https://\u2026">its title</a> (a title attribute its description, nothing else on it, words alone in it): the export makes the card';function Me(t){let e=[];return J(t,s=>{y(s,C)!==void 0&&e.push(s)},De),e}var Ss=t=>{let e=t.parentNode;for(;e&&!(D(e)||_e(e));)e=e.parentNode;return e??null};function Ns(t,e){let s=[];return J(t,o=>{let n=y(o,I);if(n===void 0)return;if(D(o))return void s.push(`${I}="${n}"${$(o)} on the instance itself: a slot is an element inside it`);if(!_e(o))return void s.push(`${I}${$(o)} on a <${o.tagName}>: a slot is a block-level <div> or <section>`);let i=Ss(o),a=i&&D(i)?e?.get(y(i,C)):null;if(!i||!D(i)||a&&Pe(i,a,o))return void s.push(`${I}="${n}"${$(o)} stands outside any instance's own markup: a slot is a part of a component package's instance, written in its template`);y(o,"data-block-id")!==void 0&&s.push(`${I}="${n}"${$(o)}: a slot is no block: it carries no data-block-id`)}),s}var vs=(t,e)=>{for(let s=e.parentNode;s;s=s.parentNode)if(s===t)return!0;return!1},Pe=(t,e,s)=>Object.values(e.parts??{}).filter(({edit:o})=>o==="text"||o==="data").some(({at:o})=>Tt(t,o).some(n=>vs(n,s))),Re=(t,e)=>is(t).filter(s=>!Pe(t,e,s)),Os=t=>t.flatMap(e=>D(e)?it.test(y(e,C))?[]:[`${C}="${y(e,C)}"${$(e)} names no custom block: write <scope>/<name>, the id of a custom block of the workspace's components/ folder`]:[`${C}${$(e)} on a <${e.tagName}>: an instance of a component is a block-level <div> or <section>`]);function Ue(t){let e=Me(t).filter(o=>D(o)&&it.test(y(o,C))),s=e.length>0?T():null;return e.flatMap(o=>{let n=y(o,C),i=s.packages.get(n);if(i&&!cs(y(o,vt),i.schema))return[];if(i)return[`line ${at(o)}: <${o.tagName} ${C}="${n}">: ${vt}="${y(o,vt)}" is past the ${i.schema??1} its package's manifest reads (schema): nothing can write it back, and the block shows read-only until the package reads it`];let a=s.problems.get(n)?.problem,c=a?`package ${n} does not load (${Kt("en",a)})`:`no package ${n} in this workspace (components/${n}/component.json)`;return[`line ${at(o)}: <${o.tagName} ${C}="${n}">: ${c}: the block shows what it holds, read-only, and moves, copies and deletes whole`]})}function Ot(t,e){let s=[];for(let{name:o,value:n}of t.attrs){if(ot[o]&&!st.has(o)){s.push(`${o}${$(t)} is gone: ${ot[o]}`);continue}if(o.startsWith("data-doc-")&&!st.has(o)&&s.push(Ce.has(o)?`${o}${$(t)} is the kit's to set: remove it`:`${o}${$(t)} is no attribute of the kit's${ze(o)}`),o==="class"){for(let i of n.split(/\s+/).filter(e))if(!st.has(i)){if(ot[i]){s.push(`class ${i}${$(t)} is gone: ${ot[i]}`);continue}s.push(Ce.has(i)?`class ${i}${$(t)} is the kit's to set: remove it`:`class ${i}${$(t)} is no class of the kit's${ze(ds(i))}: give a class of the document's own a name of its own (not doc-\u2026)`)}}}return s}var Fe=t=>t.startsWith("doc-");function Es(t){try{return new Qo.Script(ls(t),{filename:"kit.js"}),null}catch(e){let s=/^kit\.js:(\d+)/.exec(e.stack??"")?.[1];return{message:e.message,line:s?Number(s):null}}}var Et=new Map;function Ts(t){if(!t.files.includes("kit.js"))return null;if(Et.get(t.folder)?.stamp!==t.stamp){let e=Q(t,"kit.js"),s=e===null?null:Es(e),o=e===null?`${t.id}: its kit.js cannot be read`:s&&`${t.id}: its kit.js does not run: ${s.message}${s.line?` (line ${s.line})`:""}`;Et.set(t.folder,{stamp:t.stamp,failure:o})}return Et.get(t.folder).failure}function Lt(t,e=w(t),s=null){let o=ks(t,e),n=Me(e);o.push(...Os(n));let i=n.length>0?s??T():null,a=i?[...i.packages.values()]:[];i&&o.push(...L(t,i,e).map(Ts).filter(Boolean));for(let r of[...es,...a].filter(d=>d.match&&(d.parts||d.pairs)))for(let d of ns(e,r)){if(r.empty&&!(d.childNodes??[]).some(u=>u.tagName||u.nodeName==="#text"&&u.value.trim()))continue;let f=r.id==="sheets"?hs(d):null;if(f){o.push(`${r.id}${$(d)} has no tabs and is no short form: ${f.why??"it stands where no block does (in a whole block or a figure)"}; ${ys}`);continue}if(je[r.id]&&Object.values(r.parts??{}).some(u=>Tt(d,u.at).length<(u.optional?0:u.min??1))){o.push(`${r.id}${$(d)} carries the kit's class without the kit's parts: ${je[r.id]}`);continue}let h={};for(let[u,m]of Object.entries(r.parts??{})){if(m.edit==="flow"&&it.test(r.id)){let b=Re(d,r).filter(k=>y(k,I)===u);b.length===0&&!m.optional&&o.push(`${r.id}${$(d)} has no ${u} (${I}="${u}")`);for(let k of b.slice(1))o.push(`${r.id}${$(k)}: slot "${u}" twice`);h[u]=b.slice(0,1);continue}h[u]=Tt(d,m.at);let p=m.optional?0:m.min??1,g=m.max??1/0;h[u].length<p?o.push(`${r.id}${$(d)} has ${h[u].length===0?"no":`${h[u].length} of`} ${u} (${m.at.replace(":scope > ","")})${h[u].length>0?`, at least ${p}`:""}`):h[u].length>g&&o.push(`${r.id}${$(d)} has ${h[u].length} of ${u}, at most ${g}`)}if(r.only){let u=new Set(r.only.flatMap(m=>h[m]));for(let m of(d.childNodes??[]).filter(p=>p.tagName&&!u.has(p)))o.push(`${r.id}${$(d)} holds a <${m.tagName}>${$(m)}: only its ${r.only.join(", ")} (${r.only.map(p=>r.parts[p].at.replace(":scope > ","")).join(", ")}) go in it`)}if(r.shares&&o.push(...gs(r,d,h[r.shares.part])),it.test(r.id)){let u=Object.entries(r.parts??{}).filter(([,m])=>m.edit==="flow").map(([m])=>m);for(let m of Re(d,r).filter(p=>!u.includes(y(p,I))))o.push(`${r.id}${$(m)}: slot "${y(m,I)}" is no part of its manifest edited as flow`)}for(let{a:u,attrA:m,b:p,attrB:g}of r.pairs??[]){let b=h[u].map(x=>y(x,m)),k=h[p].map(x=>y(x,g));for(let x of new Set(b.filter((v,E)=>b.indexOf(v)!==E)))o.push(`${r.id}${$(d)}: ${u} "${x}" twice`);for(let x of b.filter(v=>!k.includes(v)))o.push(`${r.id}${$(d)}: ${u.replace(/s$/,"")} "${x}" has no ${p.replace(/s$/,"")} (${g}="${x}")`);for(let x of k.filter(v=>!b.includes(v)))o.push(`${r.id}${$(d)}: ${p.replace(/s$/,"")} "${x}" has no ${u.replace(/s$/,"")} (${m}="${x}")`)}}o.push(...Ns(e,i?.packages));let c=new Set,l=[];J(e,r=>{if(D(r)){let h=new Set(ss(r));o.push(...Ot(r,Fe)),J(r,u=>o.push(...Ot(u,Fe)),{stop:u=>h.has(u)});return}r.tagName==="pre"&&bs(r)&&o.push(`<pre>${$(r)} straight in the text: a code block is <div class="doc-code"> holding its title (<div class="doc-code-title">) and the <pre>`),o.push(...ws(r)),r.tagName==="a"&&ps(r,"doc-bookmark")&&o.push(`<a class="doc-bookmark">${$(r)} is no bookmark: ${xs}`),o.push(...Ot(r,fs));let d=y(r,"data-doc-bind");d!==void 0&&(d.trim()?P(r,ms)?r.tagName==="button"&&y(r,"value")===void 0?o.push(`data-doc-bind${$(r)} on a button without a value: give it the value a click chooses`):c.add(d.trim()):o.push(`data-doc-bind${$(r)} on a ${r.tagName}: only inputs, selects, textareas, buttons with a value, details and tables hold a key`):o.push(`data-doc-bind${$(r)} names no key`));let f=y(r,"data-doc-show");f!==void 0&&l.push([r,f])},De);for(let[r,d]of l){let f=d.split(":")[0].trim();!f||!d.includes(":")?o.push(`data-doc-show="${d}"${$(r)}: write key:value`):c.has(f)||o.push(`data-doc-show="${d}"${$(r)}: nothing binds "${f}" (data-doc-bind="${f}")`)}return o.push(...js(t,e)),o}var Ls=/(?<![\\$])\$(?=[^\s$])([^$]*?[^\s$\\])\$(?![$\d])/g,As=/(?:(?<![A-Za-z0-9_])[A-Za-z]|[)\]}])_[A-Za-z0-9{]/,Cs=t=>/[\\^]/.test(t)||!t.startsWith("{")&&As.test(t),zs=new Set(["head","code","pre","kbd","samp","script","style","template","textarea","noscript","svg","math","title","iframe","object"]),Is=`.doc-math-inline, .doc-math-block, .doc-code, .doc-diff, [data-doc-math-dollar], [data-doc-chart], ${rs}`;function js(t,e){let s=[],o=n=>{for(let i of n.childNodes??[])if(i.nodeName==="#text"&&i.sourceCodeLocation&&i.value.includes("$")){let{startOffset:a,endOffset:c}=i.sourceCodeLocation;for(let l of t.slice(a,c).matchAll(Ls)){if(!Cs(l[1]))continue;let r=l[1].replace(/\s+/g," "),d=r.length>60?`${r.slice(0,59)}\u2026`:r;s.push(`line ${Zt(t,a+l.index)}: $${d}$ is not drawn as a formula (single dollars are off: they are money): write \\(${d}\\)`)}}else i.tagName&&!zs.has(i.tagName)&&!P(i,Is)&&o(i)};return o(e),s}import V from"node:fs";import W from"node:path";import{COLOR_NAMES as Hs}from"../browser/shared/colors.mjs";import{FOLD_DOTS as Ks}from"../browser/shared/code-folds.mjs";import{kitPublicDirectory as Gs,kitSourceDirectory as Js,release as Vs}from"../browser/shared/paths.mjs";import{FLOW_LABEL as Ua}from"../browser/shared/components/list.mjs";var Rs={"code-title":{zh:"\u4EE3\u7801\u5757",en:"Code"},"plain-text":{zh:"\u7EAF\u6587\u672C",en:"Plain text"},"fold-code":{zh:"\u6298\u53E0\u6216\u5C55\u5F00\u4EE3\u7801\u5757",en:"Collapse or expand the code block"},"copy-code":{zh:"\u590D\u5236\u4EE3\u7801",en:"Copy code"},copied:{zh:"\u5DF2\u590D\u5236",en:"Copied"},wrap:{zh:"\u81EA\u52A8\u6362\u884C",en:"Wrap lines"},"no-wrap":{zh:"\u53D6\u6D88\u81EA\u52A8\u6362\u884C",en:"Stop wrapping lines"},fold:{zh:"\u6298\u53E0",en:"Collapse"},unfold:{zh:"\u5C55\u5F00",en:"Expand"},line:{zh:"\u7B2C {0} \u884C",en:"Line {0}"},lines:{zh:"\u7B2C {0}\u2013{1} \u884C",en:"Lines {0}\u2013{1}"},"diff-counts":{zh:"\u65B0\u589E {0} \u884C\uFF0C\u5220\u9664 {1} \u884C",en:"Lines added: {0}, removed: {1}"}};var We="data-ge-language",Fs={"code-title":"--doc-word-code-title"};function Ds(t,e,s,...o){let n=t[s];if(!n)throw new Error(`The kit has no word "${s}" here (src/render/kit/words.js).`);let i=n[e]??n.zh;return o.length===0?i:i.replace(/\{(\d+)\}/g,(a,c)=>c<o.length?String(o[c]):a)}var _s=`:root[${We}="en"], :root:not([${We}])[lang|="en" i]`;function Be(){let t=e=>Object.entries(Fs).map(([s,o])=>`${o}: ${JSON.stringify(Ds(Rs,e,s))};`).join(" ");return`:root { ${t("zh")} }
|
|
4
|
+
${_s} { ${t("en")} }`}import{LOOK as At,LOOK_ATTRIBUTES as Ms,SERIF_FONT as He,SIZE_FACTOR as Ps,SPACING as Us,WIDTH as Ct}from"../browser/shared/document-look.mjs";var Ke=[["--doc-body-font-size","--doc-body-line-height"],["--doc-small-font-size","--doc-small-line-height"],["--doc-note-font-size","--doc-note-line-height"],["--doc-title-font-size","--doc-title-line-height"],["--doc-h1-font-size","--doc-h1-line-height"],["--doc-h2-font-size","--doc-h2-line-height"],["--doc-h3-font-size","--doc-h3-line-height"],["--doc-h4-font-size","--doc-h4-line-height"],["--doc-card-title-font-size","--doc-card-title-line-height"],["--doc-table-font-size","--doc-table-line-height"]],Ws=["--doc-component-gap","--doc-block-gap","--doc-media-gap","--doc-paragraph-gap","--doc-group-gap","--doc-list-gap"],zt="--doc-content-max-width";function Bs(t){let e=new Map;for(let[,s,o]of String(t).matchAll(/^\s*(--doc-[a-z0-9-]+):\s*([^;]+);/gm))e.has(s)||e.set(s,o.trim());return e}var rt=t=>`${Math.round(t)}px`;function ct(t,{size:e="default",spacing:s="default",width:o="default"}={}){let n=r=>{let d=/^(-?[0-9.]+)px$/.exec(t.get(r)??"");if(!d)throw new Error(`src/render/kit/styles/tokens.css: ${r} is no length in px (src/render/look-css.mjs reads it)`);return Number(d[1])},i=Ps[e],{leading:a,gaps:c}=Us[s],l={};if(e!=="default"||s!=="default")for(let[r,d]of Ke){let f=n(r)*i;e!=="default"&&(l[r]=rt(f)),l[d]=rt(Math.round(f)+(n(d)-n(r))*i*a)}if(s!=="default"){for(let r of Ws)l[r]=rt(n(r)*c);l["--doc-space"]=String(c)}if(o!=="default"){if(n(zt)!==Ct.default)throw new Error(`src/render/kit/styles/tokens.css: ${zt} is not \u9ED8\u8BA4 \u6B63\u6587\u5BBD\u5EA6's ${Ct.default}px (src/shared/document-look.mjs WIDTH)`);l[zt]=rt(Ct[o])}return l}var U=(t,e)=>`${t} { ${Object.entries(e).map(([s,o])=>`${s}: ${o};`).join(" ")} }`,_=(t,e)=>`[${Ms[t]}="${e}"]`;function Ge(t){let e=Bs(t),s=e.get("--doc-font");if(!s)throw new Error("src/render/kit/styles/tokens.css: no --doc-font (src/render/look-css.mjs keeps it as --doc-sans-font)");let o=[U(`:root${_("font","serif")}`,{"--doc-sans-font":s,"--doc-font":He}),U(`:root${_("font","mixed")}`,{"--doc-heading-font":He})],[,...n]=At.size,[,...i]=At.spacing,[,...a]=At.width;for(let c of n)o.push(U(`:root${_("size",c)}`,ct(e,{size:c})));for(let c of i)o.push(U(`:root${_("spacing",c)}`,ct(e,{spacing:c})));for(let c of a)o.push(U(`:root${_("width",c)}`,ct(e,{width:c})));for(let c of n)for(let l of i){let r=ct(e,{size:c,spacing:l});o.push(U(`:root${_("size",c)}${_("spacing",l)}`,Object.fromEntries(Ke.map(([,d])=>[d,r[d]]))))}return o.join(`
|
|
5
|
+
`)}var Je=Object.fromEntries(K.filter(t=>t.file).map(t=>[t.file,t.build])),tr=Object.keys(Je),Z=t=>W.join(Js,t),Zs=(t,e,s)=>({entryPoints:[Z(t)],bundle:!0,write:!1,format:"iife",platform:"browser",target:"es2022",...typeof e=="function"?e():e,...s}),Ys=t=>{let e=Je[t];if(!e)throw new Error(`src/render/kit-build.mjs: no kit file "${t}"`);return e},lt=new Map;function qs(t,e){let s=[...e.matchAll(/^@import\s+"\.\/([a-z0-9-]+\.css)";\s*$/gm)].map(i=>i[1]),o=V.readdirSync(W.dirname(Z(t))).filter(i=>i.endsWith(".css")&&i!==W.basename(t)),n=[...o.filter(i=>!s.includes(i)).map(i=>`${i} is not listed`),...s.filter((i,a)=>!o.includes(i)||s.indexOf(i)!==a).map(i=>`${i} is listed but missing, or listed twice`)];if(n.length>0)throw new Error(`src/render/kit/${t}: ${n.join("; ")}`);return s.map(i=>W.join(W.dirname(t),i))}var Xs=t=>t.replace(/@(text|highlight)-colors\b/g,(e,s)=>Hs.map(o=>`.doc-${s}-${o}`).join(", ")),Qs=t=>{let e=Xs(t.join(`
|
|
6
|
+
`)).replaceAll("@fold-dots",Ks).replace(/^@kit-words;$/m,()=>Be());return e.replace(/^@kit-look;$/m,()=>Ge(e))};function It(t,{fresh:e=!1}={}){let s=Ys(t);if(Vs)return V.promises.readFile(W.join(Gs,t),"utf8");if(s.read)return V.promises.readFile(Z(s.read),"utf8");if(s.styles)return V.promises.readFile(Z(s.styles),"utf8").then(o=>Promise.all(qs(s.styles,o).map(n=>V.promises.readFile(Z(n),"utf8")))).then(Qs);if(e||!lt.has(t)){let o=le(Zs(s.bundle,s.options)).then(n=>n.outputFiles[0].text);o.catch(()=>lt.delete(t)),lt.set(t,o)}return lt.get(t)}import{kitNamespace as tn}from"../browser/shared/old-names.mjs";import{attr as jt,hasClass as ft}from"../browser/shared/html-tree.mjs";var Ve=t=>t.tagName==="section"&&ft(t,"doc-section"),en=new Set(["section","header","footer","nav","script","style","template","dialog","link","meta"]),on=t=>!en.has(t.tagName),dt=t=>t.nodeName==="#text"?t.value:(t.childNodes??[]).map(dt).join("");function Ye(t,e=[]){for(let s of t.childNodes??[])s.tagName&&((s.tagName==="main"&&ft(s,"doc-page")||jt(s,"data-doc-sheet")!==void 0)&&e.push(s),Ye(s.tagName==="template"?s.content:s,e));return e}var sn=/^(p|li|h[1-4]|blockquote|ul|ol)$/,qe=["doc-summary","doc-panel","doc-note","doc-callout"],nn=t=>sn.test(t.tagName)||qe.some(e=>ft(t,e)),an=new Set(["none","auto","100%","inherit","initial","unset","revert"]),Ze=t=>[...t.matchAll(/(?:^|[;{\s])(?:max-)?width\s*:\s*([^;}]+)/gi)].some(([,e])=>!an.has(e.replace(/!important/i,"").trim().toLowerCase())),rn=t=>{let e=t.trim().split(/\s*[\s>+~]\s*/).at(-1)??"",s=/^(p|li|h[1-4]|blockquote|ul|ol)\b/.test(e)||qe.some(n=>e.includes(`.${n}`)),o=[...t.matchAll(/\.([\w-]+)/g)].some(([,n])=>!tn(n))||t.includes("#");return s&&!o};function cn(t){let e=[],s=(o,n)=>{for(let i of o.childNodes??[]){if(!i.tagName)continue;let a=n||i.tagName==="main"&&ft(i,"doc-page");if(a&&nn(i)&&Ze(jt(i,"style")??"")&&e.push(`<${i.tagName}> with style="${jt(i,"style").trim()}"`),i.tagName==="style"){let c=dt(i).replace(/\/\*[\s\S]*?\*\//g,"");for(let[,l,r]of c.matchAll(/([^{}]+)\{([^{}]*)\}/g))if(Ze(r))for(let d of l.split(","))rn(d)&&e.push(`"${d.trim()}" in the document's style`)}s(i.tagName==="template"?i.content:i,a)}};return s(t,!1),e}function Xe(t,{written:e=t}={}){let s=[],o=w(t),n=cn(o);n.length>0&&s.push(`body text given a width of its own (${n.slice(0,3).join("; ")}${n.length>3?`; ${n.length-3} more`:""}): its lines break before the reading column's edge, leaving an extra right margin; let body text fill the column`);for(let i of Ye(o)){let a=i.childNodes.filter(c=>c.tagName);a.forEach((c,l)=>{if(!Ve(c))return;let r=l+1;for(;r<a.length&&on(a[r]);)r++;let d=a.slice(l+1,r);if(d.length===0||!Ve(a[r]??{})||/^h[1-4]$/.test(d[0].tagName))return;let f=c.childNodes.map(g=>g.tagName?g:null).filter(Boolean).map(dt).find(g=>g.trim())?.replace(/\s+/g," ").trim().slice(0,40)??"",[h]=d,u=dt(h).replace(/\s+/g," ").trim(),m=`<${h.tagName}>${u?` "${u.length>30?`${u.slice(0,30)}\u2026`:u}"`:""}`,p=h.sourceCodeLocation?.startLine;s.push(`${d.length} block${d.length===1?"":"s"} of body text right after the section "${f}" stand outside it${p?` (line ${p})`:""}, ${d.length===1?`the ${m}`:`the first a ${m}`}, between two sections, with no heading of their own: fine if meant, otherwise they belong inside that section`)})}return s.push(...Te(t,{written:e})),s}import{attr as Qe,hasClass as ln}from"../browser/shared/html-tree.mjs";var to="Write instead where it came from, in words, or a path relative to materials/ (materials/data.csv)",dn=new Set(["script","style","template","noscript","textarea","pre","code","kbd","samp","var"]),fn=["doc-math-inline","doc-math-block"],hn=/\\\([\s\S]*?\\\)|\\\[[\s\S]*?\\\]|\$\$[\s\S]*?\$\$/g,un=/(?<!\\)\$(?:\\[\s\S]|[^\\$])+\$/g,pn=/[\s"'<>|()[\]{};,。;:、!?()《》「」『』“”‘’【】]/u,mn=/[^\s"'<>|()[\]{};,。;:、!?()《》「」『』“”‘’【】]+/gu,so=/^[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]/u,gn=/\.[A-Za-z0-9]{1,8}$/,$n=[/(?<![A-Za-z0-9_\\])[A-Za-z]:[\\/]/g,/(?<![A-Za-z0-9_.~:/\\-])\/(?:Users|home|root|tmp|private|mnt|opt|Volumes|var\/folders)\/(?=\S)/g,/(?<![A-Za-z0-9_.~:/\\-])~\/(?=\S)/g,/(?<![A-Za-z0-9_$\\])\$(?:HOME|\{HOME\})\/(?=\S)/g,/(?<![A-Za-z0-9_:\\])\\\\[A-Za-z0-9][\w.$-]*\\(?=[^\s\\])/g,/%(?:TEMP|TMP|APPDATA|LOCALAPPDATA|USERPROFILE)%/gi],wn=/(?:^|[\\/])(?:AppData|scratchpad)(?=[\\/]|$)/i,bn=/^(?:[A-Za-z]:|[\\/]|%[A-Za-z]+%)[\s\S]*[\\/](?:temp|tmp)(?=[\\/])/i,kn=t=>t.includes("://")&&!/^file:/i.test(t),eo=12;function oo(t,e){let s=e;for(;s<t.length&&!pn.test(t[s])&&!(so.test(t[s])&&gn.test(t.slice(e,s)));)s++;return t.slice(e,s).replace(/[.,;:!?]+$/,"")}function yn(t,e=!1){let s=c=>c.replace(/[^\n]/g," "),o=t.replace(hn,s),n=e?o.replace(un,s):o,i=[],a=(c,l)=>i.some(r=>r.at<=c+l.length&&c<=r.at+r.path.length);for(let c of $n)for(let l of n.matchAll(c)){let r=oo(n,l.index);r.length>=l[0].length+2&&!a(l.index,r)&&i.push({at:l.index,path:r})}for(let c of n.matchAll(mn)){let l=c.index;for(;l<c.index+c[0].length&&so.test(n[l]);)l++;let r=oo(n,l);/[\\/]/.test(r)&&(wn.test(r)||bn.test(r))&&!kn(r)&&!a(l,r)&&i.push({at:l,path:r})}return i.sort((c,l)=>c.at-l.at)}function no(t,e=w(t)){let s=[],o=(a,c)=>{for(let l of a.childNodes??[])if(l.nodeName==="#text"){if(!l.sourceCodeLocation)continue;for(let{at:r,path:d}of yn(l.value,c))s.push({line:l.sourceCodeLocation.startLine+(l.value.slice(0,r).match(/\n/g)?.length??0),path:d})}else l.tagName&&!dn.has(l.tagName)&&Qe(l,"hidden")===void 0&&!fn.some(r=>ln(l,r))&&o(l,c||Qe(l,"data-doc-math-dollar")!==void 0)};o(e,!1);let n=s.slice(0,eo).map(({line:a,path:c})=>`line ${a}: "${c.length>80?`${c.slice(0,77)}\u2026`:c}" is a path of this machine in the text a reader reads: a reader on another machine cannot open it. ${to}`),i=s.slice(eo);return i.length>0&&n.push(`${i.length} more path${i.length===1?"":"s"} of this machine in the text a reader reads, on line${new Set(i.map(({line:a})=>a)).size===1?"":"s"} ${[...new Set(i.map(({line:a})=>a))].join(", ")}. ${to}`),n}import{elementsOf as io}from"../browser/shared/html-tree.mjs";import{netSnapshot as xn}from"../browser/shared/net-cache.mjs";import{hostIn as Sn,netHostsOf as Nn}from"../browser/shared/net-policy.mjs";var vn=(t,e)=>`<script type="application/json" data-doc-snapshot data-at="${e}">${JSON.stringify(t).replace(/</g,"\\u003c")}</script>`,Rt=t=>t.some(({needs:e})=>Array.isArray(e)&&e.includes("workspace"));function ao(t,{slug:e,packages:s,root:o,at:n=new Date,workspace:i=null}){let a=s.flatMap(({needs:f})=>Nn(f)),c=a.length===0?null:xn(o,e,f=>{try{return Sn(new URL(f).hostname,a)!==null}catch{return!1}}),l={...i&&Rt(s)?i:{},...c?{net:c}:{}};if(Object.keys(l).length===0)return t;let r=io(io(w(t)).find(f=>f.tagName==="html")??{}).find(f=>f.tagName==="head"),d=r?.sourceCodeLocation?.endTag?.startOffset??r?.sourceCodeLocation?.startTag?.endOffset;return d===void 0?t:`${t.slice(0,d)} ${vn(l,n.toISOString())}
|
|
7
|
+
${t.slice(d)}`}import{MENTION as On,MENTION_ICON as En}from"../browser/shared/components/mention.mjs";import{escapeAttribute as Tn}from"../browser/shared/escape.mjs";import{attr as ro,elementsOf as Ln,hasClass as co,walk as An}from"../browser/shared/html-tree.mjs";import{addressOn as Cn,decoded as zn,fromFile as In,hosted as jn,pageAddress as Rn,workbenchHash as Fn}from"../browser/shared/page-address.mjs";function Dn(t,e,s){let o=In(t,e),n=Cn(o,s);return n||jn(t)?n:Rn(o)??(Fn(o)===null?null:{slug:null,block:null})}function _n(t,e,s,o){let n=w(t),i=new Set,a=[];An(n,r=>{let d=ro(r,"data-block-id");d!==void 0&&i.add(d),r.tagName==="a"&&ro(r,"href")!==void 0&&r.sourceCodeLocation?.startTag&&a.push(r)});let c=new Map,l=({startOffset:r,endOffset:d})=>c.set(r,[d,""]);for(let r of a){let{prefix:d,value:f}=r.attrs.find(({name:k})=>k==="href"),h=f.startsWith("#")?zn(f.slice(1)):null,u=h===null?f&&Dn(f,e,o):i.has(h)?{slug:e,block:h}:null;if(!u)continue;let m=s(u,f);if(m===f)continue;let{attrs:p,startTag:g,endTag:b}=r.sourceCodeLocation;if(m===null)l(g),b&&l(b),co(r,On)&&Ln(r).filter(k=>co(k,En)).forEach(k=>l(k.sourceCodeLocation));else{let k=d?`${d}:href`:"href";c.set(p[k].startOffset,[p[k].endOffset,`${k}="${Tn(m)}"`])}}return[...c].sort(([r],[d])=>d-r).reduce((r,[d,[f,h]])=>`${r.slice(0,d)}${h}${r.slice(f)}`,t)}function lo(t,e,s,{blocks:o=!0,links:n}){return _n(t,e,({slug:i,block:a})=>{let c=s(i);if(c===null)return null;if(!a||!o)return i===e&&a?null:c;let l=`#${encodeURIComponent(a)}`;return i===e?l:`${c}${l}`},n)}import ht from"node:fs";import Mn from"node:path";import{extensionOf as Pn,imageFile as Un,mediaTypeOf as Wn}from"../browser/shared/media.mjs";var _t=1024*1024,Bn=_t,ho=2400,Ft=2e3,Hn=.25,Kn=new Set(["png","gif"]),fo=.75;function Gn(t){if(t.length<16||t.toString("latin1",0,4)!=="RIFF"||t.toString("latin1",8,12)!=="WEBP")return!1;for(let e=12;e+8<=t.length;){let s=t.toString("latin1",e,e+4);if(s==="VP8L")return!0;if(s==="VP8 "||s==="ANMF")return!1;let o=t.readUInt32LE(e+4);e+=8+o+o%2}return!1}function Jn(t){let e=(s,o)=>s+o<=t.length;if(e(0,24)&&t.readUInt32BE(0)===2303741511&&t.toString("latin1",12,16)==="IHDR")return{width:t.readUInt32BE(16),height:t.readUInt32BE(20)};if(e(0,10)&&/^GIF8[79]a$/.test(t.toString("latin1",0,6)))return{width:t.readUInt16LE(6),height:t.readUInt16LE(8)};if(e(0,4)&&t[0]===255&&t[1]===216){for(let s=2;e(s,4);){if(t[s]!==255)return null;let o=t[s+1];if(o===255){s+=1;continue}if(o===216||o===1||o>=208&&o<=215){s+=2;continue}if(o>=192&&o<=207&&![196,200,204].includes(o))return e(s,9)?{width:t.readUInt16BE(s+7),height:t.readUInt16BE(s+5)}:null;if(o===217||o===218)return null;s+=2+t.readUInt16BE(s+2)}return null}if(e(0,30)&&t.toString("latin1",0,4)==="RIFF"&&t.toString("latin1",8,12)==="WEBP"){let s=t.toString("latin1",12,16);if(s==="VP8 ")return{width:t.readUInt16LE(26)&16383,height:t.readUInt16LE(28)&16383};if(s==="VP8L"){let o=t.readUInt32LE(21);return{width:(o&16383)+1,height:(o>>>14&16383)+1}}return s==="VP8X"?{width:t.readUIntLE(24,3)+1,height:t.readUIntLE(27,3)+1}:null}if(e(0,12)&&t.toString("latin1",4,8)==="ftyp"&&/avi[fs]/.test(t.toString("latin1",8,Math.min(t.length,t.readUInt32BE(0))))){let s=null;for(let o=t.indexOf("ispe",0,"latin1");o>=0&&e(o,16);o=t.indexOf("ispe",o+4,"latin1")){let n={width:t.readUInt32BE(o+8),height:t.readUInt32BE(o+12)};(!s||n.width*n.height>s.width*s.height)&&(s=n)}return s}return null}var Vn=_t;function Zn(t){let e;try{e=ht.openSync(t,"r");let{size:s}=ht.fstatSync(e),o=Buffer.alloc(Math.min(s,Vn));return ht.readSync(e,o,0,o.length,0),{length:s,head:o}}catch{return null}finally{e!==void 0&&ht.closeSync(e)}}var j=t=>`${Math.max(.1,t/_t).toFixed(1)} MB`;function Yn({bytes:t,width:e,height:s,extension:o,lossless:n}){let i=Math.max(e,s),a=Math.min(1,Ft/i),c=Math.min(t,e*s*a*a*Hn);if(i>ho){if(!n)return c<=t*fo?` \u2014 a ${Ft}px copy would be about ${j(c)}`:"";let l=t*a*a;return` \u2014 a ${Ft}px copy would be about ${j(l)}${o==="png"&&c<l/2?`, or ${j(c)} as a JPEG (for a photograph)`:""}`}return!n&&c<=t*fo?` \u2014 written again as a JPEG of quality about 82, it would be about ${j(c)}`:o==="png"&&c<t/2?` \u2014 as a JPEG (for a photograph) it would be about ${j(c)}`:""}var Dt=t=>t===2?"twice":`${t} times`;function uo({html:t,directory:e,tree:s=w(t)}){let{embedded:o,unserved:n}=re({html:t,directory:e,tree:s}),i=new Map,a=(l,r,d,f=!1)=>{let h=i.get(l)??i.set(l,{at:[],shows:0,served:d}).get(l);h.at.push(r),f||(h.shows+=1)};for(let{file:l,line:r,icon:d}of o)Un(l)&&a(l,r,!0,d);for(let{file:l,line:r}of n)Wn(l).startsWith("image/")&&a(l,r,!1);let c=[];for(let[l,{at:r,shows:d,served:f}]of[...i].sort(([,h],[,u])=>Math.min(...h.at)-Math.min(...u.at))){let h=Zn(Mn.join(e,l));if(!h)continue;let{length:u,head:m}=h,p=Jn(m),g=p?Math.max(p.width,p.height):0,b=u>Bn||g>ho,k=f&&d>1;if(!b&&!k)continue;let x=[...new Set(r)],v=`line${x.length===1?"":"s"} ${x.length>1?`${x.slice(0,-1).join(", ")} and ${x.at(-1)}`:x[0]}`,E=k?`shown ${Dt(d)}: the export embeds it ${Dt(d)}; show it once and refer back to it in words`:"";if(!b){c.push(`${l} (${v}): ${E} (${j(Math.ceil(u/3)*4*d)} as data: URLs)`);continue}let H=r.length===1||!f?"":`, ${Dt(r.length)}`,R=f?r.length:1,Y=`${j(Math.ceil(u/3)*4*R)} as ${R===1?"a data: URL":"data: URLs"}`,Po=p?`, ${p.width}\xD7${p.height}px`:"",Bt=Pn(l),Ht=p?Yn({bytes:u,...p,extension:Bt,lossless:Kn.has(Bt)||Gn(m)}):"",Uo=f?`the export embeds it as it is${H}, ${Y}${Ht}`:`its name keeps it out of the preview and the export (the failure at its line says why); copied into assets/ under a name they take, the export embeds it as it is, ${Y}${Ht}: copy it in at the size the page needs`;c.push(`${l} (${v}): ${j(u)}${Po}; ${Uo}${E?`; ${E}`:""}`)}return c}import{COMPONENTS as hi}from"../browser/shared/components/index.mjs";import{withLook as ui}from"../browser/shared/document-look.mjs";import{reportsDirectory as pi}from"../browser/shared/paths.mjs";import{documentLook as mi}from"../browser/shared/workspace-look.mjs";import po from"node:fs";import{MENTION as mo,MENTION_ICON as go}from"../browser/shared/components/mention.mjs";import{escapeAttribute as qn,escapeText as Xn}from"../browser/shared/escape.mjs";import{iconUrl as Qn,validIcon as ti}from"../browser/shared/emoji/icon-value.mjs";import{attr as ei,hasClass as oi,walk as si}from"../browser/shared/html-tree.mjs";import{fromFile as ni,isFileLink as ii,pageAddress as ai}from"../browser/shared/page-address.mjs";import{reportsDirectory as ri}from"../browser/shared/paths.mjs";import{documentDirectory as ci,documentFiles as li}from"../browser/shared/workspace.mjs";function di(t,e){let{html:s,json:o}=li(ci(t,e));if(!po.existsSync(s))return null;try{let{title:n,icon:i}=JSON.parse(po.readFileSync(o,"utf8"));return{title:n,icon:i}}catch{return{}}}function fi(t,e,s,o){if(s==="words"||typeof t!="string"||!ti(t))return null;if(s==="preview")return Qn(t,e,{tab:!0});let n=qt({value:t,slug:e,tab:!0,reportsDirectory:o});return n&&`data:${n.type};base64,${n.body.toString("base64")}`}function $o(t,{slug:e,mode:s="export",reportsDirectory:o=ri}){if(!t.includes(mo))return t;let n=new Map,i=c=>(n.has(c)||n.set(c,di(c,o)),n.get(c)),a=new Map;return si(w(t),c=>{let l=c.tagName==="a"&&oi(c,mo)?ei(c,"href"):void 0,{startTag:r,endTag:d}=c.sourceCodeLocation??{};if(!l||!ii(l)||!r||!d)return;let f=ai(ni(l,e))?.slug;if(!f)return;let h=i(f);if(!h)a.set(r.endOffset-1,[r.endOffset-1," data-doc-gone"]);else if(h.title){let u=fi(h.icon,f,s,o);a.set(r.endOffset,[d.startOffset,`${u?`<img class="${go}" src="${qn(u)}" alt="">`:`<span class="${go}"></span>`}${Xn(h.title)}`])}}),[...a].sort(([c],[l])=>l-c).reduce((c,[l,[r,d]])=>`${c.slice(0,l)}${d}${c.slice(r)}`,t)}var gi=/<script\b[^>]*\bdata-doc-kit="runtime"[^>]*><\/script>/;function $i(t,e,s){let o=Gt(e).filter(({id:n})=>!s.some(i=>i.id===n)).map(Jt).join(" ");return o?t.replace(gi,n=>`${n}
|
|
8
|
+
<script data-doc-dev>${o}</script>`):t}var wo=/(<title\b[^>]*>)\s*(<\/title>)/i;function wi(t){if(!wo.test(t))return t;let e=/^en\b/i.test(/<html\b[^>]*\slang=["']?([^"'\s>]*)/i.exec(t)?.[1]??"");return t.replace(wo,(s,o,n)=>`${o}${e?"Untitled":"\u672A\u547D\u540D\u6587\u6863"}${n}`)}function Mt(t,{slug:e,mode:s="export",files:o=!0,reportsDirectory:n,kit:i,catalog:a}){let{html:c,removed:l}=bi(t,{reportsDirectory:n,kit:i,catalog:a,describe:s==="preview"}),r={slug:e,mode:s,...n?{reportsDirectory:n}:{}},d=Xt(ui(c,mi(e,n??pi)),r),f=o?ce(te(oe(ne(d,r),r),r),r):d;return{html:wi($o(f,r)),removed:l}}function bi(t,{reportsDirectory:e,kit:s,page:o=!1,describe:n=!1,catalog:i=T()}){let a=L(t,i),{html:c,removed:l,used:r}=fe(t,[...hi,...a]),d=ke(he(c,{used:r,page:o,...s?{href:s}:{}}),a);return{html:n?$i(d,i,a):d,removed:l,packages:a}}import{exportsDirectory as Ai,kitPublicDirectory as Ci,release as zi,reportsDirectory as A,vendorDirectory as Ii}from"../browser/shared/paths.mjs";import{referencedFile as ji}from"../browser/shared/media.mjs";import{decoded as Ri,fromFile as Fi,hashAddress as Di,hosted as Lo,pageAddress as _i,workbenchHash as Mi}from"../browser/shared/page-address.mjs";import{pageLinks as Pi}from"../browser/shared/page-links.mjs";import{layoutOf as Ao}from"../browser/shared/workspace.mjs";import{documentLinks as Ui,listReportSlugs as Wi}from"../browser/shared/reports.mjs";import{documentDirectory as B,documentFiles as Wt}from"../browser/shared/workspace.mjs";import{sha256 as ut}from"../browser/shared/files.mjs";import{EXPORT_CSP as Bi,GENERATOR as Hi,isolateUmd as Ki,packagesMeta as Gi,sourceMeta as Ji}from"../browser/shared/export-wrap.mjs";var So=/__REPORT_[A-Z_]+__/,No=1e6,vo=t=>t.length>1?`${t.slice(0,-1).join(", ")} and ${t.at(-1)}`:`${t[0]}`;function Vi(t){return t.map(({id:e,lines:s,columns:o})=>{let n=new Set(s).size<s.length,i=s.map((a,c)=>n?`${a}:${o[c]}`:`${a}`);return`data-block-id repeats: "${e}" on lines ${vo(i)}${n?" (line:column)":""}; each id names one block: remove it from the copy, which needs none (the later ${i.length>2?`ones, lines ${vo(i.slice(1))}`:`one, line ${i[1]}`}, unless the copy went before its original)`})}var Zi=({slug:t,htmlPath:e,metadataPath:s})=>{let o=e?{html:e,json:s??e.replace(/\.html$/,".json")}:Wt(B(t,A));return{htmlName:N.basename(o.html),jsonName:N.basename(o.json)}};function Yi({slug:t,html:e,metadata:s,htmlPath:o,metadataPath:n,tree:i=w(e)}){let a=[],{htmlName:c,jsonName:l}=Zi({slug:t,htmlPath:o,metadataPath:n}),r=/<h1\b[^>]*\bclass="[^"]*\bdoc-title\b[^"]*"[^>]*>\s*<\/h1>/i.test(e),d=[[/<meta\s+name=["']viewport["']/i,"missing viewport metadata"],[r?/<title>\s*<\/title>|<title>[^<]+<\/title>/i:/<title>[^<]+<\/title>/i,"missing document title"],[/<main(?:\s|>)/i,"missing semantic main element"],[/aria-label|aria-labelledby|<title>/i,"missing accessible labels"]];for(let[p,g]of d)p.test(e)||a.push(g);let f=Buffer.byteLength(e);f>No&&a.push(`the document's editable source is ${f.toLocaleString("en-US")} bytes, over the ${No.toLocaleString("en-US")}-byte limit: aggregate or sample the embedded data, or split the document`),So.test(e)&&a.push(`${c} still contains a starter placeholder such as __REPORT_TITLE__`);for(let[p,g]of Object.entries(s))typeof g=="string"&&So.test(g)&&a.push(`${l} "${p}" is still a starter placeholder such as __REPORT_TITLE__`);/<[a-z][^>]*\sdata-doc-placeholder\b/i.test(e)&&a.push("starter placeholder content ([data-doc-placeholder]) is still present; replace it with the document's content");let h=new Map;M(i,p=>{let g=O(p,"data-block-id"),b=p.sourceCodeLocation?.attrs?.["data-block-id"]??p.sourceCodeLocation;g!==void 0&&h.set(g,[...h.get(g)??[],{line:b?.startLine,column:b?.startCol}])});let u=[...h].filter(([,p])=>p.length>1);a.push(...Vi(u.map(([p,g])=>({id:p,lines:g.map(({line:b})=>b),columns:g.map(({column:b})=>b)}))));let m=null;if(M(i,p=>{!m&&p.tagName==="main"&&(m=p)},{inTemplates:!1}),m){let p=O(m,"data-doc-id");p===void 0?a.push(`main.doc-page needs data-doc-id="${t}"`):p!==t&&a.push(`main[data-doc-id] is "${p}": it must be the document's slug "${t}"`)}return a}var Co=t=>yo(yo(t).find(e=>e.tagName==="html")??{}).find(e=>e.tagName==="head")?.sourceCodeLocation?.startTag?.endOffset,Ut=new Set(["localStorage","sessionStorage"]);function zo(t){let e=[],s=[];return M(t,o=>{o.tagName==="script"&&O(o,"src")!==void 0&&e.push(O(o,"src")),(o.tagName==="link"?(O(o,"rel")??"").toLowerCase().split(/\s+/):[]).includes("stylesheet")&&O(o,"href")!==void 0&&s.push(O(o,"href"))}),{scripts:e,styles:s}}function Io({slug:t,html:e,directory:s=B(t,A),tree:o=w(e),uses:n=X(e,q,{tree:o}),catalog:i}){let a=[];Co(o)===void 0&&a.push("the page writes no <head> start tag, which an export puts its Content-Security-Policy right after: write <head> \u2026 </head> before <body>");let c=[];M(o,d=>{if(["script","link","img"].includes(d.tagName))for(let f of["src","href"]){let h=O(d,f)?.trim();h&&/^https?:\/\//i.test(h)&&c.push(h)}}),c.length>0&&a.push(`external resources are not portable: ${c.join(", ")}`);for(let{name:d,how:f,line:h,where:u}of n){if(!q.has(d))continue;let m={call:`calls ${d}(\u2026)`,new:`creates new ${d}(\u2026)`}[f]??`uses ${d}`;a.push(`line ${h}: ${u} ${m}: embed its data (inline JSON, DocState); the export blocks the network`)}let{scripts:l,styles:r}=zo(o);for(let d of l)ge.has(d)||a.push(`unsupported script dependency ${d}`);for(let d of r)$e.has(d)||a.push(`unsupported stylesheet dependency ${d}`);return a.push(...ie({html:e,directory:s,tree:o}),...se({html:e,directory:s,tree:o}),...ee({html:e,directory:s,tree:o}),...ae({html:e,directory:s,tree:o})),a.push(...ye(L(e,i,o))),[...new Set(a)]}var qi=[[/\bDocSheets\.mount\s*\(/,"Sheet areas start on their own: remove DocSheets.mount (an area keeps its tab under its data-doc-sheets name)"],[/\bDocCode\.(?:View|DiffView|DiffStats|enhance)\b/,'code blocks are highlighted on their own, and a diff is declared as <div class="doc-diff"> holding { path, lines } as JSON (sdk/doc-code.d.ts)'],[/\bDocTables\.(?:enhance|enhanceAll|makeSortable)\b/,"tables start on their own: remove the call"],[/\bDocDialogs\.(?:enhance|enhanceAll)\b/,"detail cards start on their own: remove the call"]];function Xi({html:t,tree:e=w(t),uses:s=X(t,Ut,{tree:e})}){let o=we(t,e),n=[...ue(t,e),...pe(t,e)];for(let[i,a]of qi)i.test(o)&&n.push(`${o.match(i)[0].replace(/\s*\($/,"")} is gone: ${a}`);for(let{name:i,line:a,where:c}of s)Ut.has(i)&&n.push(`line ${a}: ${c} uses ${i}: use DocState instead of direct browser storage`);return[...new Set(n)]}var Qi=(t,e)=>e.childNodes.find(s=>s.tagName||s.nodeName==="#text"&&s.value.trim())===t,ta=t=>ko(t,Si("highlight").match)||t.tagName==="li"&&ko(t.parentNode,`ol.${Ni}`),ea=`an icon is one of three kinds: an emoji, <div class="doc-icon">\u{1F3AF}</div>; an icon of Gallery's sets in one of ${xo.length} colors, <div class="doc-icon" data-icon="/icons/airplane_blue.svg"></div> (MingCute's names; Tabler's as /icons/tabler/plane_blue.svg; the colors ${xo.join(", ")}); or a picture of the document's folder, <div class="doc-icon"><img src="assets/logo.png" alt=""></div>`,jo=t=>t.nodeName==="#text"?t.value:(t.childNodes??[]).map(jo).join("");function Oo(t,e,s){let o=e.sourceCodeLocation?.attrs?.[s],n=o?t.slice(o.startOffset,o.endOffset):`${s}="${O(e,s)??""}"`;return n.length>72?`${n.slice(0,71)}\u2026`:n}function oa(t,e){let s=O(e,"data-icon");if(s!==void 0)return{held:Oo(t,e,"data-icon"),meant:Pt(s)==="glyph"?s:null};let o=null;if(M(e,i=>{o??=["img","svg"].includes(i.tagName)?i:null}),o?.tagName==="img"){let i=O(o,"src");return{held:`<img ${Oo(t,o,"src")}>`,meant:Pt(i)==="image"?i:null}}if(o)return{held:"an <svg>"};let n=jo(e).replace(/\s+/g," ").trim();return{held:n?`"${n.slice(0,40)}"`:"nothing"}}function sa({set:t,name:e,color:s}){let o=vi.find(a=>a!==t);if(mt(o).includes(e))return`; "${e}" is ${o==="tabler"?"Tabler":"MingCute"}'s: ${Ei(o,e,s)}`;let n=e.split("-").filter(a=>a.length>=3),i=mt(t).filter(a=>a.split("-").some(c=>n.includes(c))).slice(0,6);return i.length>0?`; names of its set near it: ${i.join(", ")}`:""}function na({html:t,tree:e=w(t)}){let{all:s,own:o}=Qt(e),n=[],i=a=>a.sourceCodeLocation?.startLine;o.length>1&&n.push(`line ${i(o[1])}: ${o.length} page icons (.doc-icon) in the header (the first at line ${i(o[0])}): a document has one, right before its title`);for(let a of s){let c=i(a),l=a.parentNode;!o.includes(a)&&!(ta(l)&&Qi(a,l))&&n.push(`line ${c}: an icon (.doc-icon) stands only right before the document's title, first in a highlight block (.doc-panel, .doc-summary), or first in a flowchart's step (ol.doc-flow > li, in its number's place)`);let r=Li(Vt(t,a)),{held:d,meant:f}=r?{}:oa(t,a);f?n.push(`line ${c}: an icon (.doc-icon) holds ${d}, an icon a page reads only in double quotes: write ${Ti(f)}`):r?Pt(r)==="glyph"&&!Yt(r)&&n.push(`line ${c}: the icon ${r} is none of the icon sets' (MingCute: /icons/<name>_<color>.svg, Tabler: /icons/tabler/<name>_<color>.svg; src/shared/emoji/data/icons.json lists the names of each)${sa(Oi(r))}`):n.push(`line ${c}: an icon (.doc-icon) holds no icon (it holds ${d}): ${ea}`)}return[...new Set(n)]}function Ro(t){let e=w(t.html),s={...t,tree:e,uses:X(t.html,new Set([...q,...Ut]),{tree:e})};return[...Yi(s),...Lt(t.html,e),...Xi(s),...na(s),...Io(s)]}function ia(t){let e=new Map(t.map(n=>[n.slug,[...Ro(n),...Nt(n.html)]])),s=new Map(t.map(n=>[N.resolve(n.htmlPath),n.slug])),o=new Map(t.map(n=>[N.resolve(n.htmlPath),n]));for(let n of t)n.scriptNotes=[];if(t.length>0)for(let{htmlPath:n,text:i,typeOnly:a,note:c}of be(t)){if(a){o.get(n)?.scriptNotes.push(c);continue}let l=n?[s.get(n)]:[...e.keys()];for(let r of l)e.get(r).push(n?i:`${i} (shared SDK declaration)`)}for(let[n,i]of e)i.length===0&&e.delete(n);return e}async function Rc(t=[],{prepare:e=null}={}){let{reports:s,failures:o}=await pt(t,{prepare:e});for(let n of s){let i=[...Ro(n),...Nt(n.html)];i.length&&o.set(n.slug,i)}return o}async function aa(t=[],{prepare:e=null,directory:s=A}={}){let{reports:o,failures:n}=await pt(t,{prepare:e,directory:s});for(let[i,a]of ia(o))n.set(i,a);return{reports:o,failures:n}}async function ra({fresh:t=!1,kit:e=Ci,vendor:s=Ii}={}){if(zi)return;let o=K.map(a=>[a,a.file?It(a.file,{fresh:t}):wt(a)]);await S.mkdir(e,{recursive:!0});let n=N.join(s,"katex","fonts");await S.mkdir(n,{recursive:!0});let i=(await S.readdir($t)).filter(a=>a.endsWith(".woff2"));await Promise.all(i.map(a=>S.copyFile(N.join($t,a),N.join(n,a)))),await Promise.all(o.map(async([a,c])=>S.writeFile(a.file?N.join(e,a.file):N.join(s,...a.vendor.path.split("/").slice(2)),await c)))}async function ca(t,e){let s=await S.readdir(t).catch(()=>[]);await Promise.all(s.filter(o=>o.endsWith(".html")&&!e.has(o.slice(0,-5))).map(o=>S.rm(N.join(t,o),{force:!0})))}async function la(t,e){let s=N.join(e,"reports.json"),o=await S.readFile(s,"utf8").then(JSON.parse,()=>[]),n=new Map(Array.isArray(o)?o.map(a=>[a.slug,a]):[]);for(let{entry:a}of t)n.set(a.slug,a);let i=[];for(let[a,c]of[...n].sort(([l],[r])=>l.localeCompare(r))){let l=N.join(e,`${a}.html`);await S.stat(l).then(()=>!0,()=>!1)&&i.push(c)}await S.writeFile(s,`${JSON.stringify(i,null,2)}
|
|
9
|
+
`)}async function da(t=[],{prepare:e=null,directory:s=A}={}){let o=Ao(s).built,{reports:n,failures:i}=await aa(t,{prepare:e,directory:s});await ra(),await S.mkdir(o,{recursive:!0}),await ca(o,new Set(await Wi(s)));let a=[];for(let c of n){let l=`${c.slug}.html`,r=N.join(o,l);if(i.has(c.slug)){await S.rm(r,{force:!0});continue}let{html:d,removed:f}=Mt(c.html,{slug:c.slug,reportsDirectory:s});await S.writeFile(r,d),a.push({report:c,html:d,removed:f,entry:{slug:c.slug,...c.metadata,preview:`/generated/${l}`,sourceSha256:ut(c.html),outputSha256:ut(d)}})}return await la(a,o),{built:a,failures:i}}var fa=t=>t.replace(/<\/script/gi,"<\\/script");async function Fo(){return new Map(await Promise.all(K.map(async t=>{let e=await(t.file?It(t.file):wt(t,{inline:!0}));return de(t).endsWith(".css")||(e=fa(e)),[t.id,t.umd?Ki(e):e]})))}function ha(t,e,s=null,o=[]){let n=Co(w(e));if(n===void 0)throw new Error(`${t}: the page writes no <head> start tag, which the export's Content-Security-Policy goes right after`);let i=s?`
|
|
10
|
+
${Ji(s)}${o.length>0?`
|
|
11
|
+
${Gi(o)}`:""}`:"";return`${e.slice(0,n)}
|
|
12
|
+
<meta name="generator" content="${Hi}">
|
|
13
|
+
<meta http-equiv="Content-Security-Policy" content="${Bi}">${i}${e.slice(n)}`}function Do(t,e,s,o=null,n=T(),i=A,a=null){let c=L(e,n);e=ao(ha(t,e,o,c),{slug:t,packages:c,root:i,workspace:a}),e=me(xe(e,n),({id:d,element:f,attribute:h})=>{let u=s.get(d);if(typeof u!="string")throw new Error(`${t}: no inline source for the asset "${d}" (loadInlineSources in src/render/pipeline.mjs)`);return`<${f} ${h}="${d}-inline">${u}</${f}>`});let{scripts:l,styles:r}=zo(w(e));if(l.length+r.length>0)throw new Error(`${t}: export still contains a linked script or stylesheet`);return e}async function Eo(t,e=A,{components:s=!0,catalog:o=T()}={}){let n=B(t,e),i=await S.readFile(Wt(n).html),a=i.toString("utf8"),c=w(a);s||(o={packages:new Map});let l=[...s?Lt(a,c,o):[],...Io({slug:t,html:a,directory:n,tree:c,catalog:o})];if(l.length>0){let r=L(a,o,c).find(({id:d})=>l[0].startsWith(`${d}:`)||l[0].startsWith(`${d} (`))?.id;throw Object.assign(new Error(`${t}: ${l[0]}`),{reason:"check",slug:t,failures:l,...r?{component:r}:{}})}return{html:a,sha256:ut(i)}}async function Fc({directory:t=A,workspace:e=null,catalog:s=T()}={}){let o=await Fo(),n=async(i,{files:a=!0}={})=>{let c=await Eo(i,t,{catalog:s}),l=Mt(c.html,{slug:i,files:a,reportsDirectory:t,catalog:s}).html;return Do(i,l,o,c.sha256,s,t,await _o(e,i,l,s))};return n.check=async i=>{await Eo(i,t,{components:!1})},n}async function _o(t,e,s,o){return typeof t!="function"||!Rt(L(s,o))?null:await t(e).catch(()=>null)??null}async function Dc(t=[],{prepare:e=null,workspace:s=null,directory:o=A}={}){let n=Ao(o).exports,i=T(),{built:a,failures:c}=await da(t,{prepare:e,directory:o}),l=await Fo();await S.mkdir(n,{recursive:!0});let r=new Set(a.map(({report:h})=>h.slug)),{links:d}=await Ui(o),f=[];for(let{report:h,html:u}of a)try{let m=lo(u,h.slug,g=>r.has(g)?`${g}.html`:null,{links:d}),p=Do(h.slug,m,l,h.fileSha256,i,o,await _o(s,h.slug,m,i));await S.writeFile(N.join(n,`${h.slug}.html`),p),f.push({slug:h.slug,bytes:Buffer.byteLength(p),sha256:ut(p)})}catch(m){c.set(h.slug,[m.message])}return{built:a,exported:f,failures:c}}function To(t){let e=new Set;return M(t,s=>{for(let o of["id","data-block-id"])O(s,o)!==void 0&&e.add(O(s,o))}),e}function ua(t,e,s){if(Lo(t)||/^(?:[a-z][a-z0-9+.-]*:|\/)/i.test(t)||ji(t))return!1;let{pathname:o}=new URL(e);return!o.startsWith(`/${s}/`)||o.endsWith(".html")}function pa({slug:t,tree:e,directory:s}){let o=[],n=To(e),i=s===B(N.basename(s),A)?A:N.dirname(s),a=new Map([[t,n]]),c=d=>{if(!a.has(d)){let f=Wt(B(d,i));a.set(d,bo(f.html)?To(w(ki(f.html,"utf8"))):null)}return a.get(d)},l=null,r=(d,f)=>f===null?_i(d):Di(f,l??=Pi((bo(i)?yi(i):[]).map(h=>({slug:h}))));return M(e,d=>{let f=d.tagName==="a"?O(d,"href"):void 0;if(!f||f==="#"||f==="#top")return;let h=d.sourceCodeLocation?.startLine;if(f.startsWith("#")){n.has(Ri(f.slice(1)))||o.push(`the link to ${f} (line ${h}) names no block or element of this document`);return}let u=Fi(f,t),m=Mi(u),p=r(u,m);(p?!c(p.slug):m!==null)?Lo(f)||o.push(`the link to ${f} (line ${h}) names a document that is not there: gallery list has the slugs`):p?.block&&!c(p.slug).has(p.block)?o.push(`the link to ${f} (line ${h}) names a block document ${p.slug} does not hold`):u&&!p&&ua(f,u,t)&&o.push(`the link to ${f} (line ${h}) leads to no document: a link to one is ../<slug>/doc.html, gallery list has the slugs`)},xi),o}function Mo({slug:t,html:e,directory:s=B(t,A),written:o=e,scriptNotes:n=[]}){let i=w(e),a=Ae(e);return{fix:[...no(e,i),...uo({html:e,directory:s,tree:i})],notes:[...Xe(e,{written:o}),...Ue(i),...pa({slug:t,tree:i,directory:s}),...a.notes,...n],readings:a.readings}}function _c(t){let{fix:e,notes:s}=Mo(t);return[...e,...s]}function Mc(t){let e=t.map(s=>[s.slug,Mo(s)]);for(let[s,{fix:o}]of e)for(let n of o)console.log(`fix ${s}: ${n}`);for(let[s,{notes:o}]of e)for(let n of o)console.log(`note ${s}: ${n}`);for(let[s,{readings:o}]of e)for(let n of o)console.log(`chart ${s}: ${n}`)}async function ma(t,{exportNote:e=!1}={}){for(let[s,o]of t){console.error(`
|
|
14
|
+
FAIL ${s}: ${o.length} problem${o.length===1?"":"s"}`);for(let i of o)console.error(` - ${i}`);let n=N.join(Ai,`${s}.html`);e&&await S.stat(n).then(()=>!0,()=>!1)&&console.error(` ${n} was not updated; it still holds an earlier export.`)}}function ga(t,{above:e=!1,allow:s=process.argv.includes("--allow-failures")}={}){t.size!==0&&(console.error(`
|
|
15
|
+
${t.size} document${t.size===1?"":"s"} failed: ${[...t.keys()].join(", ")}${e?" (the failures are listed first, above)":""}`),s||(process.exitCode=1))}async function Pc(t,{exportNote:e=!1,allow:s}={}){await ma(t,{exportNote:e}),ga(t,{allow:s})}export{Es as a,_n as b,lo as c,$o as d,Mt as e,bi as f,Vi as g,Io as h,Ro as i,ia as j,Rc as k,aa as l,ra as m,da as n,ha as o,Fc as p,Dc as q,Mo as r,_c as s,Mc as t,ma as u,ga as v,Pc as w};
|
|
@@ -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}from"./chunk-
|
|
2
|
+
import{a,b}from"./chunk-3F57LEN5.mjs";import"./chunk-QP7BOHE4.mjs";import"./chunk-GMJD7ID3.mjs";import"./chunk-JEUK3ZO7.mjs";import"./chunk-L55NOXBE.mjs";import"./chunk-7UZUQQ7Q.mjs";import"./chunk-4OZWXZE5.mjs";import"./chunk-5L7RYZCL.mjs";export{a as nameHint,b as run};
|