@heycys/gallery 0.1.1 → 0.2.0

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 (473) 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/columns/page.mjs +4 -4
  5. package/browser/editor/components/embed/index.mjs +2 -2
  6. package/browser/editor/components/embed/page.mjs +1 -1
  7. package/browser/editor/components/file/page.mjs +4 -4
  8. package/browser/editor/components/flowchart/add.mjs +7 -6
  9. package/browser/editor/components/flowchart/page.mjs +1 -1
  10. package/browser/editor/components/heading/index.mjs +7 -6
  11. package/browser/editor/components/icons.mjs +11 -0
  12. package/browser/editor/components/image/crop.mjs +6 -9
  13. package/browser/editor/components/image/index.mjs +2 -0
  14. package/browser/editor/components/image/page.mjs +172 -90
  15. package/browser/editor/components/installed/index.mjs +15 -4
  16. package/browser/editor/components/installed/page.mjs +103 -25
  17. package/browser/editor/components/installed/served.mjs +6 -5
  18. package/browser/editor/components/instances.mjs +18 -0
  19. package/browser/editor/components/list/page.mjs +3 -6
  20. package/browser/editor/components/media/icons.mjs +13 -8
  21. package/browser/editor/components/media/page.mjs +5 -3
  22. package/browser/editor/components/media/toolbar.mjs +12 -3
  23. package/browser/editor/components/paragraph/index.mjs +4 -3
  24. package/browser/editor/components/registry.mjs +30 -9
  25. package/browser/editor/components/table/index.mjs +61 -2
  26. package/browser/editor/components/table/page.mjs +1 -1
  27. package/browser/editor/page/after/index.mjs +288 -0
  28. package/browser/editor/page/align.mjs +91 -0
  29. package/browser/editor/page/annotate/card.mjs +3 -6
  30. package/browser/editor/page/autosave.mjs +310 -37
  31. package/browser/editor/page/beside.mjs +5 -6
  32. package/browser/editor/page/block-menu/index.mjs +6 -3
  33. package/browser/editor/page/blocks.mjs +3 -1
  34. package/browser/editor/page/board/client.mjs +57 -0
  35. package/browser/editor/page/board/hint.mjs +182 -0
  36. package/browser/editor/page/board/history.mjs +119 -0
  37. package/browser/editor/page/board/index.mjs +1059 -0
  38. package/browser/editor/page/board/motion.mjs +177 -0
  39. package/browser/editor/page/board/settings.mjs +210 -0
  40. package/browser/editor/page/caret.mjs +1 -1
  41. package/browser/editor/page/changes/bar.mjs +6 -14
  42. package/browser/editor/page/changes/index.mjs +2 -2
  43. package/browser/editor/page/clipboard/import/html.mjs +29 -6
  44. package/browser/editor/page/clipboard/import/inline.mjs +32 -0
  45. package/browser/editor/page/clipboard/import/markdown.mjs +58 -13
  46. package/browser/editor/page/clipboard/import/read.mjs +6 -1
  47. package/browser/editor/page/clipboard/import/to-blocks.mjs +44 -12
  48. package/browser/editor/page/clipboard/import/yuque.mjs +622 -0
  49. package/browser/editor/page/clipboard/index.mjs +133 -15
  50. package/browser/editor/page/clipboard/own/blocks.mjs +13 -14
  51. package/browser/editor/page/clipboard/own/chart-keys.mjs +41 -28
  52. package/browser/editor/page/clipboard/own/describe.mjs +6 -2
  53. package/browser/editor/page/clipboard/own/selection.mjs +1 -1
  54. package/browser/editor/page/columns/index.mjs +48 -46
  55. package/browser/editor/page/commit.mjs +80 -22
  56. package/browser/editor/page/conflicts.mjs +7 -7
  57. package/browser/editor/page/core.mjs +34 -16
  58. package/browser/editor/page/custom-page.mjs +110 -0
  59. package/browser/editor/page/editor.mjs +71 -17
  60. package/browser/editor/page/emoji-picker/styles.mjs +7 -12
  61. package/browser/editor/page/emoji-picker/upload.mjs +2 -2
  62. package/browser/editor/page/handle/index.mjs +5 -8
  63. package/browser/editor/page/history.mjs +41 -6
  64. package/browser/editor/page/insert/index.mjs +20 -22
  65. package/browser/editor/page/links/index.mjs +5 -3
  66. package/browser/editor/page/links/pages.mjs +27 -9
  67. package/browser/editor/page/look.mjs +54 -3
  68. package/browser/editor/page/margin.mjs +18 -3
  69. package/browser/editor/page/media-menu/index.mjs +6 -7
  70. package/browser/editor/page/menu.mjs +33 -14
  71. package/browser/editor/page/notices.mjs +2 -2
  72. package/browser/editor/page/page-objects.mjs +9 -2
  73. package/browser/editor/page/panel.mjs +4 -9
  74. package/browser/editor/page/present-links.mjs +15 -5
  75. package/browser/editor/page/present-shell.mjs +63 -0
  76. package/browser/editor/page/resize/index.mjs +42 -29
  77. package/browser/editor/page/selection/index.mjs +10 -2
  78. package/browser/editor/page/served.mjs +14 -0
  79. package/browser/editor/page/session.mjs +48 -4
  80. package/browser/editor/page/slash-menu/index.mjs +3 -3
  81. package/browser/editor/page/table/binding.mjs +87 -0
  82. package/browser/editor/page/table/cells.mjs +102 -46
  83. package/browser/editor/page/table/index.mjs +24 -9
  84. package/browser/editor/page/table/pictures.mjs +299 -0
  85. package/browser/editor/page/table/views.mjs +103 -0
  86. package/browser/editor/page/table/widths.mjs +82 -10
  87. package/browser/editor/page/text-select/index.mjs +26 -12
  88. package/browser/editor/page/todo-writes.mjs +75 -0
  89. package/browser/editor/page/typing/index.mjs +97 -15
  90. package/browser/editor/page/typing/leave.mjs +19 -5
  91. package/browser/editor/page/ui.mjs +13 -0
  92. package/browser/shared/block-packs.mjs +419 -0
  93. package/browser/shared/board-places.mjs +224 -0
  94. package/browser/shared/card-size.mjs +59 -0
  95. package/browser/shared/colors.mjs +3 -2
  96. package/browser/shared/component-catalog.mjs +330 -46
  97. package/browser/shared/component-source.mjs +39 -0
  98. package/browser/shared/components/heading.mjs +2 -1
  99. package/browser/shared/components/index.mjs +12 -3
  100. package/browser/shared/components/installed.mjs +35 -3
  101. package/browser/shared/components/page.mjs +20 -8
  102. package/browser/shared/components/paragraph.mjs +8 -1
  103. package/browser/shared/components/state.mjs +5 -1
  104. package/browser/shared/components/table.mjs +1 -0
  105. package/browser/shared/document-look.mjs +10 -5
  106. package/browser/shared/drafts.mjs +432 -0
  107. package/browser/shared/emoji/line-icons.mjs +37 -0
  108. package/browser/shared/extension-sidebar.mjs +126 -0
  109. package/browser/shared/extensions.mjs +79 -0
  110. package/browser/shared/file-table.mjs +101 -0
  111. package/browser/shared/http.mjs +9 -0
  112. package/browser/shared/i18n/en.mjs +330 -27
  113. package/browser/shared/json-layout.mjs +47 -0
  114. package/browser/shared/net-cache.mjs +133 -0
  115. package/browser/shared/net-keys.mjs +32 -0
  116. package/browser/shared/net-policy.mjs +177 -0
  117. package/browser/shared/outline-shape.mjs +128 -0
  118. package/browser/shared/outline.mjs +359 -67
  119. package/browser/shared/pack-manifest.mjs +88 -0
  120. package/browser/shared/page-address.mjs +6 -3
  121. package/browser/shared/page-cards.mjs +308 -0
  122. package/browser/shared/page-links.mjs +69 -6
  123. package/browser/shared/pages.mjs +500 -0
  124. package/browser/shared/paths.mjs +6 -0
  125. package/browser/shared/pinyin.mjs +92 -0
  126. package/browser/shared/present-step.mjs +17 -0
  127. package/browser/shared/preview-server.mjs +3 -7
  128. package/browser/shared/session.mjs +8 -1
  129. package/browser/shared/shipped-blocks.mjs +299 -0
  130. package/browser/shared/sidebar-head.mjs +70 -0
  131. package/browser/shared/table-chart.mjs +33 -1
  132. package/browser/shared/todos.mjs +83 -0
  133. package/browser/shared/user-directory.mjs +24 -0
  134. package/browser/shared/versions.mjs +14 -0
  135. package/browser/shared/web-links.mjs +139 -0
  136. package/browser/shared/workspace-columns.mjs +120 -0
  137. package/browser/shared/workspace-name.mjs +154 -0
  138. package/browser/shared/workspace-query.mjs +125 -0
  139. package/browser/shared/workspace-registry.mjs +272 -0
  140. package/browser/shared/workspace.mjs +171 -20
  141. package/dist/chunk-2OHANJ6Q.mjs +2 -0
  142. package/dist/chunk-3MBRL2PM.mjs +16 -0
  143. package/dist/chunk-4OKWZY5E.mjs +2 -0
  144. package/dist/chunk-4OZWXZE5.mjs +5 -0
  145. package/dist/chunk-5K44HLTZ.mjs +2 -0
  146. package/dist/{chunk-5ZKJ3H4P.mjs → chunk-5XA2ZBAE.mjs} +3 -3
  147. package/dist/{chunk-4FS7Z7WR.mjs → chunk-67N2QJYT.mjs} +1 -1
  148. package/dist/chunk-6KBYRA2C.mjs +2 -0
  149. package/dist/chunk-6N3PX4XX.mjs +8 -0
  150. package/dist/{chunk-V5JTW2LH.mjs → chunk-6QBHU4DF.mjs} +1 -1
  151. package/dist/chunk-7JDX4E65.mjs +13 -0
  152. package/dist/chunk-7M2BQQGZ.mjs +2 -0
  153. package/dist/chunk-7OG26PGF.mjs +2 -0
  154. package/dist/chunk-AHN3NFKJ.mjs +3 -0
  155. package/dist/chunk-ALZ6ZENZ.mjs +3 -0
  156. package/dist/chunk-AR5D57ZD.mjs +170 -0
  157. package/dist/{chunk-W3BGBJQW.mjs → chunk-BFJGHSQN.mjs} +1 -1
  158. package/dist/{chunk-LS4F7JUM.mjs → chunk-BZ5RAF7L.mjs} +1 -1
  159. package/dist/chunk-CMA72MAG.mjs +2 -0
  160. package/dist/{chunk-LCTHTZIL.mjs → chunk-DAZL73VK.mjs} +91 -91
  161. package/dist/{chunk-Y6RLRPG3.mjs → chunk-DJISHPUL.mjs} +1 -1
  162. package/dist/chunk-DR73Y2UJ.mjs +3 -0
  163. package/dist/{chunk-FDLXYYG4.mjs → chunk-EAIFITAV.mjs} +1 -1
  164. package/dist/{chunk-TMYZB6AV.mjs → chunk-EKNHM3P4.mjs} +1 -1
  165. package/dist/chunk-EP25HDAJ.mjs +2 -0
  166. package/dist/{chunk-GB5SOYQJ.mjs → chunk-ERLAIBOA.mjs} +2 -2
  167. package/dist/chunk-EURLTOTZ.mjs +4 -0
  168. package/dist/chunk-F4ZA6JRZ.mjs +3 -0
  169. package/dist/chunk-F6HVDZR4.mjs +2 -0
  170. package/dist/chunk-FDMAXMQA.mjs +2 -0
  171. package/dist/chunk-FETSREUN.mjs +5 -0
  172. package/dist/chunk-GHOYKMQ3.mjs +4 -0
  173. package/dist/{chunk-2B5E4CDJ.mjs → chunk-GPIWQ4X4.mjs} +1 -1
  174. package/dist/chunk-HDWTZ763.mjs +12 -0
  175. package/dist/chunk-HPOI4ZX7.mjs +6 -0
  176. package/dist/{chunk-BGGDRNYQ.mjs → chunk-HXG7EOPJ.mjs} +1 -1
  177. package/dist/chunk-IA4PSIMD.mjs +2 -0
  178. package/dist/{chunk-E7LWZRXY.mjs → chunk-ITOH5EGO.mjs} +1 -1
  179. package/dist/chunk-IV64FFI4.mjs +2 -0
  180. package/dist/chunk-J43Z6LSS.mjs +2 -0
  181. package/dist/chunk-J5PUIV3Y.mjs +4 -0
  182. package/dist/chunk-JA7G53PC.mjs +2 -0
  183. package/dist/chunk-JEUK3ZO7.mjs +2 -0
  184. package/dist/chunk-JLTZF4LA.mjs +2 -0
  185. package/dist/chunk-JZT7I2OJ.mjs +2 -0
  186. package/dist/chunk-K5XATEOO.mjs +2 -0
  187. package/dist/chunk-L2SUIS5S.mjs +2 -0
  188. package/dist/chunk-L7UP52JO.mjs +2 -0
  189. package/dist/chunk-LM4XFQHZ.mjs +2 -0
  190. package/dist/chunk-MN7BZL4R.mjs +2 -0
  191. package/dist/chunk-MTYYHM2G.mjs +15 -0
  192. package/dist/chunk-MXUBKDRO.mjs +15 -0
  193. package/dist/chunk-NAMN3RAF.mjs +2 -0
  194. package/dist/{chunk-SYGN7GLU.mjs → chunk-OEXWRJME.mjs} +1 -1
  195. package/dist/chunk-OFHXGWOX.mjs +2 -0
  196. package/dist/chunk-ORID3AE7.mjs +166 -0
  197. package/dist/chunk-PAREWQGB.mjs +4 -0
  198. package/dist/chunk-PGDE24N5.mjs +2 -0
  199. package/dist/chunk-POTA2FV4.mjs +2 -0
  200. package/dist/chunk-PUOQ65NC.mjs +2 -0
  201. package/dist/chunk-Q4UEPUWF.mjs +2 -0
  202. package/dist/chunk-QE5RG76S.mjs +549 -0
  203. package/dist/chunk-R2ZDLJYT.mjs +10 -0
  204. package/dist/{chunk-7DTINW6U.mjs → chunk-SQ6Y2ZMA.mjs} +2 -2
  205. package/dist/chunk-SWUTTZCN.mjs +2 -0
  206. package/dist/chunk-TANZRINB.mjs +2 -0
  207. package/dist/chunk-TR7TWGHB.mjs +2 -0
  208. package/dist/chunk-U5XL7D6A.mjs +3 -0
  209. package/dist/{chunk-XNROSH2T.mjs → chunk-U7NZI6N4.mjs} +2 -2
  210. package/dist/chunk-UGWMMEJ5.mjs +15 -0
  211. package/dist/chunk-UJQJKNGK.mjs +2 -0
  212. package/dist/chunk-UYVCQK3H.mjs +22 -0
  213. package/dist/chunk-VFX2KNHP.mjs +4 -0
  214. package/dist/chunk-VS7JIGJW.mjs +24 -0
  215. package/dist/chunk-W7665ZEC.mjs +6 -0
  216. package/dist/chunk-WQDQWCX5.mjs +2 -0
  217. package/dist/chunk-YI43RG4P.mjs +2 -0
  218. package/dist/chunk-YLPSMDIS.mjs +5 -0
  219. package/dist/chunk-YNAWBAYN.mjs +3 -0
  220. package/dist/chunk-YROX2O22.mjs +2 -0
  221. package/dist/chunk-ZDLPUOAG.mjs +6 -0
  222. package/dist/{chunk-IVDLMMBD.mjs → chunk-ZHEHPMBK.mjs} +1 -1
  223. package/dist/chunk-ZQS6H473.mjs +16 -0
  224. package/dist/chunk-ZTHICSSF.mjs +2 -0
  225. package/dist/chunk-ZWWC4KLF.mjs +20 -0
  226. package/dist/cli.mjs +1 -1
  227. package/dist/server.mjs +1 -1
  228. package/dist/{chunk-U6KNPJPR.mjs → update-fetch.mjs} +1 -1
  229. package/dist/worker.mjs +1 -1
  230. package/kit/board.css +95 -0
  231. package/kit/board.js +250 -0
  232. package/kit/charts.js +5 -71
  233. package/kit/code.js +17 -17
  234. package/kit/report.css +335 -18
  235. package/kit/runtime.js +1638 -125
  236. package/kit/state.js +10 -1
  237. package/kit/tables.js +130 -43
  238. package/kit/ui.js +79 -35
  239. package/package.json +2 -1
  240. package/packs/gallery/card/component.json +14 -0
  241. package/packs/gallery/card/example.html +10 -0
  242. package/packs/gallery/card/preview.svg +1 -0
  243. package/packs/gallery/card/style.css +6 -0
  244. package/packs/gallery/card/template.html +6 -0
  245. package/packs/gallery/card/writing.md +14 -0
  246. package/packs/gallery/chart-card/component.json +15 -0
  247. package/packs/gallery/chart-card/example.html +14 -0
  248. package/packs/gallery/chart-card/kit.js +130 -0
  249. package/packs/gallery/chart-card/preview.svg +1 -0
  250. package/packs/gallery/chart-card/style.css +42 -0
  251. package/packs/gallery/chart-card/template.html +13 -0
  252. package/packs/gallery/chart-card/writing.md +20 -0
  253. package/packs/gallery/chart-view/component.json +20 -0
  254. package/packs/gallery/chart-view/example.html +13 -0
  255. package/packs/gallery/chart-view/kit.js +355 -0
  256. package/packs/gallery/chart-view/preview.svg +1 -0
  257. package/packs/gallery/chart-view/style.css +94 -0
  258. package/packs/gallery/chart-view/template.html +3 -0
  259. package/packs/gallery/chart-view/writing.md +22 -0
  260. package/packs/gallery/countdown/component.json +18 -0
  261. package/packs/gallery/countdown/example.html +3 -0
  262. package/packs/gallery/countdown/kit.js +216 -0
  263. package/packs/gallery/countdown/preview.svg +1 -0
  264. package/packs/gallery/countdown/style.css +118 -0
  265. package/packs/gallery/countdown/template.html +3 -0
  266. package/packs/gallery/countdown/writing.md +22 -0
  267. package/packs/gallery/habit/component.json +14 -0
  268. package/packs/gallery/habit/example.html +3 -0
  269. package/packs/gallery/habit/kit.js +334 -0
  270. package/packs/gallery/habit/preview.svg +1 -0
  271. package/packs/gallery/habit/style.css +174 -0
  272. package/packs/gallery/habit/template.html +3 -0
  273. package/packs/gallery/habit/writing.md +21 -0
  274. package/packs/gallery/heatmap/component.json +18 -0
  275. package/packs/gallery/heatmap/example.html +3 -0
  276. package/packs/gallery/heatmap/kit.js +513 -0
  277. package/packs/gallery/heatmap/preview.svg +1 -0
  278. package/packs/gallery/heatmap/style.css +189 -0
  279. package/packs/gallery/heatmap/template.html +3 -0
  280. package/packs/gallery/heatmap/writing.md +21 -0
  281. package/packs/gallery/kanban/component.json +18 -0
  282. package/packs/gallery/kanban/example.html +12 -0
  283. package/packs/gallery/kanban/kit.js +540 -0
  284. package/packs/gallery/kanban/preview.svg +1 -0
  285. package/packs/gallery/kanban/style.css +212 -0
  286. package/packs/gallery/kanban/template.html +3 -0
  287. package/packs/gallery/kanban/writing.md +20 -0
  288. package/packs/gallery/metric/component.json +22 -0
  289. package/packs/gallery/metric/example.html +15 -0
  290. package/packs/gallery/metric/kit.js +248 -0
  291. package/packs/gallery/metric/preview.svg +1 -0
  292. package/packs/gallery/metric/style.css +92 -0
  293. package/packs/gallery/metric/template.html +3 -0
  294. package/packs/gallery/metric/writing.md +23 -0
  295. package/packs/gallery/note/component.json +14 -0
  296. package/packs/gallery/note/example.html +3 -0
  297. package/packs/gallery/note/kit.js +129 -0
  298. package/packs/gallery/note/preview.svg +1 -0
  299. package/packs/gallery/note/style.css +97 -0
  300. package/packs/gallery/note/template.html +3 -0
  301. package/packs/gallery/note/writing.md +18 -0
  302. package/packs/gallery/pack.json +8 -0
  303. package/packs/gallery/recent/component.json +13 -0
  304. package/packs/gallery/recent/example.html +1 -0
  305. package/packs/gallery/recent/kit.js +293 -0
  306. package/packs/gallery/recent/preview.svg +1 -0
  307. package/packs/gallery/recent/style.css +85 -0
  308. package/packs/gallery/recent/template.html +1 -0
  309. package/packs/gallery/recent/writing.md +15 -0
  310. package/packs/gallery/static/component.json +13 -0
  311. package/packs/gallery/static/example.html +11 -0
  312. package/packs/gallery/static/preview.svg +1 -0
  313. package/packs/gallery/static/style.css +171 -0
  314. package/packs/gallery/static/template.html +1 -0
  315. package/packs/gallery/static/writing.md +18 -0
  316. package/packs/gallery/stats/component.json +13 -0
  317. package/packs/gallery/stats/example.html +1 -0
  318. package/packs/gallery/stats/kit.js +347 -0
  319. package/packs/gallery/stats/preview.svg +1 -0
  320. package/packs/gallery/stats/style.css +73 -0
  321. package/packs/gallery/stats/template.html +1 -0
  322. package/packs/gallery/stats/writing.md +11 -0
  323. package/packs/gallery/today/component.json +12 -0
  324. package/packs/gallery/today/example.html +1 -0
  325. package/packs/gallery/today/kit.js +220 -0
  326. package/packs/gallery/today/preview.svg +1 -0
  327. package/packs/gallery/today/style.css +149 -0
  328. package/packs/gallery/today/template.html +1 -0
  329. package/packs/gallery/today/writing.md +14 -0
  330. package/packs/gallery/todos/component.json +19 -0
  331. package/packs/gallery/todos/example.html +3 -0
  332. package/packs/gallery/todos/kit.js +489 -0
  333. package/packs/gallery/todos/preview.svg +1 -0
  334. package/packs/gallery/todos/style.css +214 -0
  335. package/packs/gallery/todos/template.html +3 -0
  336. package/packs/gallery/todos/writing.md +30 -0
  337. package/packs/gallery/weather/component.json +19 -0
  338. package/packs/gallery/weather/example.html +3 -0
  339. package/packs/gallery/weather/kit.js +387 -0
  340. package/packs/gallery/weather/preview.svg +1 -0
  341. package/packs/gallery/weather/style.css +140 -0
  342. package/packs/gallery/weather/template.html +3 -0
  343. package/packs/gallery/weather/writing.md +26 -0
  344. package/packs/gallery-soft/countdown/component.json +18 -0
  345. package/packs/gallery-soft/countdown/example.html +3 -0
  346. package/packs/gallery-soft/countdown/kit.js +206 -0
  347. package/packs/gallery-soft/countdown/preview.svg +1 -0
  348. package/packs/gallery-soft/countdown/style.css +211 -0
  349. package/packs/gallery-soft/countdown/template.html +3 -0
  350. package/packs/gallery-soft/countdown/writing.md +24 -0
  351. package/packs/gallery-soft/habit/component.json +14 -0
  352. package/packs/gallery-soft/habit/example.html +3 -0
  353. package/packs/gallery-soft/habit/kit.js +366 -0
  354. package/packs/gallery-soft/habit/preview.svg +1 -0
  355. package/packs/gallery-soft/habit/style.css +251 -0
  356. package/packs/gallery-soft/habit/template.html +3 -0
  357. package/packs/gallery-soft/habit/writing.md +23 -0
  358. package/packs/gallery-soft/heatmap/component.json +18 -0
  359. package/packs/gallery-soft/heatmap/example.html +3 -0
  360. package/packs/gallery-soft/heatmap/kit.js +498 -0
  361. package/packs/gallery-soft/heatmap/preview.svg +1 -0
  362. package/packs/gallery-soft/heatmap/style.css +181 -0
  363. package/packs/gallery-soft/heatmap/template.html +3 -0
  364. package/packs/gallery-soft/heatmap/writing.md +23 -0
  365. package/packs/gallery-soft/note/component.json +14 -0
  366. package/packs/gallery-soft/note/example.html +3 -0
  367. package/packs/gallery-soft/note/kit.js +162 -0
  368. package/packs/gallery-soft/note/preview.svg +1 -0
  369. package/packs/gallery-soft/note/style.css +148 -0
  370. package/packs/gallery-soft/note/template.html +3 -0
  371. package/packs/gallery-soft/note/writing.md +20 -0
  372. package/packs/gallery-soft/pack.json +8 -0
  373. package/packs/gallery-soft/recent/component.json +13 -0
  374. package/packs/gallery-soft/recent/example.html +1 -0
  375. package/packs/gallery-soft/recent/kit.js +335 -0
  376. package/packs/gallery-soft/recent/preview.svg +1 -0
  377. package/packs/gallery-soft/recent/style.css +160 -0
  378. package/packs/gallery-soft/recent/template.html +1 -0
  379. package/packs/gallery-soft/recent/writing.md +17 -0
  380. package/packs/gallery-soft/static/component.json +13 -0
  381. package/packs/gallery-soft/static/example.html +12 -0
  382. package/packs/gallery-soft/static/preview.svg +1 -0
  383. package/packs/gallery-soft/static/style.css +186 -0
  384. package/packs/gallery-soft/static/template.html +1 -0
  385. package/packs/gallery-soft/static/writing.md +20 -0
  386. package/packs/gallery-soft/stats/component.json +13 -0
  387. package/packs/gallery-soft/stats/example.html +1 -0
  388. package/packs/gallery-soft/stats/kit.js +341 -0
  389. package/packs/gallery-soft/stats/preview.svg +1 -0
  390. package/packs/gallery-soft/stats/style.css +119 -0
  391. package/packs/gallery-soft/stats/template.html +1 -0
  392. package/packs/gallery-soft/stats/writing.md +13 -0
  393. package/packs/gallery-soft/today/component.json +12 -0
  394. package/packs/gallery-soft/today/example.html +1 -0
  395. package/packs/gallery-soft/today/kit.js +222 -0
  396. package/packs/gallery-soft/today/preview.svg +1 -0
  397. package/packs/gallery-soft/today/style.css +178 -0
  398. package/packs/gallery-soft/today/template.html +1 -0
  399. package/packs/gallery-soft/today/writing.md +16 -0
  400. package/packs/gallery-soft/todos/component.json +19 -0
  401. package/packs/gallery-soft/todos/example.html +3 -0
  402. package/packs/gallery-soft/todos/kit.js +527 -0
  403. package/packs/gallery-soft/todos/preview.svg +1 -0
  404. package/packs/gallery-soft/todos/style.css +212 -0
  405. package/packs/gallery-soft/todos/template.html +3 -0
  406. package/packs/gallery-soft/todos/writing.md +32 -0
  407. package/packs/gallery-soft/weather/component.json +19 -0
  408. package/packs/gallery-soft/weather/example.html +3 -0
  409. package/packs/gallery-soft/weather/kit.js +411 -0
  410. package/packs/gallery-soft/weather/preview.svg +1 -0
  411. package/packs/gallery-soft/weather/style.css +185 -0
  412. package/packs/gallery-soft/weather/template.html +3 -0
  413. package/packs/gallery-soft/weather/writing.md +28 -0
  414. package/release.json +12 -10
  415. package/sdk/doc-kit.d.ts +396 -5
  416. package/sdk/doc-state.d.ts +2 -0
  417. package/skill/SKILL.md +56 -23
  418. package/skill/references/block-script.md +140 -0
  419. package/skill/references/building-blocks.md +257 -0
  420. package/skill/references/extensions.md +59 -0
  421. package/skill/references/pages-and-data.md +225 -0
  422. package/skill/references/writing-html.md +8 -4
  423. package/skill/sdk/doc-kit.d.ts +396 -5
  424. package/skill/sdk/doc-state.d.ts +2 -0
  425. package/web/assets/index-BM_K-Auu.css +1 -0
  426. package/web/assets/index-DRslOBiv.js +15 -0
  427. package/web/index.html +2 -2
  428. package/dist/chunk-3HIRPVLU.mjs +0 -2
  429. package/dist/chunk-5MHMDLZD.mjs +0 -4
  430. package/dist/chunk-64K7IPLO.mjs +0 -255
  431. package/dist/chunk-6QXGZM36.mjs +0 -8
  432. package/dist/chunk-6RGJOMJP.mjs +0 -16
  433. package/dist/chunk-AJ73XJF3.mjs +0 -2
  434. package/dist/chunk-AUZGSZJH.mjs +0 -13
  435. package/dist/chunk-BFE45AKL.mjs +0 -2
  436. package/dist/chunk-BXO2ZY5P.mjs +0 -2
  437. package/dist/chunk-CEH4MRCC.mjs +0 -2
  438. package/dist/chunk-CY2FNNAB.mjs +0 -16
  439. package/dist/chunk-DFUDV4LX.mjs +0 -2
  440. package/dist/chunk-DKXG4XDG.mjs +0 -2
  441. package/dist/chunk-EZQ34M3F.mjs +0 -124
  442. package/dist/chunk-EZY3WC6Z.mjs +0 -15
  443. package/dist/chunk-FUKQNOQS.mjs +0 -9
  444. package/dist/chunk-JPOSLGOC.mjs +0 -6
  445. package/dist/chunk-JVHHHGEA.mjs +0 -3
  446. package/dist/chunk-L3QKH4OK.mjs +0 -26
  447. package/dist/chunk-LAE5NQ4B.mjs +0 -2
  448. package/dist/chunk-LEF6DRCK.mjs +0 -59
  449. package/dist/chunk-NO5NJCHO.mjs +0 -2
  450. package/dist/chunk-NQPVAU63.mjs +0 -2
  451. package/dist/chunk-NSKUTQ5J.mjs +0 -5
  452. package/dist/chunk-O35FIXRB.mjs +0 -2
  453. package/dist/chunk-P2CAZPDP.mjs +0 -3
  454. package/dist/chunk-PL6GHLGD.mjs +0 -15
  455. package/dist/chunk-QJIR2BLP.mjs +0 -6
  456. package/dist/chunk-QUPLVPB2.mjs +0 -7
  457. package/dist/chunk-R7BNENLY.mjs +0 -4
  458. package/dist/chunk-S6O4UHLC.mjs +0 -2
  459. package/dist/chunk-SGJWQKEI.mjs +0 -2
  460. package/dist/chunk-TX6JH7TR.mjs +0 -2
  461. package/dist/chunk-TYK6VNAB.mjs +0 -10
  462. package/dist/chunk-UALRNVSE.mjs +0 -4
  463. package/dist/chunk-V3HXVQEM.mjs +0 -2
  464. package/dist/chunk-V5VXUJKG.mjs +0 -2
  465. package/dist/chunk-VBXMADMP.mjs +0 -2
  466. package/dist/chunk-VNV55RUA.mjs +0 -2
  467. package/dist/chunk-VPD2PS35.mjs +0 -2
  468. package/dist/chunk-W4VKN3GF.mjs +0 -7
  469. package/dist/chunk-W5BXXPDJ.mjs +0 -3
  470. package/dist/chunk-XUNHRCOG.mjs +0 -6
  471. package/skill/references/building-components.md +0 -367
  472. package/web/assets/index-Bh74DfsV.css +0 -1
  473. package/web/assets/index-UW0RyFFt.js +0 -13
@@ -0,0 +1,257 @@
1
+ # Building a custom block
2
+
3
+ A custom block (自定义块) is a block to use again: it lives in the workspace, a document holds its instances as ordinary elements, and a custom page (自定义页: a page of the workspace's own, its 首页 among them) holds them as cards on its board. The user finds it in the "/" menu of every document there and in a custom page's 添加自定义块, as its manifest's places say ([Places, cards, settings and needs](pages-and-data.md#places-cards-settings-and-needs)).
4
+
5
+ Make one when the user clearly wants a block to use again ("做一个以后还能用的组件"), or a card of a custom page that does something or keeps data, or a document needs a control that keeps what a reader enters (a ledger, a checklist, a form, a score). A document's own `<script>` cannot write the file: what it keeps lives in the browser, is gone with the page and is no one else's, and only a block's data part, written by `context.editJSON`, reaches `doc.html`. That is reason enough though the user says nothing of using it again: make the block (`gallery block new <id> --data`) and write its instance into the document. A document is otherwise written with the kit's blocks and, for a layout of its own, a whole block ([writing-html.md](writing-html.md#kit-blocks)): never make a custom block to get a look or a chart a document's own `<style>` and `<script>` can give it, or one per document for what the kit's blocks show. A card that only shows what it holds (a few lines, links, a picture) is Gallery's own static card, `gallery/static`, with any HTML in it: no block of yours. A task board, a number or a chart over a table of the document is a view of it that Gallery ships (`gallery/kanban`, `gallery/metric`, `gallery/chart-view`: Gallery's own blocks, below): no block of yours either.
6
+
7
+ The interface is experimental in Gallery 0.x: what these pages say may change between versions, and a block may need changing with it. Three references hold it: this page is the block (its kinds of part, the flow of making and trying one, its files, manifest, parts, slots, instance and style, what `gallery block check` says, and Gallery's own blocks); [block-script.md](block-script.md) is its script, `kit.js`, and how it writes back to the file; [pages-and-data.md](pages-and-data.md) is a card of a custom page (its size, its settings) and what a block may read beyond its own parts: the workspace's data, a table of its document, the web. A custom block's files keep the word component, as Gallery 0.1 called them: its folder is under `components/`, its manifest is `component.json`, an instance is marked `data-doc-component`, and its script calls `DocKit.component`.
8
+
9
+ ## Which kind of part
10
+
11
+ A part is an element of an instance that the file means something by, and its manifest gives each one a kind, `edit` (Parts, below). Choose the kind by what the part holds:
12
+
13
+ | What the part holds | Its kind | In a document | On a custom page |
14
+ | --- | --- | --- | --- |
15
+ | words a reader types in place: a title, a label, a caption | `text`, words and marks alone | the editor's: the reader types, splits and undoes there as in any paragraph; the block reads the words and never writes them | shown, read-only: what a reader types on a card goes in a `data` part, through a field the block draws (`DocKit.input`) or the card's settings |
16
+ | what the block works from and a reader's gesture changes: a table of tasks, a script of JSON (scores, a count, settings) | `data` | the block's: it writes the part with `context.edit` on a gesture (a drag, a press, a field's Enter), one undo step, which the editor saves and merges with an Agent's writes | the block's: the same `context.edit`, which the page's service writes into that card of `page.html`, one step of the page's undo |
17
+ | what the block shows as written and only the file changes: fixed words, a picture, any HTML | `none` | shown: neither the reader nor the block changes it on the page, an Agent's write of the file does | shown, the same |
18
+ | blocks of the document's own under the block's markup: paragraphs, a table and a chart in a card | `flow`, a slot | the editor's: the reader edits them as any of the page's blocks, "/" and the handles too; the block reads them and never writes in them | not allowed: a custom page renders no document's blocks, so a block whose places hold `page` has no slot, and `gallery block check` refuses one |
19
+
20
+ What the block's script draws by itself (a clock, a total, a handle) is no part: the manifest names it in `runtime` ([Script](block-script.md#script)). A block may have no part at all, when all it shows is drawn. In a document's export every part is read-only: `text` and `flow` as the file holds them, `none` as it stands, `data` drawn by the block with every edit refused.
21
+
22
+ ## A document and a custom page
23
+
24
+ One block, one manifest and one `context` stand in either place; the two differ in who answers an edit and in how the block is laid out:
25
+
26
+ | | In a document | On a custom page |
27
+ | --- | --- | --- |
28
+ | Where it stands | a block of the page's flow, among the others, moved, copied and deleted whole by its handle | a card of a board: the instance in a `<section class="gallery-card" data-card-id="…">`, at a place and a size in square cells of 64px, twelve to a row (fewer on a narrower window, as many as fit: the cards one after another in their order, as large as they are), moved, added and removed by the user: by the grip at the card's top-right corner (a drag moves the card, a click opens its menu: 大小, 设置…, 删除). That corner is the grip's: a 28 × 28 px box, 6px in from the card's top and right edges, over the card while the pointer is on it, so a block puts no control and no text of its own there (keep that corner's 34 × 34 px clear, or start the content below it) |
29
+ | Who answers `context.edit` | the document's editor: the part written to `doc.html`, one step of the document's undo, merged with an Agent's writes, a card for the reader where both changed the part | no editor: the page's service writes that card's part in `page.html`, found by its `data-card-id`, one step of the page's own undo; when someone changed that card since the page showed it (an Agent's write of it), the write is refused and the page shown again as the file holds it, for the reader to do again |
30
+ | `text` parts | edited in place | read-only |
31
+ | Slots | the document's blocks | none |
32
+ | `context.place` | `"document"`, and `"export"` in an exported file, where `context.canEdit()` is false | `"page"` |
33
+ | `context.size` | `null`: lay out by the width, on `resize` | the card's `{ w, h, width, height }`, its cells and its content's pixels: read it again on `layout`, which comes as the card's size changes, a card held to a narrow board's row too |
34
+ | Reading state, `context.state` | kept by the instance's `data-block-id`, or by its markup where it has none | kept by its card's `data-card-id` |
35
+ | What the user sets | what the block's own controls write | that, and the card's menu 设置…, a form of the manifest's `settings` |
36
+ | What offers it | "/", 在下方新建 and the handle's grid, when its places hold `document` or the user switched it on | 添加自定义块, the workbench's top bar's button at its right (a page open alone in a tab has it above its board), which adds to the page's first board, when its places hold `page` |
37
+ | An export | read-only, as above | none: a custom page is not exported |
38
+
39
+ ## The flow
40
+
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
+
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: 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
+ 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
+ 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
+ 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.
48
+ 6. Try each gesture a reader makes, in the page, with `gallery block try`, one command for each, on the instance step 5 wrote (named after the slug by its `data-block-id` when the document holds more than one; one in another block's slot is one of them): `--drag <selector> --to <selector>` (a card dragged to another column or place), `--press <selector>` (a dot, a button), `--key <selector> <key>` (Enter, Space or an arrow on a control the block draws), `--type <selector> <words>` (words typed in a field it draws or in a text part, the Chinese through an input method, as the user types) or `--select <selector> <value>` (an option of a `<select>`, by its value or its words), as `gallery block try <slug> --drag .kanban-card --to ".kanban-column:nth-child(3)"`; `--then <key>` presses a key after it where the focus is, as `--type .habit-name 多喝水 --then Enter` for a field that writes on Enter. What a reader does in several gestures (a rename: `Control+a` in the field, the new name, Enter; a form) goes in a steps file, `--steps <file>`: a JSON list of steps, each naming one gesture as the options do, without their `--`, as `[{ "key": [".habit-name", "Control+a"] }, { "type": [".habit-name", "多喝水"], "then": "Enter" }, { "select": [".habit-unit", "杯"] }, { "drag": ".kanban-card", "to": ".kanban-column:nth-child(3)" }]`, made one after another in one page. Each selector is the first element of the instance that it finds, as `kit.js` draws it: `Nothing in the instance is …` lists the classes the instance shows. Words go in pressed at the element's middle, the caret at the end of what it holds, so that into a field that holds words already they go after them, and the Gesture line says so (`it held "餐饮", and the words went after it`); where a step before left the focus in it there is no press, and they go in at the caret where that step left it (a press puts it where the pointer lands, an arrow key moves it), which the Gesture line says too (`the caret inside what it held`); `--replace` (`"replace": true` in a step, `{ "type": [".category", "交通"], "replace": true }`) selects all the field holds first, so that they take its place, as a reader's Ctrl+A does. The command makes the trial on a scratch copy of the document, its page alone, editable, in a Chrome or Edge of its own, headless: `doc.html` is not written and the user's page shows nothing of it, and the copy goes at the end, whatever came of it. It makes each gesture there with the pointer or the keys (a drag in steps, released as it comes onto its target), waits until the copy has what it wrote, and prints it: `Wrote: tasks (-1 +1 of its 8 lines); nothing outside the instance changed (data-block-id aside)`, each part with the lines the gesture took out and put in, and under it those lines, `-` and `+`: read them, they are what a reader's gesture writes to the file (with `--steps`, `Wrote: nothing` of a step that wrote nothing, a press that opens a field, which is fine). Then it undoes as a reader does, a Ctrl+Z for each write the page took, the last first (each `context.edit` is one undo step: a gesture that wrote twice takes two), and says `Undone: one Ctrl+Z, and the copy of doc.html is as it was (data-block-id aside)`, and opens what the gestures wrote in a fresh page, where the block is to mount, write nothing as it opens and show what it showed after them of what they wrote: `Read back: …`. What the page showed and never wrote (a filter or a tab chosen, an editor left open) a fresh page does not keep, and need not: a `note` line says what differed. Write what a reader keeps, never what they only look through. `--keep` makes the trial on `doc.html` itself and leaves the write, which every page open on the document shows, the user's too: say so in the handoff. Open the picture its `Picture of the instance after …` line names: no one has looked at it for you, and the `Not opened yet: …` line after it lists it, as `gallery qa`'s does. A `note` line asks what the check's notes ask (a write that lays a part out anew: change the write as [Writing back](block-script.md#writing-back) says; none for a write that is `context.editJSON`'s own layout, nothing to change: a part on several lines that closes to one line as its list empties, or an entry in it that opens to lines of its own as it comes to hold an object; editJSON opens no part that stands on one line, which stays on one line, compact, one that closed to one line too). Exit 1 is a problem to fix in the block: gestures that wrote nothing say what came of the last (no `context.edit` came of it, the page refused one and the console says why, an HTML5 drag was dropped nowhere: a list a card is dropped on cancels `dragenter` as well as `dragover`; words typed in a field that writes on Enter: add `--then Enter`), an undo that did not take a write back says what still differs, and a fresh page that shows the block otherwise than the page did after the gestures, in what they wrote, says what (a value kept in memory and not in the part, or written in a form the mount does not read), as does one that writes as it opens (draw what the parts hold, and write on a gesture alone); fix it, run `gallery block check <id>`, and try the gestures again. Exit 2 is a mistake in the command; one found at a step after others were made is said after what those wrote, which `--keep` leaves in `doc.html`. Exit 3 (`UNVERIFIED`) is a trial not seen through, its line saying why (no browser, a page that loaded itself again as the block changed): run it once more.
49
+ A gesture the command cannot make (the block inserted from "/" by its name, or a word of `words`, the pinyin of its name), make yourself when you can drive Chrome or Edge by its DevTools protocol, from Node 22's own `fetch` and `WebSocket`, with nothing to install. Start one of its own at the `Agent 自用` address that `gallery new`, `gallery import` or `gallery open` prints: the document's page alone, editable, with no frame around it (`--headless=new --remote-debugging-port=<port> --user-data-dir=<a new folder> <address>`; `http://127.0.0.1:<port>/json/list` gives the tab's `webSocketDebuggerUrl`, and `Input.dispatchMouseEvent`, `Input.dispatchKeyEvent` and `Runtime.evaluate` do the rest). Copy `doc.html` first. A gesture's write goes to the file by itself: `<html>`'s `data-ge-save` leaves `saved` (`waiting`, then `syncing`) and says `saved` again once the file has it (`held`: a card waits for the reader; `offline` or `stopped`: the server). Then read the part in `doc.html`: it holds what the gesture meant, and nothing outside it changed but `data-block-id`: the page gives a block it saves a change of one where it has none (the instance, the section it stands in), and an undo leaves it, so compare `doc.html` with your copy with every `data-block-id` taken out. Press Ctrl+Z once with the focus in no field the block draws (in an `input`, a `select`, a `textarea` or an editable element of its own, Ctrl+Z is that field's: a click on a paragraph beside the block takes the focus off it), wait for `saved`, and see the part as it was. At the end `doc.html` is your copy again, but for those ids and what the user changed meanwhile at the address you sent: undo each step, the insert too, then close your Chrome. Anything of the trial an undo left (the page was loaded again, a card held a step), take out yourself once your Chrome is closed, as any change of yours, `doc.html` read again first: the instance, and an empty paragraph you made for it, keeping the rest and the ids. Write the whole copy back only where `doc.html` differs from it in what the trial left alone, ids aside, and never while a page of yours is open on the document: over more, it takes away what the user wrote meanwhile and shows them a card saying so, and a page of yours open on it holds on a card of its own.
50
+ In the handoff name the gestures you tried, and only those, each by its command or its steps and what it wrote, and what the user changed meanwhile, which stays. When you could not try one, by the command or yourself, say plainly in the handoff that you did not try it in the page.
51
+
52
+ Tell the user the block's name and where it is. A change to a block reaches every page open on it, by itself.
53
+
54
+ ## The files
55
+
56
+ | File | What it is |
57
+ | --- | --- |
58
+ | `component.json` | the manifest, plain data: all that Gallery itself reads of the block |
59
+ | `template.html` | what "/" puts in a document: one instance, with what a new one holds. `gallery block check` requires it: with none, or one a new block cannot be, no menu offers the block, and `gallery block list` and 设置 › 组件列表 say so |
60
+ | `example.html` | an instance as a writer would fill it: what `gallery block show` prints and what `gallery block check` runs |
61
+ | writing.md | how to write it, for an Agent: what it is for, when to use it, what goes in each part. `gallery block show` prints it |
62
+ | `style.css` | its look, optional |
63
+ | `kit.js` | its script, optional, one classic script |
64
+ | `preview.svg` | a picture for the menu, optional: a reader resting on its row sees it beside the description, or the description alone |
65
+
66
+ ## The manifest
67
+
68
+ ```json
69
+ {
70
+ "id": "local/metrics",
71
+ "apiVersion": 1,
72
+ "version": "1.0.0",
73
+ "name": { "zh": "指标条", "en": "Metric strip" },
74
+ "description": { "zh": "一排数字和它们的说明", "en": "A row of numbers and what they say" },
75
+ "words": "zhibiaotiao kpi metrics 指标 数字",
76
+ "parts": {
77
+ "title": { "at": ":scope > h3", "edit": "text" },
78
+ "numbers": { "at": ":scope > dl", "edit": "none" }
79
+ },
80
+ "markdown": "parts"
81
+ }
82
+ ```
83
+
84
+ | Field | What it holds |
85
+ | --- | --- |
86
+ | `id` | `<scope>/<name>`, as its folder is, each in lowercase letters, digits and hyphens |
87
+ | `apiVersion` | 1 |
88
+ | `version` | which version of it this is: shown, never compared |
89
+ | `name`, `description` | `{ "zh": …, "en": … }`, both: what the menu shows |
90
+ | `words` | optional: what the menu finds it by, besides its name. Write the pinyin of a Chinese name here, the whole name in one word (`任务看板 renwukanban kanban`): "/" goes by the letters an input method is composing, and finds the block while all of them are being composed only by a word that holds them. The check gives a note on a Chinese name no word here spells whole, a syllable a character: it counts how many syllables of pinyin a word reads as, and does not know which characters they spell |
91
+ | `parts` | its parts by name, below |
92
+ | `runtime` | optional: what its script leaves on a page, `{ "generated": [selectors], "attrs": { selector: [names] } }` |
93
+ | `assets` | optional: what it needs besides its script and style: the kit's files by id (`d3`, `charts`, `tables`, `dialogs`, `sheets`, `state`, `tokens`, `code`, `math`, `katex`, `katex-styles`, `katex-auto-render`), and files of its own folder a style names, by their path. `katex` gives a script the name `katex`, and what it draws needs `katex-styles` beside it, or a formula shows twice |
94
+ | `markdown` | optional: `parts` (the default: a table part as a table, a text part as a paragraph) or `text` (its words alone), how it exports to Markdown |
95
+ | `schema` | optional: the whole number of the newest shape of content its script reads, 1 when it says none: [When the content's shape changes](block-script.md#when-the-contents-shape-changes) |
96
+ | `places`, `card`, `settings`, `needs` | optional: where it may stand, its size as a card on a custom page, a card's settings, and what it uses: [Places, cards, settings and needs](pages-and-data.md#places-cards-settings-and-needs) |
97
+
98
+ A block's manifest holds nothing else: a field it does not know keeps the block from loading, and `gallery block list` says why.
99
+
100
+ ## Parts
101
+
102
+ A part is an element of an instance that the file means something by. `at` finds it: `:scope > h3`, `:scope > div.note > p`, step by step from the instance, or one selector for any depth, or a list of those with commas; each step a tag, `.class`, `[attr]` or `[attr=value]`. A part counts the elements `at` finds in one instance, each once: an instance holds at least `min` of them (1 when the manifest says none) and at most `max` (any number when it says none); `optional: true` lets it hold none, whatever `min` says. An instance with too few or too many fails `gallery check` for every document that holds one, and a `template.html` with too few or too many is in no menu.
103
+
104
+ A group of parts repeated, an item of three parts three or four times, is its three parts, each reaching into the item and each with the same `min` and `max`:
105
+
106
+ ```json
107
+ "parts": {
108
+ "name": { "at": ":scope > div.item > p.name", "edit": "text", "min": 3, "max": 4 },
109
+ "value": { "at": ":scope > div.item > p.value", "edit": "text", "min": 3, "max": 4 },
110
+ "change": { "at": ":scope > div.item > p.change", "edit": "text", "min": 3, "max": 4 }
111
+ }
112
+ ```
113
+
114
+ Each part is counted across the instance on its own: the check does not hold the parts of one item to each other, so four items, one of them without its `change`, pass, three changes being enough. Say in writing.md that every item holds all three.
115
+
116
+ `edit` says whose a part is:
117
+
118
+ | `edit` | What it means now |
119
+ | --- | --- |
120
+ | `text` | words the user types in, in the browser. It holds words and marks alone (`strong`, `em`, `b`, `i`, `u`, `s`, `code`, `a`, `sub`, `sup`, `br`): a heading, a paragraph, a label. With anything else in it, a block, a field, a picture, a comment, an element it does not close, the editor leaves it read-only, and the check fails it |
121
+ | `none` | the block's: read it, draw from it. The user changes it through the source alone |
122
+ | `data` | what a script reads its data from and writes back to (a table, a `<script type="application/json">`): the block's alone, written by `context.edit` and by nothing else, told to it when it changes |
123
+ | `flow` | a slot: blocks of the document's own in the instance, a `<div data-doc-slot="<name>">` of its markup and no `at` (Slots, below) |
124
+
125
+ What stands in an instance belongs by region:
126
+
127
+ | Where | Whose events and contents |
128
+ | --- | --- |
129
+ | a `text` part | the editor's: Enter, Backspace, undo and the selection work as in any text |
130
+ | a `data` part | the block's, and only `context.edit` changes its content. A `text` part in one, or around one, is no text part: the file holds one or the other there |
131
+ | what the manifest's `runtime` names, and all else in the instance | the block's: the editor leaves its clicks and keys alone |
132
+ | a slot, a `flow` part, and what it holds | the editor's: any block, as in the page; the block reads it and never writes in it |
133
+ | the instance as a whole, its handle | Gallery's: moving, copying and deleting it |
134
+
135
+ In the page the user types words in the text parts, edits the blocks of a slot as any, and moves, copies or deletes the instance whole; the block changes its data parts by `context.edit` on a gesture of the reader's, a drag or a press, and nothing else of it changes there. No item of a repeated group of text parts is added or taken out on the page, its text parts being the file's words: an item more or fewer is a change of the source, so say so in writing.md. A block whose items come and go keeps them in a data part, where a control of its own adds, renames or removes one by `context.edit`, as a move is written.
136
+
137
+ A block reads a text part and never writes one: what a user types there is the file's, and a script that writes it on the `source` signal hears itself without end. It draws in what is its own, and writes a data part by `context.edit` alone: a change made straight to the part stands on that page and may end up anywhere, or nowhere.
138
+
139
+ ## Slots
140
+
141
+ A slot is where an instance holds blocks of the document's own under its own markup: a card with a title over any content, a frame around a few paragraphs and a table. Its part is edited as `flow`, with no `at`, `min` or `max`, a name of lowercase letters, digits and hyphens, and `"optional": true` when an instance may have none:
142
+
143
+ ```json
144
+ "parts": {
145
+ "title": { "at": ":scope > h3", "edit": "text" },
146
+ "body": { "edit": "flow" }
147
+ }
148
+ ```
149
+
150
+ In the markup it is a `<div>` or `<section>` of the instance's own, marked with that name, once in an instance, never the instance itself and with no `data-block-id`:
151
+
152
+ <!-- the file holds -->
153
+ ```html
154
+ <div class="brief" data-doc-component="local/brief">
155
+ <h3>本周要点</h3>
156
+ <div class="brief-body" data-doc-slot="body">
157
+ <p>上线了新的导出流程。</p>
158
+ <ul>
159
+ <li>导出更快</li>
160
+ <li>离线文件更小</li>
161
+ </ul>
162
+ </div>
163
+ </div>
164
+ ```
165
+
166
+ `gallery block new <id> --flow` writes one, `body`, in place of the text paragraph. What a slot holds is written as anywhere in the document ([writing-html.md](writing-html.md)): paragraphs, headings, lists, tables, formulas, code, a chart card, pictures, a disclosure, columns, another instance; no section and no tab area. Gallery converts, spaces and draws it as it does the page's. `template.html` gives it what a new instance starts with, an empty paragraph (`<p></p>`) where the reader starts typing; `example.html` some blocks a writer would put there. "/" makes what a template's slot holds as a paste of it makes blocks: paragraphs, headings, lists, quotes, code, a plain table and a disclosure come through, and a chart (`data-doc-chart`), a card (`<figure>`), a table's `<caption>` or an instance of a block does not, so `gallery block check` fails a template's slot that holds one, at its line. Write those in `example.html`, as an Agent writes them in a document.
167
+
168
+ On the page the reader edits a slot's blocks as any of the page's: types in them, splits and turns them, moves them in and out by their handles, adds blocks there with "/", undoes. Where the block is missing, turned off or fails, the slot is still the document's and still editable; the rest of the instance shows as it stands.
169
+
170
+ The slot is the reader's, not the block's:
171
+
172
+ - `context.part("body")` gives the slot element, to read: its height, its words, its headings. A change of what it holds comes as `source`, whoever made it.
173
+ - A block never writes in it, moves it or takes it off: what it holds is the reader's words, and a page would take a change there for the reader's, and save it. It draws outside the slot, in what its manifest's `runtime` names, as `local/brief` draws its count of words under it. What a script changes there as the kit runs it (`mount`, `update`, a `context.frame` drawing, a `context.interval` or `context.timeout`) is put back at once, everything that call changed with it, and the instance fails, showing what it holds read-only; what it changes later, from a listener of its own, nothing stops, and `gallery block check` fails a script that changes what a slot holds or where it stands, as it mounts, as it is put back and as its example makes its edit. `context.edit` on a slot throws.
174
+ - Its style reaches no block in the slot: a selector that goes down from the instance by a blank (`[data-doc-component="local/brief"] p`) styles the slot's paragraphs too, which read as the page's. Write each step with `>` (`[data-doc-component="local/brief"] > h3`), or wrap the rules in `@scope ([data-doc-component="local/brief"]) to ([data-doc-slot]) { … }`; the check gives a note on each that goes down.
175
+ - With `"markdown": "parts"` a slot is written as its blocks, in its place among the parts; with `"text"`, its words.
176
+
177
+ ## Writing an instance
178
+
179
+ <!-- the file holds -->
180
+ ```html
181
+ <div class="metrics" data-doc-component="local/metrics">
182
+ <h3>本周指标</h3>
183
+ <dl>
184
+ <dt>收入</dt><dd>12 万</dd>
185
+ <dt>新客</dt><dd>3–5 位</dd>
186
+ </dl>
187
+ </div>
188
+ ```
189
+
190
+ An instance is a `<div>` or `<section>` naming its block, straight in the page or in anything that holds blocks. Classes and attributes of your own are free in it; `doc-*` and `data-doc-*` are the kit's. Nothing of Gallery's goes into an instance: no conversion, no spacing, no formula, no other block's script, but in its slots, which are the document's. Write no `data-block-id` in `template.html`: every block gets its own.
191
+
192
+ `template.html` is one instance and nothing around it, closed by its own end tag, with as many of each part as the manifest says. Write what shows well when nothing is filled in yet: the user's first look at the block is this. Nothing in it runs or leaves its block: no script but data (`<script type="application/json">`), no `on…` attribute or address of code, no `<style>`, `<link>` or `<iframe>`, no `style` that positions it `fixed`, `absolute` or `sticky`, nothing of the editor's (`data-ge-*`). No menu offers a template that breaks this, and the check fails it at its line. `example.html` may hold several, and blocks around them.
193
+
194
+ Put what the block says in the instance itself: an element a reader can read without its script, so that a reader of a file the block is not in, or a Markdown export, still has it. Where the block is missing or turned off, or its script fails or starts nothing, Gallery shows the instance as it stands and draws a script of data in it as it draws any, read-only: an array of objects as a table, an object as its keys and values, any other array as a list, cut short and saying so past twenty entries, three levels down or a few hundred values. A block with no script draws nothing of its scripts of data: what such a block says is in elements. A block that cannot fully read what it finds leaves it as it stands. A table part it leaves showing, drawing and hiding nothing. A script of data it hands to Gallery with `context.fail(error)` (or by throwing): Gallery then shows the instance as it stands, its script of data drawn read-only as above, its text parts read-only too until the page is loaded again. It never rebuilds what it found and writes that over it, and what it leaves alone nothing writes. Write no snapshot of what the block draws beside its data unless writing.md says how the snapshot is made again from that one source: otherwise it goes stale, unseen.
195
+
196
+ A picture in an instance is the document's, a file of the document's `assets/` folder; on a custom page the page's, a file of `pages/<slug>/assets/`, written `assets/<file>` all the same (the server serves it at `/pages/<slug>/assets/<file>`, and `gallery page check` says one that is not there). `example.html` and `template.html` stand in no document, so a picture there is a `data:` address, or stands in the style, a file its `assets` name.
197
+
198
+ ## Style
199
+
200
+ Every selector stands in the instance, whatever it is:
201
+
202
+ ```css
203
+ [data-doc-component="local/metrics"] dl { display: grid; grid-auto-flow: column; }
204
+ [data-doc-component="local/metrics"] dt { color: var(--doc-muted); }
205
+ @media (max-width: 480px) {
206
+ [data-doc-component="local/metrics"] dl { grid-auto-flow: row; }
207
+ }
208
+ ```
209
+
210
+ An instance stands `--doc-block-gap` from what is around it, in whatever state it is: the kit gives it that margin, and a `margin` on the instance itself changes it.
211
+
212
+ Start each one at `[data-doc-component="<id>"]`, the instance's own attribute, not a class of yours: a class is anybody's. A selector may have something before that, which only says when it applies, and nothing reaches outside it or beside it (`+`, `~`; in nesting, `& + p` is beside the instance when `&` is the instance, and fine when `&` is something in it): the check names each that does, with its line. Colors come from the kit's variables, which follow the dark theme: `--doc-text`, `--doc-muted`, `--doc-border`, `--doc-grid`, `--doc-surface`, `--doc-bg`, `--doc-accent`, `--doc-accent-soft`, `--doc-series-1` … `-6` ([writing-html.md](writing-html.md#the-page)). Text on a `--doc-accent` fill is `--doc-bg`, never `#fff`: the dark theme's accent is light. Text on `--doc-accent-soft` is `--doc-text`. A picture or a font a style names is a file of the block, listed in `assets`; an export embeds it. No `@import` and no address elsewhere.
213
+
214
+ ## Gallery's own blocks
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 "/" (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
+
218
+ ## Block packs
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; `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
+
222
+ ```json
223
+ { "id": "team-cards", "name": { "zh": "团队卡片", "en": "Team cards" }, "description": "…", "version": "1.0.0", "author": "…" }
224
+ ```
225
+
226
+ `id` is the scope (lowercase letters, digits and hyphens; not `local`, `gallery` or `gallery-soft`), `name` and `description` words or `{ zh, en }`, `version` `x.y.z`; `homepage` (an http(s) address) and `icon` (an emoji) may follow, nothing else. `gallery block pack install <folder|zip>` installs one into the workspace (copied, each block's version and fingerprint recorded; installed again, a newer version replaces a block as it was installed and keeps one changed since), `gallery block pack list` says the packs there and whether each is on, `gallery block pack remove <pack>` takes one installed out. Each refusal says why: no `pack.json` at its top, a block whose `component.json` does not name it `<pack>/<name>`, a path out of the zip, an id the workspace has a folder of that no install put there. The user installs one too (设置 › 组件列表 › 导入) and turns a pack on or off there: a pack off is in no menu and no library; what is written of its blocks shows as ever. An installed pack's files are not yours to change (installed again, a changed block stays as it is and takes no newer one): for a block like one of it, copy its folder into a scope of your own and rename its id in its files.
227
+
228
+ ## What it says
229
+
230
+ `gallery block check <id>` prints five sections, each `FAIL <file>:<line>: …` for what to fix and `note …` for what is advice:
231
+
232
+ 1. the manifest: as Gallery reads it, `template.html` there, no text part that holds more than words and marks, a note on a Chinese name no word of `words` spells whole in pinyin, by the count of its syllables, and on a `preview.svg` that is, byte for byte, one of Gallery's own blocks' (a block made with `--recipe` keeps its recipe's picture);
233
+ 2. `kit.js`: what a browser refuses, what an export refuses, what it registers, a type check against `sdk/`, what the types alone say of code a browser runs being a note;
234
+ 3. `style.css`: each selector, what an export cannot hold;
235
+ 4. `template.html` and `example.html`: as the page of a document, by what `gallery check` runs, and `template.html` as what a menu can put in;
236
+ 5. both in a temporary document, exported, in Chrome or Edge under the export's policy: the console, a dialog or a window it opens, a page that loads itself again or stops answering, mount and dehydrate, what piles up in the instance or outside it, a text part the block redraws, a data part a mount changes, a write with no gesture once the page takes edits, the way back to the file, a page wider than the window, and the pictures. The way back runs the block's `example` ([Writing back](block-script.md#writing-back)), a small edit made by the change a reader's gesture calls: it must change a data part and nothing else, the server must take what it wrote, and with the part put back, as an undo does, the block must show what it showed. Its `way back` line says what the example wrote, each part and how many of its lines changed, and that the server took it; a note says a write that lays a part out anew (lines a change did not mean, a line left blank), and a list a card is dropped on that listens for `dragover` and not for `dragenter`, at the line of `kit.js` that listens. A block with a data part and no `example` gets a note: nothing has tried its way back (none where that part is its `settings` alone, which the card's form writes and the block only reads). An `example` that changes nothing on an instance (the template's empty one, usually) is a `FAIL` said at `kit.js`; no note for a write that lays JSON out as `context.editJSON` itself does (a part on several lines closing to one line as its list empties, an entry in it opening to lines of its own as it comes to hold an object; a part on one line stays on one line). A note says too that an instance of a block with a data part, in the export's look, still shows an enabled button, field, select or textarea. After the pictures a `Not opened yet: …` line lists them all. Exit 3 and `UNVERIFIED` when no browser ran it, or the browser went while it ran: run it again, or export a document that holds it and look yourself.
237
+
238
+ With `--documents` it prints a section more for each document of the workspace that holds instances of it, those in another block's slot too: each instance run as the fifth section runs the example, each problem at its line of the document's file (`board/doc.html:15`), no document written.
239
+
240
+ Exit 0 is all five (and those), exit 1 a failure. A failure with no line is of that file as a whole, or, as `the page`, of what ran. A block the user turned off in 设置 is checked as any, with a note saying so: passing the check does not turn it on, and that stays theirs to do.
241
+
242
+ ## States
243
+
244
+ | State | In the menus | Instances there already |
245
+ | --- | --- | --- |
246
+ | available | shown | run and export |
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 or a custom page's 添加自定义块; `gallery block` and `gallery page add` still name it | run and export |
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
+ | 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
+
252
+ In an export the block's script runs with `context.canEdit()` false: the block is drawn as on the page, read-only, every edit answering false, so draw nothing to drag or press there. What the instance holds shows by itself only where its script does not draw:
253
+
254
+ - a table part, with JavaScript off, in a Markdown export, and where the block is missing, turned off or failed;
255
+ - a script of data, drawn read-only by Gallery where the block is missing, turned off or failed (`context.fail`); nothing of it shows with JavaScript off.
256
+
257
+ A block whose template a menu cannot take is in no menu in any state; its instances are written by hand as `gallery block show` prints. The user chooses whether a block is in the document's menus and whether it is disabled, a built-in block's place in the menus too (`gallery block list` names those last): the switch is about the menus alone, so a block out of them is still one to write where a document needs it. Write an instance only of what `gallery block list` gives under 文档里可用, never of one disabled or that does not load. A document never loses what an instance holds: moved, copied or sent to someone with no such block, it stays in the file.
@@ -0,0 +1,59 @@
1
+ # Extensions: a column of entries for the sidebar
2
+
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
+
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.
6
+
7
+ - `<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.
9
+
10
+ ## The file
11
+
12
+ ```json
13
+ {
14
+ "title": "语雀",
15
+ "icon": "📗",
16
+ "entries": [
17
+ {
18
+ "id": "team",
19
+ "title": "团队知识库",
20
+ "url": "https://www.yuque.com/team",
21
+ "children": [
22
+ { "id": "weekly", "title": "周报", "url": "https://www.yuque.com/team/weekly" },
23
+ { "id": "notes", "title": "会议记录", "url": "https://www.yuque.com/team/notes", "icon": "📝" }
24
+ ]
25
+ },
26
+ { "id": "mirrors", "title": "镜像站", "children": [
27
+ { "id": "npm", "title": "npm", "url": "https://www.npmjs.com/" }
28
+ ] },
29
+ { "id": "panel", "title": "发布面板", "url": "http://127.0.0.1:4318/" }
30
+ ]
31
+ }
32
+ ```
33
+
34
+ | Field | Rule |
35
+ | --- | --- |
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. |
38
+ | `entries` | Required, a list (it may be empty). Each entry is an object. Up to 8 levels deep, 2000 entries in all. |
39
+ | `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
+ | `title` (entry) | Required, 200 characters at most. |
41
+ | `url` (entry) | Optional, `http` or `https` only (`javascript:`, `file:` and `data:` make the file unreadable). A click opens that page beside the sidebar. Without it the entry only holds its `children`: a click opens and closes them. |
42
+ | `children` (entry) | Optional, a list of entries. |
43
+
44
+ The file is at most 1 MB. Fields it does not know are ignored.
45
+
46
+ ## What the user sees
47
+
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.
50
+ - The address bar holds `#~<id>/<entry id>`, so an entry can be opened again from a link.
51
+ - A file that does not read shows the column with one row, `条目读不出来:<why>`, and no entries.
52
+
53
+ ## Changing it
54
+
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.
56
+
57
+ 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
+
59
+ Do not write `.gallery/outline.json` for an extension: where its column sits is the user's to drag, and Gallery keeps it there.