@heycys/gallery 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. package/THIRD-PARTY-NOTICES.md +51 -1
  2. package/browser/editor/components/callout/index.mjs +40 -15
  3. package/browser/editor/components/columns/page.mjs +41 -28
  4. package/browser/editor/components/details/index.mjs +2 -1
  5. package/browser/editor/components/dialog/index.mjs +2 -1
  6. package/browser/editor/components/dialog/page.mjs +0 -18
  7. package/browser/editor/components/divider/index.mjs +1 -1
  8. package/browser/editor/components/figure/page.mjs +10 -1
  9. package/browser/editor/components/file/page.mjs +2 -2
  10. package/browser/editor/components/flowchart/add.mjs +2 -2
  11. package/browser/editor/components/heading/index.mjs +2 -0
  12. package/browser/editor/components/heading/page.mjs +6 -0
  13. package/browser/editor/components/highlight/index.mjs +4 -20
  14. package/browser/editor/components/icons.mjs +5 -2
  15. package/browser/editor/components/image/page.mjs +2 -2
  16. package/browser/editor/components/installed/index.mjs +71 -25
  17. package/browser/editor/components/installed/page.mjs +122 -21
  18. package/browser/editor/components/kit.mjs +3 -0
  19. package/browser/editor/components/media/page.mjs +44 -14
  20. package/browser/editor/components/pages.mjs +2 -2
  21. package/browser/editor/components/registry.mjs +56 -30
  22. package/browser/editor/components/section/index.mjs +2 -1
  23. package/browser/editor/components/set-apart.mjs +24 -0
  24. package/browser/editor/components/table/index.mjs +5 -3
  25. package/browser/editor/components/table/page.mjs +29 -18
  26. package/browser/editor/page/annotate/anchors.mjs +4 -3
  27. package/browser/editor/page/annotate/index.mjs +61 -34
  28. package/browser/editor/page/autosave.mjs +50 -4
  29. package/browser/editor/page/beside.mjs +5 -5
  30. package/browser/editor/page/block-menu/colors.mjs +3 -1
  31. package/browser/editor/page/block-menu/index.mjs +8 -6
  32. package/browser/editor/page/blocks.mjs +16 -7
  33. package/browser/editor/page/caret.mjs +4 -1
  34. package/browser/editor/page/changes/bar.mjs +102 -0
  35. package/browser/editor/page/changes/ghost.mjs +206 -0
  36. package/browser/editor/page/changes/gone-words.mjs +94 -0
  37. package/browser/editor/page/changes/index.mjs +447 -0
  38. package/browser/editor/page/changes/words.mjs +27 -0
  39. package/browser/editor/page/clipboard/import/colors.mjs +3 -3
  40. package/browser/editor/page/clipboard/index.mjs +32 -13
  41. package/browser/editor/page/clipboard/own/blocks.mjs +14 -5
  42. package/browser/editor/page/clipboard/own/describe.mjs +16 -7
  43. package/browser/editor/page/clipboard/own/export.mjs +6 -6
  44. package/browser/editor/page/clipboard/own/selection.mjs +2 -2
  45. package/browser/editor/page/clipboard/own/writers.mjs +0 -11
  46. package/browser/editor/page/columns/index.mjs +1 -1
  47. package/browser/editor/page/commit.mjs +19 -4
  48. package/browser/editor/page/conflicts.mjs +6 -26
  49. package/browser/editor/page/convert.mjs +8 -7
  50. package/browser/editor/page/core.mjs +55 -17
  51. package/browser/editor/page/drag/index.mjs +40 -24
  52. package/browser/editor/page/drag/preview.mjs +9 -4
  53. package/browser/editor/page/editor.mjs +70 -15
  54. package/browser/editor/page/emoji-picker/emoji-tab.mjs +22 -13
  55. package/browser/editor/page/emoji-picker/grid.mjs +7 -5
  56. package/browser/editor/page/emoji-picker/icon-tab.mjs +4 -4
  57. package/browser/editor/page/emoji-picker/icons.mjs +0 -1
  58. package/browser/editor/page/emoji-picker/index.mjs +11 -9
  59. package/browser/editor/page/emoji-picker/styles.mjs +161 -2
  60. package/browser/editor/page/emoji-picker/support.mjs +6 -4
  61. package/browser/editor/page/emoji-picker/upload.mjs +12 -11
  62. package/browser/editor/page/fills.mjs +5 -3
  63. package/browser/editor/page/fold/index.mjs +348 -0
  64. package/browser/editor/page/fold/rule.mjs +125 -0
  65. package/browser/editor/page/folded.mjs +23 -0
  66. package/browser/editor/page/format-bar/bar.mjs +2 -1
  67. package/browser/editor/page/format-bar/index.mjs +1 -1
  68. package/browser/editor/page/geometry.mjs +8 -6
  69. package/browser/editor/page/handle/index.mjs +17 -6
  70. package/browser/editor/page/hints/index.mjs +1 -1
  71. package/browser/editor/page/insert/index.mjs +30 -17
  72. package/browser/editor/page/long-runs.mjs +75 -0
  73. package/browser/editor/page/look.mjs +15 -3
  74. package/browser/editor/page/margin.mjs +45 -24
  75. package/browser/editor/page/menu.mjs +69 -25
  76. package/browser/editor/page/merge.mjs +24 -0
  77. package/browser/editor/page/notices.mjs +1 -1
  78. package/browser/editor/page/offered.mjs +1 -1
  79. package/browser/editor/page/outline/folds.mjs +11 -10
  80. package/browser/editor/page/outline/index.mjs +131 -45
  81. package/browser/editor/page/outline/list.mjs +23 -11
  82. package/browser/editor/page/outline/read.mjs +1 -1
  83. package/browser/editor/page/outline/strip.mjs +7 -1
  84. package/browser/editor/page/panel.mjs +5 -4
  85. package/browser/editor/page/resize/index.mjs +1 -1
  86. package/browser/editor/page/selection/delete.mjs +8 -6
  87. package/browser/editor/page/selection/index.mjs +10 -3
  88. package/browser/editor/page/session.mjs +54 -3
  89. package/browser/editor/page/table/cell-bar.mjs +4 -1
  90. package/browser/editor/page/table/cells.mjs +1 -1
  91. package/browser/editor/page/table/icons.mjs +1 -1
  92. package/browser/editor/page/table/index.mjs +13 -8
  93. package/browser/editor/page/table/widths.mjs +9 -4
  94. package/browser/editor/page/text-select/index.mjs +18 -3
  95. package/browser/editor/page/tooltip.mjs +1 -1
  96. package/browser/editor/page/type-grid.mjs +4 -3
  97. package/browser/editor/page/typing/code-edges.mjs +63 -17
  98. package/browser/editor/page/typing/index.mjs +12 -6
  99. package/browser/editor/page/typing/leave.mjs +1 -1
  100. package/browser/shared/annotations.mjs +8 -10
  101. package/browser/shared/code-folds.mjs +5 -1
  102. package/browser/shared/colors.mjs +15 -13
  103. package/browser/shared/component-catalog.mjs +24 -10
  104. package/browser/shared/components/callout.mjs +4 -2
  105. package/browser/shared/components/index.mjs +61 -7
  106. package/browser/shared/components/installed.mjs +75 -5
  107. package/browser/shared/components/page.mjs +10 -1
  108. package/browser/shared/components/table.mjs +1 -1
  109. package/browser/shared/components/text.mjs +2 -2
  110. package/browser/shared/document-look.mjs +178 -0
  111. package/browser/shared/emoji/data/LICENSE-lucide.txt +43 -0
  112. package/browser/shared/emoji/data/README.md +4 -2
  113. package/browser/shared/emoji/data/categories.json +1 -1
  114. package/browser/shared/emoji/data/keywords-en.json +1 -1
  115. package/browser/shared/emoji/data/keywords-zh.json +1 -1
  116. package/browser/shared/emoji/data/names.json +1 -1
  117. package/browser/shared/emoji/data/positions.json +1 -1
  118. package/browser/shared/emoji/data/twemoji-index.json +1 -1
  119. package/browser/shared/emoji/data/twemoji-svg.bin +0 -0
  120. package/browser/shared/emoji/data.mjs +10 -12
  121. package/browser/shared/emoji/emoji.mjs +8 -7
  122. package/browser/shared/emoji/icon-value.mjs +4 -3
  123. package/browser/shared/html-tree.mjs +11 -5
  124. package/browser/shared/i18n/en.mjs +67 -8
  125. package/browser/shared/long-runs.mjs +39 -0
  126. package/browser/shared/new-names.mjs +5 -2
  127. package/browser/shared/outline.mjs +194 -0
  128. package/browser/shared/preferences.mjs +10 -4
  129. package/browser/shared/session.mjs +5 -4
  130. package/browser/shared/workspace-look.mjs +91 -0
  131. package/browser/shared/zoom.mjs +5 -5
  132. package/dist/chunk-3HIRPVLU.mjs +2 -0
  133. package/dist/chunk-4FS7Z7WR.mjs +2 -0
  134. package/dist/{chunk-LHTFLRB6.mjs → chunk-5MHMDLZD.mjs} +2 -2
  135. package/dist/{chunk-YXAUQPVK.mjs → chunk-5ZKJ3H4P.mjs} +3 -3
  136. package/dist/{chunk-ZBIM6ARY.mjs → chunk-64K7IPLO.mjs} +55 -16
  137. package/dist/{chunk-QYKCJ7FG.mjs → chunk-6QXGZM36.mjs} +1 -1
  138. package/dist/chunk-6RGJOMJP.mjs +16 -0
  139. package/dist/{chunk-EUX7IC5J.mjs → chunk-7DTINW6U.mjs} +2 -2
  140. package/dist/{chunk-6CYG3Z4V.mjs → chunk-AJ73XJF3.mjs} +1 -1
  141. package/dist/chunk-AUZGSZJH.mjs +13 -0
  142. package/dist/{chunk-7QQBR7PB.mjs → chunk-BFE45AKL.mjs} +1 -1
  143. package/dist/chunk-BGGDRNYQ.mjs +10 -0
  144. package/dist/{chunk-L4DVONOG.mjs → chunk-BXO2ZY5P.mjs} +1 -1
  145. package/dist/chunk-CEH4MRCC.mjs +2 -0
  146. package/dist/chunk-CY2FNNAB.mjs +16 -0
  147. package/dist/{chunk-LC7YNQFG.mjs → chunk-DFUDV4LX.mjs} +1 -1
  148. package/dist/chunk-DKXG4XDG.mjs +2 -0
  149. package/dist/chunk-E7LWZRXY.mjs +4 -0
  150. package/dist/chunk-EZQ34M3F.mjs +124 -0
  151. package/dist/chunk-FDLXYYG4.mjs +4 -0
  152. package/dist/chunk-FUKQNOQS.mjs +9 -0
  153. package/dist/{chunk-DB4WKGYF.mjs → chunk-GB5SOYQJ.mjs} +2 -2
  154. package/dist/{chunk-ACOPDCNB.mjs → chunk-IVDLMMBD.mjs} +1 -1
  155. package/dist/chunk-JPOSLGOC.mjs +6 -0
  156. package/dist/chunk-JVHHHGEA.mjs +3 -0
  157. package/dist/chunk-L3QKH4OK.mjs +26 -0
  158. package/dist/{chunk-B3VTYBYR.mjs → chunk-LCTHTZIL.mjs} +2 -2
  159. package/dist/chunk-LEF6DRCK.mjs +59 -0
  160. package/dist/chunk-LS4F7JUM.mjs +2 -0
  161. package/dist/chunk-NO5NJCHO.mjs +2 -0
  162. package/dist/{chunk-UNUEWH4S.mjs → chunk-NQPVAU63.mjs} +1 -1
  163. package/dist/chunk-O35FIXRB.mjs +2 -0
  164. package/dist/chunk-PL6GHLGD.mjs +15 -0
  165. package/dist/{chunk-G7TOXONE.mjs → chunk-QJIR2BLP.mjs} +1 -1
  166. package/dist/chunk-QUPLVPB2.mjs +7 -0
  167. package/dist/chunk-R7BNENLY.mjs +4 -0
  168. package/dist/chunk-S6O4UHLC.mjs +2 -0
  169. package/dist/{chunk-HMHK3EQ6.mjs → chunk-SGJWQKEI.mjs} +1 -1
  170. package/dist/chunk-SYGN7GLU.mjs +2 -0
  171. package/dist/chunk-TYK6VNAB.mjs +10 -0
  172. package/dist/{chunk-EVJ3BX3M.mjs → chunk-U6KNPJPR.mjs} +1 -1
  173. package/dist/{chunk-YZ5Z6H4W.mjs → chunk-UALRNVSE.mjs} +1 -1
  174. package/dist/chunk-UMHUSOPJ.mjs +2 -0
  175. package/dist/chunk-V3HXVQEM.mjs +2 -0
  176. package/dist/{chunk-UXUK4PMC.mjs → chunk-V5JTW2LH.mjs} +1 -1
  177. package/dist/chunk-V5VXUJKG.mjs +2 -0
  178. package/dist/chunk-VBXMADMP.mjs +2 -0
  179. package/dist/chunk-VNV55RUA.mjs +2 -0
  180. package/dist/chunk-VPD2PS35.mjs +2 -0
  181. package/dist/chunk-W3BGBJQW.mjs +2 -0
  182. package/dist/chunk-W4VKN3GF.mjs +7 -0
  183. package/dist/chunk-W5BXXPDJ.mjs +3 -0
  184. package/dist/{chunk-Z52HTUW7.mjs → chunk-XNROSH2T.mjs} +2 -2
  185. package/dist/chunk-XUNHRCOG.mjs +6 -0
  186. package/dist/{chunk-6U2SLSDN.mjs → chunk-Y6RLRPG3.mjs} +1 -1
  187. package/dist/cli.mjs +1 -1
  188. package/dist/server.mjs +1 -1
  189. package/dist/worker.mjs +1 -1
  190. package/kit/math.js +18 -2
  191. package/kit/report.css +248 -137
  192. package/kit/runtime.js +126 -51
  193. package/kit/tables.js +51 -1
  194. package/kit/ui.js +97 -0
  195. package/package.json +1 -1
  196. package/release.json +8 -8
  197. package/sdk/doc-kit.d.ts +9 -3
  198. package/skill/SKILL.md +22 -10
  199. package/skill/references/building-components.md +46 -6
  200. package/skill/references/example-report.html +1 -1
  201. package/skill/references/writing-html.md +4 -4
  202. package/skill/sdk/doc-kit.d.ts +9 -3
  203. package/web/assets/index-Bh74DfsV.css +1 -0
  204. package/web/assets/index-UW0RyFFt.js +13 -0
  205. package/web/index.html +2 -2
  206. package/browser/editor/components/callout/page.mjs +0 -13
  207. package/dist/chunk-2PBALTR3.mjs +0 -57
  208. package/dist/chunk-3LA3EMDE.mjs +0 -15
  209. package/dist/chunk-5FRMCDPY.mjs +0 -16
  210. package/dist/chunk-5LEK2CBS.mjs +0 -2
  211. package/dist/chunk-5OFN5AHC.mjs +0 -2
  212. package/dist/chunk-5SIYS5HN.mjs +0 -2
  213. package/dist/chunk-5TEK3RAD.mjs +0 -2
  214. package/dist/chunk-7GHT2UCA.mjs +0 -15
  215. package/dist/chunk-ATCJYAR4.mjs +0 -2
  216. package/dist/chunk-C7HWOBIF.mjs +0 -2
  217. package/dist/chunk-E7VYDG2X.mjs +0 -2
  218. package/dist/chunk-FQGQH4KM.mjs +0 -2
  219. package/dist/chunk-GPF4YWWB.mjs +0 -9
  220. package/dist/chunk-GYQV7Y4J.mjs +0 -120
  221. package/dist/chunk-HQQMJCQJ.mjs +0 -10
  222. package/dist/chunk-IERUOGC3.mjs +0 -6
  223. package/dist/chunk-ITNLYXXV.mjs +0 -3
  224. package/dist/chunk-NFIBI4IP.mjs +0 -26
  225. package/dist/chunk-O52JMOCZ.mjs +0 -2
  226. package/dist/chunk-QMQUXTU4.mjs +0 -12
  227. package/dist/chunk-QVWVFC5K.mjs +0 -6
  228. package/dist/chunk-QZY6Q64C.mjs +0 -2
  229. package/dist/chunk-TDQP3DKQ.mjs +0 -10
  230. package/dist/chunk-V4CPWKMZ.mjs +0 -2
  231. package/dist/chunk-VACRB2NE.mjs +0 -3
  232. package/dist/chunk-W63L7367.mjs +0 -7
  233. package/dist/chunk-W7CXPCRV.mjs +0 -6
  234. package/dist/chunk-XINNG4F2.mjs +0 -4
  235. package/dist/chunk-YL2DPWVS.mjs +0 -4
  236. package/web/assets/index-B6Ai3wsa.js +0 -13
  237. package/web/assets/index-SYPC3EZy.css +0 -1
@@ -0,0 +1,91 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import fs from "node:fs/promises";
3
+ import { effectiveLook, lookOf, withLookField } from "./document-look.mjs";
4
+ import { writeAtomic } from "./files.mjs";
5
+ import { refusal, said } from "./i18n/index.mjs";
6
+ import { WORKSPACE_MARK, documentDirectory, documentFiles, layoutOf, markerOf } from "./workspace.mjs";
7
+
8
+ // The workspace's default look (字体与布局's 应用到全部文档, src/shared/document-look.mjs): `look` in its
9
+ // gallery.json, beside what the file says of the components, each choice that is not the default
10
+ // kept and the field gone when none is. A document shows its own choices (doc.json's `look`) over it,
11
+ // choice by choice, and a document with none of its own, a new one among them, shows it whole. A
12
+ // workspace without it, an older one's, has every choice at its default. The 写作偏好 page (a doc.json
13
+ // marked "instructions": true) has no look, the workspace's or its own. Here for the server alone: the
14
+ // render, the workbench's service and the preview's watcher read it from disk; a page and the
15
+ // workbench's app are told the look a document shows.
16
+
17
+ // gallery.json as it reads now: what it holds when it is ours (a workspace without one holds nothing),
18
+ // else why it cannot be taken (its components' messages: src/shared/component-catalog.mjs).
19
+ const UNREAD = said("gallery.json 读不出来:改好这个文件后再试");
20
+ const NOT_OURS = said("gallery.json 不是 Gallery 的文件");
21
+ const NOT_WRITABLE = ["EPERM", "EACCES", "EBUSY", "EROFS"];
22
+ function settingsOf(text) {
23
+ if (text === null) return { value: null };
24
+ const { value, ours, reads } = markerOf(text);
25
+ return ours ? { value } : { problem: reads ? NOT_OURS : UNREAD };
26
+ }
27
+ const readText = (file) => {
28
+ try {
29
+ return readFileSync(file, "utf8");
30
+ } catch (error) {
31
+ return error.code === "ENOENT" ? null : undefined;
32
+ }
33
+ };
34
+
35
+ /** The workspace's default look at `root` (lookOf's form), {} for none, for no gallery.json and for one that does not read or is not ours. */
36
+ export function workspaceLook(root) {
37
+ const text = readText(layoutOf(root).marker);
38
+ return text === undefined ? {} : lookOf(settingsOf(text).value?.look);
39
+ }
40
+
41
+ /**
42
+ * What document `slug`'s doc.json says of its look at `root`: { own: its `look` as written (null for
43
+ * none, for a doc.json that does not read and for none at all), instructions: whether it is the 写作偏好
44
+ * page's, reads: whether what it says can be taken, which a doc.json an Agent is writing may not, a
45
+ * moment; a document with no doc.json at all (one made by hand: its doc.html alone) says it has no look
46
+ * of its own, and reads, while one whose folder is gone says nothing }.
47
+ */
48
+ export function ownLookAt(slug, root) {
49
+ const files = documentFiles(documentDirectory(slug, root));
50
+ try {
51
+ const metadata = JSON.parse(readFileSync(files.json, "utf8"));
52
+ const reads = Boolean(metadata) && typeof metadata === "object" && !Array.isArray(metadata);
53
+ return { own: reads ? (metadata.look ?? null) : null, instructions: reads && metadata.instructions === true, reads };
54
+ } catch (error) {
55
+ return { own: null, instructions: false, reads: error.code === "ENOENT" && existsSync(files.html) };
56
+ }
57
+ }
58
+
59
+ /**
60
+ * The look document `slug` of the workspace at `root` shows (lookOf's form, {} for the default): its
61
+ * own over the workspace's (effectiveLook); the workspace's for a doc.json that does not read, none
62
+ * for the 写作偏好 page.
63
+ */
64
+ export function documentLook(slug, root) {
65
+ const { own, instructions } = ownLookAt(slug, root);
66
+ return instructions ? {} : effectiveLook(own, workspaceLook(root));
67
+ }
68
+
69
+ /**
70
+ * gallery.json with `look` as the workspace's default look (lookOf: each default left out, the field
71
+ * gone when all are), written at once and with all else it holds kept, made when there is none. A
72
+ * file that does not read, is another program's, changed under this write or cannot be written is
73
+ * refused (an error that says why: refusal), and stays as it is.
74
+ */
75
+ export async function writeWorkspaceLook(root, look) {
76
+ const file = layoutOf(root).marker;
77
+ const text = await fs.readFile(file, "utf8").catch((error) => {
78
+ if (error.code === "ENOENT") return null;
79
+ throw refusal(UNREAD);
80
+ });
81
+ const { value, problem } = settingsOf(text);
82
+ if (problem) throw refusal(problem);
83
+ if (value === null && Object.keys(lookOf(look)).length === 0) return; // no file, and none needed for the default
84
+ const written = withLookField(value ?? WORKSPACE_MARK, lookOf(look)); // in its place, else last; gone for the default
85
+ if (JSON.stringify(written) === JSON.stringify(value)) return;
86
+ const done = await writeAtomic(file, `${JSON.stringify(written, null, 2)}\n`, { expect: text }).catch((error) => {
87
+ if (NOT_WRITABLE.includes(error.code)) throw refusal(said("gallery.json 写不进去:可能是只读的,或被别的程序占着"));
88
+ throw error;
89
+ });
90
+ if (!done) throw refusal(said("gallery.json 刚刚被改过:再试一次"));
91
+ }
@@ -1,4 +1,4 @@
1
- import { INSTANCE } from "./components/installed.mjs";
1
+ import { INSTANCE, componentAt } from "./components/installed.mjs";
2
2
 
3
3
  // 图片放大: which pictures of a report open large when clicked (docs/render.md, "Opening a picture
4
4
  // large"). One rule for both ways in: the kit's viewer for a reader (src/render/kit/runtime/zoom.js:
@@ -10,8 +10,8 @@ import { INSTANCE } from "./components/installed.mjs";
10
10
  // A picture is an <img> of the page (main.doc-page), whatever holds it: an image block, a table's
11
11
  // cell, a card (one of the kit's or a drawing of the report's own), a column, a flowchart's node, a
12
12
  // list item, a detail card. Not one that is a control's or a link's (a click there is theirs: it
13
- // follows the link, opens the disclosure, chooses the tab), nor one in an instance of a component
14
- // package (its component's), nor an icon: the page's icon and a panel's or a node's (.doc-icon, emoji
13
+ // follows the link, opens the disclosure, chooses the tab), nor one in the own region of an instance
14
+ // of a component package (its component's; one in its slot is the document's: componentAt), nor an icon: the page's icon and a panel's or a node's (.doc-icon, emoji
15
15
  // pictures among them), a link's icon, a bookmark's pictures, a file's; nor a picture shown smaller
16
16
  // than ZOOM_LEAST each way (an icon's or an emoji's size in a line of text), nor one that did not load.
17
17
 
@@ -19,7 +19,7 @@ import { INSTANCE } from "./components/installed.mjs";
19
19
  export const ZOOM_SKIP = [
20
20
  "a[href]", "button", "summary", "label", "select", "[role=button]", "[role=link]", "[role=tab]", "[data-doc-dialog-open]",
21
21
  ".doc-icon", ".doc-link-mention", ".doc-bookmark", ".doc-file",
22
- ".doc-zoom", "[data-doc-dev]", INSTANCE,
22
+ ".doc-zoom", "[data-doc-dev]",
23
23
  ].join(", ");
24
24
 
25
25
  /** The pictures the reader's runtime watches to offer to the keyboard (runtime/zoom.js), those of the rule among them. */
@@ -43,7 +43,7 @@ const loaded = (img) => img.complete && (img.naturalWidth > 0 || /^data:image\/s
43
43
  /** Whether `img` opens large when clicked (or double-clicked in the page editor). */
44
44
  export function zoomable(img) {
45
45
  const holder = img?.hasAttribute?.(ZOOM_MARK) ? img.parentElement : img; // the runtime's own role is no control's
46
- if (img?.localName !== "img" || !img.closest(".doc-page") || holder?.closest(ZOOM_SKIP) || !loaded(img)) return false;
46
+ if (img?.localName !== "img" || !img.closest(".doc-page") || holder?.closest(ZOOM_SKIP) || holder.matches(INSTANCE) || componentAt(holder) || !loaded(img)) return false;
47
47
  const box = img.getBoundingClientRect();
48
48
  return box.width >= ZOOM_LEAST || box.height >= ZOOM_LEAST;
49
49
  }
@@ -0,0 +1,2 @@
1
+ import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
2
+ import{b as a,g as c,h as m}from"./chunk-5ZKJ3H4P.mjs";import{b as r,f as i,i as l}from"./chunk-NSKUTQ5J.mjs";import"./chunk-5L7RYZCL.mjs";import{reportsDirectory as p}from"../browser/shared/paths.mjs";var f=5e3;async function h(u){let{positional:e,options:w}=i({options:["--no-browser"],argv:u});if(e.length>1)throw new r("Name one document at most.");let{slug:n=null,block:g=null}=e.length?await l(e[0]):{};console.log(`\u5DE5\u4F5C\u533A\uFF1A${p}`);let o=await c({slug:n,baseline:n!==null});if(o.ok||console.error(o.message),n!==null&&o.reason!=="missing"){let{roundBegins:s}=await import("./chunk-CEH4MRCC.mjs");await s(n,o.ok?{}:{wait:f})}o.ok||process.exit(1);let t=await m(n,o,g);for(let s of t)console.log(s);console.log(await a(t,w))}export{h as run};
@@ -0,0 +1,2 @@
1
+ import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
2
+ import{e as p}from"./chunk-6RGJOMJP.mjs";import{f as b}from"./chunk-AUZGSZJH.mjs";import{k as d}from"./chunk-6QXGZM36.mjs";import{g as k}from"./chunk-CY2FNNAB.mjs";import v from"node:fs/promises";import h from"node:path";import{editStateDirectory as m,reportsDirectory as f}from"../browser/shared/paths.mjs";import{findPreviewServer as $}from"../browser/shared/preview-server.mjs";import{documentDirectory as S,documentFiles as g,isDocumentSource as j}from"../browser/shared/workspace.mjs";var u=e=>h.resolve(e),D=e=>h.basename(g(h.dirname(e)).json),N={busy:"it kept changing while it was being written (an Agent writing it?); nothing written. Run the export again.",timeout:"the workspace's Gallery server did not answer in 30s; nothing written. Run the export again."};async function w(e,n,o="hand-in",l=3e4){let t=`127.0.0.1:${e.port}`,s;try{s=await fetch(`http://${t}/__gallery/edit/${o}`,{method:"POST",headers:{"Content-Type":"application/json",Origin:`http://${t}`,"X-Gallery-Token":e.token},body:JSON.stringify({slug:n,workspace:f}),signal:AbortSignal.timeout(l)})}catch(a){return a.name==="TimeoutError"?{ok:!1,reason:"timeout"}:null}let i=await s.json().catch(()=>null);return typeof i?.ok!="boolean"||["elsewhere","token","host","origin"].includes(i.reason)?null:i}async function P(e){let n=await $({reportsDirectory:f}),o=null,l=[],t=new Map,s=[];for(let i of e){let{html:a,json:c}=g(S(i,f)),r=n?await w(n,i):null;if(r===null&&(o??=p({reportsDirectory:f,stateDirectory:m,finish:d}),r=await o.handIn(i),r.ok&&await o.settleNotes(i)),!r.ok){r.reason!=="missing"&&t.set(i,[`${u(a)} was not handed in: ${N[r.reason]??r.message??r.reason}`]);continue}if(r.repeated?.length){t.set(i,b(r.repeated));continue}s.push(...L(a,r)),r.written&&(r.changes.length&&s.push(...k(a,r.changes,{reread:!1})),r.added&&s.push(...T(a,r.given,r.added)),l.push(u(a))),O(r)&&l.push(u(c))}return{written:l,failures:t,lines:s}}async function _(e){let n=await $({reportsDirectory:f});if(n){for(let o of e)if(await w(n,o,"settle")===null)return}}async function C(e,{wait:n=3e4}={}){try{let o=await $({reportsDirectory:f}),l=o?await w(o,e,"round",n):null;return l!==null?l.ok?l.ended===!0:null:await p({reportsDirectory:f,stateDirectory:m,finish:d}).beginRound(e)}catch{return null}}async function H(e){try{let n=p({reportsDirectory:f,stateDirectory:m,finish:d}),{html:o}=g(S(e,f));await n.noteTaken(e,await v.readFile(o,"utf8"))}catch{}}var O=({title:e=null,icon:n=null})=>!!(e&&typeof e.from=="string"&&e.from!==e.to||n&&!n.missing),x=10;function T(e,n,o=n?.length??0,{pending:l=!1}={}){let t=`${o} block${o===1?"":"s"}`;if(l){let i=[`ids ${u(e)}: ${t} without an id yet: the export gives ${o===1?"it":"each"} one`];return o>x?i:[...i,...n.map(({line:a,tag:c})=>` line ${a} ${c}`)]}let s=[`ids ${u(e)}: ${t} given an id`];return!n||o>x?s:[...s,...n.map(({line:i,tag:a,id:c})=>` line ${i} ${a} \u2192 ${c}`)]}function L(e,{title:n=null,icon:o=null}={},{pending:l=!1}={}){let t=u(h.dirname(e)),s=D(e),i=(c,r,y)=>l?`${c} not ${r} yet (${y}): the export writes ${c.includes(" and ")?"them":"it"}`:`${c} written ${r}: ${y}`,a=[];if(n){let c=[...n.page?["<title>"]:[],...typeof n.from=="string"&&n.from!==n.to?[`${s}'s title`]:[]];c.length&&a.push(`title ${t}: ${i(c.join(" and "),"as its h1 says it",JSON.stringify(n.to))}`)}return o?.missing?a.push(`icon ${t}: ${s} has the icon ${JSON.stringify(o.from)} and the page's header none: write it there (<div class="doc-icon">\u2026</div> before the h1) or take "icon" out of ${s} (the export leaves ${s}'s as it is)`):o&&a.push(`icon ${t}: ${i(`${s}'s icon`,"as its header has it",o.to===null?"none":JSON.stringify(o.to))}`),a}function K(e,{by:n="this export"}={}){let o=e.length===1,l=[...e.filter(t=>j(h.basename(t))).map(t=>h.basename(t)).filter((t,s,i)=>i.indexOf(t)===s).map(t=>`${t}: the kit's markup, block ids`),...e.filter(t=>/^(doc|report)\.json$/.test(h.basename(t))).map(t=>h.basename(t)).filter((t,s,i)=>i.indexOf(t)===s).map(t=>`${t}: the title or icon said above`)];return`Re-read ${e.join(", ")} before editing ${o?"it":"them"}: ${n} wrote ${o?"it":"them"} (${l.join("; ")}).`}export{P as a,_ as b,C as c,H as d,T as e,L as f,K as g};
@@ -1,4 +1,4 @@
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 d,b as m,d as f}from"./chunk-ZBIM6ARY.mjs";import{readFileSync as $,realpathSync as O}from"node:fs";import l from"node:path";import{fileURLToPath as v}from"node:url";var x=l.dirname(v(import.meta.url));function g(t=x){for(let e=t;;e=l.dirname(e)){try{let i=JSON.parse($(l.join(e,"package.json"),"utf8"));if(i.name==="@heycys/gallery")return i.version}catch{}if(l.dirname(e)===e)return"0.0.0"}}var y={init:()=>import("./chunk-EVJ3BX3M.mjs"),new:()=>import("./chunk-C7HWOBIF.mjs"),import:()=>import("./chunk-QVWVFC5K.mjs"),open:()=>import("./chunk-5SIYS5HN.mjs"),serve:()=>import("./chunk-Z52HTUW7.mjs"),stop:()=>import("./chunk-TMYZB6AV.mjs"),check:()=>import("./chunk-O52JMOCZ.mjs"),export:()=>import("./chunk-5OFN5AHC.mjs"),qa:()=>import("./chunk-IERUOGC3.mjs"),list:()=>import("./chunk-QZY6Q64C.mjs"),component:()=>import("./chunk-6CYG3Z4V.mjs"),skill:()=>import("./chunk-L4DVONOG.mjs")},E=new Set(["stop","init","skill"]),S=(t,e)=>`${t.split(`
2
+ import{a as d,b as m,d as f}from"./chunk-64K7IPLO.mjs";import{readFileSync as $,realpathSync as O}from"node:fs";import l from"node:path";import{fileURLToPath as k}from"node:url";var x=l.dirname(k(import.meta.url));function g(t=x){for(let e=t;;e=l.dirname(e)){try{let i=JSON.parse($(l.join(e,"package.json"),"utf8"));if(i.name==="@heycys/gallery")return i.version}catch{}if(l.dirname(e)===e)return"0.0.0"}}var y={init:()=>import("./chunk-U6KNPJPR.mjs"),new:()=>import("./chunk-VBXMADMP.mjs"),import:()=>import("./chunk-XUNHRCOG.mjs"),open:()=>import("./chunk-3HIRPVLU.mjs"),serve:()=>import("./chunk-XNROSH2T.mjs"),stop:()=>import("./chunk-TMYZB6AV.mjs"),check:()=>import("./chunk-V5VXUJKG.mjs"),export:()=>import("./chunk-DKXG4XDG.mjs"),qa:()=>import("./chunk-JPOSLGOC.mjs"),list:()=>import("./chunk-V3HXVQEM.mjs"),move:()=>import("./chunk-LS4F7JUM.mjs"),set:()=>import("./chunk-W5BXXPDJ.mjs"),component:()=>import("./chunk-AJ73XJF3.mjs"),skill:()=>import("./chunk-BXO2ZY5P.mjs")},E=new Set(["stop","init","skill"]),S=(t,e)=>`${t.split(`
3
3
  `)[0]} (gallery ${e?`${e} --help`:"help"} says more)`,w=t=>/^--.|^-[A-Za-z]/.test(t);function j(t){let e=t.indexOf("--"),i=e===-1?t:t.slice(0,e),u=e===-1?[]:t.slice(e),n=[],s=null;for(let o=0;o<i.length;o++){let r=i[o];if(r==="--workspace"||r.startsWith("--workspace=")){let a=r.includes("=")?r.slice(r.indexOf("=")+1):o+1<i.length&&!w(i[o+1])?i[++o]:"";if(!a)return{error:"--workspace takes a folder: --workspace <dir>",usage:f};if(s!==null&&l.resolve(s)!==l.resolve(a))return{error:`Two workspaces named: ${s} and ${a}.`,usage:f};s=a;continue}n.push(r)}if(n[0]==="--version"||n[0]==="-v"||n[0]==="-V")return n.length===1&&u.length===0?{version:!0}:{error:"--version takes nothing else.",usage:f};if(n.length===0||n[0]==="help"||n[0]==="--help"||n[0]==="-h"){let o=n[0]==="help"?n[1]:void 0;return o===void 0?{help:f}:Object.hasOwn(m,o)?{help:m[o]}:{error:`No such command: ${o} (${d.join(", ")}).`,usage:f}}let[c,...p]=n;if(!Object.hasOwn(y,c))return{error:w(c)?`Unknown option: ${c} (the command comes first: gallery <command> [options]).`:`No such command: ${c} (${d.join(", ")}).`,usage:f};let h=[...p,...u];if(p.some(o=>o==="--help"||o==="-h"))return{help:m[c]};if(c==="init"){let o=new Set(["--from"]),r=[];for(let a=0;a<p.length;a++)o.has(p[a])?a++:w(p[a])||r.push(p[a]);if(r.push(...u.slice(1)),r.length>1)return{error:"Name one folder at most.",usage:m.init,command:c};if(r.length===1){if(s!==null&&l.resolve(s)!==l.resolve(r[0]))return{error:`Two workspaces named: ${r[0]} and --workspace ${s}.`,usage:m.init,command:c};s=r[0]}}return{command:c,argv:h,flag:s}}var N=(t,e)=>`Cannot write the workspace ${t} (${e}): allow Gallery to write there, or pass --workspace <a folder you may write>.`,A=(t,e=!0)=>e?`${l.join(t,"gallery.json")} is not Gallery's (another program's file of that name): pass --workspace <another folder> for Gallery's documents.`:`${l.join(t,"gallery.json")} does not read as JSON: mend the file, or pass --workspace <another folder> for Gallery's documents.`;async function G(t=process.argv.slice(2)){process.stdout.on("error",o=>{throw o.code==="EPIPE"&&process.exit(process.exitCode??0),o});let e=j(t);if(e.version)return void console.log(g());if(e.help)return void console.log(e.help);e.error&&(console.error(`${e.error}
4
- ${S(e.usage,e.command)}`),process.exit(2));let{command:i,flag:u}=e,{findWorkspace:n}=await import("../browser/shared/workspace.mjs"),s=n({flag:u});if(process.env.GALLERY_WORKSPACE=s.root,!E.has(i)){let{ensureWorkspace:o}=await import("../browser/shared/workspace.mjs");try{let{ours:r,reads:a}=await o(s.root);r||(console.error(A(s.root,a)),process.exit(1))}catch(r){if(!r.code)throw r;console.error(N(s.root,r.code)),process.exit(1)}}let{UsageError:c,usageFailureText:p}=await import("./chunk-2B5E4CDJ.mjs"),h=await y[i]();try{await h.run(e.argv,{command:i,workspace:s.root,how:s.how,version:g()})}catch(o){if(!(o instanceof c))throw o;console.error(p(m[i],o.message,o.synopsis)),process.exit(2)}}var k=t=>{try{return O.native(t)}catch{return null}};process.argv[1]&&k(process.argv[1])===k(v(import.meta.url))&&G();export{g as a,j as b,N as c,A as d,G as e};
4
+ ${S(e.usage,e.command)}`),process.exit(2));let{command:i,flag:u}=e,{findWorkspace:n}=await import("../browser/shared/workspace.mjs"),s=n({flag:u});if(process.env.GALLERY_WORKSPACE=s.root,!E.has(i)){let{ensureWorkspace:o}=await import("../browser/shared/workspace.mjs");try{let{ours:r,reads:a}=await o(s.root);r||(console.error(A(s.root,a)),process.exit(1))}catch(r){if(!r.code)throw r;console.error(N(s.root,r.code)),process.exit(1)}}let{UsageError:c,usageFailureText:p}=await import("./chunk-2B5E4CDJ.mjs"),h=await y[i]();try{await h.run(e.argv,{command:i,workspace:s.root,how:s.how,version:g()})}catch(o){if(!(o instanceof c))throw o;console.error(p(m[i],o.message,o.synopsis)),process.exit(2)}}var v=t=>{try{return O.native(t)}catch{return null}};process.argv[1]&&v(process.argv[1])===v(k(import.meta.url))&&G();export{g as a,j as b,N as c,A as d,G as e};
@@ -1,8 +1,8 @@
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{spawn as J}from"node:child_process";import P from"node:fs";import m from"node:fs/promises";import Q from"node:os";import k from"node:path";import{escapeMarkup as X}from"../browser/shared/escape.mjs";import{spawn as C}from"node:child_process";import{existsSync as H,readFileSync as M}from"node:fs";import w from"node:path";var V=e=>!["","0",void 0].includes(e),z=(e,r)=>(r.PATH??"").split(w.delimiter).some(t=>t&&H(w.join(t,e))),U=()=>{try{return process.platform==="linux"&&/microsoft/i.test(M("/proc/version","utf8"))}catch{return!1}};function K(e,{platform:r=process.platform,env:t=process.env,wsl:s=U()}={}){let n=encodeURI(e);return V(t.GALLERY_NO_BROWSER)?{skip:"GALLERY_NO_BROWSER is set"}:r==="win32"?{command:w.join(t.SystemRoot||t.windir||"C:\\Windows","System32","rundll32.exe"),args:["url.dll,FileProtocolHandler",n]}:r==="darwin"?{command:"open",args:[n]}:s?{command:"cmd.exe",args:["/c","start",'""',n.replace(/[&^]/g,"^$&")]}:!t.DISPLAY&&!t.WAYLAND_DISPLAY?{skip:"no display here (neither DISPLAY nor WAYLAND_DISPLAY is set)"}:z("xdg-open",t)?{command:"xdg-open",args:[n]}:{skip:"xdg-open is not installed"}}var q="Opened it in the default browser (if that is not Chrome or Edge, open the address there to edit).",T=e=>e.opened?q:`Not opened in a browser: ${e.why}.`;async function O(e,r){let t=K(e,r);return t.skip?{opened:!1,why:t.skip}:new Promise(s=>{let n;try{n=C(t.command,t.args,{detached:!0,stdio:"ignore",windowsHide:!0})}catch(o){return s({opened:!1,why:`${w.basename(t.command)} did not start (${o.code??o.message})`})}n.once("error",o=>s({opened:!1,why:`${w.basename(t.command)} did not start (${o.code??o.message})`})),n.once("spawn",()=>{n.unref(),s({opened:!0})})})}import{packageRoot as Z,previewLogFile as f,projectRoot as G,release as I,reportsDirectory as h}from"../browser/shared/paths.mjs";import{fullAddress as ee}from"../browser/shared/page-address.mjs";import{findPreviewServer as te,galleryVersion as F,portIsFree as re,previewServerFor as ne,readAnnouncement as oe}from"../browser/shared/preview-server.mjs";import{documentLinks as se}from"../browser/shared/reports.mjs";import{documentDirectory as ie,documentFiles as ae,layoutOf as ce}from"../browser/shared/workspace.mjs";var $="\u4EA4\u7ED9\u7528\u6237\uFF08\u73B0\u5728\u5C31\u628A\u8FD9\u4E2A\u5730\u5740\u7ED9\u7528\u6237\uFF1B\u7528 Chrome \u6216 Edge \u6253\u5F00\uFF09\uFF1A",le="Agent \u81EA\u7528\uFF08\u53EA\u6709\u6587\u6863\u9875\uFF0C\u4E0D\u4EA4\u7ED9\u7528\u6237\uFF09\uFF1A",de=e=>`send the user ${e} now, in a message of its own, before any other step; then `;function Me(e,r){let t=e.at(-1)??"";return`Next: ${t.startsWith($)?de(t.slice($.length)):""}${r}`}async function Ve(e,r){let t=e.at(-1)??"";return t.startsWith($)?r.has("--no-browser")?"Not opened in a browser (--no-browser).":T(await O(t.slice($.length))):null}var D="GALLERY_NO_PREVIEW",pe=e=>!["","0",void 0].includes(e),ze=e=>e.has("--no-preview")||pe(process.env[D]),ue=4317,fe=20,me=(e=process.env)=>{let r=Number(e.GALLERY_PORT);return Number.isInteger(r)&&r>0&&r<65536?r:ue},we=6e4,he=5*1024*1024,$e=k.join(G,"node_modules","vite","bin","vite.js"),ye=k.join(Z,"dist","server.mjs"),ge=e=>new Promise(r=>setTimeout(r,e)),A={reportsDirectory:h},Y=ce(h),R=(e,r)=>`http://127.0.0.1:${e}/generated/${r}.html`,j=e=>`http://127.0.0.1:${e}/`,ve=(e,r)=>se().then(({links:t})=>t,()=>null).then(t=>ee(`http://127.0.0.1:${e}`,r,t));async function xe({first:e=me(),count:r=fe}={}){let t=Number((await m.readFile(Y.lastPortFile,"utf8").catch(()=>"")).trim()),s=Array.from({length:Math.max(0,r)},(n,o)=>e+o);return Number.isInteger(t)&&t>0&&t<65536?[t,...s.filter(n=>n!==t)]:s}async function ke(){return await m.mkdir(k.dirname(f),{recursive:!0}),await m.stat(f).then(r=>r.size,()=>0)>he&&await m.rename(f,`${f}.1`).catch(()=>{}),P.openSync(f,"a")}async function Le(e,r){if(!I){let{writeSharedAssets:p}=await import("./chunk-5TEK3RAD.mjs");await p()}let t=await ke();P.writeSync(t,`
2
+ import{spawn as J}from"node:child_process";import P from"node:fs";import m from"node:fs/promises";import Q from"node:os";import k from"node:path";import{escapeMarkup as X}from"../browser/shared/escape.mjs";import{spawn as C}from"node:child_process";import{existsSync as H,readFileSync as M}from"node:fs";import w from"node:path";var V=e=>!["","0",void 0].includes(e),z=(e,r)=>(r.PATH??"").split(w.delimiter).some(t=>t&&H(w.join(t,e))),U=()=>{try{return process.platform==="linux"&&/microsoft/i.test(M("/proc/version","utf8"))}catch{return!1}};function K(e,{platform:r=process.platform,env:t=process.env,wsl:s=U()}={}){let n=encodeURI(e);return V(t.GALLERY_NO_BROWSER)?{skip:"GALLERY_NO_BROWSER is set"}:r==="win32"?{command:w.join(t.SystemRoot||t.windir||"C:\\Windows","System32","rundll32.exe"),args:["url.dll,FileProtocolHandler",n]}:r==="darwin"?{command:"open",args:[n]}:s?{command:"cmd.exe",args:["/c","start",'""',n.replace(/[&^]/g,"^$&")]}:!t.DISPLAY&&!t.WAYLAND_DISPLAY?{skip:"no display here (neither DISPLAY nor WAYLAND_DISPLAY is set)"}:z("xdg-open",t)?{command:"xdg-open",args:[n]}:{skip:"xdg-open is not installed"}}var q="Opened it in the default browser (if that is not Chrome or Edge, open the address there to edit).",T=e=>e.opened?q:`Not opened in a browser: ${e.why}.`;async function O(e,r){let t=K(e,r);return t.skip?{opened:!1,why:t.skip}:new Promise(s=>{let n;try{n=C(t.command,t.args,{detached:!0,stdio:"ignore",windowsHide:!0})}catch(o){return s({opened:!1,why:`${w.basename(t.command)} did not start (${o.code??o.message})`})}n.once("error",o=>s({opened:!1,why:`${w.basename(t.command)} did not start (${o.code??o.message})`})),n.once("spawn",()=>{n.unref(),s({opened:!0})})})}import{packageRoot as Z,previewLogFile as f,projectRoot as G,release as I,reportsDirectory as h}from"../browser/shared/paths.mjs";import{fullAddress as ee}from"../browser/shared/page-address.mjs";import{findPreviewServer as te,galleryVersion as F,portIsFree as re,previewServerFor as ne,readAnnouncement as oe}from"../browser/shared/preview-server.mjs";import{documentLinks as se}from"../browser/shared/reports.mjs";import{documentDirectory as ie,documentFiles as ae,layoutOf as ce}from"../browser/shared/workspace.mjs";var $="\u4EA4\u7ED9\u7528\u6237\uFF08\u73B0\u5728\u5C31\u628A\u8FD9\u4E2A\u5730\u5740\u7ED9\u7528\u6237\uFF1B\u7528 Chrome \u6216 Edge \u6253\u5F00\uFF09\uFF1A",le="Agent \u81EA\u7528\uFF08\u53EA\u6709\u6587\u6863\u9875\uFF0C\u4E0D\u4EA4\u7ED9\u7528\u6237\uFF09\uFF1A",de=e=>`send the user ${e} now, in a message of its own, before any other step; then `;function Ve(e,r){let t=e.at(-1)??"";return`Next: ${t.startsWith($)?de(t.slice($.length)):""}${r}`}async function ze(e,r){let t=e.at(-1)??"";return t.startsWith($)?r.has("--no-browser")?"Not opened in a browser (--no-browser).":T(await O(t.slice($.length))):null}var D="GALLERY_NO_PREVIEW",pe=e=>!["","0",void 0].includes(e),Ue=e=>e.has("--no-preview")||pe(process.env[D]),ue=4317,fe=20,me=(e=process.env)=>{let r=Number(e.GALLERY_PORT);return Number.isInteger(r)&&r>0&&r<65536?r:ue},we=6e4,he=5*1024*1024,$e=k.join(G,"node_modules","vite","bin","vite.js"),ye=k.join(Z,"dist","server.mjs"),ge=e=>new Promise(r=>setTimeout(r,e)),A={reportsDirectory:h},Y=ce(h),R=(e,r)=>`http://127.0.0.1:${e}/generated/${r}.html`,ve=(e,r)=>`${R(e,r)}?agent`,j=e=>`http://127.0.0.1:${e}/`,xe=(e,r)=>se().then(({links:t})=>t,()=>null).then(t=>ee(`http://127.0.0.1:${e}`,r,t));async function ke({first:e=me(),count:r=fe}={}){let t=Number((await m.readFile(Y.lastPortFile,"utf8").catch(()=>"")).trim()),s=Array.from({length:Math.max(0,r)},(n,o)=>e+o);return Number.isInteger(t)&&t>0&&t<65536?[t,...s.filter(n=>n!==t)]:s}async function Le(){return await m.mkdir(k.dirname(f),{recursive:!0}),await m.stat(f).then(r=>r.size,()=>0)>he&&await m.rename(f,`${f}.1`).catch(()=>{}),P.openSync(f,"a")}async function Se(e,r){if(!I){let{writeSharedAssets:p}=await import("./chunk-VNV55RUA.mjs");await p()}let t=await Le();P.writeSync(t,`
3
3
  [${new Date().toISOString()}] ${r}: Gallery ${F} on 127.0.0.1:${e} for ${h}
4
- `);let[s,n]=I?[[ye,"--port",String(e)],Q.homedir()]:[[$e,"--host","127.0.0.1","--port",String(e),"--strictPort"],G],o=J(process.execPath,s,{cwd:n,env:{...process.env,GALLERY_WORKSPACE:k.resolve(h),GALLERY_SERVER_KIND:"cli"},detached:!0,stdio:["ignore",t,t],windowsHide:!0});return P.closeSync(t),o.unref(),o}async function Se({slug:e=null,command:r=`gallery open${e?` ${e}`:""}`,ports:t=null,starting:s=we,baseline:n=!1}={}){let o=()=>!0;if(e){let a=ae(ie(e,h)),c=await m.readFile(a.html,"utf8").catch(()=>null);if(c===null)return{ok:!1,reason:"missing",message:`No document "${e}": ${a.html} does not exist (gallery new ${e} "<\u6807\u9898>" makes one; gallery list lists those there are).`};n&&await import("./chunk-HMHK3EQ6.mjs").then(({previewBaseline:x})=>x(e,c));let i=await m.readFile(a.json,"utf8").then(JSON.parse).catch(()=>({})),v=[/<title>([^<]*)<\/title>/i.exec(c)?.[1]?.trim(),typeof i.title=="string"?i.title.trim():""].filter(Boolean);o=x=>v.length===0||v.some(_=>x.includes(_)||x.includes(X(_)))}let p=t??await xe(),L=p.length?`${Math.min(...p)} to ${Math.max(...p)}`:"none",S=`gallery open${e?` ${e}`:""}`,E=async(a,c=[])=>{let i=await ne({...A,ports:p.slice(a),start:v=>Le(v,r)});return i.busy?.newer?{failed:{ok:!1,reason:"newer",message:`A newer Gallery (${i.busy.version}) serves this workspace (port ${i.busy.port}, pid ${i.busy.pid}) and gave no answer in 10s; this is Gallery ${F}. Update this one (npm i -g @heycys/gallery@latest), or run ${S} again in a while.`}}:i.busy?{failed:{ok:!1,reason:"busy",message:`This workspace's Gallery server (port ${i.busy.port}, pid ${i.busy.pid}) took the request and gave no answer in 10s: it is busy or stuck. Run ${S} again in a while, or stop that process first (gallery stop): a second server of this workspace is not started beside it.`}}:i.stuck?{failed:{ok:!1,reason:"stuck",message:`An older Gallery's server serves this workspace and did not stop: ${i.stuck.message}`}}:i.port===null?{failed:{ok:!1,reason:"ports",message:`No server of this workspace runs, and no port from ${L} is free to start one on: stop a server on one of them (or name another first port: GALLERY_PORT=<n>), then run ${S}.`}}:{...i,passed:[...c,...i.passed]}},u=await E(0);if(u.failed)return u.failed;let{port:l,started:d,passed:b,replaced:W}=u,y=u.running??null,N=Date.now()+s,g="",B=async()=>{if(e){let c=await fetch(`${R(l,e)}?present`,{signal:AbortSignal.timeout(5e3)}).catch(()=>null),i=c?.ok?await c.text():"";return g=c?i?`HTTP ${c.status} without the title`:`HTTP ${c.status}`:"no answer",!!(i&&o(i))}let a=await fetch(`http://127.0.0.1:${l}/__gallery/workspace/info`,{signal:AbortSignal.timeout(5e3)}).catch(()=>null);return g=a?`HTTP ${a.status}`:"no answer",!!a?.ok};for(;;await ge(300)){if(Date.now()>N)return{ok:!1,reason:"timeout",message:`${e?R(l,e):j(l)} did not answer${e?" with the document's title":""} in ${s/1e3}s (${g})${d?`; the server's output is in ${f}`:""}.`};if(d){let a=await te({...A,answering:!0});if(a&&a.pid!==d.pid){if(d.exitCode===null)try{process.kill(d.pid)}catch{}({port:l}=a),y={pid:a.pid,kind:(await oe(A))?.kind??"cli",version:null},d=null;continue}if(!a&&d.exitCode===null){g="the server started has not announced itself yet";continue}if(!a){if(!await re(l)){if(u=await E(p.indexOf(l)+1,[...b,`${l} (taken by another program while the server started)`]),u.failed)return u.failed;({port:l,started:d,passed:b}=u),y=u.running??null,N=Date.now()+s;continue}let c=await m.readFile(f,"utf8").catch(()=>"");return{ok:!1,reason:"stopped",message:`The Gallery server on port ${l} stopped (exit ${d.exitCode}). Its last words (${f}):
4
+ `);let[s,n]=I?[[ye,"--port",String(e)],Q.homedir()]:[[$e,"--host","127.0.0.1","--port",String(e),"--strictPort"],G],o=J(process.execPath,s,{cwd:n,env:{...process.env,GALLERY_WORKSPACE:k.resolve(h),GALLERY_SERVER_KIND:"cli"},detached:!0,stdio:["ignore",t,t],windowsHide:!0});return P.closeSync(t),o.unref(),o}async function be({slug:e=null,command:r=`gallery open${e?` ${e}`:""}`,ports:t=null,starting:s=we,baseline:n=!1}={}){let o=()=>!0;if(e){let a=ae(ie(e,h)),c=await m.readFile(a.html,"utf8").catch(()=>null);if(c===null)return{ok:!1,reason:"missing",message:`No document "${e}": ${a.html} does not exist (gallery new ${e} "<\u6807\u9898>" makes one; gallery list lists those there are).`};n&&await import("./chunk-SGJWQKEI.mjs").then(({previewBaseline:x})=>x(e,c));let i=await m.readFile(a.json,"utf8").then(JSON.parse).catch(()=>({})),v=[/<title>([^<]*)<\/title>/i.exec(c)?.[1]?.trim(),typeof i.title=="string"?i.title.trim():""].filter(Boolean);o=x=>v.length===0||v.some(_=>x.includes(_)||x.includes(X(_)))}let p=t??await ke(),L=p.length?`${Math.min(...p)} to ${Math.max(...p)}`:"none",S=`gallery open${e?` ${e}`:""}`,E=async(a,c=[])=>{let i=await ne({...A,ports:p.slice(a),start:v=>Se(v,r)});return i.busy?.newer?{failed:{ok:!1,reason:"newer",message:`A newer Gallery (${i.busy.version}) serves this workspace (port ${i.busy.port}, pid ${i.busy.pid}) and gave no answer in 10s; this is Gallery ${F}. Update this one (npm i -g @heycys/gallery@latest), or run ${S} again in a while.`}}:i.busy?{failed:{ok:!1,reason:"busy",message:`This workspace's Gallery server (port ${i.busy.port}, pid ${i.busy.pid}) took the request and gave no answer in 10s: it is busy or stuck. Run ${S} again in a while, or stop that process first (gallery stop): a second server of this workspace is not started beside it.`}}:i.stuck?{failed:{ok:!1,reason:"stuck",message:`An older Gallery's server serves this workspace and did not stop: ${i.stuck.message}`}}:i.port===null?{failed:{ok:!1,reason:"ports",message:`No server of this workspace runs, and no port from ${L} is free to start one on: stop a server on one of them (or name another first port: GALLERY_PORT=<n>), then run ${S}.`}}:{...i,passed:[...c,...i.passed]}},u=await E(0);if(u.failed)return u.failed;let{port:l,started:d,passed:b,replaced:W}=u,y=u.running??null,N=Date.now()+s,g="",B=async()=>{if(e){let c=await fetch(`${R(l,e)}?present`,{signal:AbortSignal.timeout(5e3)}).catch(()=>null),i=c?.ok?await c.text():"";return g=c?i?`HTTP ${c.status} without the title`:`HTTP ${c.status}`:"no answer",!!(i&&o(i))}let a=await fetch(`http://127.0.0.1:${l}/__gallery/workspace/info`,{signal:AbortSignal.timeout(5e3)}).catch(()=>null);return g=a?`HTTP ${a.status}`:"no answer",!!a?.ok};for(;;await ge(300)){if(Date.now()>N)return{ok:!1,reason:"timeout",message:`${e?R(l,e):j(l)} did not answer${e?" with the document's title":""} in ${s/1e3}s (${g})${d?`; the server's output is in ${f}`:""}.`};if(d){let a=await te({...A,answering:!0});if(a&&a.pid!==d.pid){if(d.exitCode===null)try{process.kill(d.pid)}catch{}({port:l}=a),y={pid:a.pid,kind:(await oe(A))?.kind??"cli",version:null},d=null;continue}if(!a&&d.exitCode===null){g="the server started has not announced itself yet";continue}if(!a){if(!await re(l)){if(u=await E(p.indexOf(l)+1,[...b,`${l} (taken by another program while the server started)`]),u.failed)return u.failed;({port:l,started:d,passed:b}=u),y=u.running??null,N=Date.now()+s;continue}let c=await m.readFile(f,"utf8").catch(()=>"");return{ok:!1,reason:"stopped",message:`The Gallery server on port ${l} stopped (exit ${d.exitCode}). Its last words (${f}):
5
5
  ${c.split(`
6
6
  `).slice(-15).join(`
7
7
  `)}`}}}if(await B())break}return await m.writeFile(Y.lastPortFile,`${l}
8
- `).catch(()=>{}),{ok:!0,port:l,pid:d?.pid??y?.pid??null,kind:y?.kind??"cli",started:!!d,replaced:W??null,passed:b}}var be=e=>e.length<2?e.join(""):`${e.slice(0,-1).join(", ")} and ${e.at(-1)}`;function Ae({port:e,pid:r,kind:t,started:s,replaced:n,passed:o=[]}){let p=[`pid ${r}`,...t==="dev"?["npm run dev's"]:[],...s?[`started now${o.length?`, after passing over ${be(o)}`:""}`]:[],...n?[`it replaced Gallery ${n.version??"an older version"}'s server, pid ${n.pid}`]:[]],L=s?`; its log: ${f}`:"";return`This workspace's Gallery server runs on port ${e} (${p.join(", ")}${L}). This command is done; the server runs on after it (nothing to wait for or keep running).`}async function Pe(e,r,t=null){return[Ae(r),...e?[`${le}${R(r.port,e)}`]:[],`${$}${e?await ve(r.port,{slug:e,block:t}):j(r.port)}`]}async function Ue(e,{skipped:r,command:t,ports:s=null}){let n=`gallery open ${e} starts it and prints the address to give the user`;if(r)return[`Preview: not started (--no-preview or ${D}): ${n}.`];let o=await Se({slug:e,command:t,ports:s});return o.ok?Pe(e,o):[`Preview: not started: ${o.message}`,`When that is fixed, ${n}.`]}export{Me as a,Ve as b,ze as c,R as d,j as e,xe as f,Se as g,Pe as h,Ue as i};
8
+ `).catch(()=>{}),{ok:!0,port:l,pid:d?.pid??y?.pid??null,kind:y?.kind??"cli",started:!!d,replaced:W??null,passed:b}}var Ae=e=>e.length<2?e.join(""):`${e.slice(0,-1).join(", ")} and ${e.at(-1)}`;function Pe({port:e,pid:r,kind:t,started:s,replaced:n,passed:o=[]}){let p=[`pid ${r}`,...t==="dev"?["npm run dev's"]:[],...s?[`started now${o.length?`, after passing over ${Ae(o)}`:""}`]:[],...n?[`it replaced Gallery ${n.version??"an older version"}'s server, pid ${n.pid}`]:[]],L=s?`; its log: ${f}`:"";return`This workspace's Gallery server runs on port ${e} (${p.join(", ")}${L}). This command is done; the server runs on after it (nothing to wait for or keep running).`}async function Re(e,r,t=null){return[Pe(r),...e?[`${le}${ve(r.port,e)}`]:[],`${$}${e?await xe(r.port,{slug:e,block:t}):j(r.port)}`]}async function Ke(e,{skipped:r,command:t,ports:s=null}){let n=`gallery open ${e} starts it and prints the address to give the user`;if(r)return[`Preview: not started (--no-preview or ${D}): ${n}.`];let o=await be({slug:e,command:t,ports:s});return o.ok?Re(e,o):[`Preview: not started: ${o.message}`,`When that is fixed, ${n}.`]}export{Ve as a,ze as b,Ue as c,ve as d,j as e,ke as f,be as g,Re as h,Ke as i};
@@ -1,5 +1,5 @@
1
1
  import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
2
- var n=["init","new","import","open","serve","stop","check","export","qa","list","component","skill"],a=`The workspace (the folder of your documents) is --workspace <dir>, else GALLERY_WORKSPACE, else the
2
+ var n=["init","new","import","open","serve","stop","check","export","qa","list","move","set","component","skill"],a=`The workspace (the folder of your documents) is --workspace <dir>, else GALLERY_WORKSPACE, else the
3
3
  nearest folder up from here holding gallery.json (gallery init makes one), else ~/Documents/Gallery (on Windows
4
4
  the Documents folder Explorer shows, OneDrive's when OneDrive backs it up).`,e=`A document is named by its slug, by its link (\u5468\u62A5-k3xv9q2a, what gallery list shows after /#) or by a
5
5
  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
@@ -11,10 +11,13 @@ holding report.html or doc.html) into the workspace: every document whose slug i
11
11
  others listed as skipped), its preferences.md when the workspace has none, the sidebar's order, the
12
12
  \u5199\u4F5C\u504F\u597D page, the custom emoji and the documents' recent versions. The old folder is only read:
13
13
  nothing there is changed, moved or deleted.
14
- Exits 1 when the workspace cannot be written or --from names no folder.`,new:`Usage: gallery new <slug> "<title>" ["<description>"] [--no-preview] [--no-browser]
14
+ Exits 1 when the workspace cannot be written or --from names no folder.`,new:`Usage: gallery new <slug> "<title>" ["<description>"] [--under <document>] [--after <document> | --first] [--no-preview] [--no-browser]
15
15
  A new document in <workspace>/<slug>/ from the starter: its doc.html, holding the starter's section
16
- to replace, and doc.json, with the title and the description (\u65B0\u6587\u6863 when none is given). Then says
17
- where it wrote (the workspace), where the user's writing preferences are (\u5199\u4F5C\u504F\u597D,
16
+ to replace, and doc.json, with the title and the description (\u65B0\u6587\u6863 when none is given). Where it goes
17
+ in the sidebar's tree: under --under's document, last (first with --first), or right after --after's
18
+ (at that one's level); neither, at the top level, last. A document is named there by its slug, link
19
+ or address (gallery help says how), and must be there, not in the trash; the \u5199\u4F5C\u504F\u597D page holds none.
20
+ Then says where it went (Placed it \u2026), where it wrote (the workspace), where the user's writing preferences are (\u5199\u4F5C\u504F\u597D,
18
21
  <workspace>/preferences.md, to read first: made from Gallery's default when there are none yet) and
19
22
  the next steps (the first: send the user the address now), and last starts this workspace's Gallery
20
23
  server (or uses the one running: it runs on after this command), opens the default browser at the
@@ -24,7 +27,8 @@ browser. Editing needs Chrome or Edge.
24
27
  A title or a description that starts with "-" and a letter would be read as an option: put "--"
25
28
  before the arguments (gallery new q3-review -- "-Q3 \u56DE\u987E").
26
29
  Exits 1 when the document exists, or the slug is the workspace's own (exports, the \u5199\u4F5C\u504F\u597D page's) or
27
- a document's in the trash.`,import:`Usage: gallery import <file> [<slug> ["<title>"]] [--no-preview] [--no-browser]
30
+ a document's in the trash, or a document --under or --after names is not there (nothing made), or
31
+ the new one could not be placed (made, at the top level); 2 for a document named that is in the trash.`,import:`Usage: gallery import <file> [<slug> ["<title>"]] [--no-preview] [--no-browser]
28
32
  New documents made of a file, as the workbench's \u5BFC\u5165 makes them: Markdown (.md .markdown .mdx .txt
29
33
  .text), HTML (.html .htm .xhtml, a Gallery export too), a table (.csv .tsv), Word (.docx), PDF (.pdf,
30
34
  its text), EPUB (.epub) or a .zip of them (a Notion export: one document a page, nested as there).
@@ -99,13 +103,44 @@ with a fresh profile.
99
103
  Exits 1 when anything fails (or the export it ran first did), 3 when something could not be
100
104
  verified (UNVERIFIED: no browser, or one that did not start), 2 when an export is missing or stale
101
105
  with --no-export or --blocks names an id the document has not, else 0. A warning never fails.`,list:`Usage: gallery list [<words>...]
106
+ gallery list --tree [<document>]
102
107
  The workspace's documents, for an Agent to find the one the user means: each one's slug and title,
103
- its description, its address (\u5730\u5740\uFF1A/#<link>, after the port of the workspace's server), when its file
108
+ its description, where it is in the sidebar's tree when it is under another (\u4F4D\u7F6E\uFF1Athe documents above
109
+ it, from the top), its address (\u5730\u5740\uFF1A/#<link>, after the port of the workspace's server), when its file
104
110
  was last written and where that file is, the one edited last first.
105
111
  With words, only those whose title, description or slug holds any of them (case alike, Chinese found
106
- inside words), the best first; with a document's link or whole address, that document, or that it is
107
- in the trash. First, the workspace and where \u5199\u4F5C\u504F\u597D is (made from Gallery's default when there is none
108
- yet).`,component:`Usage: gallery component new <id> [--script]
112
+ inside words), the best first, then those whose text holds them, each with its first place there
113
+ (\u6B63\u6587\uFF1A\u2026); with a document's link or whole address, that document, or that it is in the trash.
114
+ --tree lists them as the sidebar shows them, in its order, each under the one it is under, indented
115
+ two spaces a level: a line each, its slug, its title (its emoji before it), its description and its
116
+ last edit. --tree <document>: that document and the documents under it, after its \u4F4D\u7F6E line.
117
+ ${e}
118
+ First, the workspace and where \u5199\u4F5C\u504F\u597D is (made from Gallery's default when there is none yet).
119
+ Exits 1 when --tree names a document that is not there, 2 one in the trash.`,move:`Usage: gallery move <document> (--under <document> | --top) [--after <document> | --first]
120
+ Moves a document in the sidebar's tree, with the documents under it: under --under's document, to the
121
+ top level (--top), or where it is now (neither); right after --after's document (one at that level,
122
+ whose level it is when neither --under nor --top says one), first (--first), else last. Written
123
+ through the workspace's running server when there is one (an open workbench shows it at once), else
124
+ here. Nothing in the documents' files changes: links between documents go by their folders, which
125
+ stay where they are.
126
+ ${e}
127
+ Prints where it went and where it was, then its place (\u4F4D\u7F6E\uFF1A\u2026, as gallery list says it).
128
+ Exits 0 when it moved or is there already; 1 when a document named is not there or is the \u5199\u4F5C\u504F\u597D page
129
+ (listed apart: it moves nowhere and holds none), when the place is under itself or a document under
130
+ it, or --after names one at another level; 2 for a document in the trash.`,set:`Usage: gallery set <document> [--title "<title>"] [--icon <icon>|none] [--description "<text>"]
131
+ Changes a document's title, page icon or description as the workbench's \u91CD\u547D\u540D and the page's icon
132
+ picker do: the title in doc.html (the h1 of its header, and <title> where that holds the h1's words,
133
+ else the whole of it) and in doc.json; the icon in the header (div.doc-icon before the h1: made,
134
+ changed, or taken away with none) and in doc.json; the description in doc.json. An icon is an emoji,
135
+ an icon of the \u56FE\u6807 tab (/icons/<name>_<color>.svg, Tabler's /icons/tabler/<name>_<color>.svg, the
136
+ colors gray, lightgray, brown, yellow, orange, green, blue, purple, pink, red) or a picture of the
137
+ document's folder (assets/<file>). doc.html is written as an Agent writes it, the rest of it as it
138
+ is: the page open in the browser shows it, and the workbench's sidebar the new title and icon.
139
+ A title that starts with "-" and a letter is written --title="-Q3 \u56DE\u987E".
140
+ ${e}
141
+ Prints what changed, then the files to re-read before editing them.
142
+ Exits 1 when the document is not there or is the \u5199\u4F5C\u504F\u597D page, its page has no h1.doc-title, its
143
+ doc.json does not read, or the picture is not in its folder; 2 for an icon that is none of these.`,component:`Usage: gallery component new <id> [--script] [--flow]
109
144
  gallery component list
110
145
  gallery component show <id>
111
146
  gallery component check <id>
@@ -115,7 +150,8 @@ yet).`,component:`Usage: gallery component new <id> [--script]
115
150
  A component package is a block to use again, kept in the workspace: components/<scope>/<name>/. An id
116
151
  is <scope>/<name>, or a <name> alone in the scope local; a document uses one by an element naming it.
117
152
  new starts a package: component.json, template.html, example.html, writing.md and style.css, and with
118
- --script a kit.js. It passes check as it stands, and says what to write next.
153
+ --script a kit.js; with --flow a slot, body, in place of its paragraph, where a document writes blocks
154
+ of its own. It passes check as it stands, and says what to write next.
119
155
  Exits 1 when the id is taken.
120
156
  list says what the workspace has now: the components to write with, each with its version, then those
121
157
  not to write with now and why: hidden, disabled, one that does not load, a manifest one level too shallow;
@@ -127,14 +163,15 @@ never a failure, in five sections: 1 the manifest, with template.html there, tex
127
163
  words and marks alone, and a note on a Chinese name no word of its words spells whole in pinyin, a
128
164
  syllable a character, by how many syllables a word reads as; 2 kit.js: what a browser refuses, what
129
165
  an export refuses, what it registers, a type check against sdk/; 3 style.css: every selector in the
130
- instance, what an export cannot hold; 4 template.html and example.html, each read as a document's page
131
- by what gallery check runs, and template.html as what a menu can put in; 5
166
+ instance, what an export cannot hold, and a note on one that goes down into a slot; 4 template.html
167
+ and example.html, each read as a document's page by what gallery check runs, and template.html as what
168
+ a menu can put in; 5
132
169
  both in a temporary document, exported and opened as gallery qa opens one, in Chrome or Edge under the export's
133
170
  policy: what the console and the policy say, a dialog or a window it opens, mount then dehydrate then
134
171
  mount and copies put back giving the same DOM (a drawing neither the manifest's runtime nor dehydrate
135
- names piles up, and what piles up outside the instance is named too), a text part the component
136
- redraws, a data part a mount changes, a write with no gesture once the page takes edits, the way back
137
- to the file (a way back line: what the component's example wrote, each part with how many of its
172
+ names piles up, and what piles up outside the instance is named too), a slot the component writes in
173
+ or moves, a text part the component redraws, a data part a mount changes, a write with no gesture
174
+ once the page takes edits, the way back to the file (a way back line: what the component's example wrote, each part with how many of its
138
175
  lines the write took out and put in, and that the server took it; a note on a write that lays a part
139
176
  out anew, and on a list a card is dropped on that listens for dragover and not for dragenter), a page
140
177
  wider than the window, and the pictures, in <workspace>/.gallery/qa/components/<id>/, its absolute
@@ -204,7 +241,9 @@ Gallery: documents written as HTML, edited in the browser, exported as one offli
204
241
  gallery check [<slug>...] check documents (none named: all)
205
242
  gallery export <slug>... | --all write <workspace>/exports/<slug>.html
206
243
  gallery qa <slug>... [--blocks a,b] [--tiles] look at exports in Chrome or Edge
207
- gallery list [<words>...] the documents, or those the words name
244
+ gallery list [<words>...] | --tree [<slug>] the documents, those the words name, or the tree
245
+ gallery move <slug> --under <slug> | --top move a document (and those under it) in the tree
246
+ gallery set <slug> --title|--icon|--description change a document's title, icon or description
208
247
  gallery component new|list|show|check [<id>] make, list, read and check component packages
209
248
  gallery component try <slug> --press <selector> a reader's gesture on an instance, and what it wrote
210
249
  gallery skill install [--agent claude|codex] write the Agent's skill for this version
@@ -1,5 +1,5 @@
1
1
  import { createRequire as __galleryRequire } from "node:module"; import { fileURLToPath as __galleryPath } from "node:url"; const require = __galleryRequire(import.meta.url); const __filename = __galleryPath(import.meta.url); const __dirname = __galleryPath(new URL(".", import.meta.url));
2
- import{a as g}from"./chunk-HYMEEXKN.mjs";import{createRequire as re}from"node:module";import{typescriptFile as ae}from"../browser/shared/paths.mjs";var ce=re(import.meta.url),B=null;function fe(){return B??=ce(ae??"typescript"),B}var $=new Proxy({},{get:(e,n)=>fe()[n]});import _ from"node:fs/promises";import h from"node:path";import{COMPONENTS as D,instancesOf as ue}from"../browser/shared/components/index.mjs";import{PACKAGE_MARK as q}from"../browser/shared/components/installed.mjs";import{MATH_IGNORED_TAGS as pe}from"../browser/shared/components/math.mjs";import{attr as x,elementsOf as b,walk as y}from"../browser/shared/html-tree.mjs";import I from"node:path";import de from"node:vm";var L=()=>{throw new Error("esbuild is not in the release: Gallery 0.1.0 calls it only in a source checkout")},Le=L,J=L;var Te=new Proxy({},{get:L});import{projectRoot as le}from"../browser/shared/paths.mjs";var T=I.join(le,"src","shared","components","index.mjs");function F(e){let{outputFiles:n}=J({stdin:{contents:`import { FLOWS, FLOW_BLOCKS, runtimeDescriptions } from ${JSON.stringify(e)}; module.exports = { descriptions: runtimeDescriptions(), flows: FLOWS, blockFlows: FLOW_BLOCKS };`,resolveDir:I.dirname(e),loader:"js"},bundle:!0,write:!1,format:"cjs",platform:"node",logLevel:"silent"}),s={module:{exports:null}};return de.runInNewContext(n[0].text,s),JSON.parse(JSON.stringify(s.module.exports))}var W=(e=T)=>F(e).descriptions,G=(e=T)=>F(e).flows,U=(e=T)=>F(e).blockFlows;import{kitPublicDirectory as me,projectRoot as H,release as Y,vendorDirectory as z}from"../browser/shared/paths.mjs";var P=h.join(H,"node_modules"),he=h.join(P,"d3","dist","d3.min.js"),S=Y?h.join(z,"katex"):h.join(P,"katex","dist"),xe=h.join(S,"fonts"),He=h.join(S,"contrib","mhchem.min.js"),u=[{id:"styles",file:"report.css",build:{styles:"styles/index.css"},always:!0},{id:"katex-styles",vendor:{path:"/vendor/katex/katex.min.css",source:h.join(S,"katex.min.css")}},{id:"runtime",file:"runtime.js",build:{bundle:"runtime/index.js",options:()=>({minify:!1,define:{__COMPONENT_RUNTIME__:JSON.stringify(W()),__COMPONENT_FLOWS__:JSON.stringify(G()),__COMPONENT_BLOCK_FLOWS__:JSON.stringify(U())}})},api:"DocKit",always:!0},{id:"code",file:"code.js",build:{bundle:"code.js",options:{minify:!0,legalComments:"inline"}},api:"DocCode",after:["runtime"]},{id:"state",file:"state.js",build:{read:"state.js"},api:"DocState",always:!0},{id:"sheets",file:"sheets.js",build:{read:"sheets.js"},api:"DocSheets",after:["runtime","state"]},{id:"tokens",file:"tokens.js",build:{read:"tokens.js"},api:"DocTokens",always:!0},{id:"ui",file:"ui.js",build:{bundle:"ui.js",options:{minify:!1}},added:!0,after:["runtime","state","tokens"]},{id:"dialogs",file:"dialogs.js",build:{read:"dialogs.js"},api:"DocDialogs",after:["runtime"]},{id:"katex",vendor:{path:"/vendor/katex/katex.min.js",source:h.join(S,"katex.min.js")},umd:!0},{id:"katex-auto-render",vendor:{path:"/vendor/katex/auto-render.min.js",source:h.join(S,"contrib","auto-render.min.js")},umd:!0,after:["katex"]},{id:"math",file:"math.js",build:{bundle:"math-bundle.js",options:{minify:!1,legalComments:"inline",alias:{katex:h.join(H,"src","render","kit","page-katex.js")},nodePaths:[h.join(P,"katex")]}},api:"DocMath",after:["runtime","katex-styles","katex","katex-auto-render"]},{id:"d3",vendor:{path:"/vendor/d3.v7.9.0.min.js",source:he},api:"d3",umd:!0},{id:"charts",file:"charts.js",build:{bundle:"charts/index.js",options:{minify:!1}},api:"DocCharts",after:["runtime","tokens"]},{id:"tables",file:"tables.js",build:{bundle:"tables/index.js",options:{minify:!1}},api:"DocTables",after:["runtime"]}],m=e=>e.file?`/kit/${e.file}`:e.vendor.path,ge=e=>e.file?h.join(me,e.file):h.join(z,...e.vendor.path.split("/").slice(2));if(Y)for(let e of u)e.vendor&&(e.vendor.source=ge(e));var O=e=>m(e).endsWith(".css"),E=e=>e.file?"data-doc-kit":"data-doc-vendor",C=e=>u.find(n=>n.id===e),w=(e,n=m(e))=>O(e)?`<link rel="stylesheet" href="${n}" ${E(e)}="${e.id}">`:`<script src="${n}" ${E(e)}="${e.id}"></script>`,we=u.map(e=>({id:e.id,tag:w(e),always:!!e.always,element:O(e)?"style":"script",attribute:E(e)}));function Ye(e,n=m){let s=new Set,i=t=>{s.has(t)||(s.add(t),C(t)?.after?.forEach(i))};return e.forEach(i),u.filter(t=>s.has(t.id)&&!t.always&&!t.added).map(t=>w(t,n(t)))}function ye(e=u,n=D){let s=[],i=e.map(t=>t.id);for(let t of new Set(i.filter((a,o)=>i.indexOf(a)!==o)))s.push(`the asset "${t}" is listed twice`);for(let t of e){!!t.file==!!t.vendor&&s.push(`the asset "${t.id}" is a kit file (file) or a vendor file (vendor), one of them`),t.file&&!["read","bundle","styles"].some(o=>typeof t.build?.[o]=="string")&&s.push(`the kit file "${t.file}" does not say how it is made (build: read, bundle or styles)`),t.vendor&&!(t.vendor.path&&t.vendor.source)&&s.push(`the vendor asset "${t.id}" needs its public path and its source`);for(let o of t.after??[])i.includes(o)?i.indexOf(o)>i.indexOf(t.id)&&s.push(`the asset "${t.id}" loads after "${o}", which the list puts after it`):s.push(`the asset "${t.id}" loads after "${o}", which is no asset`);let a=n.filter(o=>(o.assets??[]).includes(t.id));!t.always&&!t.api&&!t.added&&a.length===0&&s.push(`no report would keep the asset "${t.id}": it is not always kept, defines no global and no component needs it`)}for(let t of n)for(let a of t.assets??[])i.includes(a)||s.push(`the component "${t.id}" needs "${a}", which is no asset`);return s}{let e=ye();if(e.length>0)throw new Error(`src/render/assets.mjs: ${e.join("; ")}`)}var K=/^(?:|module|(?:text|application)\/(?:x-)?(?:javascript|ecmascript)|text\/javascript1\.[0-5]|text\/(?:jscript|livescript))$/,$e=/^application\/(?:\S+\+)?json$/,N=e=>(x(e,"type")??"").trim().toLowerCase();function V(e){let n=$.createSourceFile("report.js",e,$.ScriptTarget.Latest,!1,$.ScriptKind.JS),s=[],i=[n];for(;i.length>0;){let t=i.pop();if(t.kind>=$.SyntaxKind.FirstJSDocNode&&t.kind<=$.SyntaxKind.LastJSDocNode)continue;let a=t.getChildren(n);a.length===0&&s.push(e.slice(t.getStart(n),t.end));for(let o=a.length-1;o>=0;o-=1)i.push(a[o])}return s.join(" ")}var Q=e=>new RegExp(`\\b(?:${e.filter(n=>n.api).map(n=>n.api).join("|")})\\b`);function ke(e,n){let s=[],i=t=>{n.test(t)&&s.push(V(t))};return y(e,t=>{t.tagName==="script"&&x(t,"src")===void 0&&K.test(N(t))&&i(t.childNodes.map(a=>a.value??"").join(""));for(let{name:a,value:o}of t.attrs??[]){if(/^on/.test(a)){i(o);continue}let f=o.replace(/[\t\n\r]/g,"").replace(/^[\x00-\x20]+/,"");if(!/^javascript:/i.test(f))continue;let r=f.slice(11);try{r=decodeURIComponent(r)}catch{}i(r)}}),s.join(`
2
+ import{a as g}from"./chunk-HYMEEXKN.mjs";import{createRequire as re}from"node:module";import{typescriptFile as ae}from"../browser/shared/paths.mjs";var ce=re(import.meta.url),B=null;function fe(){return B??=ce(ae??"typescript"),B}var $=new Proxy({},{get:(e,n)=>fe()[n]});import _ from"node:fs/promises";import h from"node:path";import{COMPONENTS as D,instancesOf as ue}from"../browser/shared/components/index.mjs";import{PACKAGE_MARK as q}from"../browser/shared/components/installed.mjs";import{MATH_IGNORED_TAGS as pe}from"../browser/shared/components/math.mjs";import{attr as x,elementsOf as b,walk as y}from"../browser/shared/html-tree.mjs";import I from"node:path";import de from"node:vm";var L=()=>{throw new Error("esbuild is not in the release: Gallery 0.1.1 calls it only in a source checkout")},Le=L,J=L;var Te=new Proxy({},{get:L});import{projectRoot as le}from"../browser/shared/paths.mjs";var T=I.join(le,"src","shared","components","index.mjs");function F(e){let{outputFiles:n}=J({stdin:{contents:`import { FLOWS, FLOW_BLOCKS, runtimeDescriptions } from ${JSON.stringify(e)}; module.exports = { descriptions: runtimeDescriptions(), flows: FLOWS, blockFlows: FLOW_BLOCKS };`,resolveDir:I.dirname(e),loader:"js"},bundle:!0,write:!1,format:"cjs",platform:"node",logLevel:"silent"}),s={module:{exports:null}};return de.runInNewContext(n[0].text,s),JSON.parse(JSON.stringify(s.module.exports))}var W=(e=T)=>F(e).descriptions,G=(e=T)=>F(e).flows,U=(e=T)=>F(e).blockFlows;import{kitPublicDirectory as me,projectRoot as H,release as Y,vendorDirectory as z}from"../browser/shared/paths.mjs";var P=h.join(H,"node_modules"),he=h.join(P,"d3","dist","d3.min.js"),S=Y?h.join(z,"katex"):h.join(P,"katex","dist"),xe=h.join(S,"fonts"),He=h.join(S,"contrib","mhchem.min.js"),u=[{id:"styles",file:"report.css",build:{styles:"styles/index.css"},always:!0},{id:"katex-styles",vendor:{path:"/vendor/katex/katex.min.css",source:h.join(S,"katex.min.css")}},{id:"runtime",file:"runtime.js",build:{bundle:"runtime/index.js",options:()=>({minify:!1,define:{__COMPONENT_RUNTIME__:JSON.stringify(W()),__COMPONENT_FLOWS__:JSON.stringify(G()),__COMPONENT_BLOCK_FLOWS__:JSON.stringify(U())}})},api:"DocKit",always:!0},{id:"code",file:"code.js",build:{bundle:"code.js",options:{minify:!0,legalComments:"inline"}},api:"DocCode",after:["runtime"]},{id:"state",file:"state.js",build:{read:"state.js"},api:"DocState",always:!0},{id:"sheets",file:"sheets.js",build:{read:"sheets.js"},api:"DocSheets",after:["runtime","state"]},{id:"tokens",file:"tokens.js",build:{read:"tokens.js"},api:"DocTokens",always:!0},{id:"ui",file:"ui.js",build:{bundle:"ui.js",options:{minify:!1}},added:!0,after:["runtime","state","tokens"]},{id:"dialogs",file:"dialogs.js",build:{read:"dialogs.js"},api:"DocDialogs",after:["runtime"]},{id:"katex",vendor:{path:"/vendor/katex/katex.min.js",source:h.join(S,"katex.min.js")},umd:!0},{id:"katex-auto-render",vendor:{path:"/vendor/katex/auto-render.min.js",source:h.join(S,"contrib","auto-render.min.js")},umd:!0,after:["katex"]},{id:"math",file:"math.js",build:{bundle:"math-bundle.js",options:{minify:!1,legalComments:"inline",alias:{katex:h.join(H,"src","render","kit","page-katex.js")},nodePaths:[h.join(P,"katex")]}},api:"DocMath",after:["runtime","katex-styles","katex","katex-auto-render"]},{id:"d3",vendor:{path:"/vendor/d3.v7.9.0.min.js",source:he},api:"d3",umd:!0},{id:"charts",file:"charts.js",build:{bundle:"charts/index.js",options:{minify:!1}},api:"DocCharts",after:["runtime","tokens"]},{id:"tables",file:"tables.js",build:{bundle:"tables/index.js",options:{minify:!1}},api:"DocTables",after:["runtime"]}],m=e=>e.file?`/kit/${e.file}`:e.vendor.path,ge=e=>e.file?h.join(me,e.file):h.join(z,...e.vendor.path.split("/").slice(2));if(Y)for(let e of u)e.vendor&&(e.vendor.source=ge(e));var O=e=>m(e).endsWith(".css"),E=e=>e.file?"data-doc-kit":"data-doc-vendor",C=e=>u.find(n=>n.id===e),w=(e,n=m(e))=>O(e)?`<link rel="stylesheet" href="${n}" ${E(e)}="${e.id}">`:`<script src="${n}" ${E(e)}="${e.id}"></script>`,we=u.map(e=>({id:e.id,tag:w(e),always:!!e.always,element:O(e)?"style":"script",attribute:E(e)}));function Ye(e,n=m){let s=new Set,i=t=>{s.has(t)||(s.add(t),C(t)?.after?.forEach(i))};return e.forEach(i),u.filter(t=>s.has(t.id)&&!t.always&&!t.added).map(t=>w(t,n(t)))}function ye(e=u,n=D){let s=[],i=e.map(t=>t.id);for(let t of new Set(i.filter((a,o)=>i.indexOf(a)!==o)))s.push(`the asset "${t}" is listed twice`);for(let t of e){!!t.file==!!t.vendor&&s.push(`the asset "${t.id}" is a kit file (file) or a vendor file (vendor), one of them`),t.file&&!["read","bundle","styles"].some(o=>typeof t.build?.[o]=="string")&&s.push(`the kit file "${t.file}" does not say how it is made (build: read, bundle or styles)`),t.vendor&&!(t.vendor.path&&t.vendor.source)&&s.push(`the vendor asset "${t.id}" needs its public path and its source`);for(let o of t.after??[])i.includes(o)?i.indexOf(o)>i.indexOf(t.id)&&s.push(`the asset "${t.id}" loads after "${o}", which the list puts after it`):s.push(`the asset "${t.id}" loads after "${o}", which is no asset`);let a=n.filter(o=>(o.assets??[]).includes(t.id));!t.always&&!t.api&&!t.added&&a.length===0&&s.push(`no report would keep the asset "${t.id}": it is not always kept, defines no global and no component needs it`)}for(let t of n)for(let a of t.assets??[])i.includes(a)||s.push(`the component "${t.id}" needs "${a}", which is no asset`);return s}{let e=ye();if(e.length>0)throw new Error(`src/render/assets.mjs: ${e.join("; ")}`)}var K=/^(?:|module|(?:text|application)\/(?:x-)?(?:javascript|ecmascript)|text\/javascript1\.[0-5]|text\/(?:jscript|livescript))$/,$e=/^application\/(?:\S+\+)?json$/,N=e=>(x(e,"type")??"").trim().toLowerCase();function V(e){let n=$.createSourceFile("report.js",e,$.ScriptTarget.Latest,!1,$.ScriptKind.JS),s=[],i=[n];for(;i.length>0;){let t=i.pop();if(t.kind>=$.SyntaxKind.FirstJSDocNode&&t.kind<=$.SyntaxKind.LastJSDocNode)continue;let a=t.getChildren(n);a.length===0&&s.push(e.slice(t.getStart(n),t.end));for(let o=a.length-1;o>=0;o-=1)i.push(a[o])}return s.join(" ")}var Q=e=>new RegExp(`\\b(?:${e.filter(n=>n.api).map(n=>n.api).join("|")})\\b`);function ke(e,n){let s=[],i=t=>{n.test(t)&&s.push(V(t))};return y(e,t=>{t.tagName==="script"&&x(t,"src")===void 0&&K.test(N(t))&&i(t.childNodes.map(a=>a.value??"").join(""));for(let{name:a,value:o}of t.attrs??[]){if(/^on/.test(a)){i(o);continue}let f=o.replace(/[\t\n\r]/g,"").replace(/^[\x00-\x20]+/,"");if(!/^javascript:/i.test(f))continue;let r=f.slice(11);try{r=decodeURIComponent(r)}catch{}i(r)}}),s.join(`
3
3
  `)}function je(e,n){let s=[],i=(o,f)=>{for(let r of o.childNodes??[]){let c=r.sourceCodeLocation;r.nodeName==="#comment"||f&&r.nodeName==="#text"?c&&s.push([c.startOffset,c.endOffset]):r.tagName==="script"?i(r,$e.test(N(r))):r.tagName&&i(r.content??r,f||pe.includes(r.tagName))}};i(e,!1);let t="",a=0;for(let[o,f]of s.sort((r,c)=>r[0]-c[0]))o<a||(t+=`${n.slice(a,o)} `,a=f);return t+n.slice(a)}function R(e,n=u,s=D){let i=n.reduce((c,d)=>c.replaceAll(w(d),""),e),t=g(i),a=je(t,i),o=ke(t,Q(n)),f=new Set,r=c=>{f.has(c)||(f.add(c),(n.find(d=>d.id===c)?.after??[]).forEach(r))};for(let c of s){if(!(c.assets??[]).length)continue;((c.uses??[]).some(l=>l.test(a))||c.match&&ue(t,c).length>0)&&c.assets.forEach(r)}for(let c of n)c.api&&new RegExp(`\\b${c.api}\\b`).test(o)&&r(c.id);return f}function ze(e,n=D){let s=R(e,u,n),i=[];for(let t of u){let a=w(t);if(t.always||t.added||s.has(t.id)||!e.includes(a))continue;let o=a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");e=e.replace(new RegExp(`[ \\t]*${o}[ \\t]*\\r?\\n?`),""),i.push(t.id)}return{html:e,removed:i,used:s}}function M(e,n){let s=[];return y(n,i=>{let t=Z(i),a=t===void 0?void 0:u.find(f=>m(f)===t.trim()),o=i.sourceCodeLocation;!a||!o||s.push({asset:a,start:o.startOffset,end:o.endOffset,line:o.startLine,exact:e.slice(o.startOffset,o.endOffset)===w(a)})},{inTemplates:!1}),s}var X=e=>e.tagName==="style"||e.tagName==="link"&&(x(e,"rel")??"").toLowerCase().split(/\s+/).includes("stylesheet"),Z=e=>e.tagName==="script"?x(e,"src"):X(e)?x(e,"href"):void 0,j=e=>!!e.sourceCodeLocation,A=e=>e.includes(`\r
4
4
  `)?`\r
5
5
  `:`
@@ -0,0 +1,16 @@
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 je,e as Oe}from"./chunk-QJIR2BLP.mjs";import{d as ve}from"./chunk-P2CAZPDP.mjs";import{a as de,c as lt,d as $e,e as xe,f as Se}from"./chunk-E7LWZRXY.mjs";import{a as me,d as pe,e as we,f as he,g as ye}from"./chunk-TYK6VNAB.mjs";import{b as ge,c as ke,e as be,g as Bt}from"./chunk-CY2FNNAB.mjs";import{a as ie}from"./chunk-UMHUSOPJ.mjs";import{F as le,G as ue,H as Ut,a as W}from"./chunk-L3QKH4OK.mjs";import{d as ce,q as fe}from"./chunk-W4VKN3GF.mjs";import{createHmac as _n,randomBytes as Gt}from"node:crypto";import{existsSync as Ln,mkdirSync as Un,readFileSync as Bn,writeFileSync as Wn}from"node:fs";import Y from"node:fs/promises";import I from"node:path";import{FILE as Yn}from"../browser/shared/annotations.mjs";import{escapeTyped as Zn}from"../browser/shared/escape.mjs";import{writeAtomic as Tt}from"../browser/shared/files.mjs";import{sendJson as _}from"../browser/shared/http.mjs";import{REQUEST_ID as Ct}from"../browser/shared/ids.mjs";import{UPLOAD_REQUEST_LIMIT as Cn}from"../browser/shared/media.mjs";import{reportsDirectory as zn}from"../browser/shared/paths.mjs";import{sameDirectory as Gn}from"../browser/shared/preview-server.mjs";import{slugPattern as et}from"../browser/shared/reports.mjs";import{documentDirectory as Hn,documentFiles as jt,isDocumentSource as Kn}from"../browser/shared/workspace.mjs";import Wt from"node:fs/promises";import Ne from"node:path";import{checkAnnotations as pn,cleanAnchor as wn,cleanItem as Ae,FILE as hn,itemsText as yn,readItems as gn,treeText as Ee}from"../browser/shared/annotations.mjs";import{writeAtomic as kn}from"../browser/shared/files.mjs";import{slugPattern as bn}from"../browser/shared/reports.mjs";import{documentDirectory as Re,documentFiles as $n}from"../browser/shared/workspace.mjs";var xn=600*1e3,Sn=600*1e3;function vn(f){let{units:c,boxes:g}=ue(f),m=[...c].sort((p,y)=>p.elStart-y.elStart),$=new Map(m.map((p,y)=>[p.id,y])),u=new Map(m.map(p=>[p.id,Ee(p.node)])),O={h2:null,h3:null,h4:null};return m.map(p=>{let y=[];for(let E=p;E;E=E.parent===null?null:c[E.parent]){let v=g[E.box];if(v?.kind==="panel"&&v.key!==null){let J=c.find(U=>U.kind==="tab"&&U.parent===v.unit&&U.key===v.key);J&&y.unshift({tab:u.get(J.id)})}let G=v?.unit===null||v?.unit===void 0?null:c[v.unit];if(G?.tag==="details"&&v.kind==="details"){let J=G.node.childNodes.find(U=>U.tagName==="summary");J&&y.push({details:Ee(J)})}}let M=y.find(E=>E.tab)?.tab,T=y.find(E=>E.details)?.details,L=[M,O.h2,O.h3,O.h4,T].filter(Boolean);return p.tag==="h2"?Object.assign(O,{h2:u.get(p.id),h3:null,h4:null}):p.tag==="h3"?Object.assign(O,{h3:u.get(p.id),h4:null}):p.tag==="h4"&&(O.h4=u.get(p.id)),{id:p.blockId,text:u.get(p.id),parent:p.parent===null?null:$.get(p.parent)??null,where:L,heading:/^h[2-4]$/.test(p.tag)}})}function Te({reportsDirectory:f,read:c,write:g=kn,dropped:m=()=>{},now:$=Date.now}){let u=new Map,O=new Map,p=new Map,y=(s,w)=>{let r=p.get(s);if(r?.text===w)return r.units;let o=vn(w);return p.set(s,{text:w,units:o}),o},M=s=>Ne.join(Re(s,f),hn),T=s=>typeof s=="string"&&bn.test(s);async function L(s){let w=await Wt.readFile(M(s),"utf8").catch(()=>null);return{text:w,items:w===null?[]:gn(w)}}async function E(s,w,r){let o=yn(w);return o===r||(o===null?await Wt.rm(M(s),{force:!0}):await g(M(s),o)),v(o)}let v=s=>s===null?"":W(s),G=s=>{let w=u.get(s)??new Map;for(let[r,o]of w)$()-o>xn&&w.delete(r);return[...w.keys()]},J=(s,w)=>w.forEach(r=>u.get(s)?.delete(r)),U=s=>{let w=O.get(s)??O.set(s,new Map).get(s);for(let[r,o]of w)$()-o>Sn&&w.delete(r);return w};async function D(s,{keep:w=null,items:r=null,before:o=void 0}={}){let k=r?{items:r,text:o}:await L(s),b=await c(s).catch(()=>null);if(!b)return{items:k.items,units:[],places:new Map,version:v(k.text),missing:!0};let R=y(s,b.text),N=U(s),h=pn(k.items,R,{keep:new Set([...N.keys(),w])});for(let j of N.keys())h.waiting.has(j)||N.delete(j);if(h.dropped.length>0){let j=u.get(s)??u.set(s,new Map).get(s);for(let F of h.dropped)j.set(F.id,$())}let x=h.changed||r?await E(s,h.items,k.text):v(k.text);return h.dropped.length>0&&m(s,h.dropped),{items:h.items,units:R,places:h.places,version:x,missing:!1}}let B=(s,{items:w,version:r})=>({ok:!0,version:r,items:w,dropped:G(s)});async function H(s){if(!T(s))return[400,{ok:!1,reason:"body"}];let w=await D(s);return w.missing?[404,{ok:!1,reason:"missing"}]:[200,B(s,w)]}async function nt(s){if(!T(s))return[400,{ok:!1,reason:"body"}];let w=await D(s);if(w.missing)return[404,{ok:!1,reason:"missing"}];let r=null,o=$n(Re(s,f));try{r=JSON.parse(await Wt.readFile(o.json,"utf8"))}catch{}let k=await c(s).catch(()=>null),b=/<h1\b[^>]*>([\s\S]*?)<\/h1>/i.exec(k?.text??"")?.[1]?.replace(/<[^>]*>/g,"").trim(),R=typeof r?.title=="string"&&r.title.trim()?r.title.trim():b||s,N=w.units.some(x=>x.heading),h=w.items.map(x=>{let j=w.units[w.places.get(x.id)?.at],F=j?.where?.length?j.where:j?.heading?[j.text]:[];return{where:F,top:N&&F.length===0,blocks:x.anchor.blocks.filter(X=>w.units.some(rt=>rt.id===X)),whole:x.anchor.kind==="blocks",quote:x.anchor.quote,text:x.text}});return[200,{ok:!0,title:R,path:Ne.resolve(o.html),items:h}]}async function K(s){let{slug:w}=s??{};if(!T(w))return[400,{ok:!1,reason:"body"}];if(!await c(w).catch(()=>null))return[404,{ok:!1,reason:"missing"}];let r=await L(w);if(s.anchors&&typeof s.anchors=="object"&&!Array.isArray(s.anchors)){let N=r.items.map(x=>{let j=Object.hasOwn(s.anchors,x.id)?wn(s.anchors[x.id]):null;return j&&j.kind===x.anchor.kind?{...x,anchor:j}:x}),h=await E(w,N,r.text);return[200,B(w,{items:N,version:h})]}let o=r.items,k=null,b=null;if(s.put!==void 0){let N=o.find(x=>x.id===s.put?.id),h=Ae({...s.put,created:N?.created??s.put?.created});if(!h)return[400,{ok:!1,reason:"item"}];o=N?o.map(x=>x.id===h.id?h:x):[...o,h],k=h.id,N||U(w).set(h.id,$()),J(w,[h.id])}else if(typeof s.remove=="string")o=o.filter(N=>N.id!==s.remove);else if(s.clear===!0)b=o,o=[];else if(Array.isArray(s.restore)){let N=new Map(o.map(j=>[j.id,j])),h=s.restore.map(j=>Ae(j,j?.updated)).filter(j=>j&&!(N.get(j.id)?.updated>j.updated)),x=new Set(h.map(j=>j.id));for(let j of x)N.has(j)||U(w).set(j,$());o=[...o.filter(j=>!x.has(j.id)),...h],J(w,[...x])}else return[400,{ok:!1,reason:"body"}];let R=await D(w,{keep:k,items:o,before:r.text});return[200,{...B(w,R),...b?{removed:b}:{}}]}async function q(s){if(!T(s))return;let{text:w}=await L(s);w!==null&&await D(s)}return{list:H,copy:nt,change:K,afterWrite:q}}import ut from"node:fs/promises";import dt from"node:path";import{writeAtomic as Me}from"../browser/shared/files.mjs";import{slugPattern as Yt}from"../browser/shared/reports.mjs";var Rt=1,St={seen:"seen.html",base:"base.html",state:"state.json"},jn=4,On=1800*1e3;function Fe({stateDirectory:f=null,shown:c,folderOf:g,isPage:m=()=>!1,log:$=null,now:u=Date.now,quiet:O=On}){let p=new Map,y=r=>dt.join(f,"changes",r),M=Promise.resolve(),T=r=>{let o=M.then(r);return M=o.catch(k=>$?.(`changes: ${k.message}`)),o};async function L(r){if(!f)return p.get(r)?.state??null;try{let o=JSON.parse(await ut.readFile(dt.join(y(r),St.state),"utf8"));return o?.v===Rt&&typeof o.seen=="string"?o:null}catch{return null}}async function E(r,o){return f?ut.readFile(dt.join(y(r),St[o]),"utf8").catch(()=>null):p.get(r)?.[o]??null}async function v(r,o,k={}){if(!f){let b=p.get(r)??{};p.set(r,{...b,...k,state:o});return}await ut.mkdir(y(r),{recursive:!0});for(let[b,R]of Object.entries(k))R===null?await ut.rm(dt.join(y(r),St[b]),{force:!0}):await Me(dt.join(y(r),St[b]),R);await Me(dt.join(y(r),St.state),`${JSON.stringify(o)}
3
+ `)}async function G(r){p.delete(r),f&&await ut.rm(y(r),{recursive:!0,force:!0,maxRetries:3})}let J=async r=>Math.round((await ut.stat(g(r)).catch(()=>null))?.birthtimeMs??0),U=r=>r?.base?`${r.since}|${r.writes}`:null,D=r=>Number.isFinite(r?.draft)&&u()-r.draft<O?r.draft:null,B=(r,o,k,b=D(r))=>[{v:Rt,born:r?.born??0,seen:o,...b===null?{}:{draft:b}},{seen:k,base:null}];async function H(r){let o=await L(r);if(!o)return null;let k=await J(r);return o.born&&k&&o.born!==k?(await G(r),null):o}async function nt(r,o){if(typeof o!="string"||!Yt.test(r)||m(r))return!1;let k=W(o),b=await H(r);if(!b)return await v(r,{v:Rt,born:await J(r),seen:k},{seen:o}),!1;if(b.seen===k)return!1;let R=await E(r,"seen"),N=new Date(u()).toISOString();if(R===null)return await v(r,...B(b,k,o)),!1;let h=c(R),x=c(o);if(!b.base){if(!lt(h,x))return await v(r,...B(b,k,o)),!1;if(D(b)!==null||$e(h))return await v(r,...B(b,k,o,u())),!1;let{draft:X,...rt}=b;return await v(r,{...rt,seen:k,base:W(h),since:N,at:N,writes:1},{seen:o,base:h}),!0}let j=await E(r,"base");if(j===null||!lt(j,x))return await v(r,...B(b,k,o)),!0;let F=lt(h,x)!==null;return await v(r,{...b,seen:k,...F?{at:N,writes:b.writes+1}:{}},{seen:o}),F}async function K(r,o,k,b){if(!Yt.test(r)||m(r))return!1;let R=await H(r),N=W(o);if(!R?.base)return await v(r,...B(R??{born:await J(r)},N,o,b?null:D(R))),!1;let h=await E(r,"base");if(h!==null&&k)try{h=k(h)}catch(x){$?.(`changes: ${r}: the baseline did not take the edit (${x.message})`)}return h===null||!lt(h,c(o))?(await v(r,...B(R,N,o)),!0):(await v(r,{...R,seen:N,base:W(h)},{seen:o,base:h}),!1)}async function q(r,o){if(!Yt.test(r)||m(r))return{ended:!1,moved:!1};let k=typeof o=="string"?await nt(r,o):!1,b=await H(r);if(b?.draft===void 0)return{ended:!1,moved:k};let{draft:R,...N}=b;return await v(r,N),{ended:D(b)!==null,moved:k}}let s=new Map;async function w(r,o){await nt(r,o);let k=c(o),b=W(k),R=await H(r);if(!R?.base)return{pending:!1,version:b};let N=`${r} ${R.base} ${b}`,h=s.get(N);if(h===void 0){let x=await E(r,"base");for(h=x===null?null:lt(x,k),s.set(N,h);s.size>jn;)s.delete(s.keys().next().value)}return h?{pending:!0,version:b,stamp:U(R),since:R.since,writes:R.writes,...h}:{pending:!1,version:b}}return{look:(r,o)=>T(()=>nt(r,o)),wrote:(r,o,k=null,{reader:b=!1}={})=>T(()=>K(r,o,k,b)),endDraft:(r,o=null)=>T(()=>q(r,o)),read:(r,o)=>T(()=>w(r,o)),stamp:r=>T(async()=>U(await H(r))),snapshot:r=>T(async()=>{let o=await H(r);return o?{state:o,seen:await E(r,"seen"),base:await E(r,"base")}:null}),clear:r=>T(async()=>{let o=await H(r);o?.base&&await v(r,{v:Rt,born:o.born,seen:o.seen},{base:null})}),restore:(r,o)=>T(async()=>{o?.state&&await v(r,o.state,{seen:o.seen,base:o.base})}),forget:r=>T(()=>G(r)),idle:()=>T(async()=>{})}}import{randomBytes as Nn}from"node:crypto";import ot from"node:fs/promises";import mt from"node:path";import{FILE as An,readItems as En}from"../browser/shared/annotations.mjs";import{writeAtomic as Rn}from"../browser/shared/files.mjs";import{documentDirectory as Tn}from"../browser/shared/workspace.mjs";var Mn=20,Pe=/^\d{8}T\d{6}Z-[a-f0-9]{8}\.json$/,Ie=80,Je=({stateDirectory:f,slug:c})=>mt.join(f,"dropped-annotations",c),_e=f=>({id:f.id,text:f.text,quote:f.anchor?.quote??"",kind:f.anchor?.kind??"text"});async function Le({stateDirectory:f,reportsDirectory:c,slug:g,time:m,items:$}){let u=Je({stateDirectory:f,reportsDirectory:c,slug:g});await ot.mkdir(u,{recursive:!0});let O=m.replace(/[-:]/g,"").replace(/\.\d+Z$/,"Z");await Rn(mt.join(u,`${O}-${Nn(4).toString("hex")}.json`),JSON.stringify({time:m,items:$}));let p=(await ot.readdir(u)).filter(y=>Pe.test(y)).sort();await Promise.all(p.slice(0,Math.max(0,p.length-Mn)).map(y=>ot.rm(mt.join(u,y),{force:!0})))}async function Mr({stateDirectory:f,reportsDirectory:c,slug:g}){let m=Je({stateDirectory:f,reportsDirectory:c,slug:g}),$=(await ot.readdir(m).catch(()=>[])).filter(p=>Pe.test(p)).sort();if($.length===0)return[];let u=new Set(En(await ot.readFile(mt.join(Tn(g,c),An),"utf8").catch(()=>"")).map(p=>p.id)),O=[];for(let p of $){let y=mt.join(m,p);try{let M=JSON.parse(await ot.readFile(y,"utf8")),T=Array.isArray(M?.items)?M.items.filter(L=>typeof L?.id=="string"&&!u.has(L.id)):[];typeof M?.time=="string"&&T.length&&O.push({time:M.time,items:T})}catch{}await ot.rm(y,{force:!0}).catch(()=>{})}return O}var Fn=(f,c=new Date)=>{let g=new Date(f),m=u=>String(u).padStart(2,"0"),$=`${m(g.getHours())}:${m(g.getMinutes())}`;return g.toDateString()===c.toDateString()?$:`${g.getFullYear()}-${m(g.getMonth()+1)}-${m(g.getDate())} ${$}`},De=f=>{let c=String(f??"").replace(/\s+/g," ").trim();return JSON.stringify(c.length>Ie?`${c.slice(0,Ie-1)}\u2026`:c)};function Zt(f,{time:c=null,items:g},{today:m=new Date}={}){let $=mt.resolve(f),u=`${g.length} \u6279\u6CE8 (annotation${g.length===1?"":"s"})`;return[`annotations ${$}: ${c?`at ${Fn(c,m)}, `:""}Gallery deleted ${u} whose words are gone from the document (rewritten or deleted):`,...g.map(({id:O,text:p,quote:y,kind:M})=>` ${O} ${De(p)} on ${M==="blocks"?"the blocks ":""}${De(y)}`)]}function Fr(f,c,{today:g=new Date}={}){return c.length?[...c.flatMap(m=>Zt(f,m,{today:g}))," they were the reader's: say in your hand-off which your edit carried out and which you left, and never write them back"]:[]}import{randomBytes as In}from"node:crypto";import pt from"node:fs/promises";import vt from"node:path";import{writeAtomic as Dn}from"../browser/shared/files.mjs";var Pn=20,Ue=/^\d{8}T\d{6}Z-[a-f0-9]{8}\.json$/,Be=({stateDirectory:f,slug:c})=>vt.join(f,"rewrites",c);async function We({stateDirectory:f,reportsDirectory:c,slug:g,time:m,changes:$}){let u=Be({stateDirectory:f,reportsDirectory:c,slug:g});await pt.mkdir(u,{recursive:!0});let O=m.replace(/[-:]/g,"").replace(/\.\d+Z$/,"Z");await Dn(vt.join(u,`${O}-${In(4).toString("hex")}.json`),JSON.stringify({time:m,changes:$}));let p=(await pt.readdir(u)).filter(y=>Ue.test(y)).sort();await Promise.all(p.slice(0,Math.max(0,p.length-Pn)).map(y=>pt.rm(vt.join(u,y),{force:!0})))}async function Ye({stateDirectory:f,reportsDirectory:c,slug:g}){let m=Be({stateDirectory:f,reportsDirectory:c,slug:g}),$=(await pt.readdir(m).catch(()=>[])).filter(O=>Ue.test(O)).sort(),u=[];for(let O of $){let p=vt.join(m,O);try{let y=JSON.parse(await pt.readFile(p,"utf8"));typeof y?.time=="string"&&Array.isArray(y.changes)&&u.push(y)}catch{}await pt.rm(p,{force:!0}).catch(()=>{})}return u}var Jn=(f,c=new Date)=>{let g=new Date(f),m=u=>String(u).padStart(2,"0"),$=`${m(g.getHours())}:${m(g.getMinutes())}`;return g.toDateString()===c.toDateString()?$:`${g.getFullYear()}-${m(g.getMonth()+1)}-${m(g.getDate())} ${$}`};function Lr(f,c,{today:g=new Date}={}){if(!c.length)return[];let m=vt.resolve(f),$=[];for(let{time:u,changes:O}of c){let p=[];for(let{line:y,rule:M,key:T}of[...O].sort((L,E)=>L.line-E.line)){let L=`line ${y} ${M}${T?` ${T}`:""}`;p.includes(L)||p.push(L)}$.push(`preview ${m}: at ${Jn(u,g)}, when the reader edited the page, the preview wrote your natural HTML as the kit's markup: ${p.join(", ")}`),$.push(...O.filter(y=>y.note).map(({line:y,rule:M,note:T})=>` line ${y}, ${M}: ${T}`))}return $.push(" re-read the file before editing it (those lines are the file's as you had left it)"),$}import{EMPTY_STYLE as Qn,emptyWordsScript as Vn,showEmpty as qn}from"../browser/editor/components/placeholder.mjs";import{TOKENS as Xn}from"../browser/editor/page/look.mjs";import{MARGIN_STYLE as tr,earlyMarginScript as er}from"../browser/editor/page/margin.mjs";var zt=/^[a-f0-9]{16}$/,Ht=2*1024*1024,nr=Cn,Ze=50,Ce=/^\d{8}T\d{6}Z-[a-f0-9]{16}\.html$/,rr=30,ze=3,Ge=200,wt="\u6587\u4EF6\u4E00\u518D\u88AB\u4FEE\u6539\uFF08\u4F8B\u5982 AI \u6B63\u5728\u5199\u5165\uFF09\uFF0C\u7A0D\u540E\u518D\u540C\u6B65",ar="\u8FD9\u6B21\u7684\u4FEE\u6539\u592A\u5927\uFF0C\u4E00\u6B21\u5B58\u4E0D\u4E0B",or=250,Mt=Symbol("again"),sr="/__gallery/edit/src/editor/page/editor.mjs",ir=f=>new Promise(c=>setTimeout(c,f));function cr(f,c=Ht){return new Promise((g,m)=>{let $=[],u=0;f.on("data",O=>{u+=O.length,u>c?$.length=0:$.push(O)}),f.on("end",()=>u>c?m(new Error("too-large")):g(Buffer.concat($).toString("utf8"))),f.on("error",m)})}function fr(f){if(!f)return Gt(16).toString("hex");let c=I.join(f,"token");try{let m=Bn(c,"utf8").trim();if(/^[a-f0-9]{32}$/.test(m))return m}catch{}let g=Gt(16).toString("hex");try{Un(f,{recursive:!0,mode:448}),Wn(c,g,{mode:384})}catch{}return g}function ma({reportsDirectory:f=zn,stateDirectory:c=null,write:g=Tt,ids:m=!0,finish:$=M=>M,log:u=null,settling:O={},reviewing:p={},onChanges:y=()=>{}}={}){let M=fr(c),T=Oe(O),L=O.wait??je,E=async(t,n,e)=>{let a=await g(t,n,e);return a!==!1&&Kn(I.basename(t))&&T.wrote(I.basename(I.dirname(t)),n),a},v=t=>Hn(t,f),G=t=>jt(v(t)).html,J=new Map,U=c&&I.join(c,"snapshots"),D=Promise.resolve(),B=Promise.resolve(),H=async(t,n,e,{by:a="time"}={})=>{let i=(await Y.readdir(t)).filter(l=>n.test(l));if(i.length<=e)return;let d=a==="name"?i.sort():(await Promise.all(i.map(async l=>({name:l,time:(await Y.stat(I.join(t,l))).mtimeMs})))).sort((l,S)=>l.time-S.time).map(({name:l})=>l);await Promise.all(d.slice(0,d.length-e).map(l=>Y.rm(I.join(t,l),{force:!0})))},nt=(t,n)=>{U&&(D=D.then(async()=>{let e=I.join(U,`${t}.html`),a=new Date;try{await Y.utimes(e,a,a);return}catch{}await Y.mkdir(U,{recursive:!0}),await Tt(e,n),await H(U,/^[a-f0-9]{16}\.html$/,Ze)}).catch(()=>{}))},K=(t,n)=>{c&&(D=D.then(async()=>{let e=I.join(c,"history",t),a=W(n);if(await Y.mkdir(e,{recursive:!0}),(await Y.readdir(e)).filter(l=>Ce.test(l)).sort().at(-1)?.endsWith(`-${a}.html`))return;let d=new Date().toISOString().replace(/[-:]/g,"").replace(/\.\d+Z$/,"Z");await Tt(I.join(e,`${d}-${a}.html`),n),await H(e,Ce,rr,{by:"name"})}).catch(()=>{}))},q=new Map,s=t=>c&&I.join(c,"receipts",t),w=(t,n,e,a)=>{for(q.set(`${t} ${n}`,{digest:e,answer:a});q.size>Ge*4;)q.delete(q.keys().next().value);let i=s(t);i&&(D=D.then(async()=>{await Y.mkdir(i,{recursive:!0}),await Tt(I.join(i,`${n}.json`),JSON.stringify({digest:e,answer:a})),await H(i,{test:d=>d.endsWith(".json")&&Ct.test(d.slice(0,-5))},Ge)}).catch(()=>{}))},r=async(t,n)=>{let e=q.get(`${t} ${n}`);if(e)return e;let a=s(t);if(!a)return null;await D;try{let i=JSON.parse(await Y.readFile(I.join(a,`${n}.json`),"utf8"));return typeof i?.digest=="string"&&i.answer?.ok?i:null}catch{return null}},o=new Map,k=(t,n)=>{let e=new Date().toISOString();if(!c)return void o.set(t,[...o.get(t)??[],{time:e,changes:n}].slice(-20));D=D.then(()=>We({stateDirectory:c,reportsDirectory:f,slug:t,time:e,changes:n})).catch(()=>{})},b=async t=>{if(!c){let n=o.get(t)??[];return o.delete(t),n}return await D,Ye({stateDirectory:c,reportsDirectory:f,slug:t})},R=(t,n)=>{for(J.delete(t),J.set(t,n);J.size>Ze;)J.delete(J.keys().next().value);nt(t,n)},N=async t=>{if(J.has(t))return J.get(t);if(!U||!zt.test(t))return null;await D;let n=await Y.readFile(I.join(U,`${t}.html`),"utf8").catch(()=>null);return n===null||W(n)!==t?null:(R(t,n),n)},h=new Map,x=t=>{let n=h.get(t);if(n)return n;let e=ge(t,{finish:$});for(h.set(t,e);h.size>8;)h.delete(h.keys().next().value);return e},j=I.join(I.resolve(f),".gallery","pages"),F=Fe({...p,stateDirectory:c,shown:t=>x(t).text,folderOf:v,log:u,isPage:t=>I.resolve(v(t)).startsWith(j+I.sep)}),X=(t,n)=>n.then(e=>{e&&y(t)},e=>u?.(`${t}: the Agent's changes not kept (${e.message})`));async function rt(t,n=void 0){if(typeof t!="string"||!et.test(t))return null;let e=G(t),a=n!==void 0?n:await Y.readFile(e,"utf8").catch(()=>null);if(a===null)return null;let{text:i,changes:d}=x(a);return{file:e,source:a,text:i,version:W(i),changes:d}}async function st(t){if(typeof t!="string"||!et.test(t))return{source:null,held:!1,signs:[],wait:0,own:!1};let n=G(t),e=await Y.readFile(n,"utf8").catch(()=>null),a=(await Y.stat(n).catch(()=>null))?.mtimeMs??0;return{source:e,...T.judge(t,{source:e,mtime:a})}}async function ht(t,n=Date.now()+L){for(;;){let e=await st(t);if(!e.held||Date.now()>=n)return e;await ir(Math.max(0,Math.min(or,n-Date.now())))}}async function Ft(t,{wait:n=L}={}){let e=await ht(t,Date.now()+n);return rt(t,e.held&&e.taken!==void 0?e.taken:e.source)}function He(t,n,{editor:e=sr,kitTags:a=()=>[]}={}){let{html:i,map:d}=de(n);R(d.version,n);let l=ce(f),S=fe(l).map(({assets:C,...V})=>({...V,kit:a(C)})),A=`<script type="application/json" id="doc-edit-map" data-doc-dev>${JSON.stringify({slug:t,token:M,...d,components:S,hidden:l.settings.hidden}).replace(/</g,"\\u003c")}</script>
4
+ <script data-doc-dev>document.currentScript.remove(); import(${JSON.stringify(e)});</script>`,Z=`<style data-doc-dev>.doc-display { display: none; }</style>
5
+ <style data-doc-dev data-ge-palette>${Xn}</style>
6
+ <style data-doc-dev>${Qn}</style>
7
+ <script data-doc-dev>${Vn()}</script>
8
+ <script data-doc-dev>document.currentScript.remove(); document.documentElement.setAttribute("data-ge-order", "file");</script>
9
+ <style data-doc-dev data-ge-margin-style>${tr}</style>
10
+ <script data-doc-dev>document.currentScript.remove(); ${er(t,{notes:Ln(I.join(v(t),Yn))})}</script>`;return{html:qn(i),snippet:A,head:Z}}let Ke=t=>R(W(t),t);async function it(t,n=Ht){if(t.method!=="POST")return{error:[405,{ok:!1,reason:"method"}]};let e=t.headers.host??"",a=t.socket.localPort;if(e!==`127.0.0.1:${a}`&&e!==`localhost:${a}`)return{error:[403,{ok:!1,reason:"host"}]};if(t.headers.origin!==`http://${e}`)return{error:[403,{ok:!1,reason:"origin"}]};if(t.headers["x-gallery-token"]!==M)return{error:[403,{ok:!1,reason:"token"}]};if(!/^application\/json\b/i.test(t.headers["content-type"]??""))return{error:[415,{ok:!1,reason:"type"}]};try{return{body:JSON.parse(await cr(t,n))}}catch(i){return{error:i.message==="too-large"?[413,{ok:!1,reason:"body",message:ar}]:[400,{ok:!1,reason:"body"}]}}}async function Qe(t,n){let{slug:e,opening:a,known:i=null,texts:d=[],units:l=[],touch:S=[],pageIds:P=null,request:A=null,agent:Z=!1}=t;if(typeof e!="string"||!et.test(e)||![d,l,S].every(Array.isArray))return[400,{ok:!1,reason:"body"}];if(A!==null&&(typeof A!="string"||!Ct.test(A)))return[400,{ok:!1,reason:"body"}];let C=A===null?null:W(JSON.stringify([a??null,d,l,S])),V=await Kt(t);if(V)return V;let z=at=>(A!==null&&w(e,A,C,at),[200,at]),Q=G(e),tt=typeof a=="string"&&zt.test(a)?await N(a):null,ee=at=>_n("sha256",M).update(`${e}
11
+ ${at}`).digest("hex").slice(0,32);for(let at=1;;at++){let{source:$t,held:un}=await st(e);if($t===null)return[404,{ok:!1,reason:"missing"}];if(un)return Date.now()<n?Mt:[409,{ok:!1,reason:"busy",message:wt}];X(e,F.look(e,$t));let{text:xt,changes:Lt}=x($t),ne=[],At=pe({current:xt,opening:tt,texts:d,units:l,touch:S,ids:m?()=>{let Et=typeof m=="function"?m():Ut();return ne.push(Et),Et}:!1,seal:ee,pageIds:P}),{title:re,icon:ae,...oe}=At,ft=At.text===xt?xt:$(At.text);ft!==At.text&&(oe.version=W(ft));let se={...oe,foreign:typeof i=="string"&&W(xt)!==i};if(ft===xt)return z({ok:!0,...se,wrote:!1,notes:[]});if(K(e,$t),!await E(Q,ft,{expect:$t})){if(at===ze)return[409,{ok:!1,reason:"busy",message:wt}];continue}K(e,ft),X(e,F.wrote(e,ft,Et=>{let mn=0;return xe(Et,{opening:tt,texts:d,units:l,touch:S,pageIds:P,seal:ee,ids:m?()=>ne[mn++]??(typeof m=="function"?m():Ut()):!1})},{reader:Z!==!0})),Lt.length&&(u&&u(Bt(Q,Lt).join(`
12
+ `)),k(e,Lt));let dn=[...re?await Ot(I.dirname(Q),re):[],...ae!==void 0?await It(I.dirname(Q),ae):[]];return z({ok:!0,...se,wrote:!0,notes:dn})}}async function Kt({slug:t,opening:n,texts:e=[],units:a=[],touch:i=[],request:d=null}){if(typeof t!="string"||!et.test(t)||typeof d!="string"||!Ct.test(d)||![e,a,i].every(Array.isArray))return null;let l=await r(t,d);return l?l.digest===W(JSON.stringify([n??null,e,a,i]))?[200,{...l.answer,again:!0}]:[409,{ok:!1,reason:"request",message:"\u540C\u4E00\u6B21\u4FDD\u5B58\u7684\u5185\u5BB9\u4E0D\u4E00\u81F4"}]:null}async function Ve(t,n){let{slug:e,opening:a,texts:i=[],units:d=[],instances:l=[],pageIds:S=null}=t;if(typeof e!="string"||!et.test(e)||!Array.isArray(i)||!Array.isArray(d)||!Array.isArray(l))return[400,{ok:!1,reason:"body"}];let{source:P,held:A}=await st(e);if(A)return Date.now()<n?Mt:[409,{ok:!1,reason:"busy",message:wt}];let Z=await rt(e,P);if(Z===null)return[404,{ok:!1,reason:"missing"}];let{text:C,version:V}=Z,z=typeof a=="string"&&zt.test(a)?await N(a):null;return[200,{ok:!0,version:V,reverted:ye({current:C,opening:z,texts:i,pageIds:S}),units:we({current:C,units:d}),parts:he({current:C,instances:l,pageIds:S})}]}let qe=600*1e3,yt=new Map;async function Qt(t,n){let e=v(t),a=null;try{a=JSON.parse(await Y.readFile(jt(e).json,"utf8"))}catch{}let{title:i,icon:d}=be(n,a);i&&typeof a?.title=="string"&&a.title!==i.to&&await Ot(e,{from:a.title,to:i.to,synced:!0}),d&&!d.missing&&await It(e,d.to)}async function Xe(t,n){let{slug:e,action:a,stamp:i=null,undo:d=null}=t;if(typeof e!="string"||!et.test(e)||!["accept","revert","undo"].includes(a))return[400,{ok:!1,reason:"body"}];let l=G(e),{source:S,held:P}=await st(e);if(S===null)return[404,{ok:!1,reason:"missing"}];if(P)return Date.now()<n?Mt:[409,{ok:!1,reason:"busy",message:wt}];if(a==="undo"){for(let[Q,tt]of yt)Date.now()-tt.at>qe&&yt.delete(Q);let z=typeof d=="string"?yt.get(d):null;return!z||z.slug!==e?[404,{ok:!1,reason:"gone",message:"\u64A4\u9500\u5DF2\u7ECF\u8FC7\u671F"}]:S!==z.after?[409,{ok:!1,reason:"moved-on",message:"\u64A4\u56DE\u4E4B\u540E\u6587\u6863\u53C8\u6539\u8FC7\u4E86\uFF0C\u6CA1\u6CD5\u64A4\u9500"}]:(K(e,S),await E(l,z.before,{expect:S})?(K(e,z.before),yt.delete(d),await Qt(e,z.before),await F.restore(e,z.saved),await F.wrote(e,z.before),y(e),[200,{ok:!0,version:W(x(z.before).text)}]):[409,{ok:!1,reason:"busy",message:wt}])}await F.look(e,S);let A=await F.snapshot(e),Z=A?.state?.base?`${A.state.since}|${A.state.writes}`:null;if(Z===null)return[200,{ok:!0,none:!0}];if(Z!==i)return[409,{ok:!1,reason:"changed",message:"Agent \u521A\u521A\u53C8\u6539\u4E86\u6587\u6863\uFF0C\u518D\u770B\u4E00\u773C"}];if(a==="accept")return await F.clear(e),y(e),[200,{ok:!0}];let C=A.base;if(K(e,S),!await E(l,C,{expect:S}))return[409,{ok:!1,reason:"busy",message:wt}];K(e,C),await Qt(e,C);let V=Gt(8).toString("hex");return yt.set(V,{slug:e,before:S,after:C,saved:A,at:Date.now()}),await F.clear(e),await F.wrote(e,C),y(e),[200,{ok:!0,version:W(x(C).text),undo:V}]}async function tn(t,n){let e=await it(t);if(e.error)return _(n,...e.error);let a=e.body??{};try{if(a.action!=="read")return _(n,...await qt(a,Xe));if(typeof a.slug!="string"||!et.test(a.slug))return _(n,400,{ok:!1,reason:"body"});let i=await Ft(a.slug,{wait:0});return i===null?_(n,404,{ok:!1,reason:"missing"}):_(n,200,{ok:!0,...await F.read(a.slug,i.source)})}catch(i){return _(n,500,{ok:!1,reason:"write",message:i.message})}}async function Ot(t,{from:n,to:e,synced:a}){let i=["\u6807\u9898\u5DF2\u66F4\u65B0",...a?[]:["\u5355\u72EC\u6253\u5F00\u6216\u5BFC\u51FA\u65F6\u7684\u9875\u9762\u540D\u79F0\u539F\u672C\u5C31\u548C\u6807\u9898\u4E0D\u540C\uFF0C\u6CA1\u6709\u8DDF\u7740\u6539"]],d=jt(t).json,l=await Y.readFile(d,"utf8").catch(()=>""),S=null;try{S=JSON.parse(l)}catch{}if(S?.title!==n)return[...i,"\u641C\u7D22\u548C\u4FA7\u680F\u91CC\uFF08\u6CA1\u6253\u5F00\u8FD9\u4EFD\u6587\u6863\u65F6\uFF09\u7684\u6587\u6863\u540D\u539F\u672C\u5C31\u548C\u6807\u9898\u4E0D\u540C\uFF0C\u6CA1\u6709\u8DDF\u7740\u6539"];let P=new RegExp(`("title"\\s*:\\s*)${JSON.stringify(n).replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}`),A=P.test(l)?l.replace(P,(Z,C)=>C+JSON.stringify(e)):`${JSON.stringify({...S,title:e},null,2)}
13
+ `;try{await E(d,A)}catch(Z){return u?.(`${I.basename(d)}'s title was not written (${Z.code??Z.message}): ${d}`),[...i,"\u641C\u7D22\u548C\u4FA7\u680F\u91CC\uFF08\u6CA1\u6253\u5F00\u8FD9\u4EFD\u6587\u6863\u65F6\uFF09\u7684\u6587\u6863\u540D\u6CA1\u80FD\u8DDF\u7740\u6539"]}return i}async function It(t,n){let e=jt(t).json,a=null;try{a=JSON.parse(await Y.readFile(e,"utf8"))}catch{}if(!a||typeof a!="object")return u?.(`${I.basename(e)} could not be read, so its icon was not written: ${e}`),["\u9875\u9762\u56FE\u6807\u5DF2\u66F4\u6362\uFF0C\u4F46\u641C\u7D22\u548C\u4FA7\u680F\u91CC\uFF08\u6CA1\u6253\u5F00\u8FD9\u4EFD\u6587\u6863\u65F6\uFF09\u7684\u56FE\u6807\u6CA1\u80FD\u8DDF\u7740\u6362"];if((a.icon??null)===n)return[];let{icon:i,...d}=a,l=n===null?d:{...d,icon:n};try{await E(e,`${JSON.stringify(l,null,2)}
14
+ `)}catch(S){return u?.(`${I.basename(e)}'s icon was not written (${S.code??S.message}): ${e}`),["\u9875\u9762\u56FE\u6807\u5DF2\u66F4\u6362\uFF0C\u4F46\u641C\u7D22\u548C\u4FA7\u680F\u91CC\uFF08\u6CA1\u6253\u5F00\u8FD9\u4EFD\u6587\u6863\u65F6\uFF09\u7684\u56FE\u6807\u6CA1\u80FD\u8DDF\u7740\u6362"]}return[]}async function en(t,n){let e=typeof n=="string"?n.replace(/\s+/g," ").trim():"";if(!e)return{ok:!1,reason:"title",message:"\u6807\u9898\u4E0D\u80FD\u4E3A\u7A7A"};let a=G(t),i=await Y.readFile(a,"utf8").catch(()=>null);if(i===null)return{ok:!1,reason:"missing"};X(t,F.look(t,i));let d=ie(i),l=le(d).find(A=>A.kind==="title");if(!l)return{ok:!1,reason:"no-title",message:"\u8FD9\u4EFD\u6587\u6863\u6CA1\u6709\u6807\u9898"};let S=Zn(e),P=me({current:d,edits:[{id:l.id,parts:[{keep:!0,html:S}]}],ids:m});return P.ok?P.text!==i&&!await E(a,P.text,{expect:i})?{ok:!1,reason:"changed-again"}:(P.text!==i&&X(t,F.wrote(t,P.text,A=>Se(A,S))),{ok:!0,title:e,notes:P.title?await Ot(I.dirname(a),P.title):[]}):{ok:!1,reason:"conflict"}}let gt=t=>(n,e)=>{let a=B.then(()=>t(n));return B=a.catch(()=>{}),a.then(([i,d])=>_(e,i,d),i=>_(e,500,{ok:!1,reason:"write",message:i.message}))},Vt=(t,{early:n=null}={})=>async(e,a)=>{let i=await it(e);if(i.error)return _(a,...i.error);let d=i.body??{};try{let l=n&&await n(d);return l?_(a,...l):_(a,...await qt(d,t))}catch(l){return _(a,500,{ok:!1,reason:"write",message:l.message})}};async function qt(t,n){let e=Date.now()+L;for(;;){await ht(t.slug,e);let a=B.then(()=>n(t,e));B=a.catch(()=>{});let i=await a;if(i!==Mt)return i}}async function Dt(t,{reader:n=!1}={}){if(typeof t!="string"||!et.test(t))return{ok:!1,reason:"missing",message:"\u627E\u4E0D\u5230\u8FD9\u4EFD\u6587\u6863"};let e=v(t),{html:a,json:i}=jt(e);for(let d=1;;d++){let{source:l,held:S}=n?await st(t):{source:await Y.readFile(a,"utf8").catch(()=>null),held:!1};if(l===null)return{ok:!1,reason:"missing",message:"\u627E\u4E0D\u5230\u8FD9\u4EFD\u6587\u6863"};if(S)return{ok:!1,reason:"busy",message:"\u6587\u4EF6\u4E00\u518D\u88AB\u4FEE\u6539\uFF08\u4F8B\u5982 AI \u6B63\u5728\u5199\u5165\uFF09\uFF0C\u6CA1\u6709\u5199\u5165"};X(t,F.look(t,l));let P=null;try{P=JSON.parse(await Y.readFile(i,"utf8"))}catch{}let{text:A,changes:Z,added:C,given:V,repeated:z,title:Q,icon:tt}=ke(l,{finish:$,next:typeof m=="function"?m:void 0,metadata:P});if(A!==l){if(K(t,l),!await E(a,A,{expect:l})){if(d===ze)return{ok:!1,reason:"busy",message:"\u6587\u4EF6\u4E00\u518D\u88AB\u4FEE\u6539\uFF08\u4F8B\u5982 AI \u6B63\u5728\u5199\u5165\uFF09\uFF0C\u6CA1\u6709\u5199\u5165"};continue}K(t,A),X(t,F.wrote(t,A)),n&&Z.length&&(u&&u(Bt(a,Z).join(`
15
+ `)),k(t,Z))}return Q&&typeof P?.title=="string"&&P.title!==Q.to&&await Ot(e,{from:P.title,to:Q.to,synced:Q.page}),tt&&!tt.missing&&await It(e,tt.to),{ok:!0,changes:A===l?[]:Z,added:A===l?0:C,given:A===l?[]:V,repeated:z,written:A!==l,title:Q,icon:tt}}}let nn=async(t,{reader:n=!1}={})=>{n&&await ht(t);let e=B.then(()=>Dt(t,{reader:n}));return B=e.catch(()=>{}),e};async function Pt(t){let n=await it(t);if(n.error)return{refused:n.error};let{slug:e,workspace:a}=n.body??{};return typeof e!="string"||!et.test(e)||typeof a!="string"?{refused:[400,{ok:!1,reason:"body"}]}:Gn(a,f)?{slug:e}:{refused:[409,{ok:!1,reason:"elsewhere",message:"\u8FD9\u4E2A\u9884\u89C8\u670D\u52A1\u5668\u7BA1\u7684\u662F\u53E6\u4E00\u4E2A\u76EE\u5F55\u7684\u6587\u6863"}]}}async function rn(t,n){try{let e=B.then(async()=>{let{slug:d,refused:l}=await Pt(t);if(l)return{answer:l};let S=await Dt(d);return{slug:S.ok?d:null,answer:[S.ok?200:S.reason==="missing"?404:409,S]}});B=e.catch(()=>{});let{slug:a,answer:i}=await e;return a&&await _t(a),_(n,...i)}catch(e){return _(n,500,{ok:!1,reason:"write",message:e.message})}}async function an(t){let{slug:n,refused:e}=await Pt(t);return e||(await _t(n),[200,{ok:!0}])}async function Xt(t){let{source:n}=await ht(t),{ended:e,moved:a}=await F.endDraft(t,n);return a&&y(t),e}async function on(t){let{slug:n,refused:e}=await Pt(t);return e||[200,{ok:!0,ended:await Xt(n)}]}let ct=ve({reportsDirectory:f}),kt=Te({reportsDirectory:f,read:t=>Ft(t,{wait:0}),write:E,dropped:(t,n)=>{let e=n.map(_e);u&&u(Zt(I.join(v(t),"annotations.json"),{items:e}).join(`
16
+ `)),c&&(D=D.then(()=>Le({stateDirectory:c,reportsDirectory:f,slug:t,time:new Date().toISOString(),items:e})).catch(()=>{}))}}),te=Promise.resolve(),Jt=t=>{let n=te.then(t);return te=n.catch(()=>{}),n},sn=t=>(n,e)=>Jt(()=>t(n)).then(([a,i])=>_(e,a,i),a=>_(e,500,{ok:!1,reason:"write",message:a.message})),cn=300,bt=new Map;async function _t(t){let n=bt.get(t);n&&(clearTimeout(n.timer),bt.delete(t));let e=Jt(()=>kt.afterWrite(t));n&&e.then(n.resolve,n.reject),await e.catch(a=>u?.(`${t}: annotations not checked: ${a.message}`)),await D}let fn=t=>{let n=t.headers.host??"",e=t.socket.localPort;return n!==`127.0.0.1:${e}`&&n!==`localhost:${e}`?[403,{ok:!1,reason:"host"}]:t.headers["x-gallery-token"]!==M?[403,{ok:!1,reason:"token"}]:null};async function ln(t){if(t.method==="GET"){let e=fn(t);if(e)return e;let a=new URL(t.url??"/","http://localhost").searchParams;return a.get("as")==="copy"?kt.copy(a.get("slug")):kt.list(a.get("slug"))}let n=await it(t);return n.error??kt.change(n.body)}let Nt=(t,n=Ht)=>async e=>{let a=await it(e,n);return a.error??t(a.body)};return{token:M,preview:He,opened:Ke,check:it,upload:gt(Nt(ct.upload,nr)),addEmoji:gt(Nt(ct.addEmoji)),unfurl:gt(Nt(ct.unfurl)),annotations:sn(ln),checkAnnotations(t){let n=bt.get(t);return n||(n={timer:0},n.done=new Promise((e,a)=>Object.assign(n,{resolve:e,reject:a})),bt.set(t,n)),clearTimeout(n.timer),n.timer=setTimeout(()=>{bt.delete(t),Jt(()=>kt.afterWrite(t)).then(n.resolve,n.reject)},cn),n.done},frameable:gt(Nt(ct.frameable)),listEmojis:ct.listEmojis,readEmoji:ct.readEmoji,respond:gt,keepVersion:K,renameReport:en,read:rt,settled:st,whenTaken:ht,readTaken:Ft,takeRewrites:b,handIn:nn,handInReport:Dt,handInRequest:rn,settleRequest:(t,n)=>an(t).then(([e,a])=>_(n,e,a),e=>_(n,500,{ok:!1,reason:"write",message:e.message})),settleNotes:_t,roundRequest:(t,n)=>on(t).then(([e,a])=>_(n,e,a),e=>_(n,500,{ok:!1,reason:"write",message:e.message})),beginRound:Xt,commit:Vt(Qe,{early:Kt}),reverted:Vt(Ve),changes:tn,noteTaken:(t,n)=>F.look(t,n),forgetChanges:t=>F.forget(t),stored:async()=>{await F.idle(),await D}}}export{Mr as a,Fr as b,Ye as c,Lr as d,ma as e};