@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
@@ -0,0 +1,28 @@
1
+ # 天气 (gallery-soft/weather)
2
+
3
+ A card for a custom page (its places are `page`): a city's weather now (the sky's picture and words, the temperature, today's highest and lowest, how it feels, the humidity and the wind) and, on a tall card, the next five days. The data comes from Open-Meteo (open-meteo.com), which needs no key. Use it when the user asks for the weather on a page, its home page among them.
4
+
5
+ It is 柔光风格's (the pack `gallery-soft`, off until the user turns it on in 设置 › 组件列表): the same card as Gallery 风格's `gallery/weather`, its settings, its data and what the user does on it the same, in the soft look of design A (a faint wash of blue from the card's top, rounded chips, big numbers). Write it only where the user asked for 柔光风格 or the page already holds its cards.
6
+
7
+ ## Settings
8
+
9
+ Its two settings are the card's form, which the user opens from the grip at the card's top right › 设置…:
10
+
11
+ | Key | Label | Type | What it is |
12
+ | --- | --- | --- | --- |
13
+ | `city` | 城市 | text | the city, as the user names it: 上海, 杭州, Berlin; looked up by that name, its first match taken |
14
+ | `unit` | 单位 | select | `℃` (the default) or `℉` |
15
+
16
+ They are kept in its data part `settings`, a `<script type="application/json">`, as example.html does: `{"city":"上海","unit":"℃"}` (on one line and compact, as the card's 设置… writes it back). The city is the one setting it cannot show anything without (`required` in its manifest): when the user did not say which, ask them, or take it from what the workspace says of where they live (写作偏好, the documents; a trip is not a home: ask when that is a guess), and tell them in the handoff which you did; never hand over a card with no city unsaid. `gallery page add <slug> gallery-soft/weather --set city=上海` writes it with the add (`--set unit=℉` the unit); for a card already there, write the city in its settings part. `{}` (template.html, what a menu adds) is a card with no city yet, which asks for one (右上角手柄 › 设置…), and `gallery page check` notes it. The block reads them and writes nothing.
17
+
18
+ ## Going online
19
+
20
+ Its needs name the two hosts it reaches, `net:api.open-meteo.com` (the weather) and `net:geocoding-api.open-meteo.com` (a city's name to its coordinates). Gallery fetches nothing for it until the user allows those: the card then shows 允许访问 api.open-meteo.com 等 2 个网站, a press of which opens Gallery's consent dialog, and the card fetches once the user says yes. Tell the user so when you put the card on a page ("点卡片上的「允许访问」"). They can take it back in 设置 › 组件列表 (允许联网). Never write the consent into gallery.json yourself: it is the user's to give.
21
+
22
+ ## How to write it
23
+
24
+ Put it on a custom page as a card of its board, `<section class="gallery-card" data-card-id="…" data-x data-y data-w data-h>`, holding one instance, after `gallery block add gallery-soft/weather`, the instance as template.html has it, then its settings as above (`gallery page add <slug> gallery-soft/weather` does the card for you). Sizes: 4 × 2 (the default: now, the range and how it feels, the humidity and the wind), 2 × 2 (the temperature and the sky alone) and 4 × 4 (and the next five days).
25
+
26
+ ## How it looks
27
+
28
+ The city beside a pin's chip and when the weather was fetched (更新于 14:05) at the top, the sky's picture in its own colors (the sun, a cloud and its shade, rain) and the temperature large beside it, the sky's words and the range beside them, the humidity and the wind under them after small pictures (on a 4 × 4 card how it feels too, and the next five days under a hairline, each its sky and its lowest and highest at the ends of a bar drawn against the whole five, warm toward the top, now ringed on today's); a 2 × 2 card the temperature beside the picture, the sky's words and the range under them; in 柔光风格's soft look (as every card of it: a faint wash of blue from the card's top, a head of a rounded tinted chip and a title, its end clear of the card's grip), light and dark. It is fetched again when its settings change and every 30 minutes. While there is nothing to show it says why on a soft disc: 写上一个城市 (no city), 找不到「…」 (a name Open-Meteo does not know), 允许联网之后显示天气 (waiting for the user's consent, the kit's button over it), 现在连不上网,取不到天气 (no network, and nothing fetched before), 网络设置把天气服务指向了本地地址 (this computer's network setup gives Open-Meteo's names an address of this computer or of a private network, which Gallery refuses). The script runs with the rights of the page's own scripts, as any block's does.
package/release.json CHANGED
@@ -1,26 +1,26 @@
1
1
  {
2
2
  "name": "@heycys/gallery",
3
- "version": "0.1.2",
4
- "built": "2026-11-09T12:40:13.596Z",
3
+ "version": "0.2.1",
4
+ "built": "2026-11-10T18:08:08.621Z",
5
5
  "stamps": {
6
- "editor": "3e8a535e1b3305fd",
6
+ "editor": "6391411681dcaf3d",
7
7
  "kit": {
8
- "styles": "b4df48c5b58e5996",
8
+ "styles": "fd4d4ec8d57ef8d1",
9
9
  "katex-styles": "81d0a0b4dcb41846",
10
- "runtime": "2e70af13bb7f6272",
11
- "code": "ac7030c365b49692",
10
+ "runtime": "ccf037942f0fee28",
11
+ "code": "f893c8b464096161",
12
12
  "state": "d4a528bd33704119",
13
13
  "sheets": "fda7b7b754e01019",
14
14
  "tokens": "a218d5d5f9008530",
15
- "ui": "9d426d38850cc54f",
15
+ "ui": "6ab6d809a853b59a",
16
16
  "dialogs": "42866e832540bf9f",
17
17
  "katex": "1b0a973a02ab84f0",
18
18
  "katex-auto-render": "63e7162ddec186d6",
19
- "math": "af1582414dca108c",
19
+ "math": "cf768d1151047082",
20
20
  "d3": "9f5a21b6070f8353",
21
21
  "charts": "22bde4e5900579fe",
22
- "tables": "7ab99911557a2efe",
23
- "board-styles": "021119be212eaf56",
22
+ "tables": "f776dc063389a916",
23
+ "board-styles": "338f6b6b6145b4dc",
24
24
  "board": "15007a0cd8566621"
25
25
  }
26
26
  }
package/skill/SKILL.md CHANGED
@@ -9,16 +9,16 @@ Create a self-contained HTML document whose claims, numbers, and visual encoding
9
9
 
10
10
  ## Before anything: the gallery command
11
11
 
12
- This skill holds the instructions; the tools are the npm package `@heycys/gallery`, the `gallery` command. This skill is Gallery 0.1.2's and needs `@heycys/gallery` ^0.1.2: a version npm's range `^0.1.2` takes, 0.1.2 or a later 0.1.x.
12
+ This skill holds the instructions; the tools are the npm package `@heycys/gallery`, the `gallery` command. This skill is Gallery 0.2.1's and needs `@heycys/gallery` ^0.2.1: a version npm's range `^0.2.1` takes, 0.2.1 or a later 0.2.x.
13
13
 
14
14
  1. Run `gallery --version`. Its first line is the version: when it is such a version, go on to step 3. A line after it may say that something is newer; that never stops the task: say it once (the handoff will do) and go on, and update nothing without the user's yes, unless they already said in this conversation to update.
15
15
  - `技能:<folder> …`: the Gallery skill there (this one, maybe) is older than the gallery. Tell the user so and offer to run the command the line gives (`gallery skill install`, with `--project` for a project's skill; run by `npx`, the line gives `npx -y @heycys/gallery@^<version> skill install`); after their yes, run it and tell them a new Agent session reads the new skill. Finish this task with the skill as it is.
16
16
  - `新版本:…`: npm has a newer Gallery. Tell the user once in the conversation and offer to update; after their yes, run the line's `npm i -g …`, then `gallery skill install`, and tell them a new Agent session reads the new skill. Where you run Gallery by `npx` (no global install), the line gives `npx -y @heycys/gallery@^<its version> skill install` instead: run that after their yes, and tell them the next commands can take the newer range: `npx -y @heycys/gallery@^<its version> …`.
17
- 2. When `gallery` is not found, or prints a version older than `^0.1.2` takes, install it with `npm i -g @heycys/gallery@^0.1.2`, then run `gallery --version` again. When the user has already said to install it (in this request or earlier in the conversation), run it without asking again; otherwise ask the user before you install anything: say that Gallery's command is missing (or which version it is) and that you would run that command, and run it once they agree.
18
- - When it prints a version newer than `^0.1.2` takes, install nothing (that would take Gallery back to an older version): this skill is older than their Gallery. Tell the user and offer to run `gallery skill install` (with `--project` when the skill is the project's, in its `.claude/skills/`; a `技能:` line gives it); after their yes, run it and ask them to start a new Agent session, which reads the new skill.
17
+ 2. When `gallery` is not found, or prints a version older than `^0.2.1` takes, install it with `npm i -g @heycys/gallery@^0.2.1`, then run `gallery --version` again. When the user has already said to install it (in this request or earlier in the conversation), run it without asking again; otherwise ask the user before you install anything: say that Gallery's command is missing (or which version it is) and that you would run that command, and run it once they agree.
18
+ - When it prints a version newer than `^0.2.1` takes, install nothing (that would take Gallery back to an older version): this skill is older than their Gallery. Tell the user and offer to run `gallery skill install` (with `--project` when the skill is the project's, in its `.claude/skills/`; a `技能:` line gives it); after their yes, run it and ask them to start a new Agent session, which reads the new skill.
19
19
  - No Node, or `node --version` older than 22.13: tell the user to install the current LTS from https://nodejs.org (or with their system's package manager), then start again.
20
- - npm says `EACCES` (macOS and Linux, where npm's global folder belongs to the system): never use `sudo`. Tell the user, and offer either of these: give npm a folder of their own (`npm config set prefix ~/.npm-global`, add `~/.npm-global/bin` to `PATH` in their shell profile, open a new terminal, install again); or run every command as `npx -y @heycys/gallery@^0.1.2 <command> …` instead of `gallery <command> …`.
21
- - Use `npx -y @heycys/gallery@^0.1.2 <command> …` likewise wherever a global install is not allowed (a sandbox, CI). It is slower: a few seconds more per command.
20
+ - npm says `EACCES` (macOS and Linux, where npm's global folder belongs to the system): never use `sudo`. Tell the user, and offer either of these: give npm a folder of their own (`npm config set prefix ~/.npm-global`, add `~/.npm-global/bin` to `PATH` in their shell profile, open a new terminal, install again); or run every command as `npx -y @heycys/gallery@^0.2.1 <command> …` instead of `gallery <command> …`.
21
+ - Use `npx -y @heycys/gallery@^0.2.1 <command> …` likewise wherever a global install is not allowed (a sandbox, CI). It is slower: a few seconds more per command.
22
22
  - On Windows, `gallery` works in PowerShell right after the install, in the same terminal. Only when PowerShell says running scripts is disabled (`gallery.ps1`): run `gallery.cmd` with the same arguments, or ask the user to run `Set-ExecutionPolicy -Scope CurrentUser RemoteSigned` once.
23
23
  - After an upgrade, run `gallery open --no-browser` once: the server of the version before stops by itself, and this starts the new one. Tell the user that `gallery skill install` brings this skill to the new version too (an Agent session started after it reads it).
24
24
  3. The documents live in a workspace, a folder: `--workspace <dir>` (every command takes it), else `GALLERY_WORKSPACE`, else the nearest folder up from the current one holding `gallery.json`, else `Gallery` in the user's Documents folder, `~/Documents/Gallery` (made on first use; on Windows the Documents folder Explorer shows, OneDrive's when OneDrive backs it up). `gallery new`, `gallery import`, `gallery list` and `gallery open` print it as `工作区:<path>`. When a command prints `Cannot write the workspace <path> (…)` (a sandbox that allows writes only in the project, or a system that has not let the terminal into Documents), ask the user to allow Gallery to write there, or pass `--workspace <a folder in the project>` to every command.
@@ -131,25 +131,26 @@ The workbench's sidebar shows the documents as a tree: a document may sit under
131
131
 
132
132
  - A new document goes where the user says: `gallery new <slug> "<title>" "<description>" --under <document>` (last under it; `--first`, first) or `--after <document>` (right after it, at its level). When they name no place, run `gallery list --tree` first when the workspace has documents, and put it under the document whose topic it belongs to (a week's notes under their project); at the top level when none fits. Say in the handoff where it went.
133
133
  - Move documents only when the user asks you to organize them: `gallery move <document> --under <document>` (or `--top`), `--after <document>` or `--first` for its place there, each with the documents under it. No file changes, and links between documents still work. Name every move in the handoff.
134
- - The sidebar lists custom pages (自定义页) too, under 新建 and 搜索, the home page (首页) first: boards of cards, not documents ([Custom pages](#custom-pages-自定义页)). A page's slug and a document's are one set: `gallery new` refuses a page's, `gallery page new` a document's.
135
- - The sidebar is in columns, one for each workspace of this machine (the default one's is 默认文档), and holds web links beside the documents. A document made or opened by `gallery new` or `gallery open` in another workspace joins the default workspace's sidebar too, as its line `默认工作区(…)的侧边栏:已加进…` says (display only: edit it in its own workspace). To put a web page in the sidebar, use `gallery link add <url> "<name>"` (`--column "<column>"`, `--under`, `--after` or `--first` for its place; `gallery link set` and `gallery link remove` change and take it out): a link is no document, so nothing checks, exports or searches it, and an address of this Gallery's own server is refused (link the document). `gallery list` and `gallery list --tree` show links and columns as the sidebar does. Say in the handoff where a link went (`位置:`).
134
+ - The sidebar lists custom pages (自定义页) too, among 新建 and 搜索 in the order the user drags them to: pages, not documents ([Custom pages](#custom-pages-自定义页)). A page's slug and a document's are one set: `gallery new` refuses a page's, `gallery page new` a document's.
135
+ - The sidebar shows every registered workspace’s documents and manually added web links, with one shared order and hierarchy in all workbenches. Files stay in their owning workspace; the current project’s column is displayed first. Use the existing `gallery list --tree` and `gallery move` commands for ordering within a workspace. Cross-workspace drag or 移动到 requires confirmation and creates a copy, including descendants; originals remain. Do not move a cross-workspace reference by editing the outline file. Explicit project-only extension columns remain local; public extension columns come from the default workspace. `gallery new` and `gallery open` still report the document’s place in the default workspace’s sidebar; `GALLERY_NO_DEFAULT_TREE=1` suppresses this join/announcement, not registered-workspace visibility.
136
+ - To put a web page in the sidebar, use `gallery link add <url> "<name>"` (`--column "<column>"`, `--under`, `--after` or `--first` for its place; `gallery link set` and `gallery link remove` change and take it out). A link is no document, so nothing checks, exports or searches it; an address of this Gallery's own server is refused (link the document). `gallery list` and `gallery list --tree` show links and columns as the sidebar does. Say in the handoff where a link went (`位置:`).
136
137
  - Change a document's title, page icon or description with `gallery set <document> --title "…" --icon <emoji, or none> --description "…"` (any of them): it writes the header of `doc.html` and `doc.json` in step, and the open page and the sidebar show it. Never edit `doc.json`'s title or icon, or the header, by hand for that. Re-read `doc.html` after it before you edit it.
137
138
 
138
139
  ## Custom pages (自定义页)
139
140
 
140
141
  A page has no 写作偏好: do not read it for rules, and Workflow step 1 is for documents (a `gallery list` that made it in passing changes nothing of that). A card made for "me" (my tasks) needs who that is: a setting of the card, never written into a block's code, asked or taken as step 4 says (写作偏好 may name them: read it for that alone, none of its rules is a page's).
141
142
 
142
- A custom page is a board of cards in the workbench's sidebar, the user's own dashboard: the folder `pages/<slug>/` of the workspace, `page.html` (its look and its boards, `<div class="gallery-board" data-board-id="main">`, each card a `<section class="gallery-card" data-card-id="…" data-x data-y data-w data-h>` around one custom block's instance, in square cells, twelve to a row) and `page.json` (its title and icon), opened at `/#@<slug>`. The user moves, resizes, adds and deletes its cards there (the grip at a card's top-right corner: a drag moves it, a click opens its menu, 大小, 设置… and 删除; 添加自定义块 is the first row of the ··· menu at the right of the workbench's top bar, and puts a card on the page's first board), and types in them. The page draws no big title: its name is the sidebar's, the tab's and the top bar's, so write no `<h1>` of the page's name (one in `header.gallery-page-head` is not drawn). Keep a card's top-right corner clear (28 × 28 px, 6px in): the grip stands over it while the pointer is on the card; you write it when they ask for a page or a card ("首页加一张卡片…", "给我做一个读书页").
143
+ A custom page is the user's own page in the workbench's sidebar, yours to design: the folder `pages/<slug>/` of the workspace, `page.html` (any HTML, CSS and script of yours, [pages-and-data.md](references/pages-and-data.md#a-page-is-yours-to-design); a board of cards is one way, `<div class="gallery-board" data-board-id="main">`, each card a `<section class="gallery-card" data-card-id="…" data-x data-y data-w data-h>` around one custom block's instance, in square cells, twelve to a row) and `page.json` (its title and icon), opened at `/#@<slug>`. On a board the user moves, resizes, adds and deletes its cards there (the grip at a card's top-right corner: a drag moves it, a click opens its menu, 大小, 设置… and 删除; 添加自定义块 is the first row of the ··· menu at the right of the workbench's top bar, and puts a card on the page's first board), and types in them. The page draws no big title: its name is the sidebar's, the tab's and the top bar's, so write no `<h1>` of the page's name (one in `header.gallery-page-head` is not drawn). Keep a card's top-right corner clear (28 × 28 px, 6px in): the grip stands over it while the pointer is on the card; you write it when they ask for a page or a card ("首页加一张卡片…", "给我做一个读书页").
143
144
 
144
- 1. Run `gallery page list` and `gallery block list` first: the pages there are, and the blocks a card can be (自定义页可用, and Gallery's own not yet added). "首页" is `pages/home`. Gallery makes it once, when its server first starts in a workspace (`gallery init` does too), with its own cards, 问候与日期 (`today`) and 便签 (`note`), which the user may have moved, filled in or taken off. A workspace only other commands have touched has none yet: `gallery page list`, and `gallery page add`, `try`, `check` and `open` of `home`, then say the home page is not made yet, and `gallery open --no-browser` makes it (it starts the server): run that once, then again. Extend it with `gallery page add home <block>`, never make it yourself (`gallery page new home` is refused once it is there, and until it is made) or write its `page.html` over whole; one the user took away stays away, a new one made by `gallery page new home "首页"` only when they ask for it. A new page, only when the user asks for one: `gallery page new <slug> "<title>"`.
145
+ 1. Run `gallery page list` and `gallery block list` first: the pages there are, and the blocks a card can be (自定义页可用, and Gallery's own not yet added). "首页" is `pages/home` (a page as any: the user may rename or trash it). Gallery makes it once, when its server first starts in a workspace (`gallery init` does too), with its own cards, which the user may have moved, filled in or taken off; until then `gallery page list` and the commands of `home` say it is not made yet, and `gallery open --no-browser` makes it: run that once, then again. Extend it with `gallery page add home <block>`, never write its `page.html` over whole; one the user trashed stays away. A new page only when the user asks: `gallery page new <slug> "<title>"`. A blank page they made in the sidebar (新建页面, `page-…`, an empty main) is one to write whole.
145
146
  2. Send the address first, before you write any card: on the `交给用户` line of `gallery page new <slug> "<title>"` (a server running prints it; without one, `gallery page open <slug> --no-browser` does), or of `gallery page open home --no-browser` for the home page, in a message of its own: the user watches the cards arrive.
146
147
  3. On a page that is there, change only the cards the request needs. Every other card keeps its `data-card-id`, its place and its data parts as they are: the user placed them, and a note's words are theirs. Put a card on with `gallery page add <slug> <block>` (the first free spot by the block's default size, or `--x --y --w --h`; it gives the card its id and pushes down what it meets); re-read `page.html` right before each change you make in it by hand, and replace that card alone.
147
- 4. Use one of Gallery's own blocks when it fits the request exactly (two packs: Gallery 风格's by a bare name, and 柔光风格's, off till the user turns it on, as `gallery-soft/<name>`; `gallery block add <name>` puts one in, and comes before `gallery page add`: `today`, `note`, `countdown`, `habit`, `weather` (a city's weather, from Open-Meteo: it goes online), and `todos`, `recent`, `stats`, `heatmap`, which read the workspace: its to-dos, the documents edited last, its counts, its edits by day; the user ticks a to-do on `todos`, and the tick is written into the document it is in as the user's own edit, which the page's Ctrl+Z takes back), and `gallery/static` for a card that only shows what you write (a heading, links, a short list, a picture: its file in `pages/<slug>/assets/`, written `assets/<file>`; it is for a custom page alone, a document's HTML is written as it is; it takes any size of cells, 4 × 2 at first, and does not grow with its words, so write the `data-w` and `data-h` it needs). When one is close but not exact (other fields, another look, another rule), do not settle for it, and do not write a block from nothing either: copy it with `gallery block new <id> --recipe <name>` and change the copy (a count by day, glasses of water or times, starts from `habit`: `gallery block new <id> --recipe habit`; a recipe, a block already made, takes no `--script`, `--flow`, `--data` or `--page`): its name, words, description, `preview.svg`, writing.md and example.html, which the command lists; Gallery's own stays as it ships. Make a block of your own from nothing ([references/building-blocks.md](references/building-blocks.md), and [references/pages-and-data.md](references/pages-and-data.md) for a card's size and settings and for what it reads: `gallery block new <id> --page --data` for a card that keeps what the user enters, `places` holding `page`) for a card that does something or keeps data the user changes that none of Gallery's is near, and for a read-only card over the workspace's data or the web's that none of Gallery's shows (a count by day, a rate, a feed, the rows of another document's table: `kanban`, `metric` and `chart-view` are views inside a document and read no table from a page): it is a block too (`needs` `workspace` or `net:<host>`; start from `heatmap` or `weather` with `--recipe`), never the page's own script or HTML. What a card holds stays in its card (a data part, its settings), never in the page's own HTML. A card that shows nothing without a setting the user did not give (`weather`'s city, `countdown`'s date, a block of your own with its owner) is asked about: ask the user, or take it from what the workspace says (写作偏好, the documents; ask when that is a guess), and tell them in the handoff what it holds and where you took it from, or that the card still asks for it. Give it with the add, `gallery page add home weather --set city=上海` (each `--set <key>=<value>`, no JSON to quote, held to the setting's type: a date is `YYYY-MM-DD`); for a card already there, write it in the card's settings part (its `<script type="application/json">`, as the block's writing.md shows), re-reading `page.html` right before and changing that part alone. `gallery page check` notes a card whose required setting is empty.
148
- 5. Try each gesture of a new block on its card: `gallery page try <slug> <card id> --press <selector>` (the gestures and `--steps` of `gallery block try`, on a scratch copy of the page): its `Wrote:` lines name that card's data parts alone, then the page's own Ctrl+Z gives the copy back and a fresh page reads it back. Then `gallery page check <slug>` until it prints `OK`: each `FAIL page.html:<line>` (a script, an id missing or twice, cards sharing cells or past the row, a block a page does not run, a file of `assets/` not there, or a stylesheet or a frame of one, a card whose content does not fit it); open the pictures its `Not opened yet` line lists (1280, 1920 and 600px wide, light and dark) and read its `Changes since …` lines: they name the cards you meant to change and no other, but those that end `(the user's, on the page)`, the user's own gestures on the page since the last check (a card moved, words typed in it): leave those as they are, never put one back. A line that ends `(put there by Gallery)` is the home page's own today or note, there before you came (a new workspace's first check of `home` lists them): leave those too.
149
- 6. At the end tell the user what you changed (each card, by what it shows) and where: the page's title in the sidebar under 新建 and 搜索 (首页 first), and the address again. A card that goes online (`weather`, or a block whose needs name `net:<host>`) shows nothing until the user allows it: tell them to press 允许访问 on the card, and never write that consent yourself.
148
+ 4. Use one of Gallery's own blocks when it fits the request exactly (two packs: Gallery 风格's by a bare name, and 柔光风格's, off till the user turns it on, as `gallery-soft/<name>`; `gallery block add <name>` puts one in, and comes before `gallery page add`: `today`, `note`, `countdown`, `habit`, `weather` (a city's weather, from Open-Meteo: it goes online), and `todos`, `recent`, `stats`, `heatmap`, which read the workspace: its to-dos, the documents edited last, its counts, its edits by day; the user ticks a to-do on `todos`, and the tick is written into the document it is in as the user's own edit, which the page's Ctrl+Z takes back), and `gallery/static` for a card that only shows what you write (a heading, links, a short list, a picture: its file in `pages/<slug>/assets/`, written `assets/<file>`; it is for a custom page alone, a document's HTML is written as it is; it takes any size of cells, 4 × 4 at first, and does not grow with its words, so write the `data-w` and `data-h` it needs). When one is close but not exact (other fields, another look, another rule), do not settle for it, and do not write a block from nothing either: copy it with `gallery block new <id> --recipe <name>` and change the copy (a count by day, glasses of water or times, starts from `habit`: `gallery block new <id> --recipe habit`; a recipe, a block already made, takes no `--script`, `--flow`, `--data` or `--page`): its name, words, description, `preview.svg`, writing.md and example.html, which the command lists; Gallery's own stays as it ships. Make a block of your own from nothing ([references/building-blocks.md](references/building-blocks.md), and [references/pages-and-data.md](references/pages-and-data.md) for a card's size and settings and for what it reads: `gallery block new <id> --page --data` for a card that keeps what the user enters, `places` holding `page`) for a card that does something or keeps data the user changes that none of Gallery's is near, and for a read-only card over the workspace's data or the web's that none of Gallery's shows (a count by day, a rate, a feed, the rows of another document's table: `kanban`, `metric` and `chart-view` are views inside a document and read no table from a page): it is a block too (`needs` `workspace` or `net:<host>`; start from `heatmap` or `weather` with `--recipe`), never the page's own script or HTML. What a card holds stays in its card (a data part, its settings), never in the page's own HTML. A card that shows nothing without a setting the user did not give (`weather`'s city, `countdown`'s date, a block of your own with its owner) is asked about: ask the user, or take it from what the workspace says (写作偏好, the documents; ask when that is a guess), and tell them in the handoff what it holds and where you took it from, or that the card still asks for it. Give it with the add, `gallery page add home weather --set city=上海` (each `--set <key>=<value>`, no JSON to quote, held to the setting's type: a date is `YYYY-MM-DD`); for a card already there, write it in the card's settings part (its `<script type="application/json">`, as the block's writing.md shows), re-reading `page.html` right before and changing that part alone. `gallery page check` notes a card whose required setting is empty.
149
+ 5. Try each gesture of a new block on its card: `gallery page try <slug> <card id> --press <selector>` (the gestures and `--steps` of `gallery block try`, on a scratch copy of the page): its `Wrote:` lines name that card's data parts alone, then the page's own Ctrl+Z gives the copy back and a fresh page reads it back. Then `gallery page check <slug>` until it prints `OK`: each `FAIL page.html:<line>` (an id missing or twice, cards sharing cells or past the row, a block a page does not run, a file of `assets/` not there or a frame of one, a card whose content does not fit it; the page's own scripts and stylesheets pass); open the pictures its `Not opened yet` line lists (1280, 1920 and 600px wide, light and dark) and read its `Changes since …` lines: they name the cards you meant to change and no other, but those that end `(the user's, on the page)`, the user's own gestures on the page since the last check (a card moved, words typed in it): leave those as they are, never put one back. A line that ends `(put there by Gallery)` is the home page's own today or note, there before you came (a new workspace's first check of `home` lists them): leave those too.
150
+ 6. At the end tell the user what you changed (each card, by what it shows) and where: the page's title in the sidebar (with 新建 and 搜索), and the address again. A card that goes online (`weather`, or a block whose needs name `net:<host>`) shows nothing until the user allows it: tell them to press 允许访问 on the card, and never write that consent yourself.
150
151
  - A page is no document: no opening summary, no source line, no export; 写作偏好 is for documents.
151
152
  - Its look is yours to choose (a header of your own that is no title, colors of its own in its `<style>`), written for both themes: the dark ones under `:root[data-doc-effective-theme="dark"]`.
152
- - No script of the page's own, and no `on…` attribute: what a card does is its block's, which the server puts in.
153
+ - Its own scripts are yours too, a board or none; what a card does is its block's, which the server puts in.
153
154
 
154
155
  ## Output contract
155
156
 
@@ -178,6 +179,6 @@ Before you hand over, do the review 写作偏好 asks for before handing in (a r
178
179
  | A custom block (a block to use again), when the user asks for one: the block, its flow, files, manifest and instance; sharing a block pack | [references/building-blocks.md](references/building-blocks.md) |
179
180
  | A block's script (`kit.js`) and how it writes back to the file | [references/block-script.md](references/block-script.md) |
180
181
  | A card of a custom page (size, settings), and a block that reads the workspace's data, a table of its document or the web | [references/pages-and-data.md](references/pages-and-data.md) |
181
- | A sidebar column of links an extension provides (`extensions/<id>/sidebar.json`), when the user asks for one | [references/extensions.md](references/extensions.md) |
182
+ | A public sidebar column of links (`gallery extension new`, default workspace’s `extensions/<id>/sidebar.json`; `--local` only for project-specific columns), when the user asks for one | [references/extensions.md](references/extensions.md) |
182
183
  | Exact API types | `sdk/*.d.ts`, from [`sdk/index.d.ts`](sdk/index.d.ts) |
183
184
  | What each command does and prints | `gallery help`, `gallery <command> --help` |
@@ -41,7 +41,7 @@ One block, one manifest and one `context` stand in either place; the two differ
41
41
  When the user wants a document that uses the block too, the document comes first: `gallery new`, its address sent, its skeleton written (SKILL.md, Workflow steps 1–4). Then make the block as below, write the instance in its section at step 5, and try it there at step 6.
42
42
 
43
43
  1. `gallery block list` first: what the workspace has now, in two groups by where a block may stand (文档里可用, in documents; 自定义页可用, on custom pages), each with its version, whether the menus can insert it, and what is there and cannot be used, with why; then Gallery's own blocks it has not added yet. When one does what the user asks, use it: `gallery block show <id>` prints its parts, how to write it and its example (`gallery block show gallery/<name>` does so for one of Gallery's own the workspace has not added yet, and ends with the line that adds it; `show` and `check` take its bare name too, `gallery block show heatmap`, as `add` does, a block of the workspace's own by that name staying `local/`'s). When one of Gallery's own does, `gallery block add <name>` puts it in as it ships, and it needs no check and no try (Gallery's own blocks, below).
44
- 2. `gallery block new <id>`: a new block in `<workspace>/components/<scope>/<name>/`, its `id` being `<scope>/<name>`, the scope `local` when you name none. It writes a block that passes the check, for you to replace. Add `--script` only when the block must do something when a reader uses it: a static block runs no code, is the one to start with, and is all most blocks need. Add `--flow` when it holds blocks of the document's own under its markup (a card around any content): a slot, `body` (Slots, below). Add `--data` for a block that keeps what a reader enters in the file, the usual reason to make one (a list of lines, a field that adds one, a button that takes one away): a data part `items` (JSON on one line, as `context.editJSON` writes it), a `kit.js` that reads it with `context.readJSON` and writes it with `context.editJSON`, a field (`DocKit.input`) and buttons hidden where nothing is written, and an `example()` that adds a line, which works on `template.html`'s empty instance as on `example.html`'s: rename the part and its fields for what the block keeps, and keep that shape. Add `--page` for a custom page's card (its places `["page"]`, a `card` of two sizes). `--data` and `--page` go together or alone, and either goes with `--script`; neither goes with `--flow` (a page has no slot, and `--data` is a part of its own), nor with `--recipe <name>`, which starts from one of Gallery's own (below). Each scaffold passes `gallery block check`, and `gallery block try` on its field (`--type .component-field "words" --then Enter`), as it is.
44
+ 2. `gallery block new <id>`: a new block in `<workspace>/components/<scope>/<name>/`, its `id` being `<scope>/<name>`, the scope `local` when you name none: the default pack (默认块包, first in 设置 › 组件列表), where a single block goes, with no pack of its own to make. It writes a block that passes the check, for you to replace. Add `--script` only when the block must do something when a reader uses it: a static block runs no code, is the one to start with, and is all most blocks need. Add `--flow` when it holds blocks of the document's own under its markup (a card around any content): a slot, `body` (Slots, below). Add `--data` for a block that keeps what a reader enters in the file, the usual reason to make one (a list of lines, a field that adds one, a button that takes one away): a data part `items` (JSON on one line, as `context.editJSON` writes it), a `kit.js` that reads it with `context.readJSON` and writes it with `context.editJSON`, a field (`DocKit.input`) and buttons hidden where nothing is written, and an `example()` that adds a line, which works on `template.html`'s empty instance as on `example.html`'s: rename the part and its fields for what the block keeps, and keep that shape. Add `--page` for a custom page's card (its places `["page"]`, a `card` of two sizes). `--data` and `--page` go together or alone, and either goes with `--script`; neither goes with `--flow` (a page has no slot, and `--data` is a part of its own), nor with `--recipe <name>`, which starts from one of Gallery's own (below). Each scaffold passes `gallery block check`, and `gallery block try` on its field (`--type .component-field "words" --then Enter`), as it is.
45
45
  3. Write its files (below): the manifest, `template.html`, `example.html`, its style and, with `--script`, `kit.js`, then what a writer needs to know.
46
46
  4. `gallery block check <id>`, until it prints `OK`. It says each problem at its file and line; one with no line is of that file, or of the page, as a whole. Then open `overview-light.png` and `overview-dark.png` in the folder it prints, each the pictures of 360, 736 and 1024px wide of a theme side by side, `example.html` above the line and `template.html` below it, then at full size each width where they show something to fix, and `edit-1024-light.png` and `edit-360-light.png`, as the editing page draws it, `context.canEdit()` true: what the block draws only where a reader can edit (a handle, a button), which an export leaves out. A block that draws nothing more there gives the export's pictures again, and the check says so. It has run them and looked at nothing for you: a `Not opened yet: …` line right before the verdict lists every picture of the run in one place, as `gallery qa`'s does: count by it. In the handoff name the pictures you opened. A block with a data part whose export (`1024-light.png`, where `context.canEdit()` is false) still shows an enabled button, field, select or textarea gets a note: a control that writes is drawn hidden there, which you see by comparing that picture with `edit-1024-light.png`.
47
47
  5. Use it where the user asked: in a document, write the element as `example.html` does (when the user wants no document, in one of its own made with `gallery new`, named in the handoff: step 6 tries the block there). The user finds it in "/" under its name. `gallery export <slug>` exports it as any block, and `gallery qa <slug>` pictures it among the cards. Around an instance, the document's words say what the block is and where its data comes from. A value that a reader's gesture changes (a count by column, a status, a score, a total) goes in the document's words only with when it held ("截至 11 月 5 日,…"), as an opening summary may need it; otherwise point to the block, which shows it as it is now. How to use the block on the editing page (drag a card, press a dot) goes in the handoff and in writing.md, not in the document: its export and PDF show the block read-only. Then `gallery block check <id> --documents`: it runs each instance the workspace's documents hold as step 4 runs the example, a section for each document, each problem at its line of the document's file (`board/doc.html:15`), the pictures in `documents/<slug>/` of the folder it prints, so that an instance filled otherwise than the example (a long title, an empty table) is tried as the reader's page runs it. It writes no document.
@@ -213,11 +213,11 @@ Start each one at `[data-doc-component="<id>"]`, the instance's own attribute, n
213
213
 
214
214
  ## Gallery's own blocks
215
215
 
216
- Gallery ships blocks of its own in two packs (below): Gallery 风格, the scope `gallery`, on; and 柔光风格, `gallery-soft`, the same page cards in a softer look, off until the user turns it on in 设置 › 组件列表 (its cards are `gallery-soft/<name>`; `gallery block add gallery-soft/<name>`). Gallery 风格's: for documents `gallery/card`, a titled card around blocks of the document's, and `gallery/chart-card`, a titled card holding a table in its slot and the bar chart its script draws from it; three views of a table of the document ([A view of a table](pages-and-data.md#a-view-of-a-table)), `gallery/kanban` (看板: its rows as cards grouped by a column, a card dragged changing that cell), `gallery/metric` (指标: a count, sum or average of a column) and `gallery/chart-view` (图表: bars of a count, sum or average by a column), which the reader inserts from a table's 视图 › and which you write after an ordinary table as `gallery block show gallery/<name>` prints (for a task board or a data dashboard in a document use them, never a block of your own); for custom pages `gallery/today` (问候与日期, a greeting and the date, drawn by the clock), `gallery/note` (便签, lines the user types on the card), `gallery/static` (静态卡片, any HTML of yours, only shown: a page's alone, as a document writes such HTML as it is), `gallery/countdown` (倒计时, the days to a date of its settings), `gallery/habit` (习惯打卡, a check-in a day and the streak, written as a recipe to start a block of your own from); `gallery/weather` (天气, a city of its settings, from Open-Meteo: it goes online, so tell the user to press 允许访问 on its card); and four that read the workspace (`needs` `workspace`), `gallery/todos` (我的待办, the to-dos not done of every document), `gallery/recent` (最近编辑, the documents edited last), `gallery/stats` (工作区统计, its counts) and `gallery/heatmap` (编辑热力图, the edits of each day of the past year), which a new workspace's 首页 holds with today and the note. Each one's writing.md, which `gallery block show` prints, says what it is for and how to fill it, and `gallery block list` names each one the workspace has not added, with its line. `gallery block add <name>` puts one in as it ships, `components/gallery/<name>/`, recording its version and what its files hold: write its instances as `gallery block show gallery/<name>` prints, with no check and no try. Change nothing in its folder: run again with a newer Gallery, `add` updates a copy that is as it was added, and never one changed since (what a system writes there as it shows the folder, a `.DS_Store`, a `Thumbs.db`, is no change). For a block like it of your own, `gallery block new <id> --recipe <name>` copies its files into a new block, every word that named it naming the new id (its classes too: `gallery-chart-card-bars` becomes `<scope>-<name>-bars`), its version 0.1.0: change its name, words and description first, and what is still the recipe's in the same folder (`preview.svg`, the menu's picture, still its drawing; writing.md, still about it; `example.html`, still its words: the command's last line names them, and `gallery block check` notes a `preview.svg` still Gallery's, byte for byte), then what you came for, and check and try it as any. `gallery block new` refuses the scopes `gallery` and `gallery-soft`.
216
+ Gallery ships blocks of its own in two packs (below): Gallery 风格, the scope `gallery`, on; and 柔光风格, `gallery-soft`, the same page cards in a softer look, off until the user turns it on in 设置 › 组件列表 (its cards are `gallery-soft/<name>`; `gallery block add gallery-soft/<name>`). Gallery 风格's: for documents `gallery/card`, a titled card around blocks of the document's, and `gallery/chart-card`, a titled card holding a table in its slot and the bar chart its script draws from it; three views of a table of the document ([A view of a table](pages-and-data.md#a-view-of-a-table)), `gallery/kanban` (看板: its rows as cards grouped by a column, a card dragged changing that cell), `gallery/metric` (指标: a count, sum or average of a column) and `gallery/chart-view` (图表: bars of a count, sum or average by a column), which the reader inserts from "/" (each reads the nearest table above it) and which you write after an ordinary table as `gallery block show gallery/<name>` prints (for a task board or a data dashboard in a document use them, never a block of your own); for custom pages `gallery/today` (问候与日期, a greeting and the date, drawn by the clock), `gallery/note` (便签, lines the user types on the card), `gallery/static` (静态卡片, any HTML of yours, only shown: a page's alone, as a document writes such HTML as it is), `gallery/countdown` (倒计时, the days to a date of its settings), `gallery/habit` (习惯打卡, a check-in a day and the streak, written as a recipe to start a block of your own from); `gallery/weather` (天气, a city of its settings, from Open-Meteo: it goes online, so tell the user to press 允许访问 on its card); and four that read the workspace (`needs` `workspace`), `gallery/todos` (我的待办, the to-dos not done of every document), `gallery/recent` (最近编辑, the documents edited last), `gallery/stats` (工作区统计, its counts) and `gallery/heatmap` (编辑热力图, the edits of each day of the past year), which a new workspace's 首页 holds with today and the note. Each one's writing.md, which `gallery block show` prints, says what it is for and how to fill it, and `gallery block list` names each one the workspace has not added, with its line. `gallery block add <name>` puts one in as it ships, `components/gallery/<name>/`, recording its version and what its files hold: write its instances as `gallery block show gallery/<name>` prints, with no check and no try. Change nothing in its folder: run again with a newer Gallery, `add` updates a copy that is as it was added, and never one changed since (what a system writes there as it shows the folder, a `.DS_Store`, a `Thumbs.db`, is no change). For a block like it of your own, `gallery block new <id> --recipe <name>` copies its files into a new block, every word that named it naming the new id (its classes too: `gallery-chart-card-bars` becomes `<scope>-<name>-bars`), its version 0.1.0: change its name, words and description first, and what is still the recipe's in the same folder (`preview.svg`, the menu's picture, still its drawing; writing.md, still about it; `example.html`, still its words: the command's last line names them, and `gallery block check` notes a `preview.svg` still Gallery's, byte for byte), then what you came for, and check and try it as any. `gallery block new` refuses the scopes `gallery` and `gallery-soft`.
217
217
 
218
218
  ## Block packs
219
219
 
220
- A block pack (自定义块包) is a scope of blocks shared as one: the folder `components/<pack>/` with a `pack.json` at its top beside a folder for each block, whose ids are `<pack>/<name>` as any block's. Gallery's two packs are packs of this kind, installed into each workspace as it first starts; a scope with no `pack.json` (`local/`) is a pack of its own, named by its scope. To share blocks the user made, when they ask: move them into a scope of their own (`team-cards/`), write its `pack.json` and hand over the folder, or a zip of it:
220
+ A block pack (自定义块包) is a scope of blocks shared as one: the folder `components/<pack>/` with a `pack.json` at its top beside a folder for each block, whose ids are `<pack>/<name>` as any block's. Gallery's two packs are packs of this kind, installed into each workspace as it first starts; `local/` is the default pack (默认块包: no `pack.json`, listed first), where a block made with no scope goes, so that one block needs no pack of its own; any other scope with no `pack.json` is a pack of its own, named by its scope. To share blocks the user made, when they ask: move them into a scope of their own (`team-cards/`), write its `pack.json` and hand over the folder, or a zip of it:
221
221
 
222
222
  ```json
223
223
  { "id": "team-cards", "name": { "zh": "团队卡片", "en": "Team cards" }, "description": "…", "version": "1.0.0", "author": "…" }
@@ -245,7 +245,7 @@ Exit 0 is all five (and those), exit 1 a failure. A failure with no line is of t
245
245
  | --- | --- | --- |
246
246
  | available | shown | run and export |
247
247
  | out of the document's menus: 在文档菜单里显示 off in 设置 › 组件列表, or a block of a page's alone not switched on | not shown in a document's ("/", 在下方新建, the handle's grid); a custom page lists one whose places hold `page` | run and export |
248
- | out of every menu: the block's master switch (at the right of its line in 设置 › 组件列表) off | not shown in a document's menus, a table's 视图 › or a custom page's 添加自定义块; `gallery block` and `gallery page add` still name it | run and export |
248
+ | out of every menu: the block's master switch (at the right of its line in 设置 › 组件列表) off | not shown in a document's menus or a custom page's 添加自定义块; `gallery block` and `gallery page add` still name it | run and export |
249
249
  | disabled, in 设置, or an `apiVersion` this Gallery does not run | not shown | show what they hold, read-only, with no script and no style, a script of data drawn by Gallery |
250
250
  | missing, or a block that does not load | not shown | show what they hold, read-only, a script of data drawn by Gallery; `gallery check` says why in a note |
251
251
 
@@ -2,10 +2,14 @@
2
2
 
3
3
  An extension gives the sidebar a column of its own, beside the workspace's own column and those of the other workspaces: a list of links, nested if you like, that the user opens in the content area. Make one only when the user asks for it ("put my usual links in the sidebar", "an entry for my team's wiki"), or when a tool you are building must show entries of its own. A single web page the user wants in the sidebar is not an extension: `gallery link add <url> "<name>"` is.
4
4
 
5
- An extension is a folder in the workspace, `extensions/<id>/`, and the one file Gallery reads in it is `sidebar.json`. The folder may hold whatever else the extension needs (a small server, its code); Gallery reads nothing else there.
5
+ An extension is a folder `extensions/<id>/` in a workspace, and the one file Gallery reads in it is `sidebar.json`. **Create public link columns in the default workspace**, shared by all projects. Use `gallery extension new <id> "<title>"`: it creates an empty file there and prints its absolute path; read that file and fill its `entries`. It never overwrites an existing file. Do not assume the current project is the default workspace.
6
+
7
+ Only when the user explicitly wants a project-specific extension, add `--local` (and `--workspace <path>` to select the project if needed). The folder may hold whatever else the extension needs (a small server, its code); Gallery reads nothing else there.
8
+
9
+ Every workbench shows the default workspace's extensions together with its project's own extensions. A project `sidebar.json` with the same `<id>` takes precedence in that project; an empty project folder does not hide the public column. Existing project files are not moved. Public titles and root order are shared: editing them from any workbench writes the same public file, and other open workbenches refresh even if the default workspace has no running server. The column's position among other columns and its folded state remain each workbench's own.
6
10
 
7
11
  - `<id>` is the folder's name: lowercase letters, digits and dashes (`yuque`, `team-wiki`), 48 characters at most, never `ws-` followed by six hex digits.
8
- - Run `gallery extension list` first: it lists the extensions that are there, so you change one rather than make a second.
12
+ - Run `gallery extension list` first: it lists the visible extensions and their actual file paths, so you change one rather than make a second. `gallery extension check <id>` resolves that same public/project source. Read the reported path rather than constructing a path under the current project.
9
13
 
10
14
  ## The file
11
15
 
@@ -33,8 +37,8 @@ An extension is a folder in the workspace, `extensions/<id>/`, and the one file
33
37
 
34
38
  | Field | Rule |
35
39
  | --- | --- |
36
- | `title` | The column's name. Required, 100 characters at most. The user cannot rename it. |
37
- | `icon` | Optional, for the column and for any entry. An emoji, or an icon of Gallery's icon picker (`/icons/<name>_<color>.svg`). Never a picture from the web: nothing is loaded from a web address. An entry with no icon shows the column's. |
40
+ | `title` | The column's name. Required, 100 characters at most. The user can rename it from the column menu; Gallery writes the new title here. |
41
+ | `icon` | Optional, for the column and for any entry. An emoji, or an icon of Gallery's icon picker (`/icons/<name>_<color>.svg`). Never a picture from the web: nothing is loaded from a web address. An entry with no icon shows the column's. With neither specified, a parent with children shows a folder, a leaf shows the ordinary document icon, whether it has a URL or is an empty group. |
38
42
  | `entries` | Required, a list (it may be empty). Each entry is an object. Up to 8 levels deep, 2000 entries in all. |
39
43
  | `id` (entry) | Required, 1 to 128 characters of `A-Z a-z 0-9 . _ : -`, used once in the file, at any level. Keep it the same for as long as the entry is the same entry: the address bar, the open page and the user's place in the sidebar go by it. |
40
44
  | `title` (entry) | Required, 200 characters at most. |
@@ -45,14 +49,14 @@ The file is at most 1 MB. Fields it does not know are ignored.
45
49
 
46
50
  ## What the user sees
47
51
 
48
- - The column sits among the sidebar's columns. The user can fold it and drag its heading to another place. They cannot drag entries into or out of it, rename them or remove them: the entries are yours.
49
- - A click on an entry with a `url` shows that page in the content area, the way a web link is shown, with 在浏览器中打开 in the top bar. The right-click menu has 在浏览器中打开, 复制网址 and 在新标签页打开. A site that does not let other pages frame it gets a card with 在浏览器中打开 instead. Pages on this computer under another port (your own server) work; Gallery's own address does not.
52
+ - The column sits among the sidebar's columns. The user can fold it and drag its heading to another place. They can reorder its top-level entries by dragging before or after another root; Gallery writes the new `entries` order here, keeping each whole subtree. They cannot change nesting, drag entries into or out of it, rename entries or remove them. Hovering the column name shows this file’s path.
53
+ - A click on an entry with a `url` shows that page in the content area, the way a web link is shown, filling the content area without a top bar. The right-click menu has 在浏览器中打开, 复制网址 and 在新标签页打开. A site that does not let other pages frame it gets a card with 在浏览器中打开 instead. Pages on this computer under another port (your own server) work; Gallery's own address does not.
50
54
  - The address bar holds `#~<id>/<entry id>`, so an entry can be opened again from a link.
51
55
  - A file that does not read shows the column with one row, `条目读不出来:<why>`, and no entries.
52
56
 
53
57
  ## Changing it
54
58
 
55
- Write the file again: Gallery reads it again within a second of every change, the sidebar updates without a reload, and an entry the user has open stays open while its `id` is still in the file. When it is gone from the file, the user is told (这个条目已被扩展移除) and taken to the home page. Write a temporary file in the same folder and rename it over `sidebar.json`, so that no one reads half a file.
59
+ Read the latest file before changing it: the user may have renamed its column or reordered its roots in Gallery. Keep those changes unless asked to replace them. Write the file again: Gallery reads it again within a second of every change, the sidebar updates without a reload, and an entry the user has open stays open while its `id` is still in the file. When it is gone from the file, the user is told (这个条目已被扩展移除) and taken to the home page. Write a temporary file in the same folder and rename it over `sidebar.json`, so that no one reads half a file.
56
60
 
57
61
  Check the file before you say it is done: `gallery extension check <id>` reads it as the sidebar does and prints what the sidebar will show, the column and each entry with its id, title and address. It exits 1 with the reason when the file would show `条目读不出来`; `note:` lines are only things it left out (an icon that is neither an emoji nor an icon of the picker). Read its output against what the user asked for: the entries in the order they asked, no entry missing.
58
62
 
@@ -1,10 +1,14 @@
1
1
  # Custom pages, and what a block reads beyond its own parts
2
2
 
3
- A block stands in a document, on a custom page (自定义页: a board of cards, the 首页 among them; SKILL.md, Custom pages, is the flow on a page) or in both. [building-blocks.md](building-blocks.md) is the block itself (the kinds of part, the files, the manifest, an instance, its style, and the two places side by side in A document and a custom page) and [block-script.md](block-script.md) is its script. This page holds what only some blocks need: the manifest fields that place a block, size it as a card and give it settings; the flow of a block made for a page; and the three things a block may read beyond its own parts, each a `needs` entry: the workspace's data (`workspace`), a table of its document (`tables`) and the web (`net:<host>`).
3
+ A block stands in a document, on a custom page (自定义页: a page of the user's that you design, a board of cards being one way to write it; SKILL.md, Custom pages, is the flow on a page) or in both. [building-blocks.md](building-blocks.md) is the block itself (the kinds of part, the files, the manifest, an instance, its style, and the two places side by side in A document and a custom page) and [block-script.md](block-script.md) is its script. This page holds what only some blocks need: the manifest fields that place a block, size it as a card and give it settings; the flow of a block made for a page; and the three things a block may read beyond its own parts, each a `needs` entry: the workspace's data (`workspace`), a table of its document (`tables`) and the web (`net:<host>`).
4
+
5
+ ## A page is yours to design
6
+
7
+ A custom page's `page.html` is written as the request wants it: any HTML, CSS and script of your own, a board of cards, or both on one page. A board is what the user rearranges: its cards are moved, resized, added and deleted on the page, and what a card holds (a block's parts) is the user's to change; what the page's own HTML and script show, only you change. Write it inside `<main class="gallery-page">` (the page then follows the workbench's theme: its dark colors under `:root[data-doc-effective-theme="dark"]`), and its own files (a picture, a stylesheet, a script) in `pages/<slug>/assets/`, written `assets/<file>`. `gallery page check` takes a page's own scripts and stylesheets as they are, and fails what still matters: a board's cards where it has them, a file of `assets/` that is not there, a page that throws or does not load. A blank page the user made in the sidebar (新建页面: its slug `page-…`, an empty `<main class="gallery-page">`, which shows the user to ask an Agent) is one to write whole.
4
8
 
5
9
  ## Places, cards, settings and needs
6
10
 
7
- A block stands in a document's flow, or as a card on a custom page's board (自定义页: a page of the workspace's own, the 首页 among them, laid out on a grid of square cells, twelve to a row), or both: one block, one manifest and one `context` for either. Four fields of the manifest say how; each may be left out.
11
+ A block stands in a document's flow, or as a card on a custom page's board (自定义页: a page of the workspace's own, its board laid out on a grid of square cells, twelve to a row), or both: one block, one manifest and one `context` for either. Four fields of the manifest say how; each may be left out.
8
12
 
9
13
  ```json
10
14
  {
@@ -21,11 +25,11 @@ A block stands in a document's flow, or as a card on a custom page's board (自
21
25
  | Field | What it holds |
22
26
  | --- | --- |
23
27
  | `places` | `"document"`, `"page"` or both, each once: `["document"]` when left out. A block of a page's alone is in no document's menu until the user switches it on (设置 › 组件列表, 在文档菜单里显示); a custom page lists only blocks whose places hold `page` and that the user has not switched off (the master switch at the right of a block's line in 设置 › 组件列表 takes it out of every menu and of that list; what is written of it keeps showing, and `gallery page add` still names it), and a card of one whose places do not, written on a page all the same, says so there and does not run |
24
- | `card` | its size on a board, in cells: `sizes`, the sizes the user picks from, `[w, h]` each, 1 to 12 wide and 1 to 24 high, the first the default (a phone's small, medium and large widget; the card's 大小 menu lists them, and dragging its corner snaps to the nearest, so a block that takes any size of the board's cells writes `min` and `max` beside them, `"min": { "w": 1, "h": 1 }, "max": { "w": 12, "h": 24 }`: the sizes then only the common ones the menu lists, each inside `min` and `max`); or, with no `sizes`, `w` (4 when left out) and `h` (the fewest whole cells its content takes when left out), with `min` and `max` as `{ w, h }`, which hold the default between them. `resize`: whether the user may drag its edge (false when left out); `fit`: `"fixed"` (the default: what does not fit scrolls in the card) or `"content"` (the card grows with what it holds and pushes the cards under it down, for a list that changes length); `bare`: true for no frame of the board's around it. With `sizes` and `"content"` together the width is the size the user picked, and the height is the content's, in whole cells, drawn and never written: a size's `h` is only the `data-h` the file holds, where `gallery page add` and the page's service put the card and what stands beside it, so write the cells its content takes at a usual length; a longer content is drawn higher and pushes the cards under it down, a shorter one is drawn lower and leaves its room empty. Read only where its places hold `page` |
28
+ | `card` | its size on a board, in cells: `sizes`, the sizes the user picks from, `[w, h]` each, 1 to 12 wide and 1 to 24 high, the first the default (a phone's small, medium and large widget; the card's 大小 menu lists them, and dragging its corner snaps to the nearest, so a block that takes any size of the board's cells writes `min` and `max` beside them, `"min": { "w": 1, "h": 1 }, "max": { "w": 12, "h": 24 }`: the sizes then only the common ones the menu lists, each inside `min` and `max`); or, with no `sizes`, `w` (4 when left out) and `h` (the fewest whole cells its content takes when left out), with `min` and `max` as `{ w, h }`, which hold the default between them. `resize`: whether the user may drag its edge (false when left out); `fit`: `"fixed"` (the default: what does not fit scrolls in the card) or `"content"` (the card grows with what it holds and pushes the cards under it down, for a list that changes length); `bare`: true for no frame of the board's around it; `consent`: for a block online, the line Gallery's consent banner on its card says, `{ "zh": "允许联网之后显示汇率", "en": "Allow internet access to show the rates" }` (what the user gets once they allow it; left out, 允许联网之后显示内容). With `sizes` and `"content"` together the width is the size the user picked, and the height is the content's, in whole cells, drawn and never written: a size's `h` is only the `data-h` the file holds, where `gallery page add` and the page's service put the card and what stands beside it, so write the cells its content takes at a usual length; a longer content is drawn higher and pushes the cards under it down, a shorter one is drawn lower and leaves its room empty. Read only where its places hold `page` |
25
29
  | `settings` | the fields of the card's form (its menu's 设置…), each `{ key, label: { zh, en }, type, options, default, required }`: `key` a lowercase letter then letters and digits, each once; `type` one of `text`, `number`, `select` (with `options`, a list of words), `date` (`YYYY-MM-DD`), `switch`, `document` (a document's slug); `default` of that type; `required: true` for a setting the card cannot show anything without (weather's city: a card with none asks the reader for it, and `gallery page check` notes it). A block with settings has a part named `settings`, edited as data, a `<script type="application/json">` holding their values by key, which its `template.html` holds as a new card's (`{}` takes each default), and reads them with `context.readJSON("settings")` |
26
30
  | `needs` | what it uses, each once: `workspace` (the workspace's data: its to-dos, recent documents, counts, edits by day, a table of another document: The workspace's data, below), `tables` (it is a view of a table of its document: A view of a table, below), `net:<host>` (the network, of that host alone: a lowercase host name, no port and no path, `*.` first for the names under it, never the name itself; the user consents first: Going online, below). 设置 › 组件列表 shows them |
27
31
 
28
- A cell is 64px square whatever the window, 16px from the next, so a card `w` cells wide is `w × 64 + (w − 1) × 16` px (4 cells: 304px; 12: 944px, the board's whole row, in the middle of the page) and as high by `h`; the frame's 18px padding and its line come off that for the block (a 4 × 2 card holds 266 × 106 px). A wider window or the sidebar folded only leaves more room beside the board. A narrower one (the sidebar dragged wide, a small window) shows fewer columns, as many as fit, 4 at the least: the cards one after another in the order of their places, each as large as it is but no wider than the row (`context.size.w` says it, on `layout`), never written; the page's file keeps its twelve-column places. So size a card for the content at 64px cells, and take a big number or a long list's room from its cells, never from the window.
32
+ A cell is 64px square whatever the window, 16px from the next, so a card `w` cells wide is `w × 64 + (w − 1) × 16` px (4 cells: 304px; 12: 944px, the board's whole row, in the middle of the page) and as high by `h`; the frame's 16px padding comes off that for the block (a 4 × 2 card holds 272 × 112 px; the frame's line is a ring outside it). A wider window or the sidebar folded only leaves more room beside the board. A narrower one (the sidebar dragged wide, a small window) shows fewer columns, as many as fit, 4 at the least: the cards one after another in the order of their places, each as large as it is but no wider than the row (`context.size.w` says it, on `layout`), never written; the page's file keeps its twelve-column places. So size a card for the content at 64px cells, and take a big number or a long list's room from its cells, never from the window.
29
33
 
30
34
  What a reader edits in each place is in [Which kind of part](building-blocks.md#which-kind-of-part) and [A document and a custom page](building-blocks.md#a-document-and-a-custom-page). So a block for a custom page keeps what a reader changes in a data part, with a field of its own or the card's settings, and no slot. On a page each `context.edit` is written at once, a step of the page's own undo (Ctrl+Z there takes it back, and the part with it); one made after someone else changed the same card is refused and the page shown again as the file is, so the block draws from what its parts hold (`source`), never from what it wrote last. `gallery block check` refuses a slot on such a block, notes each of its text parts (read-only on a custom page), notes a `card` on a block whose places hold no page, and fails a block with settings whose template holds no JSON object in its settings part. A field the manifest gets wrong (a place it does not know, a size off the grid, a setting's type or default, a need it does not know) keeps the block from loading, and `gallery block list` says why.
31
35
 
@@ -41,7 +45,7 @@ Make one only where no block of Gallery's does the job and the card does somethi
41
45
  4. `gallery page try <slug> <card id> <gesture>` for each gesture a reader makes on it (`--press`, `--drag … --to`, `--key`, `--type`, `--select`, `--then` and `--steps`, as `gallery block try` takes them, on a scratch copy of the page): its `Wrote:` lines name the card's data parts and say `nothing else in page.html changed (card ids aside)`; a write anywhere else, the card's place or another card, fails. Then the page's own undo (Ctrl+Z) gives the copy back, and a fresh page reads the card back as it was. A setting is the card's menu's 设置…, which the block only reads: its way back needs no trial.
42
46
  5. `gallery page check <slug>`, until it prints `OK`, then open its pictures (1280, 1920 and 600px wide, light and dark): a card whose content does not fit it scrolls inside it, which the check fails; give it the cells it needs, or `"fit": "content"` for one whose length changes (the check pictures the card as the file's data fills it now, a new card's, so a list that grows is seen long by trying a gesture on it that adds entries, or by filling it as the user will). A card that reads the workspace (Gallery's `todos`, `recent`, `stats`, `heatmap`, or your own block that reads `context.workspace`) is pictured once the workspace has answered, for up to 15 seconds; one still unanswered is a `note page.html:<line>: card <id> (<block>): the workspace had not answered its read of …` line, and the `OK` line then ends `; but N cards were pictured before the workspace answered it (see "note" above), so their pictures do not show what they read`. Such a picture says nothing of what the card shows: open the page in Gallery to see it, or run the check again.
43
47
 
44
- Its look: the kit's card tokens, as Gallery's own cards draw theirs, so that it sits among them in both themes. A head of a chip (`--gallery-chip-size` square, `--gallery-chip-radius`, `--gallery-accent-soft` behind an icon of lines in `--gallery-accent`) and a title (`--gallery-title-size`, 600), a quiet meta at its end where the card has a few words to say of itself (`--gallery-meta-size`, `--doc-muted`: 共 24 天, 今天 3 篇), the row one line, its end kept clear of the card's grip, which the board puts in the card's top-right corner (`padding-inline-end: var(--gallery-grip-room, 0px)` on its first row), but the meta, which may reach into that room so that it ends where your content does if it fades while the grip shows (`margin-inline-end: calc(-1 * var(--gallery-grip-room, 0px)); opacity: calc(1 - var(--gallery-grip-shown, 0))`); a big number at `--gallery-numeral-weight` and `--gallery-numeral-tracking`, `--gallery-hero-size` for the card's one main number and `--gallery-figure-size` for one among others, its unit after it at `--gallery-unit-size`, `--gallery-unit-gap` from it, in `--doc-muted`; the card's words in `--gallery-text`, its title and big numbers in `--gallery-text-strong` (softer than the document's text in dark); the accent for a ring or a bar toward a target (on `--gallery-track`), green and red (`--gallery-good`, `--gallery-bad`, their `-soft` for a pill) only for a good or a bad state; `--gallery-face-gap` between rows; what the card is about in the middle of the room under its head at every size (a foot, a date or a week, at the bottom); the pieces of a meta line a muted 3px dot apart. With nothing to show yet, the cards' empty face: one muted line of 13px in the middle, over it a 44px soft disc with a picture of lines in it (one mask, the disc at 14% and the lines whole, on a background of `--doc-muted`), what to do under it at `--gallery-meta-size`. The frame is the board's: draw no border, fill or shadow of the card's own. A button has no line: a primary one pale (`--gallery-accent-soft`, its words in the accent), the others no fill until the pointer is on them (`--doc-hover`).
48
+ Its look: the kit's card tokens, as Gallery's own cards draw theirs, so that it sits among them in both themes. Its type is `--gallery-font`, 13px. A head 20px high of a chip (`--gallery-chip-size` square, `--gallery-chip-radius`, `--gallery-fill` behind an icon of lines in `--gallery-muted`, `--gallery-chip-icon` wide) and a title (`--gallery-title-size`, 600, `--gallery-text`), a quiet meta right after it where the card has a few words to say of itself (`--gallery-meta-size`, `--gallery-faint`: 共 24 天, 今天 3 篇), 8px apart, the row one line, its end kept clear of the card's grip, which the board puts in the card's top-right corner (`padding-inline-end: var(--gallery-grip-room, 0px)` on its first row); one hero, a big number at `--gallery-numeral-weight` and `--gallery-numeral-tracking` in `--gallery-text-strong` (`--gallery-hero-size` for the card's one main number, `--gallery-figure-size` for one among others), its unit after it at `--gallery-unit` (13px), 3px from it, in `--gallery-muted`; labels in `--gallery-muted`, captions in `--gallery-faint`, lines `--gallery-hair`; the accent for a ring or a bar toward a target (on `--gallery-track`), green and red (`--gallery-good`, `--gallery-bad`, their `-soft` for a pill) only for a good or a bad state; `--gallery-face-gap` between rows; what the card is about in the middle of the room under its head at every size (a foot, a date or a week, at the bottom); the pieces of a meta line a muted 3px dot apart. With nothing to show yet, the cards' empty face under its head: a line of what is so (13.5px, 600) over what to do (12px, `--gallery-faint`), and one pale button where the reader can do it. The frame is the board's: draw no border, fill or shadow of the card's own. A button has no line: a primary one pale (`--gallery-accent-soft`, its words in `--gallery-accent-ink`), the others no fill until the pointer is on them (`--gallery-hover`).
45
49
 
46
50
  A goals card, its title a setting and its goals a script of data, a field adding one and a box ticking one off:
47
51
 
@@ -129,7 +133,7 @@ A block whose manifest's `needs` hold `"workspace"` reads what the workspace hol
129
133
 
130
134
  | Kind | Options | `data` |
131
135
  | --- | --- | --- |
132
- | `todos` | `{ done, slugs, limit }` | `[{ ref, text, done, slug, title, path }]`: each to-do of every document, those of the document edited last first, `path` the headings above it, `ref` what `setTodo` names it by |
136
+ | `todos` | `{ done, slugs, limit }` | `[{ ref, text, done, slug, title, icon, path }]`: each to-do of every document, those of the document edited last first, `icon` its document's (as `recent` gives it), `path` the headings above it, `ref` what `setTodo` names it by |
133
137
  | `recent` | `{ limit }` | `[{ slug, title, icon, edited }]` |
134
138
  | `stats` | none | `{ documents, todos: { done, total }, words, editedThisWeek }` |
135
139
  | `activity` | `{ days }` | `[{ date, edits, words, reader, agent }]`: the edits and the words added by day, from the day Gallery started keeping them |
@@ -160,7 +164,7 @@ A block whose `needs` hold `"tables"` can be a view of a table of the document:
160
164
  </div>
161
165
  ```
162
166
 
163
- A key is a letter, then letters, digits, `_` or `-`, 32 at most, and names one table of the document. The reader binds one in the page too: a table's block menu has 视图 ›, listing the blocks that read tables, which puts one in right after the table with the table's key, giving the table a new one when it has none or an earlier table carries the same key. Its template holds no `data-doc-from`: each instance has its own.
167
+ A key is a letter, then letters, digits, `_` or `-`, 32 at most, and names one table of the document. The reader binds one in the page too: a block that reads tables is a row of "/" like any, and one made there reads the nearest table above it, the table given a new key when it has none or an earlier table carries the same key; its handle's 设置… lists the document's tables to read another. Its template holds no `data-doc-from`: each instance has its own.
164
168
 
165
169
  ```js
166
170
  DocKit.component({
@@ -183,7 +187,7 @@ DocKit.component({
183
187
  - It hears its table by `data`, its detail `"table"`, whenever a change leaves the rows other than they were (a cell typed in, a row added, moved or taken out, the key changed, the table deleted or put back by an undo), also once it has a table where it had none; or by `table.subscribe(listener)`, which returns the function that takes the listener off. Read the table again each time.
184
188
  - It changes the table only by asking: `table.set(row, column, text)` (one cell's words, plain), `table.add(values, { after })`, `table.move(row, { before | after, values })` (its cells of `values` set in the same step: a card dropped in another column) and `table.remove(row)`. Each is one undo step of the page's, made as the table's own tools make it, and answers whether it was made: the file follows by itself, someone else's change of the same cell is merged word by word with the reader's, and a move, add or removal over someone else's change of the table waits on a card for the reader. `false` in an exported file and in 演示视图, before the page edits, for a row no longer in the table, for the last row of the body (`remove`) and for a table Gallery's tools do not manage (a merged cell, a `<tfoot>`, rows of different lengths). A name the header does not have throws.
185
189
  - `table.canEdit()` says whether the page would take a change of the table now, asked with no change: false in an exported file, in 演示视图, before the page edits and for a table Gallery's tools do not manage, so draw the view read-only there (no handle, no button that adds or takes out a row) rather than show controls whose every write answers `false`.
186
- - The reader puts a view in from the table's block menu, 视图 ›, the only way in: a block that reads a table is not in "/", which has no table to give it. An Agent writes the table's key and the instance's `data-doc-from` itself, as above.
190
+ - The reader puts a view in from "/" (or 在下方新建), below the table it is to read or any block after it: it reads the nearest table above it. An Agent writes the table's key and the instance's `data-doc-from` itself, as above.
187
191
  - Task boards, numbers and charts over a table are views Gallery ships: `gallery/kanban`, `gallery/metric` and `gallery/chart-view` (`gallery block add <name>`, before the instance is written: one written first stays read-only until the block is added; `gallery block show gallery/<name>` prints how to write each, a table and then the instance below it, its settings one line of JSON). Use them first; write a view of your own only for one they do not give.
188
192
  - Never write the table yourself: not its cells, not its rows, not by `context.edit`, which writes the block's own parts alone. What the view draws is its own; the table is the document's.
189
193
  - Keep what a reader only chooses in the view (its sort, a filter, what is folded) in `context.state`, never in the table.
@@ -216,6 +220,6 @@ DocKit.component({
216
220
 
217
221
  - **It resolves** with `{ data, at, cached }`: `data` the answer's JSON (`as: "json"`, the default) or its text (`as: "text"`), `at` when it was fetched (an ISO time: say it on the card, 更新于 …, as an answer may be old where the network is not there), `cached` whether it was given from what was kept. Fetch again on `source` (a setting changed) and on a timer (`context.interval`, every few minutes at least: an answer of the last minute is given again, and a block may make 20 fetches a minute).
218
222
  - **It rejects** with an `Error` whose `code` says why, which the block draws a state for: `consent` (the user has not allowed it yet; `hosts`, those waiting), `offline` (no network or the site not reached, and nothing kept; in an exported file, nothing embedded), `status` (the site answered an error, `status`), `type` (no JSON or text), `too-large`, `rate`, `key`, `private` (below), and `host` or `url` for an address it may not ask for (a host its needs do not name, or a redirect to one; another port, a user in it, not http(s), its own or a redirect's): fix the block. `private` is usually the reader's network setup, not the block: the address the name resolved to is on this computer or a private network, and no proxy on this computer took the name (the address is http, there is no proxy, the proxy is on another machine, or it is not running; an https address whose name resolves so is reached through a proxy on this computer by its name, its certificate held to the name). The Error's message names the host and the address, and `host` is set. Draw a plain state for it in the reader's words, as `gallery/weather` does (网络设置把天气服务指向了本地地址), not the generic failure.
219
- - **Consent.** Until the user allows the block, every fetch rejects `consent` and Gallery draws over its card a button of its own, 允许访问 <host> (等 N 个网站 for more); pressed, Gallery asks the user, and once they say yes the block starts again by itself (its mount runs anew, and fetches). The user can take it back in 设置 › 组件列表 (允许联网), and the block starts again and asks. Draw a short state of your own for `consent` too (the button stands over it). In the handoff, tell the user to press 允许访问 on the card; never write the consent into `gallery.json` (its `components.net`) yourself, nor ask `gallery block try` or `gallery page try` to: it is the user's to give, and `gallery page check`'s pictures show the card asking.
223
+ - **Consent.** Until the user allows the block, every fetch rejects `consent` and Gallery draws over its card, under its head row, a banner of its own: your manifest's `card.consent` (else 允许联网之后显示内容), 数据来自 the site its hosts share (else <host> 等 N 个网站) and a button, 允许访问 (on a card three cells wide or less, the line over the button); pressed, Gallery asks the user, and once they say yes the block starts again by itself (its mount runs anew, and fetches). The user can take it back in 设置 › 组件列表 (允许联网), and the block starts again and asks. Draw a short state of your own for `consent` too (the button stands over it). In the handoff, tell the user to press 允许访问 on the card; never write the consent into `gallery.json` (its `components.net`) yourself, nor ask `gallery block try` or `gallery page try` to: it is the user's to give, and `gallery page check`'s pictures show the card asking.
220
224
  - **A key.** An API that wants one in its address names where it goes by `{key}`, in its path or its query (`https://api.example.com/v6/{key}/latest`, `…/latest?apikey={key}`), and `gallery block key <host> <key>` keeps the user's key for that host in the workspace (`.gallery/keys.json`): the server writes it in as it fetches, and no page, cache or export ever holds it. Never write a key into the block's files or a page. Prefer an API that needs none. An API that takes its key in a header alone is not reached.
221
225
  - **A document and its export.** In a document an instance fetches as on a page; its export holds what the document's instances were given last (`context.fetch` answers from it, `cached: true`) and, for an address it holds nothing of, rejects `offline`: draw a placeholder for that, as the example does. `context.place` is `"export"` there.
@@ -90,6 +90,8 @@ The blocks HTML has no element for, written with the kit's classes as the exampl
90
90
 
91
91
  **A block's color** (颜色): a class on the block, never a `style`, of the colors gray, brown, orange, yellow, green, blue, purple, pink and red. A paragraph, a heading, a list item or a flowchart step takes its words' color (`doc-text-<color>`), a fill (`doc-highlight-<color>`) or both; a disclosure, a code block (on its `<pre>`), a callout or a highlight panel a fill only; a table cell one of the two. Words in a line take theirs from `<mark>` or a `<span style>`.
92
92
 
93
+ **A block's alignment and indent** (对齐与缩进): `doc-align-center` or `doc-align-right` on a paragraph, an `h1`–`h4` or a table's frame (`div.doc-table-wrap`, when the table is narrower than the text), the left being none; `doc-indent-1` … `doc-indent-8` move a paragraph or a heading in by two body characters a level. A `text-align: center` or `right` in a paragraph's or heading's `style` is rewritten as the class.
94
+
93
95
  **Columns** (`div.doc-columns` of 2 to 5 `div.doc-column`): what the reader compares across, or a picture with its words beside it (the picture's column first, so that on a phone it stands above them). `style="--doc-column-ratio: .4"` on a column gives it that share of the row: write it on every column of the row, the shares adding up to 1, or on none, and the columns share the row equally (one written on some columns only fails the check). Pictures side by side in columns: crop them to one ratio, so that their captions line up. A column holds any block but a row of columns, a section or a Sheet area. On a screen under 640px the columns stand one under another: never point at one as the left or right.
94
96
 
95
97
  **A process or steps** (步骤流程图, `ol.doc-flow`): one step an item, drawn as a card, arrows between them. A step's title is a paragraph of bold words, then any blocks it holds; an icon may stand first in it, drawn in its number's place. The kit numbers the steps (write no 1, ① or 第一步) and lays them out in rows that fill the width; `data-direction="row"` on the list keeps them in one row, `"column"` one a row; on a step it says where the arrow after it goes. A step written the short way (`<li>收集数据<p>…</p></li>`) is rewritten as a node. A flowchart has no title or caption of its own and stands in no `<figure>`: the sentence before it says what it shows; a legend goes in a `p.doc-note` beside it. A step takes a color as a list item does. A flowchart is for steps in order, each after the one before; a flow that branches, merges or loops is a drawing of boxes and arrows like the example's, and a structure or diagram a figure ([below](#figures-and-charts)).