@heycys/gallery 0.0.0-stage → 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 (806) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +50 -2
  3. package/THIRD-PARTY-NOTICES.md +3303 -0
  4. package/assets/writing-preferences.md +107 -0
  5. package/bin/gallery.mjs +10 -0
  6. package/browser/editor/components/bookmark/icons.mjs +6 -0
  7. package/browser/editor/components/bookmark/index.mjs +80 -0
  8. package/browser/editor/components/bookmark/page.mjs +147 -0
  9. package/browser/editor/components/builders.mjs +19 -0
  10. package/browser/editor/components/callout/index.mjs +64 -0
  11. package/browser/editor/components/code/index.mjs +327 -0
  12. package/browser/editor/components/code/page.mjs +561 -0
  13. package/browser/editor/components/colors.mjs +50 -0
  14. package/browser/editor/components/columns/index.mjs +104 -0
  15. package/browser/editor/components/columns/page.mjs +310 -0
  16. package/browser/editor/components/details/index.mjs +73 -0
  17. package/browser/editor/components/details/page.mjs +86 -0
  18. package/browser/editor/components/dialog/index.mjs +84 -0
  19. package/browser/editor/components/dialog/page.mjs +201 -0
  20. package/browser/editor/components/divider/index.mjs +48 -0
  21. package/browser/editor/components/embed/icons.mjs +11 -0
  22. package/browser/editor/components/embed/index.mjs +123 -0
  23. package/browser/editor/components/embed/page.mjs +309 -0
  24. package/browser/editor/components/figure/index.mjs +87 -0
  25. package/browser/editor/components/figure/page.mjs +42 -0
  26. package/browser/editor/components/file/icons.mjs +14 -0
  27. package/browser/editor/components/file/index.mjs +77 -0
  28. package/browser/editor/components/file/page.mjs +114 -0
  29. package/browser/editor/components/flowchart/add.mjs +123 -0
  30. package/browser/editor/components/flowchart/index.mjs +246 -0
  31. package/browser/editor/components/flowchart/page.mjs +453 -0
  32. package/browser/editor/components/heading/index.mjs +53 -0
  33. package/browser/editor/components/heading/page.mjs +6 -0
  34. package/browser/editor/components/highlight/index.mjs +63 -0
  35. package/browser/editor/components/icon/index.mjs +57 -0
  36. package/browser/editor/components/icon/page.mjs +286 -0
  37. package/browser/editor/components/icons.mjs +48 -0
  38. package/browser/editor/components/image/crop.mjs +189 -0
  39. package/browser/editor/components/image/index.mjs +104 -0
  40. package/browser/editor/components/image/page.mjs +385 -0
  41. package/browser/editor/components/image/viewer.mjs +213 -0
  42. package/browser/editor/components/installed/index.mjs +179 -0
  43. package/browser/editor/components/installed/page.mjs +523 -0
  44. package/browser/editor/components/installed/served.mjs +35 -0
  45. package/browser/editor/components/kit.mjs +67 -0
  46. package/browser/editor/components/list/index.mjs +194 -0
  47. package/browser/editor/components/list/join.mjs +68 -0
  48. package/browser/editor/components/list/numbers.mjs +107 -0
  49. package/browser/editor/components/list/page.mjs +632 -0
  50. package/browser/editor/components/math/index.mjs +88 -0
  51. package/browser/editor/components/math/page.mjs +236 -0
  52. package/browser/editor/components/math/tex-logo.mjs +6 -0
  53. package/browser/editor/components/media/icons.mjs +19 -0
  54. package/browser/editor/components/media/page.mjs +192 -0
  55. package/browser/editor/components/media/parts.mjs +60 -0
  56. package/browser/editor/components/media/size.mjs +20 -0
  57. package/browser/editor/components/media/toolbar.mjs +37 -0
  58. package/browser/editor/components/media/write.mjs +7 -0
  59. package/browser/editor/components/pages.mjs +46 -0
  60. package/browser/editor/components/paragraph/index.mjs +43 -0
  61. package/browser/editor/components/paragraph/page.mjs +52 -0
  62. package/browser/editor/components/placeholder-bar.mjs +17 -0
  63. package/browser/editor/components/placeholder.mjs +128 -0
  64. package/browser/editor/components/quote/index.mjs +33 -0
  65. package/browser/editor/components/registry.mjs +859 -0
  66. package/browser/editor/components/rows.mjs +16 -0
  67. package/browser/editor/components/section/index.mjs +42 -0
  68. package/browser/editor/components/section/page.mjs +141 -0
  69. package/browser/editor/components/set-apart.mjs +24 -0
  70. package/browser/editor/components/sheets/index.mjs +137 -0
  71. package/browser/editor/components/sheets/page.mjs +227 -0
  72. package/browser/editor/components/sheets/pills.mjs +226 -0
  73. package/browser/editor/components/table/grid.mjs +73 -0
  74. package/browser/editor/components/table/index.mjs +308 -0
  75. package/browser/editor/components/table/page.mjs +683 -0
  76. package/browser/editor/components/table/slots.mjs +41 -0
  77. package/browser/editor/components/widget/index.mjs +50 -0
  78. package/browser/editor/page/annotate/anchors.mjs +230 -0
  79. package/browser/editor/page/annotate/card.mjs +102 -0
  80. package/browser/editor/page/annotate/index.mjs +1656 -0
  81. package/browser/editor/page/at-menu/index.mjs +317 -0
  82. package/browser/editor/page/autosave.mjs +1023 -0
  83. package/browser/editor/page/beside.mjs +21 -0
  84. package/browser/editor/page/block-info.mjs +63 -0
  85. package/browser/editor/page/block-menu/colors.mjs +84 -0
  86. package/browser/editor/page/block-menu/index.mjs +217 -0
  87. package/browser/editor/page/blocks.mjs +255 -0
  88. package/browser/editor/page/caret.mjs +682 -0
  89. package/browser/editor/page/changes/bar.mjs +102 -0
  90. package/browser/editor/page/changes/ghost.mjs +206 -0
  91. package/browser/editor/page/changes/gone-words.mjs +94 -0
  92. package/browser/editor/page/changes/index.mjs +447 -0
  93. package/browser/editor/page/changes/words.mjs +27 -0
  94. package/browser/editor/page/chip-fills.mjs +126 -0
  95. package/browser/editor/page/clipboard/import/colors.mjs +192 -0
  96. package/browser/editor/page/clipboard/import/html.mjs +792 -0
  97. package/browser/editor/page/clipboard/import/inline.mjs +232 -0
  98. package/browser/editor/page/clipboard/import/languages.mjs +42 -0
  99. package/browser/editor/page/clipboard/import/markdown.mjs +760 -0
  100. package/browser/editor/page/clipboard/import/math.mjs +100 -0
  101. package/browser/editor/page/clipboard/import/office.mjs +245 -0
  102. package/browser/editor/page/clipboard/import/read.mjs +120 -0
  103. package/browser/editor/page/clipboard/import/rich.mjs +29 -0
  104. package/browser/editor/page/clipboard/import/to-blocks.mjs +290 -0
  105. package/browser/editor/page/clipboard/index.mjs +816 -0
  106. package/browser/editor/page/clipboard/own/blocks.mjs +211 -0
  107. package/browser/editor/page/clipboard/own/chart-keys.mjs +58 -0
  108. package/browser/editor/page/clipboard/own/describe.mjs +124 -0
  109. package/browser/editor/page/clipboard/own/export.mjs +167 -0
  110. package/browser/editor/page/clipboard/own/ids.mjs +39 -0
  111. package/browser/editor/page/clipboard/own/index.mjs +13 -0
  112. package/browser/editor/page/clipboard/own/rules.mjs +44 -0
  113. package/browser/editor/page/clipboard/own/selection.mjs +159 -0
  114. package/browser/editor/page/clipboard/own/writers.mjs +315 -0
  115. package/browser/editor/page/columns/index.mjs +360 -0
  116. package/browser/editor/page/commit.mjs +1813 -0
  117. package/browser/editor/page/conflicts.mjs +249 -0
  118. package/browser/editor/page/convert.mjs +831 -0
  119. package/browser/editor/page/core.mjs +1693 -0
  120. package/browser/editor/page/drag/drop.mjs +307 -0
  121. package/browser/editor/page/drag/index.mjs +351 -0
  122. package/browser/editor/page/drag/preview.mjs +126 -0
  123. package/browser/editor/page/edge-scroll.mjs +50 -0
  124. package/browser/editor/page/editor.mjs +1780 -0
  125. package/browser/editor/page/emoji-picker/emoji-tab.mjs +287 -0
  126. package/browser/editor/page/emoji-picker/glyph-html.mjs +26 -0
  127. package/browser/editor/page/emoji-picker/grid.mjs +81 -0
  128. package/browser/editor/page/emoji-picker/icon-tab.mjs +217 -0
  129. package/browser/editor/page/emoji-picker/icons.mjs +31 -0
  130. package/browser/editor/page/emoji-picker/index.mjs +166 -0
  131. package/browser/editor/page/emoji-picker/styles.mjs +161 -0
  132. package/browser/editor/page/emoji-picker/support.mjs +204 -0
  133. package/browser/editor/page/emoji-picker/upload.mjs +236 -0
  134. package/browser/editor/page/export-report.mjs +23 -0
  135. package/browser/editor/page/fills.mjs +62 -0
  136. package/browser/editor/page/find/index.mjs +107 -0
  137. package/browser/editor/page/flags.mjs +70 -0
  138. package/browser/editor/page/fold/index.mjs +348 -0
  139. package/browser/editor/page/fold/rule.mjs +125 -0
  140. package/browser/editor/page/folded.mjs +23 -0
  141. package/browser/editor/page/format-bar/bar.mjs +449 -0
  142. package/browser/editor/page/format-bar/brush.mjs +77 -0
  143. package/browser/editor/page/format-bar/colors.mjs +46 -0
  144. package/browser/editor/page/format-bar/index.mjs +404 -0
  145. package/browser/editor/page/formula/index.mjs +236 -0
  146. package/browser/editor/page/formula/panel.mjs +336 -0
  147. package/browser/editor/page/formula/symbols.mjs +156 -0
  148. package/browser/editor/page/frame.mjs +74 -0
  149. package/browser/editor/page/frames.mjs +196 -0
  150. package/browser/editor/page/geometry.mjs +402 -0
  151. package/browser/editor/page/gesture.mjs +45 -0
  152. package/browser/editor/page/handle/index.mjs +650 -0
  153. package/browser/editor/page/handle-sizes.mjs +14 -0
  154. package/browser/editor/page/hints/index.mjs +84 -0
  155. package/browser/editor/page/history.mjs +401 -0
  156. package/browser/editor/page/insert/index.mjs +256 -0
  157. package/browser/editor/page/kept.mjs +38 -0
  158. package/browser/editor/page/links/address.mjs +40 -0
  159. package/browser/editor/page/links/index.mjs +866 -0
  160. package/browser/editor/page/links/pages.mjs +131 -0
  161. package/browser/editor/page/links/views.mjs +369 -0
  162. package/browser/editor/page/long-runs.mjs +75 -0
  163. package/browser/editor/page/look.mjs +77 -0
  164. package/browser/editor/page/made.mjs +24 -0
  165. package/browser/editor/page/margin.mjs +373 -0
  166. package/browser/editor/page/markdown/index.mjs +88 -0
  167. package/browser/editor/page/markdown/rules.mjs +33 -0
  168. package/browser/editor/page/marks.mjs +377 -0
  169. package/browser/editor/page/media-menu/index.mjs +158 -0
  170. package/browser/editor/page/menu.mjs +544 -0
  171. package/browser/editor/page/merge.mjs +124 -0
  172. package/browser/editor/page/notices.mjs +142 -0
  173. package/browser/editor/page/offered.mjs +32 -0
  174. package/browser/editor/page/outline/folds.mjs +53 -0
  175. package/browser/editor/page/outline/index.mjs +783 -0
  176. package/browser/editor/page/outline/list.mjs +184 -0
  177. package/browser/editor/page/outline/read.mjs +201 -0
  178. package/browser/editor/page/outline/strip.mjs +287 -0
  179. package/browser/editor/page/outline/tree.mjs +248 -0
  180. package/browser/editor/page/overlay-layer.mjs +227 -0
  181. package/browser/editor/page/overlays.mjs +205 -0
  182. package/browser/editor/page/own.mjs +28 -0
  183. package/browser/editor/page/pads.mjs +71 -0
  184. package/browser/editor/page/page-objects.mjs +105 -0
  185. package/browser/editor/page/panel.mjs +65 -0
  186. package/browser/editor/page/placement.mjs +58 -0
  187. package/browser/editor/page/post.mjs +41 -0
  188. package/browser/editor/page/present-links.mjs +50 -0
  189. package/browser/editor/page/quiet.mjs +48 -0
  190. package/browser/editor/page/resize/index.mjs +327 -0
  191. package/browser/editor/page/select-all/index.mjs +262 -0
  192. package/browser/editor/page/selection/delete.mjs +61 -0
  193. package/browser/editor/page/selection/index.mjs +164 -0
  194. package/browser/editor/page/selection/marquee.mjs +174 -0
  195. package/browser/editor/page/session.mjs +168 -0
  196. package/browser/editor/page/slash-menu/index.mjs +291 -0
  197. package/browser/editor/page/storage.mjs +48 -0
  198. package/browser/editor/page/sync-state.mjs +267 -0
  199. package/browser/editor/page/table/aligns.mjs +29 -0
  200. package/browser/editor/page/table/cell-bar.mjs +141 -0
  201. package/browser/editor/page/table/cells.mjs +527 -0
  202. package/browser/editor/page/table/icons.mjs +40 -0
  203. package/browser/editor/page/table/index.mjs +990 -0
  204. package/browser/editor/page/table/lists.mjs +187 -0
  205. package/browser/editor/page/table/widths.mjs +313 -0
  206. package/browser/editor/page/tex.mjs +32 -0
  207. package/browser/editor/page/text-select/index.mjs +671 -0
  208. package/browser/editor/page/tooltip.mjs +98 -0
  209. package/browser/editor/page/type-grid.mjs +83 -0
  210. package/browser/editor/page/typing/code-edges.mjs +274 -0
  211. package/browser/editor/page/typing/index.mjs +282 -0
  212. package/browser/editor/page/typing/leave.mjs +68 -0
  213. package/browser/editor/page/ui.mjs +160 -0
  214. package/browser/shared/annotations.mjs +569 -0
  215. package/browser/shared/code-folds.mjs +14 -0
  216. package/browser/shared/code-languages.mjs +70 -0
  217. package/browser/shared/code-lines.mjs +30 -0
  218. package/browser/shared/colors.mjs +30 -0
  219. package/browser/shared/component-catalog.mjs +573 -0
  220. package/browser/shared/components/bookmark.mjs +26 -0
  221. package/browser/shared/components/callout.mjs +9 -0
  222. package/browser/shared/components/chart.mjs +20 -0
  223. package/browser/shared/components/code.mjs +37 -0
  224. package/browser/shared/components/columns.mjs +16 -0
  225. package/browser/shared/components/details.mjs +15 -0
  226. package/browser/shared/components/dialog.mjs +28 -0
  227. package/browser/shared/components/diff.mjs +18 -0
  228. package/browser/shared/components/divider.mjs +6 -0
  229. package/browser/shared/components/embed.mjs +25 -0
  230. package/browser/shared/components/figure.mjs +14 -0
  231. package/browser/shared/components/file.mjs +23 -0
  232. package/browser/shared/components/heading.mjs +6 -0
  233. package/browser/shared/components/highlight.mjs +9 -0
  234. package/browser/shared/components/icon.mjs +18 -0
  235. package/browser/shared/components/image.mjs +39 -0
  236. package/browser/shared/components/index.mjs +396 -0
  237. package/browser/shared/components/installed.mjs +232 -0
  238. package/browser/shared/components/list.mjs +146 -0
  239. package/browser/shared/components/math.mjs +49 -0
  240. package/browser/shared/components/mention.mjs +33 -0
  241. package/browser/shared/components/page.mjs +46 -0
  242. package/browser/shared/components/paragraph.mjs +9 -0
  243. package/browser/shared/components/quote.mjs +6 -0
  244. package/browser/shared/components/section.mjs +8 -0
  245. package/browser/shared/components/sheets.mjs +80 -0
  246. package/browser/shared/components/state.mjs +20 -0
  247. package/browser/shared/components/table.mjs +49 -0
  248. package/browser/shared/components/text.mjs +14 -0
  249. package/browser/shared/components/widget.mjs +10 -0
  250. package/browser/shared/copy-ids.mjs +72 -0
  251. package/browser/shared/css-references.mjs +110 -0
  252. package/browser/shared/document-look.mjs +178 -0
  253. package/browser/shared/emoji/custom.mjs +91 -0
  254. package/browser/shared/emoji/data/LICENSE-lucide.txt +43 -0
  255. package/browser/shared/emoji/data/LICENSE-mingcute.txt +202 -0
  256. package/browser/shared/emoji/data/LICENSE-tabler.txt +21 -0
  257. package/browser/shared/emoji/data/README.md +28 -0
  258. package/browser/shared/emoji/data/categories.json +1 -0
  259. package/browser/shared/emoji/data/icons.json +1 -0
  260. package/browser/shared/emoji/data/keywords-en.json +1 -0
  261. package/browser/shared/emoji/data/keywords-zh.json +1 -0
  262. package/browser/shared/emoji/data/names.json +1 -0
  263. package/browser/shared/emoji/data/positions.json +1 -0
  264. package/browser/shared/emoji/data/twemoji-index.json +1 -0
  265. package/browser/shared/emoji/data/twemoji-svg.bin +0 -0
  266. package/browser/shared/emoji/data.mjs +194 -0
  267. package/browser/shared/emoji/emoji.mjs +38 -0
  268. package/browser/shared/emoji/glyphs.mjs +134 -0
  269. package/browser/shared/emoji/icon-value.mjs +91 -0
  270. package/browser/shared/escape.mjs +20 -0
  271. package/browser/shared/export-wrap.mjs +89 -0
  272. package/browser/shared/files.mjs +33 -0
  273. package/browser/shared/html-tree.mjs +59 -0
  274. package/browser/shared/http.mjs +22 -0
  275. package/browser/shared/i18n/en.mjs +1223 -0
  276. package/browser/shared/i18n/index.mjs +132 -0
  277. package/browser/shared/ids.mjs +24 -0
  278. package/browser/shared/import-types.mjs +23 -0
  279. package/browser/shared/inline-spacing.mjs +97 -0
  280. package/browser/shared/layers.mjs +42 -0
  281. package/browser/shared/long-runs.mjs +39 -0
  282. package/browser/shared/media.mjs +162 -0
  283. package/browser/shared/new-names.mjs +67 -0
  284. package/browser/shared/number-reading.mjs +92 -0
  285. package/browser/shared/old-names.mjs +143 -0
  286. package/browser/shared/outline.mjs +194 -0
  287. package/browser/shared/page-address.mjs +140 -0
  288. package/browser/shared/page-links.mjs +86 -0
  289. package/browser/shared/paths.mjs +73 -0
  290. package/browser/shared/preferences.mjs +116 -0
  291. package/browser/shared/preview-server.mjs +247 -0
  292. package/browser/shared/qa-levels.mjs +93 -0
  293. package/browser/shared/reading-place.mjs +91 -0
  294. package/browser/shared/renamed-storage.mjs +220 -0
  295. package/browser/shared/reports.mjs +46 -0
  296. package/browser/shared/search.mjs +85 -0
  297. package/browser/shared/session.mjs +77 -0
  298. package/browser/shared/table-chart.mjs +113 -0
  299. package/browser/shared/table-hides.mjs +120 -0
  300. package/browser/shared/table-slots.mjs +75 -0
  301. package/browser/shared/words.mjs +23 -0
  302. package/browser/shared/workspace-look.mjs +91 -0
  303. package/browser/shared/workspace.mjs +535 -0
  304. package/browser/shared/writing-preferences.mjs +68 -0
  305. package/browser/shared/zoom.mjs +57 -0
  306. package/dist/chunk-2B5E4CDJ.mjs +2 -0
  307. package/dist/chunk-342HXE3Q.mjs +2 -0
  308. package/dist/chunk-3HIRPVLU.mjs +2 -0
  309. package/dist/chunk-43B75J5T.mjs +2 -0
  310. package/dist/chunk-4FS7Z7WR.mjs +2 -0
  311. package/dist/chunk-4K5KC6V2.mjs +2 -0
  312. package/dist/chunk-5L7RYZCL.mjs +2 -0
  313. package/dist/chunk-5MHMDLZD.mjs +4 -0
  314. package/dist/chunk-5ZKJ3H4P.mjs +8 -0
  315. package/dist/chunk-64K7IPLO.mjs +255 -0
  316. package/dist/chunk-6QXGZM36.mjs +8 -0
  317. package/dist/chunk-6RGJOMJP.mjs +16 -0
  318. package/dist/chunk-742D2WWJ.mjs +19 -0
  319. package/dist/chunk-7DTINW6U.mjs +48 -0
  320. package/dist/chunk-A55HN5OK.mjs +2 -0
  321. package/dist/chunk-AGDILNWB.mjs +2 -0
  322. package/dist/chunk-AJ73XJF3.mjs +2 -0
  323. package/dist/chunk-AUZGSZJH.mjs +13 -0
  324. package/dist/chunk-BFE45AKL.mjs +2 -0
  325. package/dist/chunk-BGGDRNYQ.mjs +10 -0
  326. package/dist/chunk-BXO2ZY5P.mjs +2 -0
  327. package/dist/chunk-C564NU2H.mjs +77 -0
  328. package/dist/chunk-CEH4MRCC.mjs +2 -0
  329. package/dist/chunk-CY2FNNAB.mjs +16 -0
  330. package/dist/chunk-DFUDV4LX.mjs +2 -0
  331. package/dist/chunk-DKXG4XDG.mjs +2 -0
  332. package/dist/chunk-E7LWZRXY.mjs +4 -0
  333. package/dist/chunk-EZQ34M3F.mjs +124 -0
  334. package/dist/chunk-EZY3WC6Z.mjs +15 -0
  335. package/dist/chunk-FDLXYYG4.mjs +4 -0
  336. package/dist/chunk-FUKQNOQS.mjs +9 -0
  337. package/dist/chunk-GB5SOYQJ.mjs +7 -0
  338. package/dist/chunk-GRAXKKG4.mjs +2 -0
  339. package/dist/chunk-HYMEEXKN.mjs +4 -0
  340. package/dist/chunk-IVDLMMBD.mjs +2 -0
  341. package/dist/chunk-JPOSLGOC.mjs +6 -0
  342. package/dist/chunk-JVHHHGEA.mjs +3 -0
  343. package/dist/chunk-L3QKH4OK.mjs +26 -0
  344. package/dist/chunk-LAE5NQ4B.mjs +2 -0
  345. package/dist/chunk-LCTHTZIL.mjs +960 -0
  346. package/dist/chunk-LEF6DRCK.mjs +59 -0
  347. package/dist/chunk-LKX55H76.mjs +2 -0
  348. package/dist/chunk-LS4F7JUM.mjs +2 -0
  349. package/dist/chunk-MAFIGVXY.mjs +2 -0
  350. package/dist/chunk-NO5NJCHO.mjs +2 -0
  351. package/dist/chunk-NQPVAU63.mjs +2 -0
  352. package/dist/chunk-NSKUTQ5J.mjs +5 -0
  353. package/dist/chunk-O35FIXRB.mjs +2 -0
  354. package/dist/chunk-P2CAZPDP.mjs +3 -0
  355. package/dist/chunk-PL6GHLGD.mjs +15 -0
  356. package/dist/chunk-QAIHRH3I.mjs +13 -0
  357. package/dist/chunk-QJIR2BLP.mjs +6 -0
  358. package/dist/chunk-QR6A54KJ.mjs +3 -0
  359. package/dist/chunk-QUPLVPB2.mjs +7 -0
  360. package/dist/chunk-R7BNENLY.mjs +4 -0
  361. package/dist/chunk-S6O4UHLC.mjs +2 -0
  362. package/dist/chunk-SGJWQKEI.mjs +2 -0
  363. package/dist/chunk-SYGN7GLU.mjs +2 -0
  364. package/dist/chunk-TMYZB6AV.mjs +2 -0
  365. package/dist/chunk-TX6JH7TR.mjs +2 -0
  366. package/dist/chunk-TYK6VNAB.mjs +10 -0
  367. package/dist/chunk-U3SSPL4K.mjs +8 -0
  368. package/dist/chunk-U6KNPJPR.mjs +2 -0
  369. package/dist/chunk-UALRNVSE.mjs +4 -0
  370. package/dist/chunk-UH4SIXTR.mjs +2 -0
  371. package/dist/chunk-UMHUSOPJ.mjs +2 -0
  372. package/dist/chunk-V3HXVQEM.mjs +2 -0
  373. package/dist/chunk-V5JTW2LH.mjs +27 -0
  374. package/dist/chunk-V5VXUJKG.mjs +2 -0
  375. package/dist/chunk-V6XZ4VIR.mjs +2 -0
  376. package/dist/chunk-VBXMADMP.mjs +2 -0
  377. package/dist/chunk-VNV55RUA.mjs +2 -0
  378. package/dist/chunk-VPD2PS35.mjs +2 -0
  379. package/dist/chunk-W3BGBJQW.mjs +2 -0
  380. package/dist/chunk-W4VKN3GF.mjs +7 -0
  381. package/dist/chunk-W5BXXPDJ.mjs +3 -0
  382. package/dist/chunk-W7XHE4CT.mjs +2 -0
  383. package/dist/chunk-XNROSH2T.mjs +4 -0
  384. package/dist/chunk-XUNHRCOG.mjs +6 -0
  385. package/dist/chunk-Y34NR5JL.mjs +2 -0
  386. package/dist/chunk-Y6RLRPG3.mjs +3 -0
  387. package/dist/chunk-YEY3RSFQ.mjs +2 -0
  388. package/dist/cli.mjs +2 -0
  389. package/dist/server.mjs +2 -0
  390. package/dist/worker.mjs +5 -0
  391. package/kit/charts.js +355 -0
  392. package/kit/code.js +164 -0
  393. package/kit/dialogs.js +157 -0
  394. package/kit/math.js +2004 -0
  395. package/kit/report.css +2932 -0
  396. package/kit/runtime.js +1782 -0
  397. package/kit/sheets.js +123 -0
  398. package/kit/state.js +217 -0
  399. package/kit/tables.js +1499 -0
  400. package/kit/tokens.js +29 -0
  401. package/kit/ui.js +658 -0
  402. package/package.json +41 -4
  403. package/release.json +25 -0
  404. package/sdk/column-widths.d.ts +56 -0
  405. package/sdk/doc-charts.d.ts +82 -0
  406. package/sdk/doc-code.d.ts +28 -0
  407. package/sdk/doc-dialogs.d.ts +4 -0
  408. package/sdk/doc-kit.d.ts +147 -0
  409. package/sdk/doc-math.d.ts +3 -0
  410. package/sdk/doc-sheets.d.ts +15 -0
  411. package/sdk/doc-state.d.ts +41 -0
  412. package/sdk/doc-tables.d.ts +24 -0
  413. package/sdk/doc-tokens.d.ts +22 -0
  414. package/sdk/index.d.ts +30 -0
  415. package/skill/SKILL.md +150 -0
  416. package/skill/agents/openai.yaml +5 -0
  417. package/skill/references/building-components.md +367 -0
  418. package/skill/references/example-report.html +356 -0
  419. package/skill/references/writing-html.md +187 -0
  420. package/skill/sdk/column-widths.d.ts +56 -0
  421. package/skill/sdk/doc-charts.d.ts +82 -0
  422. package/skill/sdk/doc-code.d.ts +28 -0
  423. package/skill/sdk/doc-dialogs.d.ts +4 -0
  424. package/skill/sdk/doc-kit.d.ts +147 -0
  425. package/skill/sdk/doc-math.d.ts +3 -0
  426. package/skill/sdk/doc-sheets.d.ts +15 -0
  427. package/skill/sdk/doc-state.d.ts +41 -0
  428. package/skill/sdk/doc-tables.d.ts +24 -0
  429. package/skill/sdk/doc-tokens.d.ts +22 -0
  430. package/skill/sdk/index.d.ts +30 -0
  431. package/starter/doc.html +21 -0
  432. package/starter/doc.json +5 -0
  433. package/vendor/d3.v7.9.0.min.js +2 -0
  434. package/vendor/katex/auto-render.min.js +1 -0
  435. package/vendor/katex/contrib/mhchem.min.js +1 -0
  436. package/vendor/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  437. package/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  438. package/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  439. package/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  440. package/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  441. package/vendor/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
  442. package/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  443. package/vendor/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
  444. package/vendor/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
  445. package/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  446. package/vendor/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
  447. package/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  448. package/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  449. package/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  450. package/vendor/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
  451. package/vendor/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  452. package/vendor/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  453. package/vendor/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  454. package/vendor/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  455. package/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  456. package/vendor/katex/katex.min.css +1 -0
  457. package/vendor/katex/katex.min.js +1 -0
  458. package/vendor/pdfjs/LICENSE +177 -0
  459. package/vendor/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
  460. package/vendor/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
  461. package/vendor/pdfjs/cmaps/78-H.bcmap +0 -0
  462. package/vendor/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
  463. package/vendor/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
  464. package/vendor/pdfjs/cmaps/78-V.bcmap +0 -0
  465. package/vendor/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
  466. package/vendor/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
  467. package/vendor/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
  468. package/vendor/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
  469. package/vendor/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
  470. package/vendor/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
  471. package/vendor/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
  472. package/vendor/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
  473. package/vendor/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
  474. package/vendor/pdfjs/cmaps/Add-H.bcmap +0 -0
  475. package/vendor/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
  476. package/vendor/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
  477. package/vendor/pdfjs/cmaps/Add-V.bcmap +0 -0
  478. package/vendor/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
  479. package/vendor/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
  480. package/vendor/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
  481. package/vendor/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
  482. package/vendor/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
  483. package/vendor/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
  484. package/vendor/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
  485. package/vendor/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
  486. package/vendor/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
  487. package/vendor/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
  488. package/vendor/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
  489. package/vendor/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
  490. package/vendor/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
  491. package/vendor/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
  492. package/vendor/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
  493. package/vendor/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
  494. package/vendor/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
  495. package/vendor/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
  496. package/vendor/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
  497. package/vendor/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
  498. package/vendor/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
  499. package/vendor/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
  500. package/vendor/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
  501. package/vendor/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
  502. package/vendor/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
  503. package/vendor/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
  504. package/vendor/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
  505. package/vendor/pdfjs/cmaps/B5-H.bcmap +0 -0
  506. package/vendor/pdfjs/cmaps/B5-V.bcmap +0 -0
  507. package/vendor/pdfjs/cmaps/B5pc-H.bcmap +0 -0
  508. package/vendor/pdfjs/cmaps/B5pc-V.bcmap +0 -0
  509. package/vendor/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
  510. package/vendor/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
  511. package/vendor/pdfjs/cmaps/CNS1-H.bcmap +0 -0
  512. package/vendor/pdfjs/cmaps/CNS1-V.bcmap +0 -0
  513. package/vendor/pdfjs/cmaps/CNS2-H.bcmap +0 -0
  514. package/vendor/pdfjs/cmaps/CNS2-V.bcmap +3 -0
  515. package/vendor/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
  516. package/vendor/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
  517. package/vendor/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
  518. package/vendor/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
  519. package/vendor/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
  520. package/vendor/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
  521. package/vendor/pdfjs/cmaps/EUC-H.bcmap +0 -0
  522. package/vendor/pdfjs/cmaps/EUC-V.bcmap +0 -0
  523. package/vendor/pdfjs/cmaps/Ext-H.bcmap +0 -0
  524. package/vendor/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
  525. package/vendor/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
  526. package/vendor/pdfjs/cmaps/Ext-V.bcmap +0 -0
  527. package/vendor/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
  528. package/vendor/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
  529. package/vendor/pdfjs/cmaps/GB-H.bcmap +4 -0
  530. package/vendor/pdfjs/cmaps/GB-V.bcmap +0 -0
  531. package/vendor/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
  532. package/vendor/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
  533. package/vendor/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
  534. package/vendor/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
  535. package/vendor/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
  536. package/vendor/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
  537. package/vendor/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
  538. package/vendor/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
  539. package/vendor/pdfjs/cmaps/GBT-H.bcmap +0 -0
  540. package/vendor/pdfjs/cmaps/GBT-V.bcmap +0 -0
  541. package/vendor/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
  542. package/vendor/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
  543. package/vendor/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
  544. package/vendor/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
  545. package/vendor/pdfjs/cmaps/H.bcmap +0 -0
  546. package/vendor/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
  547. package/vendor/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
  548. package/vendor/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
  549. package/vendor/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
  550. package/vendor/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
  551. package/vendor/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
  552. package/vendor/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
  553. package/vendor/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
  554. package/vendor/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
  555. package/vendor/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
  556. package/vendor/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
  557. package/vendor/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
  558. package/vendor/pdfjs/cmaps/Hankaku.bcmap +0 -0
  559. package/vendor/pdfjs/cmaps/Hiragana.bcmap +0 -0
  560. package/vendor/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
  561. package/vendor/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
  562. package/vendor/pdfjs/cmaps/KSC-H.bcmap +0 -0
  563. package/vendor/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
  564. package/vendor/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
  565. package/vendor/pdfjs/cmaps/KSC-V.bcmap +0 -0
  566. package/vendor/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
  567. package/vendor/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
  568. package/vendor/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
  569. package/vendor/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
  570. package/vendor/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
  571. package/vendor/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
  572. package/vendor/pdfjs/cmaps/Katakana.bcmap +0 -0
  573. package/vendor/pdfjs/cmaps/LICENSE +36 -0
  574. package/vendor/pdfjs/cmaps/NWP-H.bcmap +0 -0
  575. package/vendor/pdfjs/cmaps/NWP-V.bcmap +0 -0
  576. package/vendor/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
  577. package/vendor/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
  578. package/vendor/pdfjs/cmaps/Roman.bcmap +0 -0
  579. package/vendor/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
  580. package/vendor/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
  581. package/vendor/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
  582. package/vendor/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
  583. package/vendor/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
  584. package/vendor/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
  585. package/vendor/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
  586. package/vendor/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
  587. package/vendor/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
  588. package/vendor/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
  589. package/vendor/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
  590. package/vendor/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
  591. package/vendor/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
  592. package/vendor/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
  593. package/vendor/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
  594. package/vendor/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
  595. package/vendor/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
  596. package/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
  597. package/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
  598. package/vendor/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
  599. package/vendor/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
  600. package/vendor/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
  601. package/vendor/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
  602. package/vendor/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
  603. package/vendor/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
  604. package/vendor/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
  605. package/vendor/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
  606. package/vendor/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
  607. package/vendor/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
  608. package/vendor/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
  609. package/vendor/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
  610. package/vendor/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
  611. package/vendor/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
  612. package/vendor/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
  613. package/vendor/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
  614. package/vendor/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
  615. package/vendor/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
  616. package/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
  617. package/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
  618. package/vendor/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
  619. package/vendor/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
  620. package/vendor/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
  621. package/vendor/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
  622. package/vendor/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
  623. package/vendor/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
  624. package/vendor/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
  625. package/vendor/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
  626. package/vendor/pdfjs/cmaps/V.bcmap +0 -0
  627. package/vendor/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
  628. package/vendor/pdfjs/legacy/build/pdf.min.mjs +27 -0
  629. package/vendor/pdfjs/legacy/build/pdf.worker.min.mjs +27 -0
  630. package/vendor/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
  631. package/vendor/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
  632. package/vendor/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
  633. package/vendor/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
  634. package/vendor/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
  635. package/vendor/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
  636. package/vendor/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
  637. package/vendor/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
  638. package/vendor/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
  639. package/vendor/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
  640. package/vendor/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
  641. package/vendor/pdfjs/standard_fonts/LICENSE_LIBERATION +363 -0
  642. package/vendor/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
  643. package/vendor/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
  644. package/vendor/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
  645. package/vendor/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
  646. package/vendor/types/@types/d3/LICENSE +21 -0
  647. package/vendor/types/@types/d3/index.d.ts +39 -0
  648. package/vendor/types/@types/d3/package.json +81 -0
  649. package/vendor/types/@types/d3-array/LICENSE +21 -0
  650. package/vendor/types/@types/d3-array/index.d.ts +1118 -0
  651. package/vendor/types/@types/d3-array/package.json +56 -0
  652. package/vendor/types/@types/d3-axis/LICENSE +21 -0
  653. package/vendor/types/@types/d3-axis/index.d.ts +293 -0
  654. package/vendor/types/@types/d3-axis/package.json +47 -0
  655. package/vendor/types/@types/d3-brush/LICENSE +21 -0
  656. package/vendor/types/@types/d3-brush/index.d.ts +255 -0
  657. package/vendor/types/@types/d3-brush/package.json +42 -0
  658. package/vendor/types/@types/d3-chord/LICENSE +21 -0
  659. package/vendor/types/@types/d3-chord/index.d.ts +471 -0
  660. package/vendor/types/@types/d3-chord/package.json +40 -0
  661. package/vendor/types/@types/d3-color/LICENSE +21 -0
  662. package/vendor/types/@types/d3-color/index.d.ts +669 -0
  663. package/vendor/types/@types/d3-color/package.json +55 -0
  664. package/vendor/types/@types/d3-contour/LICENSE +21 -0
  665. package/vendor/types/@types/d3-contour/index.d.ts +222 -0
  666. package/vendor/types/@types/d3-contour/package.json +38 -0
  667. package/vendor/types/@types/d3-delaunay/LICENSE +21 -0
  668. package/vendor/types/@types/d3-delaunay/index.d.ts +316 -0
  669. package/vendor/types/@types/d3-delaunay/package.json +30 -0
  670. package/vendor/types/@types/d3-dispatch/LICENSE +21 -0
  671. package/vendor/types/@types/d3-dispatch/index.d.ts +96 -0
  672. package/vendor/types/@types/d3-dispatch/package.json +51 -0
  673. package/vendor/types/@types/d3-drag/LICENSE +21 -0
  674. package/vendor/types/@types/d3-drag/index.d.ts +395 -0
  675. package/vendor/types/@types/d3-drag/package.json +42 -0
  676. package/vendor/types/@types/d3-dsv/LICENSE +21 -0
  677. package/vendor/types/@types/d3-dsv/index.d.ts +482 -0
  678. package/vendor/types/@types/d3-dsv/package.json +45 -0
  679. package/vendor/types/@types/d3-ease/LICENSE +21 -0
  680. package/vendor/types/@types/d3-ease/index.d.ts +316 -0
  681. package/vendor/types/@types/d3-ease/package.json +40 -0
  682. package/vendor/types/@types/d3-fetch/LICENSE +21 -0
  683. package/vendor/types/@types/d3-fetch/index.d.ts +282 -0
  684. package/vendor/types/@types/d3-fetch/package.json +37 -0
  685. package/vendor/types/@types/d3-force/LICENSE +21 -0
  686. package/vendor/types/@types/d3-force/index.d.ts +899 -0
  687. package/vendor/types/@types/d3-force/package.json +45 -0
  688. package/vendor/types/@types/d3-format/LICENSE +21 -0
  689. package/vendor/types/@types/d3-format/index.d.ts +337 -0
  690. package/vendor/types/@types/d3-format/package.json +45 -0
  691. package/vendor/types/@types/d3-geo/LICENSE +21 -0
  692. package/vendor/types/@types/d3-geo/index.d.ts +1371 -0
  693. package/vendor/types/@types/d3-geo/package.json +48 -0
  694. package/vendor/types/@types/d3-hierarchy/LICENSE +21 -0
  695. package/vendor/types/@types/d3-hierarchy/index.d.ts +928 -0
  696. package/vendor/types/@types/d3-hierarchy/package.json +50 -0
  697. package/vendor/types/@types/d3-interpolate/LICENSE +21 -0
  698. package/vendor/types/@types/d3-interpolate/index.d.ts +387 -0
  699. package/vendor/types/@types/d3-interpolate/package.json +47 -0
  700. package/vendor/types/@types/d3-path/LICENSE +21 -0
  701. package/vendor/types/@types/d3-path/index.d.ts +108 -0
  702. package/vendor/types/@types/d3-path/package.json +41 -0
  703. package/vendor/types/@types/d3-polygon/LICENSE +21 -0
  704. package/vendor/types/@types/d3-polygon/index.d.ts +41 -0
  705. package/vendor/types/@types/d3-polygon/package.json +40 -0
  706. package/vendor/types/@types/d3-quadtree/LICENSE +21 -0
  707. package/vendor/types/@types/d3-quadtree/index.d.ts +204 -0
  708. package/vendor/types/@types/d3-quadtree/package.json +45 -0
  709. package/vendor/types/@types/d3-random/LICENSE +21 -0
  710. package/vendor/types/@types/d3-random/index.d.ts +313 -0
  711. package/vendor/types/@types/d3-random/package.json +41 -0
  712. package/vendor/types/@types/d3-scale/LICENSE +21 -0
  713. package/vendor/types/@types/d3-scale/index.d.ts +2669 -0
  714. package/vendor/types/@types/d3-scale/package.json +53 -0
  715. package/vendor/types/@types/d3-scale-chromatic/LICENSE +21 -0
  716. package/vendor/types/@types/d3-scale-chromatic/index.d.ts +520 -0
  717. package/vendor/types/@types/d3-scale-chromatic/package.json +46 -0
  718. package/vendor/types/@types/d3-selection/LICENSE +21 -0
  719. package/vendor/types/@types/d3-selection/index.d.ts +1210 -0
  720. package/vendor/types/@types/d3-selection/package.json +56 -0
  721. package/vendor/types/@types/d3-shape/LICENSE +21 -0
  722. package/vendor/types/@types/d3-shape/index.d.ts +2792 -0
  723. package/vendor/types/@types/d3-shape/package.json +53 -0
  724. package/vendor/types/@types/d3-time/LICENSE +21 -0
  725. package/vendor/types/@types/d3-time/index.d.ts +697 -0
  726. package/vendor/types/@types/d3-time/package.json +46 -0
  727. package/vendor/types/@types/d3-time-format/LICENSE +21 -0
  728. package/vendor/types/@types/d3-time-format/index.d.ts +202 -0
  729. package/vendor/types/@types/d3-time-format/package.json +40 -0
  730. package/vendor/types/@types/d3-timer/LICENSE +21 -0
  731. package/vendor/types/@types/d3-timer/index.d.ts +68 -0
  732. package/vendor/types/@types/d3-timer/package.json +45 -0
  733. package/vendor/types/@types/d3-transition/LICENSE +21 -0
  734. package/vendor/types/@types/d3-transition/index.d.ts +664 -0
  735. package/vendor/types/@types/d3-transition/package.json +47 -0
  736. package/vendor/types/@types/d3-zoom/LICENSE +21 -0
  737. package/vendor/types/@types/d3-zoom/index.d.ts +611 -0
  738. package/vendor/types/@types/d3-zoom/package.json +48 -0
  739. package/vendor/types/@types/geojson/LICENSE +21 -0
  740. package/vendor/types/@types/geojson/index.d.ts +202 -0
  741. package/vendor/types/@types/geojson/package.json +46 -0
  742. package/vendor/typescript/LICENSE.txt +55 -0
  743. package/vendor/typescript/lib.decorators.d.ts +384 -0
  744. package/vendor/typescript/lib.decorators.legacy.d.ts +22 -0
  745. package/vendor/typescript/lib.dom.d.ts +39429 -0
  746. package/vendor/typescript/lib.dom.iterable.d.ts +571 -0
  747. package/vendor/typescript/lib.es2015.collection.d.ts +147 -0
  748. package/vendor/typescript/lib.es2015.core.d.ts +597 -0
  749. package/vendor/typescript/lib.es2015.d.ts +28 -0
  750. package/vendor/typescript/lib.es2015.generator.d.ts +77 -0
  751. package/vendor/typescript/lib.es2015.iterable.d.ts +605 -0
  752. package/vendor/typescript/lib.es2015.promise.d.ts +81 -0
  753. package/vendor/typescript/lib.es2015.proxy.d.ts +128 -0
  754. package/vendor/typescript/lib.es2015.reflect.d.ts +144 -0
  755. package/vendor/typescript/lib.es2015.symbol.d.ts +46 -0
  756. package/vendor/typescript/lib.es2015.symbol.wellknown.d.ts +326 -0
  757. package/vendor/typescript/lib.es2016.array.include.d.ts +116 -0
  758. package/vendor/typescript/lib.es2016.d.ts +21 -0
  759. package/vendor/typescript/lib.es2016.intl.d.ts +31 -0
  760. package/vendor/typescript/lib.es2017.arraybuffer.d.ts +21 -0
  761. package/vendor/typescript/lib.es2017.d.ts +26 -0
  762. package/vendor/typescript/lib.es2017.date.d.ts +31 -0
  763. package/vendor/typescript/lib.es2017.intl.d.ts +44 -0
  764. package/vendor/typescript/lib.es2017.object.d.ts +49 -0
  765. package/vendor/typescript/lib.es2017.sharedmemory.d.ts +135 -0
  766. package/vendor/typescript/lib.es2017.string.d.ts +45 -0
  767. package/vendor/typescript/lib.es2017.typedarrays.d.ts +53 -0
  768. package/vendor/typescript/lib.es2018.asyncgenerator.d.ts +77 -0
  769. package/vendor/typescript/lib.es2018.asynciterable.d.ts +53 -0
  770. package/vendor/typescript/lib.es2018.d.ts +24 -0
  771. package/vendor/typescript/lib.es2018.intl.d.ts +83 -0
  772. package/vendor/typescript/lib.es2018.promise.d.ts +30 -0
  773. package/vendor/typescript/lib.es2018.regexp.d.ts +37 -0
  774. package/vendor/typescript/lib.es2019.array.d.ts +79 -0
  775. package/vendor/typescript/lib.es2019.d.ts +24 -0
  776. package/vendor/typescript/lib.es2019.intl.d.ts +23 -0
  777. package/vendor/typescript/lib.es2019.object.d.ts +33 -0
  778. package/vendor/typescript/lib.es2019.string.d.ts +37 -0
  779. package/vendor/typescript/lib.es2019.symbol.d.ts +24 -0
  780. package/vendor/typescript/lib.es2020.bigint.d.ts +765 -0
  781. package/vendor/typescript/lib.es2020.d.ts +27 -0
  782. package/vendor/typescript/lib.es2020.date.d.ts +42 -0
  783. package/vendor/typescript/lib.es2020.intl.d.ts +474 -0
  784. package/vendor/typescript/lib.es2020.number.d.ts +28 -0
  785. package/vendor/typescript/lib.es2020.promise.d.ts +47 -0
  786. package/vendor/typescript/lib.es2020.sharedmemory.d.ts +99 -0
  787. package/vendor/typescript/lib.es2020.string.d.ts +44 -0
  788. package/vendor/typescript/lib.es2020.symbol.wellknown.d.ts +41 -0
  789. package/vendor/typescript/lib.es2021.d.ts +23 -0
  790. package/vendor/typescript/lib.es2021.intl.d.ts +166 -0
  791. package/vendor/typescript/lib.es2021.promise.d.ts +48 -0
  792. package/vendor/typescript/lib.es2021.string.d.ts +33 -0
  793. package/vendor/typescript/lib.es2021.weakref.d.ts +78 -0
  794. package/vendor/typescript/lib.es2022.array.d.ts +121 -0
  795. package/vendor/typescript/lib.es2022.d.ts +25 -0
  796. package/vendor/typescript/lib.es2022.error.d.ts +75 -0
  797. package/vendor/typescript/lib.es2022.intl.d.ts +145 -0
  798. package/vendor/typescript/lib.es2022.object.d.ts +26 -0
  799. package/vendor/typescript/lib.es2022.regexp.d.ts +39 -0
  800. package/vendor/typescript/lib.es2022.string.d.ts +25 -0
  801. package/vendor/typescript/lib.es5.d.ts +4601 -0
  802. package/vendor/typescript/package.json +4 -0
  803. package/vendor/typescript/typescript.js +446 -0
  804. package/web/assets/index-Bh74DfsV.css +1 -0
  805. package/web/assets/index-UW0RyFFt.js +13 -0
  806. package/web/index.html +14 -0
@@ -0,0 +1,535 @@
1
+ import { execFile, spawnSync } from "node:child_process";
2
+ import { createHash } from "node:crypto";
3
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
4
+ import fs from "node:fs/promises";
5
+ import os from "node:os";
6
+ import path from "node:path";
7
+
8
+ // A workspace: the folder of the user's documents (docs/internals.md, "Where things live"). Found in
9
+ // this order: --workspace <dir> (the gallery command sets GALLERY_WORKSPACE from it before it loads
10
+ // anything else), the GALLERY_WORKSPACE environment variable, the nearest folder up from the current
11
+ // one holding a gallery.json that says it is ours ({ "gallery": "workspace", "version": 1 }: another
12
+ // program's gallery.json is not), else Gallery in the user's Documents folder (~/Documents/Gallery:
13
+ // documentsFolder() says which folder that is on each system). Its root shows the user's documents,
14
+ // gallery.json, preferences.md (写作偏好), exports/ and components/ only:
15
+ //
16
+ // <workspace>/gallery.json, preferences.md, exports/<slug>.html (the offline deliverables)
17
+ // <workspace>/components/<scope>/<name>/ a component package (./component-catalog.mjs), no document
18
+ // <workspace>/<slug>/doc.html, doc.json (report.html, report.json in a document made before
19
+ // Gallery 0.1: read and written under those names, never renamed), assets/, materials/, annotations.json
20
+ // <workspace>/.gallery/ everything else Gallery keeps: the sidebar's outline, the trash, the emoji
21
+ // library, the 写作偏好 page (pages/<slug>/), the edit state (state/), qa's pictures, backups, built
22
+ // previews, the server's announcement, port and log, and what was adopted of an old layout.
23
+ //
24
+ // A document is a folder at the root holding doc.html or report.html, its name a slug that is not
25
+ // reserved (exports, generated, which the preview's addresses keep, the names Windows keeps for
26
+ // devices: a workspace moves between systems) and not a dot name. components/ holds no document, but
27
+ // one of that name made before the packages came stays one, and no new one takes it (COMPONENTS_FOLDER).
28
+ // Nothing here writes outside the workspace, and nothing writes an old folder it copies from.
29
+ // Node's built-ins only: every system reads its layout from here.
30
+
31
+ export const WORKSPACE_FILE = "gallery.json";
32
+ /**
33
+ * What tells a workspace's gallery.json from another program's file of that name, which is all a
34
+ * reader of it looks at: what else it holds is whose it is (`components`, ./component-catalog.mjs).
35
+ */
36
+ export const WORKSPACE_MARK = { gallery: "workspace", version: 1 };
37
+ /** A document's slug: lowercase kebab-case. */
38
+ export const slugPattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
39
+ /** The names Windows keeps for devices, which no folder of a workspace takes: a workspace moves between systems. */
40
+ export const DEVICE_NAMES = new Set(["con", "prn", "aux", "nul", ...[1, 2, 3, 4, 5, 6, 7, 8, 9].flatMap((n) => [`com${n}`, `lpt${n}`])]);
41
+ /**
42
+ * Names at the root that are never a document's: exports/; generated, for ../generated/doc.html would
43
+ * be the page of the document called doc (the preview's /generated/<slug>.html, src/server/routes.mjs);
44
+ * and the names Windows keeps for devices.
45
+ */
46
+ export const RESERVED = new Set(["exports", "generated", ...DEVICE_NAMES]);
47
+ /**
48
+ * The folder of a workspace's component packages. Unlike RESERVED it hides nothing: a document called
49
+ * so, made before the packages came, keeps its folder and stays a document beside them. It is only a
50
+ * name no new document takes (slugTaken, keptName), the next free one coming instead.
51
+ */
52
+ export const COMPONENTS_FOLDER = "components";
53
+ /** A component package's manifest, which is what makes a folder of components/ a package. */
54
+ export const PACKAGE_MANIFEST = "component.json";
55
+ /** The folders a document keeps beside its files: what is its own of a folder it shares with the packages. */
56
+ export const DOCUMENT_FOLDERS = ["assets", "materials"];
57
+ /** Whether a new document may not be called `name`, whatever the workspace holds. */
58
+ export const keptName = (name) => RESERVED.has(name) || name === COMPONENTS_FOLDER;
59
+ /** Whether `name` may be a document's slug. */
60
+ export const isSlugName = (name) => typeof name === "string" && slugPattern.test(name) && !RESERVED.has(name);
61
+ /** The slug of the 写作偏好 page made new (one copied from an old layout keeps its own). */
62
+ export const PAGE_SLUG = "writing-preferences";
63
+
64
+ /**
65
+ * Where a checkout of Gallery, or an old full skill, kept its edit state before the workspace (before
66
+ * Gallery 0.1, under the editor's old name): <folder>/node_modules/.cache/report-edit. Read only by the
67
+ * migrations (copyOldDocuments, adoptOldLayout, gallery skill install, the dev server).
68
+ */
69
+ export const oldStateOf = (folder) => path.join(folder, "node_modules", ".cache", "report-edit");
70
+
71
+ // The file names of a document: the new ones, and those of a document made before Gallery 0.1.
72
+ const NEW = { html: "doc.html", json: "doc.json" };
73
+ const OLD = { html: "report.html", json: "report.json" };
74
+ /** Whether `name` is the source file of a document (doc.html, or report.html in an old one). */
75
+ export const isDocumentSource = (name) => name === NEW.html || name === OLD.html;
76
+ /** Whether `name` is a file of a document's own (its source, its metadata or its 批注). */
77
+ export const isDocumentFile = (name) => [NEW.html, NEW.json, OLD.html, OLD.json, "annotations.json"].includes(name);
78
+
79
+ /**
80
+ * What the text of a gallery.json is, a byte-order mark passed over, which an editor on Windows may
81
+ * write: { value, ours, reads }, `reads` whether it is JSON at all, `ours` whether it says it is
82
+ * Gallery's. One that does not read says neither: it may be anyone's, a workspace's with a slip in it.
83
+ */
84
+ export function markerOf(text) {
85
+ try {
86
+ const value = JSON.parse(text.replace(/^\uFEFF/, ""));
87
+ return { value, ours: value?.gallery === WORKSPACE_MARK.gallery, reads: true };
88
+ } catch {
89
+ return { value: null, ours: false, reads: false };
90
+ }
91
+ }
92
+
93
+ const markerAt = (file) => {
94
+ try {
95
+ return markerOf(readFileSync(file, "utf8"));
96
+ } catch {
97
+ return { value: null, ours: false, reads: false };
98
+ }
99
+ };
100
+
101
+ /**
102
+ * Where the workspace is: { root, how } (how: "flag", "env", "found" or "default"). Reads gallery.json
103
+ * files on the way up, writes nothing (ensureWorkspace makes it).
104
+ */
105
+ export function findWorkspace({ flag = null, env = process.env, cwd = process.cwd(), home = os.homedir() } = {}) {
106
+ if (typeof flag === "string" && flag) return { root: path.resolve(cwd, flag), how: "flag" };
107
+ if (env.GALLERY_WORKSPACE) return { root: path.resolve(cwd, env.GALLERY_WORKSPACE), how: "env" };
108
+ for (let directory = path.resolve(cwd); ; directory = path.dirname(directory)) {
109
+ if (markerAt(path.join(directory, WORKSPACE_FILE)).ours) return { root: directory, how: "found" };
110
+ if (path.dirname(directory) === directory) break;
111
+ }
112
+ return { root: path.join(documentsFolder({ home, env }), "Gallery"), how: "default" };
113
+ }
114
+
115
+ // Where Windows keeps the Documents folder Explorer shows as 文档: the Personal shell folder, as the
116
+ // user's own registry holds it (%USERPROFILE%\Documents as Windows sets it up; OneDrive's Documents
117
+ // when OneDrive backs the folder up, another drive's when the user moved it there).
118
+ const SHELL_FOLDERS = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders";
119
+
120
+ /**
121
+ * The Personal shell folder's value as reg.exe prints it (%USERPROFILE%\Documents, or a path), else
122
+ * null. reg.exe writes in the console's code page (GBK on a Chinese Windows): a value with any other
123
+ * byte than ASCII is read again with the code page set to UTF-8, so that a folder named in Chinese
124
+ * (OneDrive - 公司) comes out whole; an ASCII one costs one reg.exe (about 30 ms).
125
+ */
126
+ function registryDocuments() {
127
+ const system = process.env.SystemRoot ?? process.env.windir ?? "C:\\Windows";
128
+ const valueOf = (output) => /^\s*Personal\s+REG_(?:EXPAND_)?SZ\s+(.+?)\s*$/m.exec(output)?.[1] ?? null;
129
+ const query = (bytes) => bytes.status === 0 && Buffer.isBuffer(bytes.stdout) ? bytes.stdout : null;
130
+ const ascii = query(spawnSync(path.join(system, "System32", "reg.exe"), ["query", SHELL_FOLDERS, "/v", "Personal"], { windowsHide: true, timeout: 5000 }));
131
+ if (!ascii) return null;
132
+ if (ascii.every((byte) => byte < 0x80)) return valueOf(ascii.toString("utf8"));
133
+ const command = `"chcp 65001 >nul & "${path.join(system, "System32", "reg.exe")}" query "${SHELL_FOLDERS}" /v Personal"`;
134
+ const utf8 = query(spawnSync(process.env.ComSpec ?? path.join(system, "System32", "cmd.exe"), ["/d", "/s", "/c", command], { windowsHide: true, windowsVerbatimArguments: true, timeout: 5000 }));
135
+ return utf8 ? valueOf(utf8.toString("utf8")) : null;
136
+ }
137
+
138
+ const sameFolder = (a, b, platform) => {
139
+ const [one, two] = [path.resolve(a), path.resolve(b)];
140
+ return platform === "win32" ? one.toLowerCase() === two.toLowerCase() : one === two;
141
+ };
142
+
143
+ /**
144
+ * The user's Documents folder, the default workspace's parent: on Windows the one Explorer shows as
145
+ * 文档 (SHELL_FOLDERS' Personal, its %VARIABLES% expanded), read for the user's own home alone (a test
146
+ * or a sandbox naming another HOME/USERPROFILE gets <that home>/Documents, never the user's folder);
147
+ * on Linux the XDG documents folder (~/.config/user-dirs.dirs' XDG_DOCUMENTS_DIR: ~/文档 on a Chinese
148
+ * desktop); a folder either names that is not there, or not absolute, is passed over; else, and on
149
+ * macOS, <home>/Documents. `realHome`, `readRegistry`, `readText` and `exists` are the tests'.
150
+ */
151
+ export function documentsFolder({
152
+ home = os.homedir(), env = process.env, platform = process.platform,
153
+ realHome = (() => { try { return os.userInfo().homedir; } catch { return null; } })(),
154
+ readRegistry = registryDocuments, readText = (file) => readFileSync(file, "utf8"), exists = existsSync,
155
+ } = {}) {
156
+ const fallback = path.join(home, "Documents");
157
+ const usable = (folder) => folder && path.isAbsolute(folder) && exists(folder) ? path.normalize(folder) : null;
158
+ if (platform === "win32") {
159
+ if (!realHome || !sameFolder(home, realHome, platform)) return fallback;
160
+ let value = null;
161
+ try {
162
+ value = readRegistry();
163
+ } catch {}
164
+ if (!value) return fallback;
165
+ const variables = Object.fromEntries(Object.entries(env).map(([name, setting]) => [name.toUpperCase(), setting]));
166
+ variables.USERPROFILE ??= home;
167
+ let unknown = false;
168
+ const expanded = value.replace(/%([^%]+)%/g, (whole, name) => variables[name.toUpperCase()] ?? ((unknown = true), whole));
169
+ return (!unknown && usable(expanded)) || fallback;
170
+ }
171
+ if (platform === "linux") {
172
+ let text = "";
173
+ try {
174
+ text = readText(path.join(env.XDG_CONFIG_HOME || path.join(home, ".config"), "user-dirs.dirs"));
175
+ } catch {}
176
+ const value = /^\s*XDG_DOCUMENTS_DIR\s*=\s*"([^"]*)"/m.exec(text)?.[1];
177
+ if (!value) return fallback;
178
+ const folder = value.replace(/^\$HOME(?=\/|$)/, home);
179
+ // XDG says $HOME itself when the user turned the folder off: the home is no documents folder.
180
+ return sameFolder(folder, home, platform) ? fallback : usable(folder) ?? fallback;
181
+ }
182
+ return fallback;
183
+ }
184
+
185
+ /** Every place of a workspace, by what it holds. Only paths: nothing is read or made. */
186
+ export function layoutOf(root) {
187
+ const resolved = path.resolve(root);
188
+ const gallery = path.join(resolved, ".gallery");
189
+ const state = path.join(gallery, "state");
190
+ return {
191
+ root: resolved,
192
+ marker: path.join(resolved, WORKSPACE_FILE),
193
+ preferences: path.join(resolved, "preferences.md"),
194
+ exports: path.join(resolved, "exports"),
195
+ components: path.join(resolved, COMPONENTS_FOLDER),
196
+ gallery,
197
+ outline: path.join(gallery, "outline.json"),
198
+ trash: path.join(gallery, "trash"),
199
+ emojiLibrary: path.join(gallery, "emoji-library"),
200
+ pages: path.join(gallery, "pages"),
201
+ state,
202
+ history: path.join(state, "history"),
203
+ qa: path.join(gallery, "qa"),
204
+ backups: path.join(gallery, "backups"),
205
+ built: path.join(gallery, "built"),
206
+ logs: path.join(gallery, "logs"),
207
+ serverLog: path.join(gallery, "logs", "server.log"),
208
+ serverFile: path.join(gallery, "server.json"),
209
+ lastPortFile: path.join(gallery, "last-port"),
210
+ migrated: path.join(gallery, "migrated.json"),
211
+ };
212
+ }
213
+
214
+ /**
215
+ * Make the workspace when it is not there: the folder, its gallery.json (never over one that is
216
+ * there) and .gallery/ (hidden on Windows; dot folders are already on macOS and Linux), its state
217
+ * folder only its owner's on POSIX (the token there authorizes writes). Resolves to { made: whether
218
+ * gallery.json was written now, ours: whether the gallery.json there is ours, reads: whether it reads
219
+ * at all (markerOf) }.
220
+ */
221
+ export async function ensureWorkspace(root) {
222
+ const layout = layoutOf(root);
223
+ await fs.mkdir(layout.root, { recursive: true });
224
+ let made = true;
225
+ try {
226
+ await fs.writeFile(layout.marker, `${JSON.stringify(WORKSPACE_MARK, null, 2)}\n`, { flag: "wx" });
227
+ } catch (error) {
228
+ if (error.code !== "EEXIST") throw error;
229
+ made = false;
230
+ }
231
+ const hidden = !existsSync(layout.gallery);
232
+ await fs.mkdir(layout.state, { recursive: true, mode: 0o700 });
233
+ if (hidden && process.platform === "win32") execFile("attrib", ["+h", layout.gallery], { windowsHide: true }, () => {}); // once; a failure leaves it shown
234
+ const { ours, reads } = markerAt(layout.marker);
235
+ return { made, ours, reads };
236
+ }
237
+
238
+ /**
239
+ * A document folder's two files: { html, json, old: whether they are the old names, both: whether
240
+ * the folder holds both doc.html and report.html }. doc.html there: the new names; else report.html
241
+ * there: the old ones (read and written so, never renamed); neither: the new ones (a document to be made).
242
+ */
243
+ export function documentFiles(directory) {
244
+ const hasNew = existsSync(path.join(directory, NEW.html));
245
+ const old = !hasNew && existsSync(path.join(directory, OLD.html));
246
+ const names = old ? OLD : NEW;
247
+ return {
248
+ html: path.join(directory, names.html),
249
+ json: path.join(directory, names.json),
250
+ old,
251
+ both: hasNew && existsSync(path.join(directory, OLD.html)),
252
+ };
253
+ }
254
+
255
+ /** Where document `slug` is: the 写作偏好 page's folder under .gallery/pages/ when it is one, else <root>/<slug>. */
256
+ export function documentDirectory(slug, root) {
257
+ const page = path.join(layoutOf(root).pages, slug);
258
+ return existsSync(page) ? page : path.join(path.resolve(root), slug);
259
+ }
260
+
261
+ /** Whether `slug` can name no new document: a name kept, or held by a folder at the root or a page. */
262
+ export function slugTaken(slug, root) {
263
+ return keptName(slug) || existsSync(path.join(path.resolve(root), slug)) || existsSync(path.join(layoutOf(root).pages, slug));
264
+ }
265
+
266
+ // The folders right in `directory`, by name, sorted: no dot name, and no link, which leads out of it.
267
+ const foldersIn = (directory) => {
268
+ try {
269
+ return readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name).sort();
270
+ } catch {
271
+ return [];
272
+ }
273
+ };
274
+
275
+ /**
276
+ * The component packages of a workspace, sorted: [{ id: "<scope>/<name>", folder }], each a folder
277
+ * two down in components/ holding component.json, whatever it says. Any other folder there is no
278
+ * package and is passed over: one being written, or what a document called components keeps.
279
+ */
280
+ export function packageFolders(root) {
281
+ const { components } = layoutOf(root);
282
+ return foldersIn(components).flatMap((scope) => foldersIn(path.join(components, scope))
283
+ .map((name) => ({ id: `${scope}/${name}`, folder: path.join(components, scope, name) }))
284
+ .filter(({ folder }) => existsSync(path.join(folder, PACKAGE_MANIFEST))));
285
+ }
286
+
287
+ /**
288
+ * The manifests one level too shallow: [{ name, file }], each a component.json right in a folder of
289
+ * components/, which no catalog reads: a package is <scope>/<name>, and `name` is what the folder would
290
+ * be called under a scope. What tells a package's writer why theirs is not there.
291
+ */
292
+ export function shallowPackages(root) {
293
+ const { components } = layoutOf(root);
294
+ return foldersIn(components).map((name) => ({ name, file: path.join(components, name, PACKAGE_MANIFEST) })).filter(({ file }) => existsSync(file));
295
+ }
296
+
297
+ const readJson = (file) => fs.readFile(file, "utf8").then(JSON.parse).catch(() => null); // not there, or half written: null
298
+ const isFolder = (target) => fs.stat(target).then((stat) => stat.isDirectory(), () => false);
299
+ const exists = (target) => fs.access(target).then(() => true, () => false);
300
+
301
+ // The folders of `directory` that are documents (D2): a name that is no dot name and not reserved,
302
+ // holding doc.html or report.html; with their metadata's `instructions` mark.
303
+ async function documentsIn(directory) {
304
+ const entries = await fs.readdir(directory, { withFileTypes: true }).catch((error) => {
305
+ if (error.code === "ENOENT" || error.code === "ENOTDIR") return [];
306
+ throw error;
307
+ });
308
+ const found = await Promise.all(entries
309
+ .filter((entry) => entry.isDirectory() && !entry.name.startsWith(".") && !RESERVED.has(entry.name))
310
+ .map(async ({ name }) => {
311
+ const folder = path.join(directory, name);
312
+ const files = documentFiles(folder);
313
+ if (!(await exists(files.html))) return null;
314
+ return { slug: name, folder, instructions: (await readJson(files.json))?.instructions === true };
315
+ }));
316
+ return found.filter(Boolean).sort((a, b) => (a.slug < b.slug ? -1 : a.slug > b.slug ? 1 : 0));
317
+ }
318
+
319
+ /**
320
+ * The documents of a workspace, by slug, sorted: the folders at its root holding doc.html or
321
+ * report.html, but exports/, dot names and an old layout's 写作偏好 page (marked "instructions": true:
322
+ * the page lives in .gallery/pages/ now). A folder holding neither (a user's own materials/) is left alone.
323
+ */
324
+ export async function listDocumentSlugs(root) {
325
+ return (await documentsIn(path.resolve(root))).filter((entry) => !entry.instructions).map((entry) => entry.slug);
326
+ }
327
+
328
+ /** The 写作偏好 page's slug (the first document under .gallery/pages/), or null when there is none yet. */
329
+ export async function pageSlug(root) {
330
+ return (await documentsIn(layoutOf(root).pages))[0]?.slug ?? null;
331
+ }
332
+
333
+ /** The id of an entry of the trash, a folder of .gallery/trash/. */
334
+ export const trashIdPattern = /^[a-z0-9]+-[a-z0-9]+$/;
335
+
336
+ /** What the trash holds, the latest first: each folder's entry.json ({ id, slug, title, at, parent, index }). */
337
+ export async function listTrash(root) {
338
+ const { trash } = layoutOf(root);
339
+ const names = await fs.readdir(trash).catch(() => []);
340
+ const entries = await Promise.all(names.filter((name) => trashIdPattern.test(name)).map((id) => readJson(path.join(trash, id, "entry.json"))));
341
+ return entries.filter(Boolean).sort((a, b) => b.at - a.at);
342
+ }
343
+
344
+ // ---------- copying an old layout ----------
345
+
346
+ const copyTree = (from, to) => fs.cp(from, to, { recursive: true, errorOnExist: true, force: false, preserveTimestamps: true });
347
+
348
+ // The files of `from` copied into `to` that `to` does not hold (by name, one level): the names copied.
349
+ async function copyMissing(from, to, { filter = () => true } = {}) {
350
+ const names = (await fs.readdir(from).catch(() => [])).filter(filter);
351
+ const copied = [];
352
+ for (const name of names) {
353
+ const target = path.join(to, name);
354
+ if (await exists(target)) continue;
355
+ await fs.mkdir(to, { recursive: true });
356
+ await copyTree(path.join(from, name), target);
357
+ copied.push(name);
358
+ }
359
+ return copied;
360
+ }
361
+
362
+ // The emoji library of `from` (library.json and its images) brought into `to`'s: the images it lacks
363
+ // by name, library.json's entries it lacks by id. The number of entries added.
364
+ async function mergeEmojiLibrary(from, to) {
365
+ if (!(await isFolder(from))) return 0;
366
+ await copyMissing(from, to, { filter: (name) => name !== "library.json" && !name.startsWith(".") });
367
+ const old = await readJson(path.join(from, "library.json"));
368
+ if (!Array.isArray(old)) return 0;
369
+ const stored = await readJson(path.join(to, "library.json"));
370
+ const current = Array.isArray(stored) ? stored : [];
371
+ const known = new Set(current.map((entry) => entry?.id));
372
+ const added = old.filter((entry) => entry && typeof entry.id === "string" && !known.has(entry.id));
373
+ if (added.length || !Array.isArray(stored)) {
374
+ await fs.mkdir(to, { recursive: true });
375
+ await fs.writeFile(path.join(to, "library.json"), `${JSON.stringify([...current, ...added], null, 2)}\n`);
376
+ }
377
+ return added.length;
378
+ }
379
+
380
+ // An old outline's nesting of `slugs` only: each under its nearest ancestor among them, else at the top.
381
+ function outlineOf(stored, slugs) {
382
+ const children = { "": [] };
383
+ const keep = new Set(slugs);
384
+ const seen = new Set();
385
+ const walk = (parent, under) => {
386
+ for (const slug of stored?.children?.[parent] ?? []) {
387
+ if (typeof slug !== "string" || seen.has(slug)) continue;
388
+ seen.add(slug);
389
+ if (keep.has(slug)) (children[under] ??= []).push(slug);
390
+ walk(slug, keep.has(slug) ? slug : under);
391
+ }
392
+ };
393
+ walk("", "");
394
+ for (const slug of slugs) if (!seen.has(slug)) children[""].push(slug);
395
+ return children;
396
+ }
397
+
398
+ /**
399
+ * Copy an old layout's documents into workspace `to` (gallery init --from, gallery skill install over
400
+ * an old skill): `from` a folder of document folders (an old Gallery's reports/), `state` its edit
401
+ * state (oldStateOf the folder beside it, when there). Copied: every document whose name is a slug
402
+ * free in `to` (the others left, listed: `skipped`, a slug taken or a name that is no slug, and `kept`,
403
+ * a name no new document takes, which is free of no workspace); preferences.md when `to` has none; the sidebar's order
404
+ * (.workspace.json), as `to`'s when it has none, else the copied documents added at its top in their
405
+ * old nesting; the 写作偏好 page (a folder marked "instructions": true) into .gallery/pages/ when `to`
406
+ * has none; the custom emoji library (images by name, entries by id); the recent versions of the
407
+ * documents copied; the component packages `from` holds, each one `to` does not. Never the trash,
408
+ * exports, qa pictures or backups. `from` is only read. Resolves to { copied, skipped, kept, preferences:
409
+ * "copied"|"kept"|null, outline: "copied"|"appended"|null, page: "copied"|"kept"|null, emoji: entries
410
+ * added, history: documents whose versions were copied, packages: the ids of those copied }.
411
+ */
412
+ export async function copyOldDocuments({ from, to, state = undefined }) {
413
+ const source = path.resolve(from);
414
+ const layout = layoutOf(to);
415
+ await ensureWorkspace(layout.root);
416
+ const oldState = state === undefined ? oldStateOf(path.dirname(source)) : state;
417
+ const found = await documentsIn(source);
418
+ const copied = [];
419
+ const skipped = [];
420
+ const kept = [];
421
+ let page = null;
422
+ for (const { slug, folder, instructions } of found) {
423
+ if (instructions) {
424
+ if (await pageSlug(layout.root)) page = "kept";
425
+ else {
426
+ await fs.mkdir(layout.pages, { recursive: true });
427
+ await copyTree(folder, path.join(layout.pages, slug));
428
+ page = "copied";
429
+ }
430
+ continue;
431
+ }
432
+ if (!isSlugName(slug) || slugTaken(slug, layout.root)) {
433
+ (keptName(slug) ? kept : skipped).push(slug);
434
+ continue;
435
+ }
436
+ await copyTree(folder, path.join(layout.root, slug));
437
+ copied.push(slug);
438
+ }
439
+
440
+ let preferences = null;
441
+ if (await exists(path.join(source, "preferences.md"))) {
442
+ preferences = (await exists(layout.preferences)) ? "kept" : "copied";
443
+ if (preferences === "copied") await fs.copyFile(path.join(source, "preferences.md"), layout.preferences);
444
+ }
445
+
446
+ let outline = null;
447
+ const stored = await readJson(path.join(source, ".workspace.json"));
448
+ if (stored && copied.length) {
449
+ const nested = outlineOf(stored, copied);
450
+ const current = await readJson(layout.outline);
451
+ if (!current?.children) {
452
+ await fs.writeFile(layout.outline, `${JSON.stringify({ version: 1, children: nested }, null, 2)}\n`);
453
+ outline = "copied";
454
+ } else {
455
+ const children = { ...current.children };
456
+ for (const [parent, list] of Object.entries(nested)) children[parent] = [...(children[parent] ?? []), ...list];
457
+ await fs.writeFile(layout.outline, `${JSON.stringify({ version: 1, children }, null, 2)}\n`);
458
+ outline = "appended";
459
+ }
460
+ }
461
+
462
+ const emoji = await mergeEmojiLibrary(path.join(source, ".emoji-library"), layout.emojiLibrary);
463
+
464
+ let history = 0;
465
+ if (oldState) {
466
+ for (const slug of copied) {
467
+ const versions = path.join(oldState, "history", slug);
468
+ const target = path.join(layout.history, slug);
469
+ if (!(await isFolder(versions)) || (await exists(target))) continue;
470
+ await fs.mkdir(layout.history, { recursive: true });
471
+ await copyTree(versions, target);
472
+ history++;
473
+ }
474
+ }
475
+
476
+ const packages = [];
477
+ for (const { id, folder } of packageFolders(source)) {
478
+ const target = path.join(layout.components, ...id.split("/"));
479
+ if (await exists(target)) continue;
480
+ await fs.mkdir(path.dirname(target), { recursive: true });
481
+ await copyTree(folder, target);
482
+ packages.push(id);
483
+ }
484
+ return { copied, skipped, kept, preferences, outline, page, emoji, history, packages };
485
+ }
486
+
487
+ // A directory as a key of the old edit state (the old preview-server's directoryKey: one folder for
488
+ // each directory of reports there, for checkouts that shared it).
489
+ const canonical = (directory) => (process.platform === "win32" ? path.resolve(directory).toLowerCase() : path.resolve(directory));
490
+ const oldKey = (directory) => createHash("sha256").update(canonical(directory)).digest("hex").slice(0, 16);
491
+
492
+ /**
493
+ * Bring a workspace's own old layout into .gallery/, once (the dev checkout's reports/, a folder of
494
+ * documents made before Gallery 0.1): reports' .workspace.json → .gallery/outline.json, .trash/ →
495
+ * .gallery/trash/, .emoji-library/ → .gallery/emoji-library/, a root page marked "instructions": true
496
+ * → .gallery/pages/ (when there is none); and with `devState` (the old edit state, oldStateOf the
497
+ * checkout whose reports/ this is) its token, source snapshots, and the recent
498
+ * versions, commit answers, rewrites and dropped 批注 of this workspace's documents → .gallery/state/.
499
+ * Everything is copied, never over what is there; the old copies are left. .gallery/migrated.json
500
+ * says it was done: a second call does nothing. Resolves to { adopted: whether it ran, copied: what was }.
501
+ */
502
+ export async function adoptOldLayout(root, { devState = null } = {}) {
503
+ const layout = layoutOf(root);
504
+ if (await exists(layout.migrated)) return { adopted: false, copied: [] };
505
+ await ensureWorkspace(layout.root);
506
+ const copied = [];
507
+ const once = async (what, from, to) => {
508
+ if (!(await exists(from)) || (await exists(to))) return;
509
+ await fs.mkdir(path.dirname(to), { recursive: true });
510
+ await copyTree(from, to);
511
+ copied.push(what);
512
+ };
513
+ await once("outline", path.join(layout.root, ".workspace.json"), layout.outline);
514
+ if ((await copyMissing(path.join(layout.root, ".trash"), layout.trash)).length) copied.push("trash");
515
+ if ((await mergeEmojiLibrary(path.join(layout.root, ".emoji-library"), layout.emojiLibrary)) > 0) copied.push("emoji-library");
516
+ const oldPage = (await documentsIn(layout.root)).find((entry) => entry.instructions);
517
+ if (oldPage && !(await pageSlug(layout.root))) await once("page", oldPage.folder, path.join(layout.pages, oldPage.slug));
518
+
519
+ if (devState && (await isFolder(devState))) {
520
+ const slugs = [...(await listDocumentSlugs(layout.root)), ...(oldPage ? [oldPage.slug] : [])];
521
+ await once("token", path.join(devState, "token"), path.join(layout.state, "token"));
522
+ if ((await copyMissing(path.join(devState, "snapshots"), path.join(layout.state, "snapshots"))).length) copied.push("snapshots");
523
+ const key = oldKey(layout.root);
524
+ for (const slug of slugs) {
525
+ for (const [kind, from] of [
526
+ ["history", path.join(devState, "history", slug)],
527
+ ["receipts", path.join(devState, "receipts", slug)],
528
+ ["rewrites", path.join(devState, "rewrites", key, slug)],
529
+ ["dropped-annotations", path.join(devState, "dropped-annotations", key, slug)],
530
+ ]) await once(`${kind}/${slug}`, from, path.join(layout.state, kind, slug));
531
+ }
532
+ }
533
+ await fs.writeFile(layout.migrated, `${JSON.stringify({ version: 1, at: new Date().toISOString(), copied }, null, 2)}\n`);
534
+ return { adopted: true, copied };
535
+ }
@@ -0,0 +1,68 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { defaultPreferencesFile, reportsDirectory as defaultReportsDirectory } from "./paths.mjs";
4
+
5
+ // 写作偏好: the user's rules for writing a report, which an Agent reads before it writes (SKILL.md),
6
+ // at <workspace>/preferences.md (shared/workspace.mjs). Gallery ships its default (writing-preferences.md,
7
+ // beside this module; the release's assets/writing-preferences.md: paths.mjs defaultPreferencesFile): what
8
+ // to write, in what order, the opening summary, titles, fidelity to the materials, evidence). The first
9
+ // time the preferences are read and there is no preferences.md in the workspace (by gallery new, gallery
10
+ // import, gallery list, or the workbench's 写作偏好 in 设置), it is made from that default; from then on it is the user's, edited in the workbench (its page, src/shared/reports.mjs
11
+ // isInstructions, written as this file when the user saves it: src/transfer/service.mjs), and
12
+ // never written over by the default again: a file that exists stays as it is, an empty one too.
13
+
14
+ /** Gallery's default writing preferences (Markdown). */
15
+ export { defaultPreferencesFile };
16
+
17
+ /** Where the user's writing preferences are, for the documents of workspace `reportsDirectory`. */
18
+ export const preferencesFileOf = (reportsDirectory = defaultReportsDirectory) => path.join(reportsDirectory, "preferences.md");
19
+
20
+ /**
21
+ * The user's writing preferences: { file, text, made }, the file made from Gallery's default
22
+ * first when there is none (`made`), never over one that exists (another reader making it at the
23
+ * same moment: its file is read).
24
+ */
25
+ export async function readWritingPreferences(reportsDirectory = defaultReportsDirectory) {
26
+ const file = preferencesFileOf(reportsDirectory);
27
+ const existing = await fs.readFile(file, "utf8").catch((error) => {
28
+ if (error.code === "ENOENT") return null;
29
+ throw error;
30
+ });
31
+ if (existing !== null) return { file, text: existing, made: false };
32
+ const text = await fs.readFile(defaultPreferencesFile, "utf8");
33
+ await fs.mkdir(reportsDirectory, { recursive: true });
34
+ try {
35
+ await fs.writeFile(file, text, { flag: "wx" });
36
+ } catch (error) {
37
+ if (error.code !== "EEXIST") throw error;
38
+ return { file, text: await fs.readFile(file, "utf8"), made: false };
39
+ }
40
+ return { file, text, made: true };
41
+ }
42
+
43
+ /** Whether preferences (their Markdown) say anything: a letter or a digit under the title (its first line, a # heading). */
44
+ export const saysAnything = (text) => /[\p{L}\p{N}]/u.test(text.replace(/^\s*# [^\n]*/, ""));
45
+
46
+ // Markdown's words as their letters alone, under its title: a comment's words are words; every other
47
+ // tag, a picture's address (the page keeps its pictures under names of its own), the marks, spaces
48
+ // and numbers are not.
49
+ const lettersOf = (text) => text
50
+ .replace(/<!--|-->/g, " ")
51
+ .replace(/!\[((?:\\.|[^\]\\])*)\]\([^)]*\)/g, "$1")
52
+ .replace(/<\/?[A-Za-z][^>]*>/g, " ")
53
+ .replace(/[^\p{L}]/gu, "");
54
+ const underTitle = (text) => text.replace(/^\s*# [^\n]*/, "");
55
+
56
+ /**
57
+ * The lines of preferences `file` (Markdown) whose words the page made of it does not hold, as its
58
+ * Markdown `page` writes them (what writing the page back over the file would take out: a comment, a
59
+ * link's address on this computer), trimmed, in order: each a line whose letters are not, in a row,
60
+ * among the page's. Words joined or split again, spaced, numbered or marked otherwise are the same.
61
+ */
62
+ export function unshownLines(file, page) {
63
+ const shown = lettersOf(underTitle(page));
64
+ return underTitle(file).split("\n").map((line) => line.trim()).filter((line) => {
65
+ const letters = lettersOf(line);
66
+ return letters !== "" && !shown.includes(letters);
67
+ });
68
+ }
@@ -0,0 +1,57 @@
1
+ import { INSTANCE, componentAt } from "./components/installed.mjs";
2
+
3
+ // 图片放大: which pictures of a report open large when clicked (docs/render.md, "Opening a picture
4
+ // large"). One rule for both ways in: the kit's viewer for a reader (src/render/kit/runtime/zoom.js:
5
+ // a click, in an export, a build, the preview's 演示视图), and the page editor's while editing
6
+ // (editor/components/image/viewer.mjs: a double-click, notion-lite's rule, 展开 and 全屏查看 on an
7
+ // image block). Nothing is written for it: a picture is one by where it stands and how large it is
8
+ // shown, so an Agent's report gets it without a word in its markup.
9
+ //
10
+ // A picture is an <img> of the page (main.doc-page), whatever holds it: an image block, a table's
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
+ // 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 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
+ // pictures among them), a link's icon, a bookmark's pictures, a file's; nor a picture shown smaller
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
+
18
+ /** What a picture inside of opens nothing: a control or a link, an icon, the kit's and the preview's own. */
19
+ export const ZOOM_SKIP = [
20
+ "a[href]", "button", "summary", "label", "select", "[role=button]", "[role=link]", "[role=tab]", "[data-doc-dialog-open]",
21
+ ".doc-icon", ".doc-link-mention", ".doc-bookmark", ".doc-file",
22
+ ".doc-zoom", "[data-doc-dev]",
23
+ ].join(", ");
24
+
25
+ /** The pictures the reader's runtime watches to offer to the keyboard (runtime/zoom.js), those of the rule among them. */
26
+ export const ZOOM_PICTURES = ".doc-page img";
27
+
28
+ /**
29
+ * The runtime's mark on a picture that opens, offered to the keyboard while the page is read (not
30
+ * edited): with it a tab stop, a button's role and a name saying what it does, which the picture
31
+ * itself is no control of its own for the rule (its role is the runtime's). An export of the view
32
+ * takes them off (the image description's runtime).
33
+ */
34
+ export const ZOOM_MARK = "data-doc-zoom";
35
+
36
+ /** The least a picture is shown, in CSS pixels, across or down, to open large. */
37
+ export const ZOOM_LEAST = 48;
38
+
39
+ // A picture loaded: one of pixels has a size of its own; an SVG may have none (no width, height or
40
+ // viewBox) and still draw.
41
+ const loaded = (img) => img.complete && (img.naturalWidth > 0 || /^data:image\/svg|\.svg(?:[?#]|$)/i.test(img.currentSrc || img.src));
42
+
43
+ /** Whether `img` opens large when clicked (or double-clicked in the page editor). */
44
+ export function zoomable(img) {
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) || holder.matches(INSTANCE) || componentAt(holder) || !loaded(img)) return false;
47
+ const box = img.getBoundingClientRect();
48
+ return box.width >= ZOOM_LEAST || box.height >= ZOOM_LEAST;
49
+ }
50
+
51
+ /** The words shown under a picture opened large: the caption of the image block or card it is the one picture of, else none. */
52
+ export function zoomCaption(img) {
53
+ const figure = img.closest("figure");
54
+ if (!figure || [...figure.querySelectorAll("img")].filter((each) => each.closest("figure") === figure).length !== 1) return null;
55
+ const caption = figure.querySelector(":scope > figcaption, :scope > .doc-figure-caption");
56
+ return caption && caption.textContent.trim() ? caption : null;
57
+ }