@heycys/gallery 0.1.2 → 0.2.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 (338) hide show
  1. package/THIRD-PARTY-NOTICES.md +2 -2
  2. package/browser/editor/components/align.mjs +58 -0
  3. package/browser/editor/components/code/index.mjs +1 -1
  4. package/browser/editor/components/embed/page.mjs +1 -1
  5. package/browser/editor/components/file/page.mjs +4 -4
  6. package/browser/editor/components/heading/index.mjs +7 -6
  7. package/browser/editor/components/icon/page.mjs +6 -4
  8. package/browser/editor/components/icons.mjs +5 -2
  9. package/browser/editor/components/image/index.mjs +2 -0
  10. package/browser/editor/components/image/page.mjs +172 -90
  11. package/browser/editor/components/installed/index.mjs +6 -2
  12. package/browser/editor/components/installed/page.mjs +80 -13
  13. package/browser/editor/components/media/icons.mjs +13 -8
  14. package/browser/editor/components/media/page.mjs +5 -3
  15. package/browser/editor/components/media/toolbar.mjs +12 -3
  16. package/browser/editor/components/paragraph/index.mjs +4 -3
  17. package/browser/editor/components/registry.mjs +17 -5
  18. package/browser/editor/components/table/index.mjs +4 -2
  19. package/browser/editor/page/after/index.mjs +288 -0
  20. package/browser/editor/page/align.mjs +91 -0
  21. package/browser/editor/page/beside.mjs +5 -6
  22. package/browser/editor/page/block-menu/index.mjs +6 -3
  23. package/browser/editor/page/blocks.mjs +3 -1
  24. package/browser/editor/page/board/hint.mjs +64 -27
  25. package/browser/editor/page/board/index.mjs +160 -71
  26. package/browser/editor/page/board/motion.mjs +177 -0
  27. package/browser/editor/page/board/settings.mjs +4 -3
  28. package/browser/editor/page/clipboard/import/read.mjs +20 -2
  29. package/browser/editor/page/clipboard/index.mjs +10 -3
  30. package/browser/editor/page/clipboard/own/blocks.mjs +3 -4
  31. package/browser/editor/page/clipboard/own/describe.mjs +6 -2
  32. package/browser/editor/page/commit.mjs +2 -2
  33. package/browser/editor/page/core.mjs +3 -1
  34. package/browser/editor/page/custom-page.mjs +15 -11
  35. package/browser/editor/page/editor.mjs +31 -14
  36. package/browser/editor/page/history.mjs +19 -4
  37. package/browser/editor/page/insert/index.mjs +20 -22
  38. package/browser/editor/page/menu.mjs +15 -7
  39. package/browser/editor/page/page-objects.mjs +3 -7
  40. package/browser/editor/page/present-links.mjs +5 -4
  41. package/browser/editor/page/present-shell.mjs +63 -0
  42. package/browser/editor/page/selection/index.mjs +10 -2
  43. package/browser/editor/page/table/binding.mjs +87 -0
  44. package/browser/editor/page/table/icons.mjs +0 -2
  45. package/browser/editor/page/table/index.mjs +10 -14
  46. package/browser/editor/page/table/views.mjs +5 -52
  47. package/browser/editor/page/table/widths.mjs +82 -10
  48. package/browser/editor/page/typing/index.mjs +44 -12
  49. package/browser/editor/page/typing/leave.mjs +19 -5
  50. package/browser/shared/block-packs.mjs +23 -8
  51. package/browser/shared/component-catalog.mjs +15 -8
  52. package/browser/shared/component-source.mjs +3 -1
  53. package/browser/shared/components/heading.mjs +2 -1
  54. package/browser/shared/components/installed.mjs +1 -1
  55. package/browser/shared/components/page.mjs +2 -0
  56. package/browser/shared/components/paragraph.mjs +8 -1
  57. package/browser/shared/components/table.mjs +1 -0
  58. package/browser/shared/document-copy.mjs +43 -0
  59. package/browser/shared/drafts.mjs +10 -3
  60. package/browser/shared/emoji/icon-value.mjs +2 -2
  61. package/browser/shared/emoji/line-icons.mjs +37 -0
  62. package/browser/shared/extensions.mjs +83 -7
  63. package/browser/shared/http.mjs +9 -0
  64. package/browser/shared/i18n/en.mjs +50 -17
  65. package/browser/shared/outline-shape.mjs +6 -0
  66. package/browser/shared/outline.mjs +165 -12
  67. package/browser/shared/pack-manifest.mjs +12 -1
  68. package/browser/shared/pages.mjs +169 -57
  69. package/browser/shared/pinyin.mjs +92 -0
  70. package/browser/shared/present-step.mjs +17 -0
  71. package/browser/shared/sidebar-head.mjs +70 -0
  72. package/browser/shared/web-links.mjs +5 -0
  73. package/browser/shared/workspace-columns.mjs +11 -7
  74. package/dist/{chunk-N7AZZLGT.mjs → chunk-2GKGEVMR.mjs} +29 -24
  75. package/dist/chunk-2OHANJ6Q.mjs +2 -0
  76. package/dist/{chunk-HYMEEXKN.mjs → chunk-2RKIHJI2.mjs} +1 -1
  77. package/dist/{chunk-742D2WWJ.mjs → chunk-36FIRJIF.mjs} +2 -2
  78. package/dist/{chunk-BPL64HGA.mjs → chunk-3A5I2GJK.mjs} +1 -1
  79. package/dist/{chunk-RFDZXFJF.mjs → chunk-3OFXMN6N.mjs} +1 -1
  80. package/dist/chunk-46ACXOU5.mjs +2 -0
  81. package/dist/{chunk-PUOQ65NC.mjs → chunk-4AMTKWDO.mjs} +1 -1
  82. package/dist/{chunk-VTKNEYT3.mjs → chunk-4DNHHJSL.mjs} +1 -1
  83. package/dist/chunk-5DPABPBI.mjs +2 -0
  84. package/dist/chunk-5IIH335D.mjs +3 -0
  85. package/dist/chunk-5L26JUYA.mjs +2 -0
  86. package/dist/{chunk-3NJACR4W.mjs → chunk-5MEXZ2UF.mjs} +1 -1
  87. package/dist/{chunk-ZHEHPMBK.mjs → chunk-6MPKCH3P.mjs} +1 -1
  88. package/dist/{chunk-C564NU2H.mjs → chunk-74RPP2M2.mjs} +1 -1
  89. package/dist/chunk-7M2BQQGZ.mjs +2 -0
  90. package/dist/{chunk-VXACTLO3.mjs → chunk-7M7UPWU6.mjs} +1 -1
  91. package/dist/{chunk-ZB4H7ZN4.mjs → chunk-7N2LPG33.mjs} +1 -1
  92. package/dist/{chunk-UBBRTJ2R.mjs → chunk-7XDYK3UC.mjs} +1 -1
  93. package/dist/chunk-AEMVZYZQ.mjs +166 -0
  94. package/dist/{chunk-POQSE4C2.mjs → chunk-AFGUR7SY.mjs} +1 -1
  95. package/dist/{chunk-QKXMPUXC.mjs → chunk-AMDGVDNV.mjs} +1 -1
  96. package/dist/{chunk-KTKHRC6H.mjs → chunk-ASAXY2DJ.mjs} +1 -1
  97. package/dist/{chunk-NVRNLK25.mjs → chunk-BYSF5UMM.mjs} +2 -2
  98. package/dist/{chunk-U3SSPL4K.mjs → chunk-CCSGFCLZ.mjs} +1 -1
  99. package/dist/{chunk-NWFBE2YA.mjs → chunk-CG3UHDKH.mjs} +1 -1
  100. package/dist/chunk-CPS4SRPF.mjs +5 -0
  101. package/dist/{chunk-B4P2CM2J.mjs → chunk-CZ5KJSGK.mjs} +1 -1
  102. package/dist/chunk-DAMVDXR3.mjs +2 -0
  103. package/dist/{chunk-NG375ILQ.mjs → chunk-DH6GMDNN.mjs} +1 -1
  104. package/dist/chunk-DHB7UZ7F.mjs +3 -0
  105. package/dist/{chunk-MHW7ZKOU.mjs → chunk-DKR7LFIY.mjs} +1 -1
  106. package/dist/chunk-DLFZJJEE.mjs +2 -0
  107. package/dist/{chunk-6EZ7FNIK.mjs → chunk-F4ZA6JRZ.mjs} +1 -1
  108. package/dist/{chunk-6VTU6KEO.mjs → chunk-FCK6NXON.mjs} +1 -1
  109. package/dist/{chunk-ZWPMCK7P.mjs → chunk-FX42XU6J.mjs} +1 -1
  110. package/dist/chunk-FXQBADMN.mjs +5 -0
  111. package/dist/{chunk-W3BGBJQW.mjs → chunk-G4YP7GVC.mjs} +1 -1
  112. package/dist/{chunk-V6XZ4VIR.mjs → chunk-GWOYMENX.mjs} +1 -1
  113. package/dist/chunk-HATA2W7X.mjs +2 -0
  114. package/dist/{chunk-YI43RG4P.mjs → chunk-HBAUKKQH.mjs} +1 -1
  115. package/dist/{chunk-MAFIGVXY.mjs → chunk-HM4E43VM.mjs} +1 -1
  116. package/dist/{chunk-CRJEG7MT.mjs → chunk-JI6T3A4Y.mjs} +1 -1
  117. package/dist/{chunk-NFMCP2HI.mjs → chunk-JJNRIFND.mjs} +2 -2
  118. package/dist/chunk-JL6R4FG4.mjs +4 -0
  119. package/dist/{chunk-UMHUSOPJ.mjs → chunk-JXLSHVJ2.mjs} +1 -1
  120. package/dist/{chunk-FJYN7RTH.mjs → chunk-KFZBYDIS.mjs} +1 -1
  121. package/dist/{chunk-ZTHICSSF.mjs → chunk-KH24LWAT.mjs} +1 -1
  122. package/dist/{chunk-RKPWLGZ3.mjs → chunk-KUILYI7H.mjs} +1 -1
  123. package/dist/{chunk-RMECZA2K.mjs → chunk-L7W624FD.mjs} +1 -1
  124. package/dist/chunk-LE44MD3O.mjs +4 -0
  125. package/dist/{chunk-4K5KC6V2.mjs → chunk-LV24RY2E.mjs} +1 -1
  126. package/dist/{chunk-43B75J5T.mjs → chunk-MKTX5PGV.mjs} +1 -1
  127. package/dist/{chunk-LKX55H76.mjs → chunk-NAGMRVW4.mjs} +1 -1
  128. package/dist/{chunk-D4CKRD3V.mjs → chunk-NFABH3QW.mjs} +2 -2
  129. package/dist/{chunk-PVER7LSC.mjs → chunk-NIW7F7LU.mjs} +2 -2
  130. package/dist/{chunk-PAREWQGB.mjs → chunk-NWRZXELO.mjs} +1 -1
  131. package/dist/{chunk-OJKMINIU.mjs → chunk-OU3S466R.mjs} +15 -15
  132. package/dist/{chunk-5ZJA7CXT.mjs → chunk-PAFSFVYB.mjs} +1 -1
  133. package/dist/chunk-QCEATQC4.mjs +2 -0
  134. package/dist/{chunk-Y34NR5JL.mjs → chunk-QJ3TFJLQ.mjs} +1 -1
  135. package/dist/{chunk-IA4PSIMD.mjs → chunk-QK3VISCA.mjs} +1 -1
  136. package/dist/{chunk-ZUNVAXLH.mjs → chunk-QXVNUASA.mjs} +1 -1
  137. package/dist/{chunk-GRAXKKG4.mjs → chunk-QZ35UAB4.mjs} +1 -1
  138. package/dist/{chunk-UGWYKHBL.mjs → chunk-S2Y7VI4H.mjs} +2 -2
  139. package/dist/{chunk-OW5NWPOJ.mjs → chunk-SAHS56QM.mjs} +1 -1
  140. package/dist/{chunk-QOUEFUCH.mjs → chunk-SOD23RGL.mjs} +1 -1
  141. package/dist/chunk-TDWJKOLN.mjs +2 -0
  142. package/dist/{chunk-V6RIYQZZ.mjs → chunk-TOE6DPLH.mjs} +1 -1
  143. package/dist/chunk-UGO5N3EI.mjs +15 -0
  144. package/dist/{chunk-Q47PLKIJ.mjs → chunk-UGWMMEJ5.mjs} +1 -1
  145. package/dist/{chunk-NWR2LT5B.mjs → chunk-V5JRSGZF.mjs} +1 -1
  146. package/dist/{chunk-BZ5RAF7L.mjs → chunk-VA3KAQZD.mjs} +1 -1
  147. package/dist/chunk-VG5JEIUQ.mjs +12 -0
  148. package/dist/{chunk-UNOYVIYR.mjs → chunk-VGTMLQWZ.mjs} +1 -1
  149. package/dist/chunk-VKSRM7EY.mjs +22 -0
  150. package/dist/{chunk-YQGT4AB2.mjs → chunk-VNUWREXU.mjs} +1 -1
  151. package/dist/{chunk-AGDILNWB.mjs → chunk-VPVOAJ7X.mjs} +1 -1
  152. package/dist/{chunk-HLYV7RIH.mjs → chunk-WCWYNFDF.mjs} +1 -1
  153. package/dist/chunk-WTEGUPFG.mjs +16 -0
  154. package/dist/{chunk-N76HWBA3.mjs → chunk-XKOHV4H6.mjs} +1 -1
  155. package/dist/{chunk-HMYTM3GT.mjs → chunk-XMKHCUI6.mjs} +1 -1
  156. package/dist/{chunk-OUUP3WKT.mjs → chunk-XQRUG4G3.mjs} +1 -1
  157. package/dist/{chunk-32ZUEFZ7.mjs → chunk-YBB5LWZK.mjs} +1 -1
  158. package/dist/{chunk-SX4LJYT6.mjs → chunk-YFJU3O7G.mjs} +1 -1
  159. package/dist/chunk-YPPJVDQI.mjs +2 -0
  160. package/dist/chunk-ZANMKAWS.mjs +2 -0
  161. package/dist/{chunk-6QBHU4DF.mjs → chunk-ZCP7BTOZ.mjs} +1 -1
  162. package/dist/{chunk-ERLAIBOA.mjs → chunk-ZEY2RLBT.mjs} +2 -2
  163. package/dist/{chunk-SQ6Y2ZMA.mjs → chunk-ZO7SFB2E.mjs} +2 -2
  164. package/dist/cli.mjs +1 -1
  165. package/dist/server.mjs +1 -1
  166. package/dist/worker.mjs +1 -1
  167. package/kit/board.css +5 -5
  168. package/kit/code.js +15 -15
  169. package/kit/math.js +1 -1
  170. package/kit/report.css +123 -44
  171. package/kit/runtime.js +45 -7
  172. package/kit/tables.js +2 -0
  173. package/kit/ui.js +2 -0
  174. package/package.json +1 -1
  175. package/packs/gallery/chart-view/kit.js +3 -3
  176. package/packs/gallery/chart-view/writing.md +1 -1
  177. package/packs/gallery/countdown/component.json +1 -1
  178. package/packs/gallery/countdown/kit.js +89 -29
  179. package/packs/gallery/countdown/preview.svg +1 -1
  180. package/packs/gallery/countdown/style.css +88 -100
  181. package/packs/gallery/countdown/writing.md +2 -2
  182. package/packs/gallery/habit/component.json +3 -3
  183. package/packs/gallery/habit/kit.js +114 -75
  184. package/packs/gallery/habit/preview.svg +1 -1
  185. package/packs/gallery/habit/style.css +133 -205
  186. package/packs/gallery/habit/writing.md +2 -2
  187. package/packs/gallery/heatmap/component.json +2 -2
  188. package/packs/gallery/heatmap/kit.js +335 -173
  189. package/packs/gallery/heatmap/preview.svg +1 -1
  190. package/packs/gallery/heatmap/style.css +158 -170
  191. package/packs/gallery/heatmap/writing.md +2 -2
  192. package/packs/gallery/kanban/kit.js +3 -3
  193. package/packs/gallery/kanban/writing.md +1 -1
  194. package/packs/gallery/metric/kit.js +3 -3
  195. package/packs/gallery/metric/writing.md +1 -1
  196. package/packs/gallery/note/component.json +3 -3
  197. package/packs/gallery/note/kit.js +40 -13
  198. package/packs/gallery/note/preview.svg +1 -1
  199. package/packs/gallery/note/style.css +51 -30
  200. package/packs/gallery/note/writing.md +2 -2
  201. package/packs/gallery/recent/component.json +2 -2
  202. package/packs/gallery/recent/kit.js +141 -86
  203. package/packs/gallery/recent/preview.svg +1 -1
  204. package/packs/gallery/recent/style.css +53 -126
  205. package/packs/gallery/recent/writing.md +2 -2
  206. package/packs/gallery/static/component.json +2 -2
  207. package/packs/gallery/static/preview.svg +1 -1
  208. package/packs/gallery/static/style.css +99 -66
  209. package/packs/gallery/static/writing.md +2 -2
  210. package/packs/gallery/stats/component.json +3 -3
  211. package/packs/gallery/stats/kit.js +253 -72
  212. package/packs/gallery/stats/preview.svg +1 -1
  213. package/packs/gallery/stats/style.css +64 -142
  214. package/packs/gallery/stats/writing.md +2 -2
  215. package/packs/gallery/today/component.json +2 -2
  216. package/packs/gallery/today/kit.js +62 -27
  217. package/packs/gallery/today/preview.svg +1 -1
  218. package/packs/gallery/today/style.css +101 -72
  219. package/packs/gallery/today/writing.md +2 -2
  220. package/packs/gallery/todos/component.json +1 -1
  221. package/packs/gallery/todos/kit.js +218 -71
  222. package/packs/gallery/todos/preview.svg +1 -1
  223. package/packs/gallery/todos/style.css +170 -223
  224. package/packs/gallery/todos/writing.md +1 -1
  225. package/packs/gallery/weather/component.json +2 -2
  226. package/packs/gallery/weather/kit.js +165 -90
  227. package/packs/gallery/weather/preview.svg +1 -1
  228. package/packs/gallery/weather/style.css +100 -218
  229. package/packs/gallery/weather/writing.md +1 -1
  230. package/packs/gallery-soft/countdown/component.json +18 -0
  231. package/packs/gallery-soft/countdown/example.html +3 -0
  232. package/packs/gallery-soft/countdown/kit.js +206 -0
  233. package/packs/gallery-soft/countdown/preview.svg +1 -0
  234. package/packs/gallery-soft/countdown/style.css +211 -0
  235. package/packs/gallery-soft/countdown/template.html +3 -0
  236. package/packs/gallery-soft/countdown/writing.md +24 -0
  237. package/packs/gallery-soft/habit/component.json +14 -0
  238. package/packs/gallery-soft/habit/example.html +3 -0
  239. package/packs/gallery-soft/habit/kit.js +366 -0
  240. package/packs/gallery-soft/habit/preview.svg +1 -0
  241. package/packs/gallery-soft/habit/style.css +251 -0
  242. package/packs/gallery-soft/habit/template.html +3 -0
  243. package/packs/gallery-soft/habit/writing.md +23 -0
  244. package/packs/gallery-soft/heatmap/component.json +18 -0
  245. package/packs/gallery-soft/heatmap/example.html +3 -0
  246. package/packs/gallery-soft/heatmap/kit.js +498 -0
  247. package/packs/gallery-soft/heatmap/preview.svg +1 -0
  248. package/packs/gallery-soft/heatmap/style.css +181 -0
  249. package/packs/gallery-soft/heatmap/template.html +3 -0
  250. package/packs/gallery-soft/heatmap/writing.md +23 -0
  251. package/packs/gallery-soft/note/component.json +14 -0
  252. package/packs/gallery-soft/note/example.html +3 -0
  253. package/packs/gallery-soft/note/kit.js +162 -0
  254. package/packs/gallery-soft/note/preview.svg +1 -0
  255. package/packs/gallery-soft/note/style.css +148 -0
  256. package/packs/gallery-soft/note/template.html +3 -0
  257. package/packs/gallery-soft/note/writing.md +20 -0
  258. package/packs/gallery-soft/recent/component.json +13 -0
  259. package/packs/gallery-soft/recent/example.html +1 -0
  260. package/packs/gallery-soft/recent/kit.js +335 -0
  261. package/packs/gallery-soft/recent/preview.svg +1 -0
  262. package/packs/gallery-soft/recent/style.css +160 -0
  263. package/packs/gallery-soft/recent/template.html +1 -0
  264. package/packs/gallery-soft/recent/writing.md +17 -0
  265. package/packs/gallery-soft/static/component.json +13 -0
  266. package/packs/gallery-soft/static/example.html +12 -0
  267. package/packs/gallery-soft/static/preview.svg +1 -0
  268. package/packs/gallery-soft/static/style.css +186 -0
  269. package/packs/gallery-soft/static/template.html +1 -0
  270. package/packs/gallery-soft/static/writing.md +20 -0
  271. package/packs/gallery-soft/stats/component.json +13 -0
  272. package/packs/gallery-soft/stats/example.html +1 -0
  273. package/packs/gallery-soft/stats/kit.js +341 -0
  274. package/packs/gallery-soft/stats/preview.svg +1 -0
  275. package/packs/gallery-soft/stats/style.css +119 -0
  276. package/packs/gallery-soft/stats/template.html +1 -0
  277. package/packs/gallery-soft/stats/writing.md +13 -0
  278. package/packs/gallery-soft/today/component.json +12 -0
  279. package/packs/gallery-soft/today/example.html +1 -0
  280. package/packs/gallery-soft/today/kit.js +222 -0
  281. package/packs/gallery-soft/today/preview.svg +1 -0
  282. package/packs/gallery-soft/today/style.css +178 -0
  283. package/packs/gallery-soft/today/template.html +1 -0
  284. package/packs/gallery-soft/today/writing.md +16 -0
  285. package/packs/gallery-soft/todos/component.json +19 -0
  286. package/packs/gallery-soft/todos/example.html +3 -0
  287. package/packs/gallery-soft/todos/kit.js +527 -0
  288. package/packs/gallery-soft/todos/preview.svg +1 -0
  289. package/packs/gallery-soft/todos/style.css +212 -0
  290. package/packs/gallery-soft/todos/template.html +3 -0
  291. package/packs/gallery-soft/todos/writing.md +32 -0
  292. package/packs/gallery-soft/weather/component.json +19 -0
  293. package/packs/gallery-soft/weather/example.html +3 -0
  294. package/packs/gallery-soft/weather/kit.js +411 -0
  295. package/packs/gallery-soft/weather/preview.svg +1 -0
  296. package/packs/gallery-soft/weather/style.css +185 -0
  297. package/packs/gallery-soft/weather/template.html +3 -0
  298. package/packs/gallery-soft/weather/writing.md +28 -0
  299. package/release.json +10 -10
  300. package/skill/SKILL.md +15 -14
  301. package/skill/references/building-blocks.md +4 -4
  302. package/skill/references/extensions.md +11 -7
  303. package/skill/references/pages-and-data.md +13 -9
  304. package/skill/references/writing-html.md +2 -0
  305. package/web/assets/index-BHC5ZOMh.js +15 -0
  306. package/web/assets/index-xP0uw3a0.css +1 -0
  307. package/web/index.html +2 -2
  308. package/dist/chunk-2NRBY6AJ.mjs +0 -2
  309. package/dist/chunk-35NQ4PLQ.mjs +0 -2
  310. package/dist/chunk-3KJHLHUO.mjs +0 -2
  311. package/dist/chunk-4AV456RQ.mjs +0 -2
  312. package/dist/chunk-5XYHDBJ5.mjs +0 -2
  313. package/dist/chunk-6A53MZYZ.mjs +0 -2
  314. package/dist/chunk-6EXH3ORZ.mjs +0 -166
  315. package/dist/chunk-BVEFGE4B.mjs +0 -2
  316. package/dist/chunk-D4EURAX4.mjs +0 -4
  317. package/dist/chunk-DQCE7TJY.mjs +0 -5
  318. package/dist/chunk-FWNRPMCJ.mjs +0 -12
  319. package/dist/chunk-FWW4CSAZ.mjs +0 -2
  320. package/dist/chunk-GY3FAUVM.mjs +0 -2
  321. package/dist/chunk-JVHHHGEA.mjs +0 -3
  322. package/dist/chunk-L7UP52JO.mjs +0 -2
  323. package/dist/chunk-NAMN3RAF.mjs +0 -2
  324. package/dist/chunk-PZDLJJTJ.mjs +0 -3
  325. package/dist/chunk-SXHBYZST.mjs +0 -16
  326. package/dist/chunk-TEZAWDSQ.mjs +0 -2
  327. package/dist/chunk-UFNYFFKO.mjs +0 -20
  328. package/dist/chunk-UKSHDZZ6.mjs +0 -2
  329. package/dist/chunk-VJPFVNNW.mjs +0 -15
  330. package/dist/chunk-VS3ZMVGX.mjs +0 -5
  331. package/web/assets/index-BK2e_07w.js +0 -13
  332. package/web/assets/index-CWFI83mF.css +0 -1
  333. /package/dist/{chunk-YEY3RSFQ.mjs → chunk-5MMN3N5J.mjs} +0 -0
  334. /package/dist/{chunk-UH4SIXTR.mjs → chunk-74UW7QSL.mjs} +0 -0
  335. /package/dist/{chunk-W7XHE4CT.mjs → chunk-EKGYYOSP.mjs} +0 -0
  336. /package/dist/{chunk-QAIHRH3I.mjs → chunk-KNZJT4ET.mjs} +0 -0
  337. /package/dist/{chunk-A55HN5OK.mjs → chunk-N3DSBH5S.mjs} +0 -0
  338. /package/dist/{chunk-QR6A54KJ.mjs → chunk-ZW2A6GBW.mjs} +0 -0
@@ -11,7 +11,8 @@ import { t } from "../../../shared/i18n/index.mjs";
11
11
 
12
12
  // A table's column widths (notion-lite's: a 3px strip on each column's right edge; the plan's D4:
13
13
  // the kit's own widths until the reader sizes a column). Dragging a strip sizes its column (35px at
14
- // least, nothing snapped), shown as it goes (Esc puts it back), written when let go as one undo
14
+ // least; the last one's, the table's right edge, snaps where the table is exactly as wide as the
15
+ // text: SNAP), shown as it goes (Esc puts it back), written when let go as one undo
15
16
  // step: every column's width on the topmost cell of that column alone (--doc-column-width,
16
17
  // index.mjs COLUMN_WIDTH; shared/table-slots.mjs widthHolder: a merged cell holds none), the kit laying the table
17
18
  // out at them (tables/layout.js manualLayout); the first
@@ -50,6 +51,8 @@ const STYLE = `
50
51
  .ge-trows > b > svg { width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; transform: rotate(90deg); }
51
52
  ${gestureLock("data-ge-tresize", { cursor: "col-resize", select: true })}
52
53
  `;
54
+ const SNAP = 6; // px: the last column's edge within this of the width that fills the text lands on it (as the resize tool's: resize/)
55
+ const LIVE = 60000; // ms: the notice saying the table is full stays while the drag lasts (taken off when it ends)
53
56
  const DOUBLE = 500; // two presses on a strip within this many ms are a double click (a press on the armed edge after its click too)
54
57
  const EDGE = 8; // the edges' strips reach this far past the table (the resize tool's grab)
55
58
  const ARROWS = '<svg viewBox="0 0 12 12" aria-hidden="true"><path d="M1.5 6h9M3.5 4 1.5 6l2 2M8.5 4l2 2-2 2"/></svg>';
@@ -62,8 +65,29 @@ export function createColumnWidths(tools) {
62
65
  let armed = null; // an edge clicked: { unit, axis: "x" (right) | "y" (bottom), at: when, shown }, the next drag of it the table's size
63
66
  let quick = null; // the armed right edge pressed soon after its click: { unit, index, x } (let go there, a double click)
64
67
 
65
- /** Each column's width as the table shows it now, px. */
66
- const shown = (unit) => tools.geometry(unit).columns.map((column) => Math.round((column.right - column.left) * 100) / 100);
68
+ /**
69
+ * Each column's width as the table shows it now, px: the width of its cells, not the distance
70
+ * between their edges. A table scrolled sideways keeps its first column in sight (position: sticky,
71
+ * tables.css: a header column or .doc-table--sticky-first), so the edges of those cells are not the
72
+ * columns' and the column under them would read as the part of it in sight: every width then sums
73
+ * to the frame's, the table seeming full, the columns before the border squeezed when it was pressed.
74
+ */
75
+ const shown = (unit) => {
76
+ const { slots } = tableState(unit);
77
+ if (!slots) return tools.geometry(unit).columns.map((column) => Math.round((column.right - column.left) * 100) / 100);
78
+ const cells = [...slots.places].map(([cell, place]) => ({ ...place, width: cell.getBoundingClientRect().width }));
79
+ const widths = Array(slots.columns).fill(null);
80
+ for (const { c, cols, width } of cells) if (cols === 1) widths[c] ??= width;
81
+ // A column no single cell gives a width: what the cells merged over it leave, shared out.
82
+ for (const { c, cols, width } of cells.filter((cell) => cell.cols > 1).sort((a, b) => a.cols - b.cols)) {
83
+ const over = Array.from({ length: cols }, (_, i) => c + i);
84
+ const open = over.filter((i) => widths[i] === null);
85
+ if (open.length === 0) continue;
86
+ const left = Math.max(0, width - over.reduce((sum, i) => sum + (widths[i] ?? 0), 0));
87
+ for (const i of open) widths[i] = left / open.length;
88
+ }
89
+ return widths.map((width) => Math.round((width ?? 0) * 100) / 100);
90
+ };
67
91
  /** The cells holding the columns' widths: per column, its topmost cell alone, or null. */
68
92
  const holders = (unit) => {
69
93
  const { slots } = tableState(unit);
@@ -101,20 +125,56 @@ export function createColumnWidths(tools) {
101
125
  return done;
102
126
  }
103
127
 
104
- // Shown as it goes: the holders' widths set straight (taken back before the undo step).
105
- function preview(unit, widths) {
128
+ // Shown as it goes: the holders' widths set straight (taken back before the undo step), the
129
+ // table's own width (--doc-span) off while it lasts, as the kit would else keep the columns in
130
+ // proportion to it and the table where it was.
131
+ function preview(drag, widths) {
132
+ const { unit } = drag;
133
+ if (drag.span === undefined) {
134
+ drag.span = unit.style.getPropertyValue(SPAN);
135
+ unit.style.removeProperty(SPAN);
136
+ }
106
137
  holders(unit).forEach((cell, c) => cell?.style.setProperty(COLUMN_WIDTH, `${widths[c]}px`));
107
138
  relayout(unit);
108
139
  }
109
- function putBack({ unit, before }) {
140
+ function putBack({ unit, before, span }) {
110
141
  for (const [cell, width] of before) {
111
142
  if (width) cell.style.setProperty(COLUMN_WIDTH, width);
112
143
  else cell.style.removeProperty(COLUMN_WIDTH);
113
144
  if (cell.getAttribute("style") === "") cell.removeAttribute("style");
114
145
  }
146
+ if (span) unit.style.setProperty(SPAN, span);
115
147
  relayout(unit);
116
148
  }
117
149
 
150
+ // The columns' widths together (px) at which the table is exactly as wide as the text (or the
151
+ // column it stands in): the room its frame has, as the kit lays a table out at the reader's widths
152
+ // (tables/layout.js manualLayout: a table of that width or more has the frame at 100%, one less
153
+ // a frame as wide as it). Null where the frame has none.
154
+ function fillOf(unit) {
155
+ const parent = unit.parentElement;
156
+ if (!parent) return null;
157
+ const sides = (node) => {
158
+ const style = getComputedStyle(node);
159
+ return ["borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight"].reduce((sum, name) => sum + (parseFloat(style[name]) || 0), 0);
160
+ };
161
+ const room = parent.getBoundingClientRect().width - sides(parent) - sides(unit);
162
+ return room > 0 ? room : null;
163
+ }
164
+
165
+ // The last column's right edge is the table's: within SNAP of the width that fills the text, the
166
+ // last column takes what the others leave of it (rounded down: never a hair past the frame).
167
+ // True when it did. `widths` is changed in place.
168
+ function snapFull({ last, fill, start, index }, widths) {
169
+ if (!last || fill === null) return false;
170
+ const rest = start.reduce((sum, width, c) => (c === index ? sum : sum + width), 0);
171
+ const wanted = Math.floor((fill - rest) * 100) / 100;
172
+ if (wanted < MIN_COLUMN_WIDTH || Math.abs(rest + widths[index] - fill) > SNAP) return false;
173
+ widths[index] = wanted;
174
+ return true;
175
+ }
176
+ const FULL = () => [t("表格"), t("宽度"), t("铺满正文")];
177
+
118
178
  // A column fitted to its widest cell of it alone, unwrapped (+1px): by its words, not the words an
119
179
  // Agent took out that the page shows in it (changes/: out of the layout while it is measured).
120
180
  function fit(unit, index) {
@@ -221,7 +281,7 @@ export function createColumnWidths(tools) {
221
281
  return fit(unit, index);
222
282
  }
223
283
  const { rows } = tableParts(unit);
224
- drag = { unit, index, x: event.clientX, last, fresh: true, start: shown(unit), before: new Map(rows.flatMap((row) => [...row.cells]).map((cell) => [cell, widthOf(cell)])) };
284
+ drag = { unit, index, x: event.clientX, last, fill: last ? fillOf(unit) : null, told: false, fresh: true, start: shown(unit), before: new Map(rows.flatMap((row) => [...row.cells]).map((cell) => [cell, widthOf(cell)])) };
225
285
  document.documentElement.setAttribute("data-ge-tresize", "");
226
286
  document.documentElement.setPointerCapture?.(event.pointerId);
227
287
  });
@@ -262,8 +322,16 @@ export function createColumnWidths(tools) {
262
322
  drag.moved = true;
263
323
  const widths = [...drag.start];
264
324
  widths[drag.index] = Math.max(MIN_COLUMN_WIDTH, Math.round(drag.start[drag.index] + event.clientX - drag.x));
325
+ // The last column's edge snaps to the table that fills the text; the bottom notice says so while it holds.
326
+ const snapped = snapFull(drag, widths);
265
327
  drag.widths = widths;
266
- preview(drag.unit, widths);
328
+ drag.snapped = snapped;
329
+ preview(drag, widths);
330
+ if (snapped !== drag.told) {
331
+ drag.told = snapped;
332
+ if (snapped) tools.say(t("{0}{1}:{2}", ...FULL()), "note", LIVE);
333
+ else tools.settle();
334
+ }
267
335
  tools.draw();
268
336
  }, true);
269
337
 
@@ -273,9 +341,13 @@ export function createColumnWidths(tools) {
273
341
  document.documentElement.removeAttribute("data-ge-tresize");
274
342
  if (!done) return;
275
343
  putBack(done);
276
- if (!cancel && done.widths) set(done.unit, done.widths);
344
+ if (done.told) tools.settle(); // the notice of the table filling the text: the result's follows, or nothing
345
+ // Back at the widths it had, snapped to a table that was full already (or dragged out and back): nothing to write.
346
+ const unchanged = done.widths?.every((width, c) => Math.abs(width - done.start[c]) < 0.5);
347
+ if (!cancel && done.widths) {
348
+ if (!unchanged && set(done.unit, done.widths) && done.snapped) tools.say(t("已调整{0}{1}:{2} · Ctrl+Z 撤销", ...FULL()));
277
349
  // The last strip clicked (pressed, not moved): the table's right edge armed.
278
- else if (!cancel && done.last) return arm(done.unit, "x");
350
+ } else if (!cancel && done.last) return arm(done.unit, "x");
279
351
  tools.draw();
280
352
  }
281
353
  document.addEventListener("pointerup", () => end(false), true);
@@ -7,6 +7,7 @@ import { joinCode } from "../marks.mjs";
7
7
  import { numberWithUnit, sideOf, WORD } from "../../../shared/inline-spacing.mjs";
8
8
  import { pageOf, pagesAround } from "../page-objects.mjs";
9
9
  import { BLOCK_TYPES, HOSTS, accepts, firstSaysOf, placeholderOf, textFilters, textTypeOf } from "../../components/registry.mjs";
10
+ import { unalign } from "../align.mjs";
10
11
  import { t } from "../../../shared/i18n/index.mjs";
11
12
 
12
13
  // Typing in a block (docs/editor.md, "Browser side"): every key goes first to the component the block
@@ -14,7 +15,7 @@ import { t } from "../../../shared/i18n/index.mjs";
14
15
  // `if (!ctx.def.keys?.enter?.(ctx)) splitBlock(...)`, and then to the rules of every block. Enter
15
16
  // splits it, Backspace and Delete at its edges merge it with the block before or after, or remove it
16
17
  // once empty, the caret going to the neighbouring block. Backspace in a container with nothing
17
- // written in it (`removedEmpty`) deletes the container. Chinese typed next to a Latin letter or
18
+ // written in it (`removedEmpty`) or in an empty heading turns it into an empty paragraph. Chinese typed next to a Latin letter or
18
19
  // digit gets a space between them (autoSpace; not a number and its unit, nor in a block written without), and an empty block under the caret says what it takes
19
20
  // (placeholder). Plain typing and input methods stay with the browser; the keys are routed here by
20
21
  // editor.mjs.
@@ -53,8 +54,11 @@ function writtenTogether(host, node, start, end) {
53
54
  * deleted as the selected ones are (selection/delete.mjs). adding(): the block the "/" menu the
54
55
  * handle's "+" opened is open in (slash-menu/), or null. leave: where Enter and Backspace leave a
55
56
  * container (leave.mjs). showHidden(node): the folds hiding a block opened (fold/ showAround).
57
+ * look(element, change): the editor's undoable change of classes (a block's alignment, align.mjs).
58
+ * afterAbove(host): Backspace at the start of a text block right after a block of no text, the caret
59
+ * put after that block (after/ back); whether it was.
56
60
  */
57
- export function createTyping({ struct, say, keepText, paragraphBefore, removeBlocks, selectBlock = () => {}, adding = () => null, leave, showHidden = () => {} }) {
61
+ export function createTyping({ struct, say, keepText, paragraphBefore, removeBlocks, selectBlock = () => {}, adding = () => null, leave, showHidden = () => {}, look = () => false, afterAbove = () => false }) {
58
62
  // A key, asked of the component of the text block `host` and then of what stands around it, nearest
59
63
  // first (docs/editor.md, "The order of keys"): whether it was theirs. `ctx` is notion-lite's, as
60
64
  // much of it as a key reads, the block being an element here.
@@ -101,8 +105,8 @@ export function createTyping({ struct, say, keepText, paragraphBefore, removeBlo
101
105
  function split(host) {
102
106
  if (HOSTS[host.getAttribute("data-ge-kind")]?.opensBody) return enterBody(host);
103
107
  // The caret at the very start of a block with text: an empty paragraph goes before the block and
104
- // the caret stays (a block that splits does this itself, splitBlock). This comes first: in a code
105
- // block too, whose own Enter breaks the line.
108
+ // the caret stays (a block that splits does this itself, splitBlock). Only hosts that opt in take
109
+ // this rule; code keeps its own Enter, which breaks the line even at the start.
106
110
  const own = HOSTS[host.getAttribute("data-ge-kind")]?.opensBefore; // not a cell, a card's field, the title
107
111
  if (own && !can(host, "split") && !isEmpty(host) && atEdge(host, false) && paragraphBefore(host)) return;
108
112
  // Its component's Enter (a code block's line, a nested item out a level, a title going into its
@@ -152,10 +156,33 @@ export function createTyping({ struct, say, keepText, paragraphBefore, removeBlo
152
156
  return true;
153
157
  }
154
158
 
155
- // An empty container deleted whole (one undo step, which selects it again); the caret at the end of
156
- // the block before it, or at the start of the one after it when it was first (a formula block passed
157
- // over: textNear).
159
+ // Whether a block may not go (keepText): the reason said, a note that stays a while.
160
+ function kept(node) {
161
+ const reason = keepText(node);
162
+ if (reason) say(reason, "note", 6000);
163
+ return Boolean(reason);
164
+ }
165
+
166
+ // An empty container turned into an empty paragraph where it stands, the caret in it (the user's,
167
+ // 2026-11-09: as an empty heading, an empty item and every other empty block go back to body text,
168
+ // not away with the caret on the block before); one undo step, which brings the container back.
169
+ // Where its box takes no paragraph it is deleted whole (one undo step, which selects it again), the
170
+ // caret at the end of the block before it, or at the start of the one after it when it was first (a
171
+ // formula block passed over: textNear).
158
172
  function removeContainer(container) {
173
+ const box = container.parentElement;
174
+ const paragraph = newParagraphHost(document);
175
+ if (box && accepts(boxKind(box), paragraph.getAttribute("data-ge-type"))) {
176
+ if (kept(container)) return true;
177
+ const parts = withLeads(container);
178
+ struct([box], [], () => {
179
+ parts[0].before(paragraph);
180
+ parts.forEach((part) => part.remove());
181
+ return { touched: [paragraph], focus: paragraph };
182
+ });
183
+ caretAt(paragraph, "start");
184
+ return true;
185
+ }
159
186
  const list = hosts();
160
187
  const inside = list.filter((node) => container.contains(node));
161
188
  const before = textNear(inside[0], -1, list);
@@ -181,11 +208,7 @@ export function createTyping({ struct, say, keepText, paragraphBefore, removeBlo
181
208
  ? (next ? [next, "start"] : [previous, "end"])
182
209
  : (previous ? [previous, "end"] : [next, "start"]);
183
210
  const node = removalTarget(host);
184
- const kept = keepText(node);
185
- if (kept) {
186
- say(kept, "note", 6000);
187
- return true;
188
- }
211
+ if (kept(node)) return true;
189
212
  struct([node.parentNode], [host], () => {
190
213
  takeOut(node);
191
214
  return { touched: [], focus: target };
@@ -203,6 +226,9 @@ export function createTyping({ struct, say, keepText, paragraphBefore, removeBlo
203
226
  // Backspace at the start of a block. Returns whether it was handled.
204
227
  function backspace(host) {
205
228
  opened(previousLine(host));
229
+ // A paragraph's or a heading's alignment, then its indent a level at a time, goes before anything
230
+ // else, one undo step each (align.mjs unalign: Feishu's 退对齐 and 反缩进 before a join).
231
+ if (unalign(host, look)) return true;
206
232
  // The block's component (a list item's: a nested item moves out a level, the first or last item of
207
233
  // a top-level list leaves it as body text, an emptied item holding lists stays), then what stands
208
234
  // around it (the item a block stands under; a node, at the start of its first line, holding
@@ -212,6 +238,12 @@ export function createTyping({ struct, say, keepText, paragraphBefore, removeBlo
212
238
  const container = emptyContainer(host);
213
239
  if (container) return removeContainer(container);
214
240
  if (leave.backspace(host)) return true;
241
+ // An empty heading (or small text) is an empty paragraph, where it stands (leave.mjs emptied).
242
+ if (leave.emptied(host)) return true;
243
+ // Right after a block of no text (a picture, a table, a code block, a callout, a divider, a card…):
244
+ // the caret after it, at its bottom right (after/), an empty block going (the user's, 2026-11-09:
245
+ // Backspace there went into the block, or past a picture to the text before it); never a join.
246
+ if (afterAbove(host)) return true;
215
247
  if (isEmpty(host)) return removeHost(host, false);
216
248
  if (merge(host)) return true;
217
249
  // A block holding blocks that did not join the line above says why, as its component puts it.
@@ -14,6 +14,8 @@ import { BLOCK_TYPES, LEAVES_BY_ENTER, accepts } from "../../components/registry
14
14
  // too) moves out after the box, which goes if nothing is left in it (`leaveBox`).
15
15
  // - A block of a type that says `resettable` (a quote's paragraph, a list item) turns into a
16
16
  // paragraph where it stands, its container splitting around it (convert.mjs).
17
+ // - Backspace in an empty block of a type that says `emptyToText` (a heading, small text) turns it
18
+ // into an empty paragraph where it stands (`emptied`; the user's, 2026-11-09).
17
19
  // Enter in a title that goes into its content (a disclosure, a card, a code block) is another rule
18
20
  // (their components').
19
21
 
@@ -36,8 +38,10 @@ export function leaveBox(host) {
36
38
  * and touchedBy (a structural undo step), convertHost, typeOf and targetsOf (convert.mjs).
37
39
  */
38
40
  export function createLeaving({ struct, touchedBy, convertHost, typeOf, targetsOf }) {
39
- // A block of a type that resets, which can be body text where it stands.
40
- const resets = (host) => BLOCK_TYPES[typeOf(host)]?.resettable === true && targetsOf(host).includes("paragraph");
41
+ // A block of a type that says `field` (resettable, emptyToText), which can be body text where it stands.
42
+ const says = (host, field) => BLOCK_TYPES[typeOf(host)]?.[field] === true && targetsOf(host).includes("paragraph");
43
+ const resets = (host) => says(host, "resettable");
44
+ const toText = (host) => convertHost(host, "paragraph");
41
45
 
42
46
  // Enter on an empty text block. True when it left its container or became text.
43
47
  function enter(host) {
@@ -52,7 +56,7 @@ export function createLeaving({ struct, touchedBy, convertHost, typeOf, targetsO
52
56
  return true;
53
57
  }
54
58
  if (!resets(host)) return false;
55
- convertHost(host, "paragraph");
59
+ toText(host);
56
60
  return true;
57
61
  }
58
62
 
@@ -60,9 +64,19 @@ export function createLeaving({ struct, touchedBy, convertHost, typeOf, targetsO
60
64
  // quote's first paragraph), turns into body text before the container. True when it did.
61
65
  function backspace(host) {
62
66
  if (!resets(host) || host.parentElement?.firstElementChild !== host) return false;
63
- convertHost(host, "paragraph");
67
+ toText(host);
64
68
  return true;
65
69
  }
66
70
 
67
- return { enter, backspace };
71
+ // Backspace in an empty text block of a type that says `emptyToText` (a heading, small text): it turns
72
+ // into an empty paragraph where it stands, the caret in it, one undo step (the user's, 2026-11-09: as an
73
+ // emptied item or quote paragraph, and as every container left empty, goes back to body text). True
74
+ // when it did.
75
+ function emptied(host) {
76
+ if (!isEmpty(host) || !says(host, "emptyToText")) return false;
77
+ toText(host);
78
+ return true;
79
+ }
80
+
81
+ return { enter, backspace, emptied };
68
82
  }
@@ -2,7 +2,7 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { componentSettings, problemIn, writeComponentSettings } from "./component-catalog.mjs";
4
4
  import { refusal, said } from "./i18n/index.mjs";
5
- import { PACK_FILE, PACK_ID, readPackManifest } from "./pack-manifest.mjs";
5
+ import { DEFAULT_PACK, OWN_SCOPE, PACK_FILE, PACK_ID, readPackManifest } from "./pack-manifest.mjs";
6
6
  import { packsDirectory } from "./paths.mjs";
7
7
  import { filesIn, fingerprintOf, fingerprintOfFiles, isSystemFile, recordOf, shippedBlocks, shippedPackIds, versionAfter, writeRecord, writingOrder } from "./shipped-blocks.mjs";
8
8
  import { DEVICE_NAMES, PACKAGE_MANIFEST, layoutOf, markerOf, packageFolders } from "./workspace.mjs";
@@ -10,8 +10,9 @@ import { DEVICE_NAMES, PACKAGE_MANIFEST, layoutOf, markerOf, packageFolders } fr
10
10
  // Block packs (自定义块包: notes/plans/block-packs-plan-2026-11-09.md; docs/render.md "Block packs"). A pack
11
11
  // is a scope of the workspace's custom blocks, components/<id>/, with its pack.json (./pack-manifest.mjs)
12
12
  // and a folder of each of its blocks, <id>/<name>/, the blocks' ids <id>/<name> as ever, so that nothing
13
- // written of a block changes; a scope with no pack.json (local/, the Agent's own) is a pack of its own,
14
- // named by its scope. A pack is shared as its folder, or a zip of it (the folder itself, or what it
13
+ // written of a block changes; a scope with no pack.json is a pack of its own, named by its scope, and
14
+ // local/ (OWN_SCOPE: gallery block new <name>'s, where an Agent's block goes when it names no pack) is the
15
+ // default pack (默认块包, pack-manifest.mjs DEFAULT_PACK), always listed, first. A pack is shared as its folder, or a zip of it (the folder itself, or what it
15
16
  // holds, at the zip's top), and installed into a workspace by gallery block pack install (src/cli/component.mjs)
16
17
  // or 设置 › 组件列表's 导入 (src/server/component-settings.mjs), which both read it (src/transfer/pack-source.mjs)
17
18
  // and hand its files here, checked alike:
@@ -43,6 +44,18 @@ import { DEVICE_NAMES, PACKAGE_MANIFEST, layoutOf, markerOf, packageFolders } fr
43
44
  /** Gallery's own packs that a workspace has switched off when they are first installed. */
44
45
  export const OFF_AT_FIRST = Object.freeze(["gallery-soft"]);
45
46
 
47
+ /**
48
+ * The ids of Gallery's own packs that are off though gallery.json names no switch for them: one off at first
49
+ * (OFF_AT_FIRST) that this workspace has not installed yet, which its first install will switch off. A
50
+ * start that installs none (NO_PACKS, a workspace made by hand) has the library offer Gallery's own blocks
51
+ * from the package, and a pack that is off when it comes in is not one of them. `switches` is the catalog
52
+ * settings' `packs` (true on, false off, by id).
53
+ */
54
+ export function offUntilInstalled(root, switches = {}) {
55
+ const installed = recordOf(root).packs;
56
+ return OFF_AT_FIRST.filter((id) => switches?.[id] === undefined && !isTable(installed?.[id]));
57
+ }
58
+
46
59
  /** The environment variable that keeps a start (and gallery init) from installing Gallery's own packs: the tests' workspaces. */
47
60
  export const NO_PACKS = "GALLERY_NO_PACKS";
48
61
 
@@ -285,14 +298,16 @@ const both = (problem) => ({ zh: problemIn("zh", problem), en: problemIn("en", p
285
298
  * switch, gallery.json's components.packs), changed (of what was installed, the blocks changed since, and
286
299
  * pack.json where it was), newer (of one of Gallery's own that was changed since, Gallery's version of it
287
300
  * when that comes after the one installed, which is not put over it; else null) }]: Gallery's own first,
288
- * then those installed, then the workspace's own, each by id.
301
+ * then those installed, then the workspace's own, each by id; and before them all the default pack (local/,
302
+ * OWN_SCOPE: kind "default", named and described by DEFAULT_PACK, its switch as any pack's), whether or
303
+ * not it holds a block yet: where an Agent's block goes when it names no pack.
289
304
  */
290
305
  export function workspacePacks(root, { settings = null, shippedIds = shippedPackIds(), directory = packsDirectory } = {}) {
291
306
  const { components } = layoutOf(root);
292
307
  const record = recordOf(root);
293
308
  const installed = isTable(record.packs) ? record.packs : {};
294
309
  const blocks = packageFolders(root);
295
- const scopes = new Set(blocks.map(({ id }) => id.split("/")[0]));
310
+ const scopes = new Set([OWN_SCOPE, ...blocks.map(({ id }) => id.split("/")[0])]);
296
311
  try {
297
312
  for (const name of fs.readdirSync(components)) if (PACK_ID.test(name) && fs.existsSync(path.join(components, name, PACK_FILE))) scopes.add(name);
298
313
  } catch {}
@@ -336,7 +351,7 @@ export function workspacePacks(root, { settings = null, shippedIds = shippedPack
336
351
  const ownBlocks = official ? shippedBlocks(directory) : [];
337
352
  const behind = official && shipped && changed.some((block) => (block.endsWith(`/${PACK_FILE}`) ? versionAfter(shipped.version, manifest?.version ?? null) : (ownBlocks.some((one) => one.id === block) && versionAfter(ownBlocks.find((one) => one.id === block).version, versionAt(block)))));
338
353
  const newer = behind ? shipped.version : null;
339
- const told = manifest ?? (problem ? null : shipped);
354
+ const told = id === OWN_SCOPE ? DEFAULT_PACK : manifest ?? (problem ? null : shipped);
340
355
  return {
341
356
  id,
342
357
  name: told?.name ?? { zh: id, en: id },
@@ -345,7 +360,7 @@ export function workspacePacks(root, { settings = null, shippedIds = shippedPack
345
360
  author: told?.author ?? null,
346
361
  homepage: told?.homepage ?? null,
347
362
  icon: told?.icon ?? null,
348
- kind: official ? "official" : was ? "installed" : "own",
363
+ kind: id === OWN_SCOPE ? "default" : official ? "official" : was ? "installed" : "own",
349
364
  problem: problem ? both(problem) : null,
350
365
  blocks: ids.length,
351
366
  enabled: switches[id] !== false,
@@ -353,7 +368,7 @@ export function workspacePacks(root, { settings = null, shippedIds = shippedPack
353
368
  newer,
354
369
  };
355
370
  });
356
- const rank = ({ id, kind }) => (kind === "official" ? shippedIds.indexOf(id) : kind === "installed" ? 1000 : 2000);
371
+ const rank = ({ id, kind }) => (kind === "default" ? -1 : kind === "official" ? shippedIds.indexOf(id) : kind === "installed" ? 1000 : 2000);
357
372
  return listed.sort((a, b) => rank(a) - rank(b) || (a.id < b.id ? -1 : 1));
358
373
  }
359
374
 
@@ -10,7 +10,7 @@ import { writeAtomic } from "./files.mjs";
10
10
  import { attr, walk } from "./html-tree.mjs";
11
11
  import { HOST, NET, netHostsOf } from "./net-policy.mjs";
12
12
  import { inLanguage, refusal, said, saying, told } from "./i18n/index.mjs";
13
- import { PACK_FILE, PACK_ID, readPackManifest } from "./pack-manifest.mjs";
13
+ import { DEFAULT_PACK, OWN_SCOPE, PACK_FILE, PACK_ID, readPackManifest } from "./pack-manifest.mjs";
14
14
  import { DEVICE_NAMES, PACKAGE_MANIFEST, WORKSPACE_MARK, findWorkspace, layoutOf, markerOf, packageFolders } from "./workspace.mjs";
15
15
 
16
16
  // 组件包, custom blocks (自定义块) as the UI and the Agent's documents call them: what the workspace's
@@ -64,7 +64,7 @@ const PLACES = ["document", "page"];
64
64
  const DOCUMENT_ONLY = ["document"];
65
65
  // What `card` says of a card on a board, in cells of the grid: a row is 12 of them, and a card at most
66
66
  // 24 high.
67
- const CARD_FIELDS = ["sizes", "w", "h", "min", "max", "resize", "fit", "bare"];
67
+ const CARD_FIELDS = ["sizes", "w", "h", "min", "max", "resize", "fit", "bare", "consent"];
68
68
  const GRID = { w: 12, h: 24 };
69
69
  const FITS = ["fixed", "content"];
70
70
  const NO_CARD = { sizes: null, any: false, w: 4, h: null, min: { w: 1, h: 1 }, max: { ...GRID }, resize: false, fit: "fixed", bare: false };
@@ -268,7 +268,9 @@ function placesOf(places) {
268
268
  // the fewest whole cells its content takes). With `sizes`, the first is the default, and no w or h is
269
269
  // written beside them; a min or a max beside them frees the card (`any`): the sizes are the common ones
270
270
  // its 大小 menu lists, any whole size between min and max is its too (resizing by the corner, a place),
271
- // and each of the sizes stands inside them.
271
+ // and each of the sizes stands inside them. `consent` ({ zh, en }, where it says one) is what the kit's
272
+ // banner on its card says while it waits for the reader to let it online (允许联网之后显示天气), in place of
273
+ // the kit's own line (允许联网之后显示内容).
272
274
  function cardOf(card) {
273
275
  if (card === undefined) return NO_CARD;
274
276
  if (!isTable(card)) fail(said("{0} 要写成一张表", "card"));
@@ -307,12 +309,14 @@ function cardOf(card) {
307
309
  }
308
310
  for (const flag of ["resize", "bare"]) if (card[flag] !== undefined && typeof card[flag] !== "boolean") fail(said("{0} 要写成 true 或 false", `card.${flag}`));
309
311
  if (card.fit !== undefined && !FITS.includes(card.fit)) fail(said("card.fit 只能是 fixed 或 content"));
312
+ if (card.consent !== undefined) bothLanguages(card.consent, "card.consent");
310
313
  return {
311
314
  sizes: card.sizes ? card.sizes.map(([width, height]) => [width, height]) : null,
312
315
  any, w, h, min, max,
313
316
  resize: card.resize ?? false,
314
317
  fit: card.fit ?? "fixed",
315
318
  bare: card.bare ?? false,
319
+ ...(card.consent !== undefined ? { consent: { zh: card.consent.zh, en: card.consent.en } } : {}),
316
320
  };
317
321
  }
318
322
 
@@ -635,7 +639,8 @@ export function readCatalog(root = workspaceRoot(), held = NO_SETTINGS, { on = n
635
639
  /**
636
640
  * What the pack.json of each scope of `scopes` (and of each folder of components/ that holds one) names
637
641
  * it: a Map, by scope, of { zh, en }, or null where it has none or one that does not read (a scope of
638
- * blocks with no pack.json is a pack of its own by its scope's name: ./block-packs.mjs).
642
+ * blocks with no pack.json is a pack of its own by its scope's name, the default pack, local/, by its own:
643
+ * ./pack-manifest.mjs DEFAULT_PACK, ./block-packs.mjs).
639
644
  */
640
645
  export function packNames(root, scopes = []) {
641
646
  const { components } = layoutOf(root);
@@ -647,7 +652,7 @@ export function packNames(root, scopes = []) {
647
652
  for (const scope of [...new Set([...scopes, ...withFile])].sort()) {
648
653
  let name = null;
649
654
  try {
650
- name = readPackManifest(readFileSync(path.join(components, scope, PACK_FILE), "utf8")).name;
655
+ name = scope === OWN_SCOPE ? DEFAULT_PACK.name : readPackManifest(readFileSync(path.join(components, scope, PACK_FILE), "utf8")).name;
651
656
  } catch {}
652
657
  names.set(scope, name);
653
658
  }
@@ -687,9 +692,9 @@ const stateOf = (found, settings) => (found.problem ? (found.disabled ? "disable
687
692
  * What the kit is told of a package: where its instances are, its parts, what it leaves on a page, how far
688
693
  * its content's shape goes, and what it uses (`needs`, where it names any: the kit gives an instance
689
694
  * context.workspace for "workspace", context.fetch for a host of the net and context.table() for
690
- * "tables").
695
+ * "tables"), and the line its card's consent banner says (`consent`, its card's, where it says one).
691
696
  */
692
- export const descriptionOf = ({ id, match, parts, runtime, schema, needs }) => ({ id, match, parts, ...(runtime ? { runtime } : {}), ...(schema !== undefined ? { schema } : {}), ...(needs?.length ? { needs } : {}) });
697
+ export const descriptionOf = ({ id, match, parts, runtime, schema, needs, card }) => ({ id, match, parts, ...(runtime ? { runtime } : {}), ...(schema !== undefined ? { schema } : {}), ...(needs?.length ? { needs } : {}), ...(card?.consent ? { consent: card.consent } : {}) });
693
698
 
694
699
  /**
695
700
  * What the kit is told of a catalog, each by DocKit.describe, the one way a page learns a package's
@@ -786,7 +791,8 @@ export const templateOf = (found) => readTemplate(found).markup ?? null;
786
791
  * no route and no dynamic import. One entry for each package that loads, by id: { id, version, name:
787
792
  * { zh, en }, description: { zh, en }, words, definition, stamp, template (the markup "/" puts in: one
788
793
  * instance of it, or null), preview (the address of its picture, or null), state ("normal", or "hidden": a menu offers what is "normal" and reads no setting), places (which the page's
789
- * settingState reads with gallery.json's lists as its event stream says them), needs, markdown, assets (the kit's files it asks for,
794
+ * settingState reads with gallery.json's lists as its event stream says them), needs, settings (the fields of its 设置 form, a
795
+ * manifest's `settings`, [] where it has none), markdown, assets (the kit's files it asks for,
790
796
  * by id), tags (packageTags: what loads it in a page that was served without it, the line that tells the
791
797
  * kit of its parts among them), pack ({ id, name }: the pack it is of, its scope, and what its pack.json names
792
798
  * it, null where none does: a menu writes the pack's name after a block's in grey where two packs offer
@@ -806,6 +812,7 @@ export const menuOf = ({ packages, settings = NO_SETTINGS, packs = new Map() })
806
812
  state: stateOf(found, settings),
807
813
  places: found.places,
808
814
  needs: found.needs,
815
+ settings: found.settings,
809
816
  markdown: found.markdown,
810
817
  assets: found.assets,
811
818
  tags: packageTags(found),
@@ -16,7 +16,7 @@ export const SOURCE_ATTRIBUTES = ["data-checked", "rowspan", "colspan", "data-so
16
16
 
17
17
  /**
18
18
  * The classes that are a block's or a cell's look, which a reader sets and the file keeps: a text color
19
- * or a fill (doc-text-<color>, doc-highlight-<color>), a cell's alignments and its bold (table.mjs's
19
+ * or a fill (doc-text-<color>, doc-highlight-<color>), a text block's alignment and indent (a table's frame's alignment is the same two classes), a cell's alignments and its bold (table.mjs's
20
20
  * CELL_ALIGN_CLASSES, CELL_VALIGN_CLASSES, CELL_BOLD_CLASS, the editor's CELL_LOOKS). What the kit and
21
21
  * the editor toggle as they lay a page out (a table's number and doc-table--auto, a code block's
22
22
  * folds) is none, so that no component hears its own layout as a change of the file, and draws again
@@ -28,6 +28,8 @@ export const LOOK_CLASSES = new Set([
28
28
  // file would bring its description, prose and all, into the kit's runtime (tests/unit/installed.mjs
29
29
  // holds the two lists together).
30
30
  "doc-align-left", "doc-align-center", "doc-align-right", "doc-valign-top", "doc-valign-middle", "doc-valign-bottom", "doc-bold",
31
+ // A paragraph's or a heading's indent (the editor's components/align.mjs INDENTS; its alignment is a cell's classes above).
32
+ ...Array.from({ length: 8 }, (_, index) => `doc-indent-${index + 1}`),
31
33
  ]);
32
34
 
33
35
  /** Whether a class attribute's look classes (LOOK_CLASSES) differ from `before` to `after`, either null for none. */
@@ -1,4 +1,5 @@
1
- // A heading, levels 1 to 4 (the fourth body-sized): a basic block.
1
+ // A heading, levels 1 to 4 (the fourth body-sized): a basic block. Aligned and indented as a paragraph
2
+ // is (paragraph.mjs TEXT_ALIGN_CLASSES, described there and by the table).
2
3
  export default {
3
4
  id: "heading",
4
5
  category: "block",
@@ -124,7 +124,7 @@ export const PACKAGE_MARK = "data-doc-package";
124
124
  export const ARRIVING = "data-ge-arriving";
125
125
 
126
126
  /**
127
- * Whether the document's insert entries ("/", 在下方新建, the handle's grid, a table's 视图 ›) offer the
127
+ * Whether the document's insert entries ("/", 在下方新建, the handle's grid) offer the
128
128
  * block `id` whose manifest's `places` are those (left out: ["document"]), by gallery.json's lists
129
129
  * (`settings`: hidden, shown, disabled, unlisted, packsOff, each left out for none): one that says it stands in a
130
130
  * document is offered unless hidden; one that does not, only where shown; one disabled never, as it does
@@ -47,6 +47,8 @@ export default {
47
47
  // a copy of the view keeps; never written in doc.html.
48
48
  state: { html: ["data-doc-theme", ...Object.values(LOOK_ATTRIBUTES)] },
49
49
  internal: ["doc-display*", "data-doc-export-copy", "data-theme", "doc-export-id", "doc-reveal", "doc-kit-error", "doc-net-consent*", "data-doc-snapshot",
50
+ // A consent bar on a card under 240px of content (runtime/net.js), its line over its button.
51
+ "data-doc-net-narrow",
50
52
  // The time an export's snapshot was made (its data-doc-snapshot tag's: render/net-snapshot.mjs), which context.workspace.query answers as `at`.
51
53
  "data-at",
52
54
  // A custom page's (no document's: src/render/page-html.mjs, the kit's board/): its cards' cells, the Agent's
@@ -1,9 +1,16 @@
1
1
  // A paragraph (文本), or small text (小字, p.doc-note): a basic block. Small text may end in a part at
2
2
  // the line's right end (span.doc-tab: the page editor's Tab).
3
+
4
+ /**
5
+ * A paragraph's or a heading's alignment and indent (the page editor's 对齐与缩进): centred or at the
6
+ * right (left is neither), moved in by levels of two body characters (styles/flow.css).
7
+ */
8
+ export const TEXT_ALIGN_CLASSES = ["doc-align-center", "doc-align-right", ...Array.from({ length: 8 }, (_, index) => `doc-indent-${index + 1}`)];
9
+
3
10
  export default {
4
11
  id: "paragraph",
5
12
  category: "block",
6
13
  match: "p",
7
14
  tail: ".doc-tab", // small text's end part, a span at the line's right end
8
- classes: ["doc-note", "doc-tab"],
15
+ classes: ["doc-note", "doc-tab", ...TEXT_ALIGN_CLASSES.filter((name) => name.startsWith("doc-indent-"))], // the alignments are the table's (a cell's), the same classes
9
16
  };
@@ -30,6 +30,7 @@ export default {
30
30
  "data-number-columns": "off: no column read as numbers (none centered, none sortable by number), on the table or its frame",
31
31
  "data-doc-chart-source": "on its frame: the key a chart drawn from it reads it by (data-doc-chart-data on the chart's host)",
32
32
  },
33
+ // The frame may be placed centred or at the right (doc-align-center, doc-align-right, a text block's: the page editor's 对齐 ›).
33
34
  // A cell may also be given a text color or a fill (doc-text-*, doc-highlight-*: text.mjs), an alignment, a vertical one and bold
34
35
  // (doc-bold); a header row's cell's look is doc-bold doc-highlight-gray, as the page editor gives it (a header column's th scope="row" none).
35
36
  classes: ["doc-table", "doc-table-wrap", "doc-table-meta", "doc-table--sticky-first", ...CELL_ALIGN_CLASSES, ...CELL_VALIGN_CLASSES, CELL_BOLD_CLASS],
@@ -0,0 +1,43 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { parse } from "parse5";
4
+ import { attr, walk } from "./html-tree.mjs";
5
+ import { escapeAttribute } from "./escape.mjs";
6
+ import { newNames } from "./new-names.mjs";
7
+ import { COMPONENTS_FOLDER, DOCUMENT_FOLDERS, SHARED_FOLDERS, documentFiles, packageFolders, readLink } from "./workspace.mjs";
8
+
9
+ /** Files belonging to a document, excluding packages/pages sharing a legacy reserved folder. */
10
+ export async function documentNames(root, slug) {
11
+ const entries = await fs.readdir(path.join(root, slug), { withFileTypes: true });
12
+ if (!SHARED_FOLDERS.includes(slug)) return entries.map(({ name }) => name);
13
+ const scopes = slug === COMPONENTS_FOLDER ? new Set(packageFolders(root).map(({ id }) => id.split("/")[0])) : new Set();
14
+ return entries.filter(entry => entry.isFile() || (DOCUMENT_FOLDERS.includes(entry.name) && !scopes.has(entry.name))).map(({ name }) => name);
15
+ }
16
+
17
+ /** Same copy primitive for duplicate and cross-workspace copy: local assets and metadata stay intact. */
18
+ export async function copyEntryFiles(root, slug, destination, copy, { names = new Map() } = {}) {
19
+ const source = path.join(root, slug);
20
+ const document = await fs.access(documentFiles(source).html).then(() => true, () => false);
21
+ const link = document ? null : await readLink(source);
22
+ const own = new Set(["", ...(await documentNames(root, slug))]);
23
+ await fs.cp(source, destination, { recursive: true, errorOnExist: true, force: false, filter: from => own.has(path.relative(source, from).split(path.sep)[0]) });
24
+ if (link) return [];
25
+ const file = documentFiles(destination).html;
26
+ const html = await fs.readFile(file, "utf8");
27
+ const text = newNames(html);
28
+ const edits = new Map(), packages = new Set();
29
+ walk(parse(text.replace(/^\uFEFF/, " "), { sourceCodeLocationInfo: true }), node => {
30
+ const component = attr(node, "data-doc-component");
31
+ if (component) packages.add(component);
32
+ for (const { name, value } of node.attrs ?? []) {
33
+ const at = node.sourceCodeLocation?.attrs?.[name];
34
+ if (!at) continue;
35
+ const relative = /^(\.\.\/)([a-z0-9]+(?:-[a-z0-9]+)*)(\/.*)$/.exec(value);
36
+ const next = name === "data-doc-id" && value === slug ? copy : ["href", "src", "poster"].includes(name) && relative && names.has(relative[2]) ? `../${names.get(relative[2])}${relative[3]}` : value;
37
+ if (next !== value) edits.set(at.startOffset, { to: at.endOffset, text: `${name}="${escapeAttribute(next)}"` });
38
+ }
39
+ });
40
+ const next = [...edits].sort(([a], [b]) => b - a).reduce((text, [from, edit]) => text.slice(0, from) + edit.text + text.slice(edit.to), text);
41
+ await fs.writeFile(file, next);
42
+ return [...packages];
43
+ }