@heycys/gallery 0.2.1 → 0.2.2
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 +9 -5
- 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 +19 -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-BYSF5UMM.mjs → chunk-236JJXWY.mjs} +2 -2
- package/dist/{chunk-3A5I2GJK.mjs → chunk-2KAVXMKG.mjs} +1 -1
- package/dist/chunk-2T4PZQEP.mjs +2 -0
- package/dist/{chunk-SAHS56QM.mjs → chunk-3SKOU6OZ.mjs} +1 -1
- package/dist/{chunk-S2Y7VI4H.mjs → chunk-3XZOA7AH.mjs} +2 -2
- 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-SOD23RGL.mjs → chunk-4KUO7R2M.mjs} +8 -8
- package/dist/chunk-4SNV4HA5.mjs +2 -0
- package/dist/chunk-53XDTHTG.mjs +4 -0
- package/dist/chunk-5XV3YYLG.mjs +2 -0
- package/dist/{chunk-VNUWREXU.mjs → chunk-65NTKF4N.mjs} +1 -1
- package/dist/chunk-6GV3CBB2.mjs +2 -0
- package/dist/{chunk-DH6GMDNN.mjs → chunk-6L6V7YR2.mjs} +1 -1
- package/dist/{chunk-TOE6DPLH.mjs → chunk-6NLXUKAY.mjs} +1 -1
- package/dist/chunk-6Q7ASAXJ.mjs +3 -0
- 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-36FIRJIF.mjs → chunk-742D2WWJ.mjs} +2 -2
- package/dist/{chunk-7M7UPWU6.mjs → chunk-7EFHNQ5B.mjs} +1 -1
- package/dist/{chunk-JI6T3A4Y.mjs → chunk-7ISBBDJR.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-BLNQUR5R.mjs +168 -0
- package/dist/chunk-BMX3VUHY.mjs +2 -0
- package/dist/chunk-BN7M3IN7.mjs +8 -0
- package/dist/{chunk-AMDGVDNV.mjs → chunk-BQNTTFPL.mjs} +1 -1
- package/dist/chunk-C257H6IA.mjs +2 -0
- package/dist/{chunk-74RPP2M2.mjs → chunk-C564NU2H.mjs} +1 -1
- package/dist/chunk-CHQU37CA.mjs +2 -0
- package/dist/{chunk-WCWYNFDF.mjs → chunk-E4IHAIJ7.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-PAFSFVYB.mjs → chunk-ERE2BXYV.mjs} +1 -1
- package/dist/{chunk-ZEY2RLBT.mjs → chunk-ERLAIBOA.mjs} +2 -2
- package/dist/chunk-FFV733MA.mjs +2 -0
- package/dist/{chunk-CZ5KJSGK.mjs → chunk-GJJRBGMY.mjs} +1 -1
- package/dist/{chunk-VA3KAQZD.mjs → chunk-GKOBB6DH.mjs} +1 -1
- package/dist/chunk-GMJD7ID3.mjs +2 -0
- package/dist/{chunk-QZ35UAB4.mjs → chunk-GRAXKKG4.mjs} +1 -1
- package/dist/{chunk-2RKIHJI2.mjs → chunk-HYMEEXKN.mjs} +1 -1
- package/dist/{chunk-DKR7LFIY.mjs → chunk-IA2SIEJQ.mjs} +1 -1
- package/dist/{chunk-QK3VISCA.mjs → chunk-IA4PSIMD.mjs} +1 -1
- package/dist/chunk-JPG2LBQM.mjs +11 -0
- package/dist/{chunk-VGTMLQWZ.mjs → chunk-JXXHAXYH.mjs} +1 -1
- package/dist/{chunk-5MEXZ2UF.mjs → chunk-K3JKPFL5.mjs} +1 -1
- package/dist/{chunk-LE44MD3O.mjs → chunk-KLQP46Y3.mjs} +1 -1
- 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-4DNHHJSL.mjs → chunk-MKIBJTJZ.mjs} +1 -1
- package/dist/{chunk-L7W624FD.mjs → chunk-MNWJ4EZY.mjs} +1 -1
- package/dist/{chunk-FXQBADMN.mjs → chunk-NHP66IWR.mjs} +1 -1
- package/dist/{chunk-YBB5LWZK.mjs → chunk-OEIJLMPI.mjs} +1 -1
- package/dist/{chunk-NWRZXELO.mjs → chunk-PAREWQGB.mjs} +1 -1
- package/dist/{chunk-7N2LPG33.mjs → chunk-PDZR3L3C.mjs} +1 -1
- package/dist/{chunk-YFJU3O7G.mjs → chunk-PLB7L22J.mjs} +1 -1
- package/dist/{chunk-4AMTKWDO.mjs → chunk-PUOQ65NC.mjs} +1 -1
- package/dist/chunk-Q4MS6OFC.mjs +2 -0
- package/dist/{chunk-3OFXMN6N.mjs → chunk-Q7P3Q5YX.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-ZO7SFB2E.mjs → chunk-SQ6Y2ZMA.mjs} +2 -2
- 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-CPS4SRPF.mjs → chunk-ULXSPX5H.mjs} +2 -2
- package/dist/{chunk-JXLSHVJ2.mjs → chunk-UMHUSOPJ.mjs} +1 -1
- package/dist/chunk-USIHBCSW.mjs +15 -0
- package/dist/{chunk-GWOYMENX.mjs → chunk-V6XZ4VIR.mjs} +1 -1
- package/dist/{chunk-AFGUR7SY.mjs → chunk-VPMRP2TL.mjs} +1 -1
- package/dist/{chunk-WTEGUPFG.mjs → chunk-VRPVVMRB.mjs} +1 -1
- package/dist/chunk-VZ2RQ3AM.mjs +2 -0
- package/dist/{chunk-XKOHV4H6.mjs → chunk-W5NPH5UA.mjs} +1 -1
- package/dist/chunk-WFGPMCTZ.mjs +4 -0
- package/dist/chunk-XZCFPKGO.mjs +2 -0
- package/dist/{chunk-QJ3TFJLQ.mjs → chunk-Y34NR5JL.mjs} +1 -1
- package/dist/{chunk-V5JRSGZF.mjs → chunk-YN37ZDLW.mjs} +1 -1
- package/dist/chunk-ZFGMJVJC.mjs +2 -0
- 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 +12 -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-xP0uw3a0.css → index-FLb9jCfl.css} +1 -1
- package/web/assets/index-czjrXVjf.js +15 -0
- 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};
|