@heycys/gallery 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (465) 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 +45 -32
  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/embed/index.mjs +2 -2
  9. package/browser/editor/components/figure/page.mjs +10 -1
  10. package/browser/editor/components/file/page.mjs +2 -2
  11. package/browser/editor/components/flowchart/add.mjs +7 -6
  12. package/browser/editor/components/flowchart/page.mjs +1 -1
  13. package/browser/editor/components/heading/index.mjs +2 -0
  14. package/browser/editor/components/heading/page.mjs +6 -0
  15. package/browser/editor/components/highlight/index.mjs +4 -20
  16. package/browser/editor/components/icons.mjs +13 -2
  17. package/browser/editor/components/image/crop.mjs +6 -9
  18. package/browser/editor/components/image/page.mjs +2 -2
  19. package/browser/editor/components/installed/index.mjs +82 -29
  20. package/browser/editor/components/installed/page.mjs +146 -34
  21. package/browser/editor/components/installed/served.mjs +6 -5
  22. package/browser/editor/components/instances.mjs +18 -0
  23. package/browser/editor/components/kit.mjs +3 -0
  24. package/browser/editor/components/list/page.mjs +3 -6
  25. package/browser/editor/components/media/page.mjs +44 -14
  26. package/browser/editor/components/pages.mjs +2 -2
  27. package/browser/editor/components/registry.mjs +68 -33
  28. package/browser/editor/components/section/index.mjs +2 -1
  29. package/browser/editor/components/set-apart.mjs +24 -0
  30. package/browser/editor/components/table/index.mjs +64 -5
  31. package/browser/editor/components/table/page.mjs +30 -19
  32. package/browser/editor/page/annotate/anchors.mjs +4 -3
  33. package/browser/editor/page/annotate/card.mjs +3 -6
  34. package/browser/editor/page/annotate/index.mjs +61 -34
  35. package/browser/editor/page/autosave.mjs +357 -38
  36. package/browser/editor/page/beside.mjs +5 -5
  37. package/browser/editor/page/block-menu/colors.mjs +3 -1
  38. package/browser/editor/page/block-menu/index.mjs +8 -6
  39. package/browser/editor/page/blocks.mjs +16 -7
  40. package/browser/editor/page/board/client.mjs +57 -0
  41. package/browser/editor/page/board/hint.mjs +145 -0
  42. package/browser/editor/page/board/history.mjs +119 -0
  43. package/browser/editor/page/board/index.mjs +970 -0
  44. package/browser/editor/page/board/settings.mjs +209 -0
  45. package/browser/editor/page/caret.mjs +5 -2
  46. package/browser/editor/page/changes/bar.mjs +94 -0
  47. package/browser/editor/page/changes/ghost.mjs +206 -0
  48. package/browser/editor/page/changes/gone-words.mjs +94 -0
  49. package/browser/editor/page/changes/index.mjs +447 -0
  50. package/browser/editor/page/changes/words.mjs +27 -0
  51. package/browser/editor/page/clipboard/import/colors.mjs +3 -3
  52. package/browser/editor/page/clipboard/import/html.mjs +29 -6
  53. package/browser/editor/page/clipboard/import/inline.mjs +32 -0
  54. package/browser/editor/page/clipboard/import/markdown.mjs +58 -13
  55. package/browser/editor/page/clipboard/import/read.mjs +6 -1
  56. package/browser/editor/page/clipboard/import/to-blocks.mjs +44 -12
  57. package/browser/editor/page/clipboard/import/yuque.mjs +622 -0
  58. package/browser/editor/page/clipboard/index.mjs +156 -26
  59. package/browser/editor/page/clipboard/own/blocks.mjs +25 -16
  60. package/browser/editor/page/clipboard/own/chart-keys.mjs +41 -28
  61. package/browser/editor/page/clipboard/own/describe.mjs +16 -7
  62. package/browser/editor/page/clipboard/own/export.mjs +6 -6
  63. package/browser/editor/page/clipboard/own/selection.mjs +3 -3
  64. package/browser/editor/page/clipboard/own/writers.mjs +0 -11
  65. package/browser/editor/page/columns/index.mjs +48 -46
  66. package/browser/editor/page/commit.mjs +98 -25
  67. package/browser/editor/page/conflicts.mjs +13 -33
  68. package/browser/editor/page/convert.mjs +8 -7
  69. package/browser/editor/page/core.mjs +81 -27
  70. package/browser/editor/page/custom-page.mjs +106 -0
  71. package/browser/editor/page/drag/index.mjs +40 -24
  72. package/browser/editor/page/drag/preview.mjs +9 -4
  73. package/browser/editor/page/editor.mjs +120 -28
  74. package/browser/editor/page/emoji-picker/emoji-tab.mjs +22 -13
  75. package/browser/editor/page/emoji-picker/grid.mjs +7 -5
  76. package/browser/editor/page/emoji-picker/icon-tab.mjs +4 -4
  77. package/browser/editor/page/emoji-picker/icons.mjs +0 -1
  78. package/browser/editor/page/emoji-picker/index.mjs +11 -9
  79. package/browser/editor/page/emoji-picker/styles.mjs +156 -2
  80. package/browser/editor/page/emoji-picker/support.mjs +6 -4
  81. package/browser/editor/page/emoji-picker/upload.mjs +14 -13
  82. package/browser/editor/page/fills.mjs +5 -3
  83. package/browser/editor/page/fold/index.mjs +348 -0
  84. package/browser/editor/page/fold/rule.mjs +125 -0
  85. package/browser/editor/page/folded.mjs +23 -0
  86. package/browser/editor/page/format-bar/bar.mjs +2 -1
  87. package/browser/editor/page/format-bar/index.mjs +1 -1
  88. package/browser/editor/page/geometry.mjs +8 -6
  89. package/browser/editor/page/handle/index.mjs +22 -14
  90. package/browser/editor/page/hints/index.mjs +1 -1
  91. package/browser/editor/page/history.mjs +24 -4
  92. package/browser/editor/page/insert/index.mjs +30 -17
  93. package/browser/editor/page/links/index.mjs +5 -3
  94. package/browser/editor/page/links/pages.mjs +27 -9
  95. package/browser/editor/page/long-runs.mjs +75 -0
  96. package/browser/editor/page/look.mjs +69 -6
  97. package/browser/editor/page/margin.mjs +63 -27
  98. package/browser/editor/page/media-menu/index.mjs +6 -7
  99. package/browser/editor/page/menu.mjs +86 -31
  100. package/browser/editor/page/merge.mjs +24 -0
  101. package/browser/editor/page/notices.mjs +3 -3
  102. package/browser/editor/page/offered.mjs +1 -1
  103. package/browser/editor/page/outline/folds.mjs +11 -10
  104. package/browser/editor/page/outline/index.mjs +131 -45
  105. package/browser/editor/page/outline/list.mjs +23 -11
  106. package/browser/editor/page/outline/read.mjs +1 -1
  107. package/browser/editor/page/outline/strip.mjs +7 -1
  108. package/browser/editor/page/page-objects.mjs +13 -2
  109. package/browser/editor/page/panel.mjs +9 -13
  110. package/browser/editor/page/present-links.mjs +11 -2
  111. package/browser/editor/page/resize/index.mjs +42 -29
  112. package/browser/editor/page/selection/delete.mjs +8 -6
  113. package/browser/editor/page/selection/index.mjs +10 -3
  114. package/browser/editor/page/served.mjs +14 -0
  115. package/browser/editor/page/session.mjs +101 -6
  116. package/browser/editor/page/slash-menu/index.mjs +3 -3
  117. package/browser/editor/page/table/cell-bar.mjs +4 -1
  118. package/browser/editor/page/table/cells.mjs +103 -47
  119. package/browser/editor/page/table/icons.mjs +3 -1
  120. package/browser/editor/page/table/index.mjs +40 -16
  121. package/browser/editor/page/table/pictures.mjs +299 -0
  122. package/browser/editor/page/table/views.mjs +150 -0
  123. package/browser/editor/page/table/widths.mjs +9 -4
  124. package/browser/editor/page/text-select/index.mjs +43 -14
  125. package/browser/editor/page/todo-writes.mjs +75 -0
  126. package/browser/editor/page/tooltip.mjs +1 -1
  127. package/browser/editor/page/type-grid.mjs +4 -3
  128. package/browser/editor/page/typing/code-edges.mjs +63 -17
  129. package/browser/editor/page/typing/index.mjs +65 -9
  130. package/browser/editor/page/typing/leave.mjs +1 -1
  131. package/browser/editor/page/ui.mjs +13 -0
  132. package/browser/shared/annotations.mjs +8 -10
  133. package/browser/shared/block-packs.mjs +404 -0
  134. package/browser/shared/board-places.mjs +224 -0
  135. package/browser/shared/card-size.mjs +59 -0
  136. package/browser/shared/code-folds.mjs +5 -1
  137. package/browser/shared/colors.mjs +17 -14
  138. package/browser/shared/component-catalog.mjs +345 -54
  139. package/browser/shared/component-source.mjs +37 -0
  140. package/browser/shared/components/callout.mjs +4 -2
  141. package/browser/shared/components/index.mjs +72 -9
  142. package/browser/shared/components/installed.mjs +110 -8
  143. package/browser/shared/components/page.mjs +22 -3
  144. package/browser/shared/components/state.mjs +5 -1
  145. package/browser/shared/components/table.mjs +1 -1
  146. package/browser/shared/components/text.mjs +2 -2
  147. package/browser/shared/document-look.mjs +183 -0
  148. package/browser/shared/drafts.mjs +432 -0
  149. package/browser/shared/emoji/data/LICENSE-lucide.txt +43 -0
  150. package/browser/shared/emoji/data/README.md +4 -2
  151. package/browser/shared/emoji/data/categories.json +1 -1
  152. package/browser/shared/emoji/data/keywords-en.json +1 -1
  153. package/browser/shared/emoji/data/keywords-zh.json +1 -1
  154. package/browser/shared/emoji/data/names.json +1 -1
  155. package/browser/shared/emoji/data/positions.json +1 -1
  156. package/browser/shared/emoji/data/twemoji-index.json +1 -1
  157. package/browser/shared/emoji/data/twemoji-svg.bin +0 -0
  158. package/browser/shared/emoji/data.mjs +10 -12
  159. package/browser/shared/emoji/emoji.mjs +8 -7
  160. package/browser/shared/emoji/icon-value.mjs +4 -3
  161. package/browser/shared/extension-sidebar.mjs +126 -0
  162. package/browser/shared/extensions.mjs +79 -0
  163. package/browser/shared/file-table.mjs +101 -0
  164. package/browser/shared/html-tree.mjs +11 -5
  165. package/browser/shared/i18n/en.mjs +374 -35
  166. package/browser/shared/json-layout.mjs +47 -0
  167. package/browser/shared/long-runs.mjs +39 -0
  168. package/browser/shared/net-cache.mjs +133 -0
  169. package/browser/shared/net-keys.mjs +32 -0
  170. package/browser/shared/net-policy.mjs +177 -0
  171. package/browser/shared/new-names.mjs +5 -2
  172. package/browser/shared/outline-shape.mjs +128 -0
  173. package/browser/shared/outline.mjs +458 -0
  174. package/browser/shared/pack-manifest.mjs +77 -0
  175. package/browser/shared/page-address.mjs +6 -3
  176. package/browser/shared/page-cards.mjs +308 -0
  177. package/browser/shared/page-links.mjs +69 -6
  178. package/browser/shared/pages.mjs +388 -0
  179. package/browser/shared/paths.mjs +6 -0
  180. package/browser/shared/preferences.mjs +10 -4
  181. package/browser/shared/preview-server.mjs +3 -7
  182. package/browser/shared/session.mjs +13 -5
  183. package/browser/shared/shipped-blocks.mjs +299 -0
  184. package/browser/shared/table-chart.mjs +33 -1
  185. package/browser/shared/todos.mjs +83 -0
  186. package/browser/shared/user-directory.mjs +24 -0
  187. package/browser/shared/versions.mjs +14 -0
  188. package/browser/shared/web-links.mjs +134 -0
  189. package/browser/shared/workspace-columns.mjs +120 -0
  190. package/browser/shared/workspace-look.mjs +91 -0
  191. package/browser/shared/workspace-name.mjs +154 -0
  192. package/browser/shared/workspace-query.mjs +125 -0
  193. package/browser/shared/workspace-registry.mjs +272 -0
  194. package/browser/shared/workspace.mjs +171 -20
  195. package/browser/shared/zoom.mjs +5 -5
  196. package/dist/chunk-2NRBY6AJ.mjs +2 -0
  197. package/dist/chunk-32ZUEFZ7.mjs +2 -0
  198. package/dist/chunk-35NQ4PLQ.mjs +2 -0
  199. package/dist/chunk-3KJHLHUO.mjs +2 -0
  200. package/dist/chunk-3NJACR4W.mjs +2 -0
  201. package/dist/chunk-4AV456RQ.mjs +2 -0
  202. package/dist/chunk-4OZWXZE5.mjs +5 -0
  203. package/dist/chunk-5XYHDBJ5.mjs +2 -0
  204. package/dist/chunk-5ZJA7CXT.mjs +2 -0
  205. package/dist/chunk-6A53MZYZ.mjs +2 -0
  206. package/dist/chunk-6EXH3ORZ.mjs +166 -0
  207. package/dist/chunk-6EZ7FNIK.mjs +3 -0
  208. package/dist/{chunk-UXUK4PMC.mjs → chunk-6QBHU4DF.mjs} +1 -1
  209. package/dist/{chunk-6U2SLSDN.mjs → chunk-6VTU6KEO.mjs} +1 -1
  210. package/dist/chunk-B4P2CM2J.mjs +3 -0
  211. package/dist/chunk-BPL64HGA.mjs +4 -0
  212. package/dist/chunk-BVEFGE4B.mjs +2 -0
  213. package/dist/chunk-BZ5RAF7L.mjs +2 -0
  214. package/dist/chunk-CRJEG7MT.mjs +2 -0
  215. package/dist/{chunk-B3VTYBYR.mjs → chunk-D4CKRD3V.mjs} +91 -91
  216. package/dist/chunk-D4EURAX4.mjs +4 -0
  217. package/dist/chunk-DQCE7TJY.mjs +5 -0
  218. package/dist/chunk-DR73Y2UJ.mjs +3 -0
  219. package/dist/{chunk-TMYZB6AV.mjs → chunk-EKNHM3P4.mjs} +1 -1
  220. package/dist/{chunk-DB4WKGYF.mjs → chunk-ERLAIBOA.mjs} +2 -2
  221. package/dist/chunk-EURLTOTZ.mjs +4 -0
  222. package/dist/chunk-FJYN7RTH.mjs +4 -0
  223. package/dist/chunk-FWNRPMCJ.mjs +12 -0
  224. package/dist/chunk-FWW4CSAZ.mjs +2 -0
  225. package/dist/{chunk-2B5E4CDJ.mjs → chunk-GPIWQ4X4.mjs} +1 -1
  226. package/dist/chunk-GY3FAUVM.mjs +2 -0
  227. package/dist/chunk-HLYV7RIH.mjs +2 -0
  228. package/dist/chunk-HMYTM3GT.mjs +15 -0
  229. package/dist/chunk-IA4PSIMD.mjs +2 -0
  230. package/dist/chunk-JEUK3ZO7.mjs +2 -0
  231. package/dist/chunk-JVHHHGEA.mjs +3 -0
  232. package/dist/chunk-KTKHRC6H.mjs +2 -0
  233. package/dist/chunk-L7UP52JO.mjs +2 -0
  234. package/dist/chunk-MHW7ZKOU.mjs +2 -0
  235. package/dist/chunk-N76HWBA3.mjs +10 -0
  236. package/dist/chunk-N7AZZLGT.mjs +548 -0
  237. package/dist/chunk-NAMN3RAF.mjs +2 -0
  238. package/dist/{chunk-YXAUQPVK.mjs → chunk-NFMCP2HI.mjs} +3 -3
  239. package/dist/chunk-NG375ILQ.mjs +2 -0
  240. package/dist/chunk-NVRNLK25.mjs +6 -0
  241. package/dist/chunk-NWFBE2YA.mjs +2 -0
  242. package/dist/chunk-NWR2LT5B.mjs +2 -0
  243. package/dist/chunk-OJKMINIU.mjs +20 -0
  244. package/dist/chunk-OUUP3WKT.mjs +2 -0
  245. package/dist/chunk-OW5NWPOJ.mjs +10 -0
  246. package/dist/chunk-PAREWQGB.mjs +4 -0
  247. package/dist/chunk-POQSE4C2.mjs +2 -0
  248. package/dist/chunk-PUOQ65NC.mjs +2 -0
  249. package/dist/{chunk-Z52HTUW7.mjs → chunk-PVER7LSC.mjs} +2 -2
  250. package/dist/chunk-PZDLJJTJ.mjs +3 -0
  251. package/dist/chunk-Q47PLKIJ.mjs +15 -0
  252. package/dist/chunk-Q4UEPUWF.mjs +2 -0
  253. package/dist/chunk-QKXMPUXC.mjs +2 -0
  254. package/dist/chunk-QOUEFUCH.mjs +16 -0
  255. package/dist/chunk-RFDZXFJF.mjs +13 -0
  256. package/dist/chunk-RKPWLGZ3.mjs +4 -0
  257. package/dist/chunk-RMECZA2K.mjs +2 -0
  258. package/dist/{chunk-EUX7IC5J.mjs → chunk-SQ6Y2ZMA.mjs} +2 -2
  259. package/dist/chunk-SX4LJYT6.mjs +8 -0
  260. package/dist/chunk-SXHBYZST.mjs +16 -0
  261. package/dist/chunk-TANZRINB.mjs +2 -0
  262. package/dist/chunk-TEZAWDSQ.mjs +2 -0
  263. package/dist/chunk-UBBRTJ2R.mjs +24 -0
  264. package/dist/chunk-UFNYFFKO.mjs +20 -0
  265. package/dist/chunk-UGWYKHBL.mjs +170 -0
  266. package/dist/chunk-UKSHDZZ6.mjs +2 -0
  267. package/dist/chunk-UMHUSOPJ.mjs +2 -0
  268. package/dist/chunk-UNOYVIYR.mjs +2 -0
  269. package/dist/chunk-V6RIYQZZ.mjs +4 -0
  270. package/dist/chunk-VJPFVNNW.mjs +15 -0
  271. package/dist/chunk-VS3ZMVGX.mjs +5 -0
  272. package/dist/chunk-VTKNEYT3.mjs +6 -0
  273. package/dist/chunk-VXACTLO3.mjs +3 -0
  274. package/dist/chunk-W3BGBJQW.mjs +2 -0
  275. package/dist/chunk-YI43RG4P.mjs +2 -0
  276. package/dist/chunk-YQGT4AB2.mjs +6 -0
  277. package/dist/chunk-ZB4H7ZN4.mjs +2 -0
  278. package/dist/{chunk-ACOPDCNB.mjs → chunk-ZHEHPMBK.mjs} +1 -1
  279. package/dist/chunk-ZTHICSSF.mjs +2 -0
  280. package/dist/chunk-ZUNVAXLH.mjs +2 -0
  281. package/dist/chunk-ZWPMCK7P.mjs +2 -0
  282. package/dist/cli.mjs +1 -1
  283. package/dist/server.mjs +1 -1
  284. package/dist/{chunk-EVJ3BX3M.mjs → update-fetch.mjs} +1 -1
  285. package/dist/worker.mjs +1 -1
  286. package/kit/board.css +95 -0
  287. package/kit/board.js +250 -0
  288. package/kit/charts.js +5 -71
  289. package/kit/code.js +14 -14
  290. package/kit/math.js +18 -2
  291. package/kit/report.css +500 -151
  292. package/kit/runtime.js +1720 -170
  293. package/kit/state.js +10 -1
  294. package/kit/tables.js +172 -37
  295. package/kit/ui.js +166 -27
  296. package/package.json +2 -1
  297. package/packs/gallery/card/component.json +14 -0
  298. package/packs/gallery/card/example.html +10 -0
  299. package/packs/gallery/card/preview.svg +1 -0
  300. package/packs/gallery/card/style.css +6 -0
  301. package/packs/gallery/card/template.html +6 -0
  302. package/packs/gallery/card/writing.md +14 -0
  303. package/packs/gallery/chart-card/component.json +15 -0
  304. package/packs/gallery/chart-card/example.html +14 -0
  305. package/packs/gallery/chart-card/kit.js +130 -0
  306. package/packs/gallery/chart-card/preview.svg +1 -0
  307. package/packs/gallery/chart-card/style.css +42 -0
  308. package/packs/gallery/chart-card/template.html +13 -0
  309. package/packs/gallery/chart-card/writing.md +20 -0
  310. package/packs/gallery/chart-view/component.json +20 -0
  311. package/packs/gallery/chart-view/example.html +13 -0
  312. package/packs/gallery/chart-view/kit.js +355 -0
  313. package/packs/gallery/chart-view/preview.svg +1 -0
  314. package/packs/gallery/chart-view/style.css +94 -0
  315. package/packs/gallery/chart-view/template.html +3 -0
  316. package/packs/gallery/chart-view/writing.md +22 -0
  317. package/packs/gallery/countdown/component.json +18 -0
  318. package/packs/gallery/countdown/example.html +3 -0
  319. package/packs/gallery/countdown/kit.js +156 -0
  320. package/packs/gallery/countdown/preview.svg +1 -0
  321. package/packs/gallery/countdown/style.css +130 -0
  322. package/packs/gallery/countdown/template.html +3 -0
  323. package/packs/gallery/countdown/writing.md +22 -0
  324. package/packs/gallery/habit/component.json +14 -0
  325. package/packs/gallery/habit/example.html +3 -0
  326. package/packs/gallery/habit/kit.js +295 -0
  327. package/packs/gallery/habit/preview.svg +1 -0
  328. package/packs/gallery/habit/style.css +246 -0
  329. package/packs/gallery/habit/template.html +3 -0
  330. package/packs/gallery/habit/writing.md +21 -0
  331. package/packs/gallery/heatmap/component.json +18 -0
  332. package/packs/gallery/heatmap/example.html +3 -0
  333. package/packs/gallery/heatmap/kit.js +351 -0
  334. package/packs/gallery/heatmap/preview.svg +1 -0
  335. package/packs/gallery/heatmap/style.css +201 -0
  336. package/packs/gallery/heatmap/template.html +3 -0
  337. package/packs/gallery/heatmap/writing.md +21 -0
  338. package/packs/gallery/kanban/component.json +18 -0
  339. package/packs/gallery/kanban/example.html +12 -0
  340. package/packs/gallery/kanban/kit.js +540 -0
  341. package/packs/gallery/kanban/preview.svg +1 -0
  342. package/packs/gallery/kanban/style.css +212 -0
  343. package/packs/gallery/kanban/template.html +3 -0
  344. package/packs/gallery/kanban/writing.md +20 -0
  345. package/packs/gallery/metric/component.json +22 -0
  346. package/packs/gallery/metric/example.html +15 -0
  347. package/packs/gallery/metric/kit.js +248 -0
  348. package/packs/gallery/metric/preview.svg +1 -0
  349. package/packs/gallery/metric/style.css +92 -0
  350. package/packs/gallery/metric/template.html +3 -0
  351. package/packs/gallery/metric/writing.md +23 -0
  352. package/packs/gallery/note/component.json +14 -0
  353. package/packs/gallery/note/example.html +3 -0
  354. package/packs/gallery/note/kit.js +102 -0
  355. package/packs/gallery/note/preview.svg +1 -0
  356. package/packs/gallery/note/style.css +76 -0
  357. package/packs/gallery/note/template.html +3 -0
  358. package/packs/gallery/note/writing.md +18 -0
  359. package/packs/gallery/pack.json +8 -0
  360. package/packs/gallery/recent/component.json +13 -0
  361. package/packs/gallery/recent/example.html +1 -0
  362. package/packs/gallery/recent/kit.js +238 -0
  363. package/packs/gallery/recent/preview.svg +1 -0
  364. package/packs/gallery/recent/style.css +158 -0
  365. package/packs/gallery/recent/template.html +1 -0
  366. package/packs/gallery/recent/writing.md +15 -0
  367. package/packs/gallery/static/component.json +13 -0
  368. package/packs/gallery/static/example.html +11 -0
  369. package/packs/gallery/static/preview.svg +1 -0
  370. package/packs/gallery/static/style.css +138 -0
  371. package/packs/gallery/static/template.html +1 -0
  372. package/packs/gallery/static/writing.md +18 -0
  373. package/packs/gallery/stats/component.json +13 -0
  374. package/packs/gallery/stats/example.html +1 -0
  375. package/packs/gallery/stats/kit.js +166 -0
  376. package/packs/gallery/stats/preview.svg +1 -0
  377. package/packs/gallery/stats/style.css +151 -0
  378. package/packs/gallery/stats/template.html +1 -0
  379. package/packs/gallery/stats/writing.md +11 -0
  380. package/packs/gallery/today/component.json +12 -0
  381. package/packs/gallery/today/example.html +1 -0
  382. package/packs/gallery/today/kit.js +185 -0
  383. package/packs/gallery/today/preview.svg +1 -0
  384. package/packs/gallery/today/style.css +120 -0
  385. package/packs/gallery/today/template.html +1 -0
  386. package/packs/gallery/today/writing.md +14 -0
  387. package/packs/gallery/todos/component.json +19 -0
  388. package/packs/gallery/todos/example.html +3 -0
  389. package/packs/gallery/todos/kit.js +342 -0
  390. package/packs/gallery/todos/preview.svg +1 -0
  391. package/packs/gallery/todos/style.css +267 -0
  392. package/packs/gallery/todos/template.html +3 -0
  393. package/packs/gallery/todos/writing.md +30 -0
  394. package/packs/gallery/weather/component.json +19 -0
  395. package/packs/gallery/weather/example.html +3 -0
  396. package/packs/gallery/weather/kit.js +312 -0
  397. package/packs/gallery/weather/preview.svg +1 -0
  398. package/packs/gallery/weather/style.css +258 -0
  399. package/packs/gallery/weather/template.html +3 -0
  400. package/packs/gallery/weather/writing.md +26 -0
  401. package/packs/gallery-soft/pack.json +8 -0
  402. package/release.json +13 -11
  403. package/sdk/doc-kit.d.ts +404 -7
  404. package/sdk/doc-state.d.ts +2 -0
  405. package/skill/SKILL.md +71 -26
  406. package/skill/references/block-script.md +140 -0
  407. package/skill/references/building-blocks.md +257 -0
  408. package/skill/references/example-report.html +1 -1
  409. package/skill/references/extensions.md +59 -0
  410. package/skill/references/pages-and-data.md +221 -0
  411. package/skill/references/writing-html.md +9 -7
  412. package/skill/sdk/doc-kit.d.ts +404 -7
  413. package/skill/sdk/doc-state.d.ts +2 -0
  414. package/web/assets/index-BK2e_07w.js +13 -0
  415. package/web/assets/index-CWFI83mF.css +1 -0
  416. package/web/index.html +2 -2
  417. package/browser/editor/components/callout/page.mjs +0 -13
  418. package/dist/chunk-2PBALTR3.mjs +0 -57
  419. package/dist/chunk-3LA3EMDE.mjs +0 -15
  420. package/dist/chunk-5FRMCDPY.mjs +0 -16
  421. package/dist/chunk-5LEK2CBS.mjs +0 -2
  422. package/dist/chunk-5OFN5AHC.mjs +0 -2
  423. package/dist/chunk-5SIYS5HN.mjs +0 -2
  424. package/dist/chunk-5TEK3RAD.mjs +0 -2
  425. package/dist/chunk-6CYG3Z4V.mjs +0 -2
  426. package/dist/chunk-7GHT2UCA.mjs +0 -15
  427. package/dist/chunk-7QQBR7PB.mjs +0 -2
  428. package/dist/chunk-ATCJYAR4.mjs +0 -2
  429. package/dist/chunk-C7HWOBIF.mjs +0 -2
  430. package/dist/chunk-E7VYDG2X.mjs +0 -2
  431. package/dist/chunk-EZY3WC6Z.mjs +0 -15
  432. package/dist/chunk-FQGQH4KM.mjs +0 -2
  433. package/dist/chunk-G7TOXONE.mjs +0 -6
  434. package/dist/chunk-GPF4YWWB.mjs +0 -9
  435. package/dist/chunk-GYQV7Y4J.mjs +0 -120
  436. package/dist/chunk-HMHK3EQ6.mjs +0 -2
  437. package/dist/chunk-HQQMJCQJ.mjs +0 -10
  438. package/dist/chunk-IERUOGC3.mjs +0 -6
  439. package/dist/chunk-ITNLYXXV.mjs +0 -3
  440. package/dist/chunk-L4DVONOG.mjs +0 -2
  441. package/dist/chunk-LAE5NQ4B.mjs +0 -2
  442. package/dist/chunk-LC7YNQFG.mjs +0 -2
  443. package/dist/chunk-LHTFLRB6.mjs +0 -4
  444. package/dist/chunk-NFIBI4IP.mjs +0 -26
  445. package/dist/chunk-NSKUTQ5J.mjs +0 -5
  446. package/dist/chunk-O52JMOCZ.mjs +0 -2
  447. package/dist/chunk-P2CAZPDP.mjs +0 -3
  448. package/dist/chunk-QMQUXTU4.mjs +0 -12
  449. package/dist/chunk-QVWVFC5K.mjs +0 -6
  450. package/dist/chunk-QYKCJ7FG.mjs +0 -8
  451. package/dist/chunk-QZY6Q64C.mjs +0 -2
  452. package/dist/chunk-TDQP3DKQ.mjs +0 -10
  453. package/dist/chunk-TX6JH7TR.mjs +0 -2
  454. package/dist/chunk-UNUEWH4S.mjs +0 -2
  455. package/dist/chunk-V4CPWKMZ.mjs +0 -2
  456. package/dist/chunk-VACRB2NE.mjs +0 -3
  457. package/dist/chunk-W63L7367.mjs +0 -7
  458. package/dist/chunk-W7CXPCRV.mjs +0 -6
  459. package/dist/chunk-XINNG4F2.mjs +0 -4
  460. package/dist/chunk-YL2DPWVS.mjs +0 -4
  461. package/dist/chunk-YZ5Z6H4W.mjs +0 -4
  462. package/dist/chunk-ZBIM6ARY.mjs +0 -216
  463. package/skill/references/building-components.md +0 -327
  464. package/web/assets/index-B6Ai3wsa.js +0 -13
  465. package/web/assets/index-SYPC3EZy.css +0 -1
@@ -35,7 +35,7 @@ export function sharedWidths(wrap, count, share = 1) {
35
35
  * `numbers` is false (识别数字列: index.mjs NUMBERS). `looks`, `widths` and `spans` as tableData
36
36
  * describes them: each cell's look classes, each column's width, each cell's [rowspan, colspan]
37
37
  * (a cell merged makes a row hold fewer cells); where `looks` is given the cells have just those,
38
- * where not a header cell takes the header's look. `chart`: the key a chart drawn from it reads it
38
+ * where not a header row's cell takes the header's look (a header column's none). `chart`: the key a chart drawn from it reads it
39
39
  * by (its frame's data-doc-chart-source), when it has one.
40
40
  */
41
41
  export function newTable(doc, { rows, header = false, column = false, numbers = true, looks, widths, spans, chart }) {
@@ -55,7 +55,7 @@ export function newTable(doc, { rows, header = false, column = false, numbers =
55
55
  const first = at[r][index] === 0;
56
56
  const cell = newCell(doc, head || (column && first) ? "th" : "td", !head && column && first ? "row" : null);
57
57
  if (looks) cell.classList.add(...(looks[r][index] ?? "").split(" ").filter(Boolean));
58
- else if (cell.localName === "th") headerLook(cell, true);
58
+ else if (head) headerLook(cell, true);
59
59
  const [down, across] = spans?.[r]?.[index] ?? [1, 1];
60
60
  setSpan(cell, down, across);
61
61
  if (Array.isArray(html)) cell.append(...html);
@@ -120,7 +120,7 @@ function cellNodes(doc, html, inline) {
120
120
  * row, its names' column a header column, its numeric columns read (the page's own copy as it was).
121
121
  */
122
122
  export function build({ doc, block, inline }) {
123
- const rows = block.rows.map((row) => row.map((html) => cellNodes(doc, html, inline)));
123
+ const rows = block.rows.map((row) => row.map((html) => cellNodes(doc, html, (text) => inline(text, { pictures: true })))); // a cell's pictures its own
124
124
  const table = newTable(doc, { rows, header: Boolean(block.header), column: Boolean(block.column), numbers: block.numbers !== false, looks: block.looks, widths: block.widths, spans: block.spans, chart: block.chart });
125
125
  if (block.outside) optimizeTable(table);
126
126
  return table;
@@ -139,7 +139,7 @@ export function build({ doc, block, inline }) {
139
139
  /**
140
140
  * A table standing for an empty block (its type's `create`): three columns, a header row and two rows
141
141
  * (the plan's D6), the caret in its first cell (notion-lite's). It is two fifths as wide as the text
142
- * it stands in, its columns equal and fixed (typing does not move them); 一键调整列宽 is the reader's
142
+ * it stands in, its columns equal and fixed (typing does not move them); 自动调整列宽 is the reader's
143
143
  * to choose (a pasted table has the kit's widths). Its numeric columns are not read (识别数字列 off):
144
144
  * typing numbers does not center or sort them.
145
145
  */
@@ -164,8 +164,8 @@ export function create({ tables }) {
164
164
 
165
165
  /**
166
166
  * A new cell: a text block made on the page (td, or th with its scope). A header cell made in a
167
- * header row or column takes the look of the header cell beside it (`model`: lookLike), one of a
168
- * new table the header's (newTable).
167
+ * header row takes the look of the header cell beside it (`model`: lookLike), one of a new table
168
+ * the header's (newTable); a header column's cell is made plain.
169
169
  */
170
170
  export function newCell(doc, tag = "td", scope = null, model = null) {
171
171
  const cell = doc.createElement(tag);
@@ -175,9 +175,15 @@ export function newCell(doc, tag = "td", scope = null, model = null) {
175
175
  return cell;
176
176
  }
177
177
 
178
- // A cell that becomes a header cell takes the header's look (index.mjs HEADER_LOOK: bold, and the
179
- // gray fill unless it has a color of its own); one that stops being one loses it. These are looks
180
- // as any other: the reader may change them.
178
+ // Whether a cell of `tag` and `scope` wears the header row's look (index.mjs HEADER_LOOK): a th that is
179
+ // no row's header. A header column's th (scope="row") has no look of its own: 标题列 only makes the
180
+ // column stay at the left when the frame scrolls sideways (the user's, 2026-11-06).
181
+ const wearsHeaderLook = (tag, scope) => tag === "th" && (scope ?? "").trim().toLowerCase() !== "row";
182
+
183
+ // A cell that becomes a header row's cell (wearsHeaderLook) takes the header's look (index.mjs
184
+ // HEADER_LOOK: bold, and the gray fill unless it has a color of its own); one that stops being one
185
+ // loses it; a header column's cell has none (标题列 only sticks). These are looks as any other: the
186
+ // reader may change them.
181
187
  function headerLook(cell, on) {
182
188
  const [bold, fill] = HEADER_LOOK;
183
189
  if (!on) return cell.classList.remove(bold, fill);
@@ -185,7 +191,7 @@ function headerLook(cell, on) {
185
191
  if (!BLOCK_COLORS.some((name) => cell.classList.contains(name))) cell.classList.add(fill);
186
192
  }
187
193
 
188
- // A header cell made beside another of its header row or column: its color and bold as that one's
194
+ // A header cell made beside another of its header row: its color and bold as that one's
189
195
  // (a header the reader made plain, or the Agent wrote plain, stays so).
190
196
  function lookLike(cell, model) {
191
197
  const [bold] = HEADER_LOOK;
@@ -253,10 +259,10 @@ export function columnRange(unit, from, to = from) {
253
259
  }
254
260
 
255
261
  // The cell a new row has in column `c`: as the row it is made beside has it there (a header
256
- // column's th), never a header row's th.
262
+ // column's th, plain), never a header row's th.
257
263
  const cellLike = (doc, slots, r, c) => {
258
264
  const model = r === null ? null : slots.matrix[r]?.[c];
259
- return model?.localName === "th" && model.getAttribute("scope") === "row" && c === 0 ? newCell(doc, "th", "row", model) : newCell(doc);
265
+ return model?.localName === "th" && model.getAttribute("scope") === "row" && c === 0 ? newCell(doc, "th", "row") : newCell(doc);
260
266
  };
261
267
 
262
268
  /** A new row at `at` (0 … rows): in the tbody (in the thead only between its rows). Returns it. */
@@ -304,7 +310,7 @@ export function insertColumn(unit, at) {
304
310
  const head = row.parentElement.localName === "thead";
305
311
  const first = slots.matrix[r][0];
306
312
  const beside = slots.matrix[r][Math.max(0, at - 1)];
307
- const cell = head ? newCell(doc, "th", null, beside) : at === 0 && headerColumn ? newCell(doc, "th", "row", first) : newCell(doc);
313
+ const cell = head ? newCell(doc, "th", null, beside) : at === 0 && headerColumn ? newCell(doc, "th", "row") : newCell(doc);
308
314
  row.insertBefore(cell, cellFrom(slots, row, at));
309
315
  made.push(cell);
310
316
  // A header column stays the first: the cell that was first is a plain one now.
@@ -464,7 +470,7 @@ export function labelColumn(unit) {
464
470
 
465
471
  /**
466
472
  * 一键优化 (the table's block menu; a table pasted from elsewhere comes in so): the kit's column
467
- * widths (一键调整列宽: many columns scroll sideways in the frame), a header row, the first column a
473
+ * widths (自动调整列宽: many columns scroll sideways in the frame), a header row, the first column a
468
474
  * header column when its words are the rows' names, its numeric columns read (识别数字列: centered,
469
475
  * sorted by their header), and a frame shown whole (显示全部行) that is taller than the kit's scroll
470
476
  * height scrolling again (one that scrolls already stays as it is). Inside one undo step (the
@@ -491,7 +497,7 @@ export function optimizeTable(unit) {
491
497
  return changed;
492
498
  }
493
499
 
494
- /** The header column on (each body row's cell in the first column th scope="row") or off (td). */
500
+ /** The header column on (each body row's cell in the first column th scope="row") or off (td); its cells' looks untouched either way (the header column only sticks). */
495
501
  export function setHeaderColumn(unit, on) {
496
502
  const { rows, body, headerColumn, slots } = tableState(unit);
497
503
  if (on === headerColumn) return false;
@@ -596,7 +602,7 @@ export function splitCell(unit, cell) {
596
602
  const before = cellFrom(slots, rows[r], place.c + place.cols);
597
603
  for (let c = place.c; c < place.c + place.cols; c++) {
598
604
  if (r === place.r && c === place.c) continue;
599
- const piece = rowHeader ? (c === 0 ? newCell(doc, "th", "row", cell) : newCell(doc)) : newCell(doc, cell.localName, null, cell);
605
+ const piece = rowHeader ? (c === 0 ? newCell(doc, "th", "row") : newCell(doc)) : newCell(doc, cell.localName, null, cell);
600
606
  rows[r].insertBefore(piece, before);
601
607
  made.push(piece);
602
608
  }
@@ -647,11 +653,16 @@ function keepWidths(unit, mutate) {
647
653
  /**
648
654
  * A cell as a td or th (`scope`: a th's, null for none): a new element of that tag in its place,
649
655
  * taking its attributes, a copy of its content (the old cell keeps its own, for undo to put back)
650
- * and its identity (it stays the same cell to the commits); the header's look taken or lost with it.
656
+ * and its identity (it stays the same cell to the commits); the header row's look taken or lost when
657
+ * the cell comes into or leaves the kind that wears it (wearsHeaderLook): a header column's th wears
658
+ * none, and a cell switched between td and it keeps its looks. A th only given another scope stays
659
+ * itself unless its look changes (a new element then too, so undo puts its classes back).
651
660
  */
652
661
  export function retagCell(cell, tag, scope = null) {
653
662
  if (!cell) return cell;
654
- if (cell.localName === tag) {
663
+ const look = wearsHeaderLook(tag, tag === "th" ? scope : null);
664
+ const changes = wearsHeaderLook(cell.localName, cell.getAttribute("scope")) !== look;
665
+ if (cell.localName === tag && !changes) {
655
666
  if (tag === "th" && scope) cell.setAttribute("scope", scope);
656
667
  else cell.removeAttribute("scope");
657
668
  return cell;
@@ -659,7 +670,7 @@ export function retagCell(cell, tag, scope = null) {
659
670
  const next = cell.ownerDocument.createElement(tag);
660
671
  for (const { name, value } of [...cell.attributes]) if (name !== "scope") next.setAttribute(name, value);
661
672
  if (tag === "th" && scope) next.setAttribute("scope", scope);
662
- headerLook(next, tag === "th");
673
+ if (changes) headerLook(next, look);
663
674
  next.append(...[...cell.childNodes].map((node) => node.cloneNode(true)));
664
675
  cell.replaceWith(next);
665
676
  return next;
@@ -26,9 +26,10 @@ const unitOf = (node) => {
26
26
  /**
27
27
  * The text of `elements` (in page order) as the server reads a block, a line between them: { text,
28
28
  * at }, `at[i]` where character `i` comes from ({ node, offset } in a text node, { element } for a
29
- * formula's TeX, null for a line's end).
29
+ * formula's TeX, null for a line's end). `skip(child)`: an element of theirs read past (a list item's
30
+ * blocks, when its own words alone are read: changes/).
30
31
  */
31
- export function readText(elements) {
32
+ export function readText(elements, { skip = null } = {}) {
32
33
  let text = "";
33
34
  const at = [];
34
35
  const put = (char, place) => { text += char; at.push(place); };
@@ -59,7 +60,7 @@ export function readText(elements) {
59
60
  space({ element: child });
60
61
  continue;
61
62
  }
62
- if (child.matches(SKIP)) continue;
63
+ if (child.matches(SKIP) || skip?.(child)) continue;
63
64
  const words = isMention(child) ? sourceWords(child) : null;
64
65
  if (words !== null) {
65
66
  for (const char of words) (/\s/.test(char) ? space : (place) => put(char, place))({ element: child });
@@ -32,8 +32,7 @@ export const STYLE = `
32
32
  .ge-note-marker { width: ${RAIL.marker}px; height: ${RAIL.marker}px; box-sizing: border-box; margin: 0; padding: 0; border: 0; border-radius: 6px; background: transparent; display: grid; place-items: center; color: var(--ge-ico2); cursor: pointer; pointer-events: auto; }
33
33
  .ge-note-marker svg { width: 18px; height: 18px; fill: currentColor; stroke: none; }
34
34
  .ge-note-marker[hidden], .ge-note-card[hidden] { display: none; }
35
- .ge-note-marker:hover, .ge-note-marker[data-hot] { background: var(--ge-hover); color: var(--ge-ico); }
36
- .ge-note-marker:active { background: var(--ge-press); }
35
+ .ge-note-marker[data-hot] { background: var(--ge-hover); color: var(--ge-ico); }
37
36
  .ge-note-marker:focus-visible { outline: 2px solid var(--ge-focus); outline-offset: -2px; }
38
37
  /* The card, where the format bar would stand: a popover as the bar is, as wide as ${RAIL.card}px or the column. Its face is what shows; the card itself stands still, so a face going left under the pointer keeps it. */
39
38
  .ge-note-card { z-index: 1; width: ${RAIL.card}px; box-sizing: border-box; color: var(--ge-tx); pointer-events: auto; cursor: text; }
@@ -60,8 +59,6 @@ export const STYLE = `
60
59
  .ge-note-card[data-long][data-top] textarea { --top: 28px; }
61
60
  /* Its delete button, on the field's first line, in the room the field leaves it. */
62
61
  .ge-note-delete { position: absolute; top: 7px; right: 7px; width: 24px; height: 24px; box-sizing: border-box; margin: 0; padding: 0; border: 0; border-radius: 6px; background: transparent; display: grid; place-items: center; color: var(--ge-ico3); cursor: pointer; }
63
- .ge-note-delete:hover { background: var(--ge-hover); }
64
- .ge-note-delete:active { background: var(--ge-press); }
65
62
  .ge-note-delete svg { width: 18px; height: 18px; pointer-events: none; }
66
63
  .ge-note-bar { width: 2px; border-radius: 1px; background: var(--ge-note-line); }
67
64
  .ge-note-bar[data-hot] { background: var(--ge-note-hot-line); }
@@ -74,13 +71,13 @@ export const STYLE = `
74
71
  export const layerNode = () => element("div", { class: "ge-note-layer", "data-doc-dev": "" });
75
72
 
76
73
  export function markerNode(id) {
77
- return element("button", { type: "button", class: "ge-note-marker", "data-note": id, "aria-label": t("批注"), tabindex: "-1", html: MARKER_ICON });
74
+ return element("button", { type: "button", class: "ge-note-marker ge-icon-btn", "data-note": id, "aria-label": t("批注"), tabindex: "-1", html: MARKER_ICON });
78
75
  }
79
76
 
80
77
  /** A card: a plain-text field, and the button that deletes what it holds, on its face. */
81
78
  export function cardNode() {
82
79
  const field = element("textarea", { rows: "1", spellcheck: "false", maxlength: TEXT_MOST, placeholder: t("写下建议…"), "aria-label": t("批注") });
83
- const erase = element("button", { type: "button", class: "ge-note-delete", "aria-label": t("删除批注"), tabindex: "-1", html: ICONS.trash });
80
+ const erase = element("button", { type: "button", class: "ge-note-delete ge-icon-btn", "aria-label": t("删除批注"), tabindex: "-1", html: ICONS.trash });
84
81
  tooltip(erase, t("删除批注"));
85
82
  return { node: element("div", { class: "ge-note-card", role: "group" }, element("div", { class: "ge-note-face" }, field, erase)), field, erase };
86
83
  }
@@ -5,6 +5,7 @@ import { caretAt, editable, select } from "../caret.mjs";
5
5
  import { ordered } from "../block-info.mjs";
6
6
  import { firstHost, isHost, unitElement } from "../core.mjs";
7
7
  import { createFills } from "../fills.mjs";
8
+ import { reveal } from "../folded.mjs";
8
9
  import { FOLLOW, task } from "../frames.mjs";
9
10
  import { BAR } from "../handle-sizes.mjs";
10
11
  import { MARGIN, margin, onMargin, rightRoom, setMargin } from "../margin.mjs";
@@ -44,17 +45,17 @@ import { HOT, MARK, STYLE, barNode, cardNode, fitField, layerNode, markerNode }
44
45
  // mark (blocks, the fill selected blocks have, in a warm colour: fills.mjs): words have it where the
45
46
  // format bar stood (below their last line, by their last character), blocks at the last one's bottom
46
47
  // right (at the window's bottom where that is below it), always inside the column. It exists once
47
- // it is left or something is typed in it, words or none: one with no words is a plain mark of its place
48
- // (Esc on a new one that never held words takes it back); typing saves it (500ms after the last key, at
49
- // once when it closes); a press elsewhere, Esc, Enter, Tab or Ctrl+Alt+M close it into a marker
48
+ // something is typed in it (white space is nothing): a card left with none leaves nothing, and a saved
49
+ // one emptied goes as its card closes, offered back as its delete button's is (an annotation has words:
50
+ // the user's, 2026-11-06); typing saves it (500ms after the last key, at once when it closes; a text
51
+ // with no words never: the file keeps its last words while the card is open); a press elsewhere, Esc, Enter, Tab or Ctrl+Alt+M close it into a marker
50
52
  // in the column's right gutter, at its first line or the middle of its several blocks (right of a
51
53
  // section's strip for what is in that section; the place the button beside a block stands on:
52
54
  // markerSpot(), which says no where a marker stands already). Closed
53
55
  // by a key the caret goes back to its words, or to its blocks where the keys opened it; a card of
54
56
  // blocks the pointer opened places none. Resting on a marker (or clicking it) shows its card again
55
57
  // where it was written, by its words, which light up, and it stays while the pointer goes over to it.
56
- // The button at a card's right deletes it, and that alone does, or its words or blocks going: a card
57
- // emptied stays, with no words. One card shows at a time, and starting on the words of an annotation already there shows its
58
+ // The button at a card's right deletes it, and so does emptying it, or its words or blocks going. One card shows at a time, and starting on the words of an annotation already there shows its
58
59
  // card rather than a second one. The workbench's list asks for the page's annotations (rows()) and
59
60
  // goes to one (goTo()): what hides it opened, the page scrolled to it, its card shown as resting on its
60
61
  // marker shows it, until a press elsewhere or the words leave the window. Markers stack without
@@ -109,6 +110,7 @@ export function createAnnotate({ slug, token, isEditing, picked, unpick = () =>
109
110
  let reading = null; // the first read from the server, under way or done (taken back when it failed)
110
111
  let counted = false; // that read is in and what it brought found: the page can say how many it has
111
112
  let items = new Map(); // id -> { id, created, updated, text, anchor } in page order, as the server last said, with the page's own changes
113
+ let filed = new Map(); // id -> its text as the file last held it (the server's last answer): what 撤销 brings back of one emptied in its card
112
114
  let version = null; // the file's, as last read or written
113
115
  const lost = new Map(); // id -> an annotation a check deleted this visit (its words gone): back when an undo brings them back
114
116
  const timers = new Map(); // id -> the timer of its save (typed, not saved yet)
@@ -132,9 +134,9 @@ export function createAnnotate({ slug, token, isEditing, picked, unpick = () =>
132
134
  let remeasure = true; // all of them to measure again (what may move them: the page's size, its structure), else those in `stale`
133
135
  const stale = new Set(); // ids found again since they were measured
134
136
  // The annotation whose card shows, or stands in front: { id, focus, hover, keys, located, side, begun,
135
- // held, opening, within }: `keys`, opened by the keys, which give the caret back; `located`, shown by
137
+ // opening, within }: `keys`, opened by the keys, which give the caret back; `located`, shown by
136
138
  // the workbench's list; `side`, by its words, "below" or "above" them, kept while it is written;
137
- // `begun`, new, and `held`, having held words; `opening`, opened for writing and not laid out yet in
139
+ // `begun`, new; `opening`, opened for writing and not laid out yet in
138
140
  // the margin; `within`, what it is laid out by there instead of its anchor, which is out of the window.
139
141
  let shown = null;
140
142
  let hot = null; // the id whose words are under the pointer
@@ -198,6 +200,7 @@ export function createAnnotate({ slug, token, isEditing, picked, unpick = () =>
198
200
  heard = true;
199
201
  version = answer.version;
200
202
  const dropped = new Set(answer.dropped ?? []);
203
+ filed = new Map((answer.items ?? []).map((item) => [item.id, item.text]));
201
204
  const next = new Map();
202
205
  for (const item of answer.items ?? []) {
203
206
  const mine = items.get(item.id);
@@ -298,12 +301,13 @@ export function createAnnotate({ slug, token, isEditing, picked, unpick = () =>
298
301
  return answer;
299
302
  }
300
303
 
301
- // Save it now: made (its first save) or changed, with words or with none (a plain mark of its place).
304
+ // Save it now: made (its first save) or changed; never with no words (left so, it goes: close).
302
305
  async function save(id) {
303
306
  clearTimeout(timers.get(id));
304
307
  timers.delete(id);
305
308
  const item = items.get(id);
306
309
  if (!item) return;
310
+ if (!item.text.trim()) return; // no words: nothing to save, the file keeps its last words
307
311
  if (!item.anchor) {
308
312
  if (!made.has(id)) return;
309
313
  item.anchor = anchorOf(id);
@@ -366,14 +370,16 @@ export function createAnnotate({ slug, token, isEditing, picked, unpick = () =>
366
370
 
367
371
  /** Save what is typed and not saved yet, now (Ctrl+S, the workbench's save, the page closing: `keepalive`). */
368
372
  function flush({ keepalive = false } = {}) {
369
- const ids = [...new Set([...timers.keys(), ...[...made.keys()].filter((id) => !sending.has(id))])]; // one begun and not saved yet counts, typed in or not
373
+ // What was typed, and one begun and not saved yet; one with no words saves nothing (save), and one
374
+ // the file has keeps its last words (the page going, no 撤销 could be offered for its going).
375
+ const ids = [...new Set([...timers.keys(), ...[...made.keys()].filter((id) => !sending.has(id))])];
370
376
  if (keepalive) {
371
377
  sync({ keepalive: true });
372
378
  for (const id of ids) {
373
379
  clearTimeout(timers.get(id));
374
380
  timers.delete(id);
375
381
  const item = items.get(id);
376
- if (!item) continue;
382
+ if (!item?.text.trim()) continue;
377
383
  if (!item.anchor && made.has(id)) item.anchor = anchorOf(id);
378
384
  postJson(ROUTE, token, { slug, put: wire(item) }, { keepalive: true }).catch(() => {});
379
385
  }
@@ -460,9 +466,9 @@ export function createAnnotate({ slug, token, isEditing, picked, unpick = () =>
460
466
  // A card's field has the focus (a card being written); `shown.focus` follows it.
461
467
  const focused = () => Boolean(document.activeElement?.closest?.(".ge-note-card"));
462
468
  const writing = () => Boolean(shown) && focused();
463
- // A new one that has held no words yet (`begun`, not `held`): no annotation until it is left, Esc
464
- // taking it back.
465
- const drafted = (id) => shown?.id === id && shown.begun && !shown.held;
469
+ // A new one with no words (made on the page, not saved yet, nothing typed but white space): no
470
+ // annotation yet: no marker, no count, no row; left so, it leaves nothing (close).
471
+ const drafted = (id) => made.has(id) && !(items.get(id)?.text ?? "").trim();
466
472
 
467
473
  // The annotation already on `selection` (the same words or blocks), or undefined.
468
474
  function sameAs(selection) {
@@ -533,7 +539,7 @@ export function createAnnotate({ slug, token, isEditing, picked, unpick = () =>
533
539
  if (closing) {
534
540
  event.preventDefault();
535
541
  event.stopPropagation();
536
- backToText({ drop: event.key === "Escape" && drafted(id) });
542
+ backToText();
537
543
  }
538
544
  });
539
545
  // A press in a card edits it, the caret where pressed (at the end of its text for a press beside the
@@ -604,7 +610,7 @@ export function createAnnotate({ slug, token, isEditing, picked, unpick = () =>
604
610
  if (!focus) return true;
605
611
  card.field.focus({ preventScroll: true });
606
612
  if (document.activeElement !== card.field) {
607
- if (made.has(id) && !item.text) {
613
+ if (drafted(id)) {
608
614
  items.delete(id);
609
615
  made.delete(id);
610
616
  dropView(id);
@@ -627,6 +633,15 @@ export function createAnnotate({ slug, token, isEditing, picked, unpick = () =>
627
633
  wake();
628
634
  }
629
635
 
636
+ // What 撤销 puts back of one going at the reader's word (its delete button, emptied and closed): as
637
+ // it is, or, emptied in its card, with the words the file last held; null when the file never had it.
638
+ function backOf(id) {
639
+ const item = items.get(id);
640
+ if (!item?.anchor) return null;
641
+ const text = item.text.trim() ? item.text : filed.get(id);
642
+ return text ? { ...wire(item), text } : null;
643
+ }
644
+
630
645
  // An annotation gone at the reader's word, from the page and the file (one never saved leaves nothing).
631
646
  function forget(id) {
632
647
  const item = items.get(id);
@@ -640,26 +655,30 @@ export function createAnnotate({ slug, token, isEditing, picked, unpick = () =>
640
655
  dropView(id);
641
656
  }
642
657
 
643
- // The card closes into its marker: what was typed saved at once, one with no words saved as it is
644
- // (a plain mark of its place). `drop`: it goes instead (its delete button, Esc on a new one). With
645
- // room it goes back among the others.
658
+ // The card closes into its marker: what was typed saved at once. One left with no words is none: it
659
+ // goes, from the page and the file, and one the file had is offered back as its delete button's is
660
+ // (`removed`, with its last words). `drop`: it goes whatever it says (its delete button, which offers
661
+ // it back itself). With room it goes back among the others.
646
662
  function close({ drop = false } = {}) {
647
663
  if (!shown) return;
648
664
  const { id } = shown;
649
665
  shown = null;
650
666
  const item = items.get(id);
651
- if (drop) forget(id);
652
- else if (item && (timers.has(id) || !item.anchor)) save(id);
667
+ if (item && (drop || !item.text.trim())) {
668
+ const back = drop ? null : backOf(id);
669
+ forget(id);
670
+ if (back) removed([back]);
671
+ } else if (item && (timers.has(id) || !item.anchor)) save(id);
653
672
  changed();
654
673
  wake();
655
674
  }
656
675
 
657
- // A card's delete button: its annotation goes at once, and the workbench offers it back. One never
658
- // saved leaves nothing to bring back.
676
+ // A card's delete button: its annotation goes at once, and the workbench offers it back (emptied in
677
+ // its card, with the words the file last held). One never saved leaves nothing to bring back.
659
678
  function erase(id) {
660
679
  const item = items.get(id);
661
680
  if (!item) return;
662
- const was = item.anchor ? wire(item) : null;
681
+ const was = backOf(id);
663
682
  if (shown?.id !== id) {
664
683
  forget(id);
665
684
  changed();
@@ -699,7 +718,6 @@ export function createAnnotate({ slug, token, isEditing, picked, unpick = () =>
699
718
  const was = drafted(id);
700
719
  item.text = field.value;
701
720
  item.updated = new Date().toISOString();
702
- if (item.text.trim() && shown?.id === id) shown.held = true;
703
721
  schedule(id);
704
722
  changed();
705
723
  if (!standing || was !== drafted(id)) wake();
@@ -824,7 +842,7 @@ export function createAnnotate({ slug, token, isEditing, picked, unpick = () =>
824
842
  const view = views.get(id);
825
843
  if (!view || drafted(id)) return false;
826
844
  const start = view.range?.startContainer ?? view.units[0];
827
- globalThis.DocKit.reveal(start.nodeType === 1 ? start : start.parentElement);
845
+ reveal(start.nodeType === 1 ? start : start.parentElement); // a folded heading's section too (fold/)
828
846
  remeasure = true; // what was hidden stands now, before the observer says so
829
847
  const line = lineOf(view);
830
848
  if (!line) return false;
@@ -896,7 +914,7 @@ export function createAnnotate({ slug, token, isEditing, picked, unpick = () =>
896
914
  const view = known ?? {};
897
915
  if (!found || (found.units?.length ?? 0) === 0) {
898
916
  // A new one with no words, not saved yet, is about nothing now: it goes with them, for no save to keep.
899
- if (made.has(id) && !item.anchor && !item.text) {
917
+ if (drafted(id) && !item.anchor) {
900
918
  forget(id);
901
919
  if (shown?.id === id) shown = null;
902
920
  continue;
@@ -946,16 +964,25 @@ export function createAnnotate({ slug, token, isEditing, picked, unpick = () =>
946
964
  }
947
965
 
948
966
  // The outermost closed disclosure `node` is hidden in (in its content, not its title, nor `node`
949
- // itself: it shows, as its title), or null.
967
+ // itself: it shows, as its title), or the folded heading whose section hides it (fold/: the
968
+ // outermost, the heading its own title), whichever holds the other; null where neither hides it.
950
969
  function closedAround(node) {
951
970
  const element = node?.nodeType === 1 ? node : node?.parentElement;
952
971
  let found = null;
953
972
  for (let details = element?.closest("details:not([open])"); details; details = details.parentElement?.closest("details:not([open])")) {
954
973
  if (details !== node && !details.querySelector(":scope > summary")?.contains(element)) found = details;
955
974
  }
956
- return found;
975
+ let marked = null;
976
+ for (let at = element?.closest("[data-ge-folded]"); at; at = at.parentElement?.closest("[data-ge-folded]")) marked = at;
977
+ const heading = marked && document.querySelector(`[data-ge-id="${CSS.escape(marked.getAttribute("data-ge-folded"))}"]`);
978
+ if (!heading) return found;
979
+ return found && found.contains(heading) ? found : heading;
957
980
  }
958
981
 
982
+ // What stands for a closed disclosure or a folded section (closedAround): the disclosure's title, or
983
+ // the heading itself, which has none.
984
+ const titleOf = (closed) => closed.querySelector(":scope > summary") ?? closed;
985
+
959
986
  // The first line of `node` (window coordinates): { top, height, left }: of its first words; where a
960
987
  // picture standing as a block comes before them, the picture's top (as the handle's first line,
961
988
  // handle/: not its caption, far from there); its box's top where it holds neither.
@@ -987,13 +1014,13 @@ export function createAnnotate({ slug, token, isEditing, picked, unpick = () =>
987
1014
  // holds), box (what it stands for as shown) }, or null when it does not show: its first line, or all
988
1015
  // of them for several blocks, from the first's top to the last's bottom, the marker at their middle.
989
1016
  // In a closed disclosure (laid out though hidden), its title's line: checked first, as the hidden
990
- // text still has boxes.
1017
+ // text still has boxes; in a folded heading's section (fold/), the heading's.
991
1018
  function lineOf(view) {
992
1019
  const start = view.range?.startContainer ?? view.units?.find((unit) => unit.isConnected);
993
1020
  if (!start?.isConnected) return null;
994
1021
  const closed = closedAround(start);
995
1022
  if (closed) {
996
- const summary = closed.querySelector(":scope > summary");
1023
+ const summary = titleOf(closed);
997
1024
  if (!summary?.getClientRects().length) return null;
998
1025
  const box = summary.getBoundingClientRect();
999
1026
  return { ...firstLine(summary), folded: true, box, bottom: box.bottom };
@@ -1074,13 +1101,13 @@ export function createAnnotate({ slug, token, isEditing, picked, unpick = () =>
1074
1101
  // What a card stands by (window coordinates), or null when it does not show: words, their box and
1075
1102
  // where their last line ends ({ words, top, left, right: the last character's, bottom: the last
1076
1103
  // line's }); blocks, theirs ({ top, bottom and right: the last one's }); in a closed disclosure (laid
1077
- // out though hidden), its title as a block.
1104
+ // out though hidden), its title as a block; in a folded heading's section, the heading.
1078
1105
  function anchorBox(target) {
1079
1106
  const start = target.range?.startContainer ?? target.units?.find((unit) => unit.isConnected);
1080
1107
  if (!start?.isConnected) return null;
1081
1108
  const closed = closedAround(start);
1082
1109
  if (closed) {
1083
- const summary = closed.querySelector(":scope > summary");
1110
+ const summary = titleOf(closed);
1084
1111
  if (!summary?.getClientRects().length) return null;
1085
1112
  const box = summary.getBoundingClientRect();
1086
1113
  return { top: box.top, bottom: box.bottom, right: box.right };
@@ -1379,7 +1406,7 @@ export function createAnnotate({ slug, token, isEditing, picked, unpick = () =>
1379
1406
  quiet = false;
1380
1407
 
1381
1408
  // A block anchor's blocks filled while it is shown, or its card in the margin is under the pointer;
1382
- // those in a closed disclosure, the disclosure.
1409
+ // those in a closed disclosure, the disclosure; in a folded section, its heading.
1383
1410
  const filled = views.get(shown?.id ?? (standing ? hot : null));
1384
1411
  fills.paint(filled && !filled.range && !filled.hidden ? ordered(filled.units.filter((unit) => unit.isConnected).map((unit) => closedAround(unit) ?? unit)) : []);
1385
1412
  paintMarks();
@@ -1562,7 +1589,7 @@ export function createAnnotate({ slug, token, isEditing, picked, unpick = () =>
1562
1589
  },
1563
1590
  };
1564
1591
 
1565
- /** How many annotations the page has (their words or blocks still there; a new one once left, or once it has words). */
1592
+ /** How many annotations the page has (their words or blocks still there; a new one once it has words). */
1566
1593
  const count = () => [...items.keys()].filter((id) => views.has(id) && !drafted(id)).length;
1567
1594
 
1568
1595
  provide("annotations", () => ({