@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
@@ -1,4 +1,4 @@
1
- import { pageLink, pageOfLink } from "./page-links.mjs";
1
+ import { earlierLink, pageLink, pageOfLink } from "./page-links.mjs";
2
2
 
3
3
  // A document's address, as a link, a paste or the address bar may write it (docs/workbench.md, "A
4
4
  // document's addresses"), read in one place: { slug, block }, block null for the page itself. Pure: the
@@ -19,7 +19,8 @@ import { pageLink, pageOfLink } from "./page-links.mjs";
19
19
  // which has the list. pageAddress reads no port, as a link outlives a server; but this computer runs
20
20
  // other programs too, and other workspaces, whose folder of one name has one page id, so an address
21
21
  // on another port (elsewhere) is a document's only if the list holds it, by its folder name or its
22
- // link of now (addressOn).
22
+ // link of now (addressOn), or for a folder named doc- and eight characters, the link it had before
23
+ // those eight were its id (shared/page-links.mjs earlierId).
23
24
 
24
25
  const SLUG = "[a-z0-9]+(?:-[a-z0-9]+)*"; // shared/workspace.mjs slugPattern, which needs Node
25
26
  const FILE = "(?:doc|report)\\.html";
@@ -96,7 +97,9 @@ export function workbenchHash(text) {
96
97
  export function addressOn(text, links, origin = "http://127.0.0.1") {
97
98
  const place = pageAddress(text, links);
98
99
  const name = place && elsewhere(text, origin) ? workbenchHash(text)?.split("/")[0] : undefined;
99
- return name === undefined || links.has(name) || links.get(place.slug) === name ? place : null;
100
+ if (name === undefined || links.has(name)) return place;
101
+ const link = links.get(place.slug);
102
+ return link === name || earlierLink(place.slug, link) === name ? place : null;
100
103
  }
101
104
 
102
105
  /** Whether `text` is an address of a document of this workspace, as far as can be told with no list. */
@@ -0,0 +1,308 @@
1
+ import { createHash } from "node:crypto";
2
+ import { parse } from "parse5";
3
+ import { cellsOf } from "./card-size.mjs";
4
+ import { escapeAttribute } from "./escape.mjs";
5
+ import { attr, elementsOf, hasClass, walk } from "./html-tree.mjs";
6
+ import { ATTRIBUTE } from "./components/installed.mjs";
7
+
8
+ // The cards of a custom page's page.html as the server reads and writes them (the spec
9
+ // notes/plans/custom-blocks-spec-2026-11-07.md §5, §8; docs/render.md "A custom page"): its boards
10
+ // (div.gallery-board, data-board-id), each card a direct child of one (.gallery-card, data-card-id,
11
+ // data-x, data-y, data-w, data-h) around one instance of a custom block. What the page service
12
+ // (src/editor/page-service.mjs), gallery page add and the page as it is served (src/server/routes.mjs)
13
+ // read of a page, and the text they write: every change is a splice of the file's own text (an
14
+ // attribute's value, a card put in or taken out), every other byte staying, as a document's commits
15
+ // write. A card's id is what everything goes by: one that has none (or one that is no id, or one a
16
+ // card before it took) is given the lowest c<n> no card holds, in the file's order, the same ids
17
+ // however often it is read, so that the page shows a card by the id its first write gives it. A card's
18
+ // base (what a write to it is held to, the spec §8) is a hash of its markup, its frame's attributes and
19
+ // its instance, once those ids are in. Node's (parse5), the server's and the command line's.
20
+
21
+ /** What a card's id and a board's may be (the spec §5). */
22
+ export const CARD_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
23
+
24
+ /**
25
+ * The attributes the author of a custom page writes on its boards and cards (the spec §5): the page's
26
+ * own, which no document's component describes (tests/unit/components.mjs takes them as known names).
27
+ */
28
+ export const PAGE_ATTRIBUTES = Object.freeze(["data-board-id", "data-card-id", "data-x", "data-y", "data-w", "data-h"]);
29
+
30
+ const BOARD_CLASS = "gallery-board";
31
+ const CARD_CLASS = "gallery-card";
32
+ const isInstanceNode = (node) => (node.tagName === "div" || node.tagName === "section") && attr(node, ATTRIBUTE) !== undefined;
33
+
34
+ /** A hash of `text` as the page service names a version of a card by: 16 hex digits, line endings as \n. */
35
+ export const hashOf = (text) => createHash("sha256").update(text.replace(/\r\n?/g, "\n")).digest("hex").slice(0, 16);
36
+
37
+ const parsed = (text) => parse(text.replace(/^/, " "), { sourceCodeLocationInfo: true });
38
+
39
+ /**
40
+ * What page.html `text` holds: { boards: [{ id, node, cards }], cards } where each card is { id (as
41
+ * written: null where it has none), node, board (its board's id, or null), x, y, w, h (the cells the
42
+ * board draws it at: card-size.mjs cellsOf), instance (the instance it holds, or null), block (its
43
+ * block's id, or null), start, end (its place in the text), closed (written with its own end tag) }.
44
+ * A card is a board's child; a board is any element of the class, its cards in the file's order.
45
+ */
46
+ export function readPage(text) {
47
+ const boards = [];
48
+ walk(parsed(text), (node) => {
49
+ if (!hasClass(node, BOARD_CLASS)) return;
50
+ const cards = elementsOf(node).filter((child) => hasClass(child, CARD_CLASS) && child.sourceCodeLocation).map((child) => {
51
+ let instance = elementsOf(child).find(isInstanceNode) ?? null;
52
+ if (!instance) walk(child, (inner) => { instance ??= isInstanceNode(inner) ? inner : null; });
53
+ const place = child.sourceCodeLocation;
54
+ const dataset = { x: attr(child, "data-x"), y: attr(child, "data-y"), w: attr(child, "data-w"), h: attr(child, "data-h") };
55
+ return {
56
+ id: attr(child, "data-card-id") ?? null, node: child, board: attr(node, "data-board-id") ?? null, ...cellsOf({ dataset }),
57
+ instance, block: instance ? attr(instance, ATTRIBUTE) : null, start: place.startOffset, end: place.endOffset, closed: Boolean(place.endTag),
58
+ };
59
+ });
60
+ boards.push({ id: attr(node, "data-board-id") ?? null, node, cards });
61
+ }, { inTemplates: false });
62
+ return { boards, cards: boards.flatMap((board) => board.cards) };
63
+ }
64
+
65
+ /** The ids the cards of a page go by, in the file's order: each its own where it is an id no card before it took, else the lowest c<n> none holds. */
66
+ export function cardIds(cards) {
67
+ const held = new Set(cards.map(({ id }) => id).filter((id) => typeof id === "string" && CARD_ID_PATTERN.test(id)));
68
+ const taken = new Set();
69
+ let next = 1;
70
+ return cards.map(({ id }) => {
71
+ if (typeof id === "string" && CARD_ID_PATTERN.test(id) && !taken.has(id)) {
72
+ taken.add(id);
73
+ return id;
74
+ }
75
+ while (held.has(`c${next}`) || taken.has(`c${next}`)) next++;
76
+ const made = `c${next}`;
77
+ taken.add(made);
78
+ return made;
79
+ });
80
+ }
81
+
82
+ /** The lowest c<n> none of `ids` is. */
83
+ export function freeCardId(ids) {
84
+ const held = new Set(ids);
85
+ let n = 1;
86
+ while (held.has(`c${n}`)) n++;
87
+ return `c${n}`;
88
+ }
89
+
90
+ // The splices that set an element's attributes (`values`: name -> value, null to take one off),
91
+ // [{ start, end, text }]: an attribute there gets its value written anew, in double quotes; one not
92
+ // there goes in after its class (or its tag's name), in the order given.
93
+ function attributeSplices(text, node, values) {
94
+ const { startTag } = node.sourceCodeLocation;
95
+ const places = startTag.attrs ?? {};
96
+ const splices = [];
97
+ const fresh = [];
98
+ for (const [name, value] of Object.entries(values)) {
99
+ const place = places[name];
100
+ if (place) {
101
+ splices.push({ start: place.startOffset, end: place.endOffset, text: value === null ? "" : `${name}="${escapeAttribute(String(value))}"` });
102
+ if (value === null && text[place.startOffset - 1] === " ") splices.at(-1).start -= 1;
103
+ } else if (value !== null) fresh.push(` ${name}="${escapeAttribute(String(value))}"`);
104
+ }
105
+ if (fresh.length) {
106
+ const at = places.class?.endOffset ?? startTag.startOffset + 1 + node.tagName.length;
107
+ splices.push({ start: at, end: at, text: fresh.join("") });
108
+ }
109
+ return splices;
110
+ }
111
+
112
+ /** `text` with `splices` ([{ start, end, text }], none overlapping) made, from the last on. */
113
+ export function spliced(text, splices) {
114
+ return [...splices].sort((a, b) => b.start - a.start || b.end - a.end).reduce((out, { start, end, text: put }) => out.slice(0, start) + put + out.slice(end), text);
115
+ }
116
+
117
+ /**
118
+ * Page.html `text` with every card given an id (cardIds): { text, filled: the ids given, by the
119
+ * cards' order }. The same text when each has its own.
120
+ */
121
+ export function withCardIds(text) {
122
+ const { cards } = readPage(text);
123
+ const ids = cardIds(cards);
124
+ const splices = cards.flatMap((card, index) => (card.id === ids[index] ? [] : attributeSplices(text, card.node, { "data-card-id": ids[index] })));
125
+ return { text: splices.length ? spliced(text, splices) : text, filled: cards.flatMap((card, index) => (card.id === ids[index] ? [] : [ids[index]])) };
126
+ }
127
+
128
+ /** A card's base: the hash of its markup as `text` writes it (its frame's attributes and its instance). */
129
+ export const baseOf = (text, card) => hashOf(text.slice(card.start, card.end));
130
+
131
+ /**
132
+ * The cards of page.html `text` as the page service answers with them, once every card has its id
133
+ * (withCardIds; `text` already so when it was written): [{ id, board, x, y, w, h, base, block }].
134
+ */
135
+ export function cardsOf(text) {
136
+ const own = withCardIds(text).text;
137
+ return readPage(own).cards.map((card) => ({ id: card.id, board: card.board, x: card.x, y: card.y, w: card.w, h: card.h, base: baseOf(own, card), block: card.block }));
138
+ }
139
+
140
+ // A card's place as page.html writes it: its board, then its data-x, -y, -w and -h as written.
141
+ const placeWritten = (card) => [card.board, ...["x", "y", "w", "h"].map((axis) => attr(card.node, `data-${axis}`))].join(",");
142
+
143
+ /**
144
+ * A card's markup in `text` without its place (the data-x, -y, -w and -h of its start tag): what tells
145
+ * a change of its own (its frame's other attributes, its instance) from a move.
146
+ */
147
+ export function unplacedOf(text, card) {
148
+ const end = card.node.sourceCodeLocation.startTag.endOffset;
149
+ return text.slice(card.start, end).replace(/\s+data-[xywh]="[^"]*"/g, "") + text.slice(end, card.end);
150
+ }
151
+
152
+ /**
153
+ * The cards page.html `after` changed of `before`, each by the id the page service gives it
154
+ * (withCardIds): { <id>: kinds }, a kind "added", "removed", "cells" (another board, or its data-x, -y,
155
+ * -w or -h as written: placeWritten) or "content" (its markup but its place: unplacedOf); a card that
156
+ * did not change is none of it. What the page service tells of each write (its writes.jsonl).
157
+ */
158
+ export function cardsChanged(before, after) {
159
+ const [was, now] = [withCardIds(before).text, withCardIds(after).text];
160
+ const [a, b] = [readPage(was).cards, readPage(now).cards];
161
+ const changed = {};
162
+ for (const card of a) if (!b.some((one) => one.id === card.id)) changed[card.id] = ["removed"];
163
+ for (const card of b) {
164
+ const old = a.find((one) => one.id === card.id);
165
+ if (!old) {
166
+ changed[card.id] = ["added"];
167
+ continue;
168
+ }
169
+ const kinds = [...(placeWritten(old) !== placeWritten(card) ? ["cells"] : []), ...(unplacedOf(was, old) !== unplacedOf(now, card) ? ["content"] : [])];
170
+ if (kinds.length) changed[card.id] = kinds;
171
+ }
172
+ return changed;
173
+ }
174
+
175
+ /** `text` (every card with its id) with each card `cells` names (id -> { x, y, w, h }) at those cells: its data-x, -y, -w and -h written. */
176
+ export function withCells(text, cells) {
177
+ const { cards } = readPage(text);
178
+ const splices = cards.flatMap((card) => {
179
+ const to = cells.get(card.id);
180
+ if (!to) return [];
181
+ const values = {};
182
+ for (const axis of ["x", "y", "w", "h"]) if (to[axis] !== undefined && attr(card.node, `data-${axis}`) !== String(to[axis])) values[`data-${axis}`] = to[axis];
183
+ return Object.keys(values).length ? attributeSplices(text, card.node, values) : [];
184
+ });
185
+ return splices.length ? spliced(text, splices) : text;
186
+ }
187
+
188
+ // Where a card's markup stands with what goes with it: its whole line, its line break with it (the
189
+ // file's last line to the end of the text), when only blanks stand before and after it there; else the
190
+ // markup alone, whatever shares its line with it staying where it is, its indent too (a page written on
191
+ // one line: the cards after it and the closing tags).
192
+ function lineOf(text, start, end) {
193
+ const before = text.lastIndexOf("\n", start - 1) + 1;
194
+ const after = text.indexOf("\n", end);
195
+ const rest = after === -1 ? text.slice(end) : text.slice(end, after);
196
+ if (!/^[ \t]*$/.test(text.slice(before, start)) || !/^[ \t\r]*$/.test(rest)) return { from: start, to: end };
197
+ return { from: before, to: after === -1 ? text.length : after + 1 };
198
+ }
199
+
200
+ /** `text` with card `id` taken out, and the card as it was written: { text, html }, or null when no card has that id. */
201
+ export function withoutCard(text, id) {
202
+ const card = readPage(text).cards.find((one) => one.id === id);
203
+ if (!card) return null;
204
+ const { from, to } = lineOf(text, card.start, card.end);
205
+ return { text: text.slice(0, from) + text.slice(to), html: text.slice(card.start, card.end) };
206
+ }
207
+
208
+ // The blanks a line of `text` starts with, at `offset`.
209
+ const indentAt = (text, offset) => /^[ \t]*/.exec(text.slice(text.lastIndexOf("\n", offset - 1) + 1))[0];
210
+
211
+ /** `markup` with each line after its first taken `by` further in. */
212
+ const indented = (markup, by) => markup.replace(/\r?\n/g, (eol) => `${eol}${by}`);
213
+
214
+ /**
215
+ * The markup of a new card: `<section class="gallery-card" data-card-id data-x data-y data-w data-h>`
216
+ * around `instance` (one instance's markup, as a block's template is), at `indent` (its first line's
217
+ * blanks, which the text it goes in gives), the instance two spaces further in.
218
+ */
219
+ export function cardMarkup({ id, x, y, w, h }, instance, indent = "", eol = "\n") {
220
+ const open = `<section class="${CARD_CLASS}" data-card-id="${escapeAttribute(id)}" data-x="${x}" data-y="${y}" data-w="${w}" data-h="${h}">`;
221
+ return `${open}${eol}${indent} ${indented(instance.trim().replace(/\r?\n/g, eol), `${indent} `)}${eol}${indent}</section>`;
222
+ }
223
+
224
+ /**
225
+ * `text` with the card `markup` (cardMarkup's, or a card as withoutCard gave it) put last in board
226
+ * `board` (its data-board-id), on a line of its own, as far in as its cards are (two spaces further in
227
+ * than the board where it has none): { text, start } (where the card starts), or null when no board
228
+ * has that id. `markup` that starts at an indent of its own is put back at the board's.
229
+ */
230
+ export function withCard(text, board, markup) {
231
+ const found = readPage(text).boards.find((one) => one.id === board);
232
+ if (!found) return null;
233
+ const { node } = found;
234
+ const place = node.sourceCodeLocation;
235
+ const eol = text.includes("\r\n") ? "\r\n" : "\n";
236
+ const last = found.cards.at(-1);
237
+ const indent = last ? indentAt(text, last.start) : `${indentAt(text, place.startOffset)} `;
238
+ // The indent the card's markup stood at (its end tag's line, what withoutCard leaves of it), each of its
239
+ // lines moved from there to this board's: none where the two are one, so that a card put back where it
240
+ // was is its old text again, byte for byte.
241
+ const from = markup.match(/\n([ \t]*)<\/[a-z]+>\s*$/)?.[1] ?? "";
242
+ const body = markup.trim().replace(/\r?\n/g, "\n").split("\n").map((line, index) => (index === 0 || from === indent ? line : line.startsWith(from) ? `${indent}${line.slice(from.length)}` : line)).join(eol);
243
+ if (place.endTag) {
244
+ const close = place.endTag.startOffset;
245
+ const lineStart = text.lastIndexOf("\n", close - 1) + 1;
246
+ const onOwnLine = /^[ \t]*$/.test(text.slice(lineStart, close));
247
+ const at = onOwnLine ? lineStart : close;
248
+ const put = `${onOwnLine ? "" : eol}${indent}${body}${eol}`;
249
+ return { text: text.slice(0, at) + put + text.slice(at), start: at + put.indexOf(body) };
250
+ }
251
+ const at = place.endOffset;
252
+ const put = `${eol}${indent}${body}`;
253
+ return { text: text.slice(0, at) + put + text.slice(at), start: at + put.indexOf(body) };
254
+ }
255
+
256
+ /**
257
+ * Page.html `text` as it is served (src/server/routes.mjs): every card with its id (withCardIds), and
258
+ * on each card what the page's board reads of it and no file holds (all data-ge-*, which nothing writes
259
+ * back): `data-ge-base`, its base; and by what `blockOf(id)` says of its block ({ fit, bare, runs }, or
260
+ * null for one there is none of), `data-ge-fit="content"`, `data-ge-bare`, and `data-ge-state`
261
+ * (`document`: a block whose places lack page; `disabled`: turned off; `missing`: none there) with its
262
+ * instance put in a <template> (`data-ge-held`) where the block does not run on the page, so that no
263
+ * script starts it and the board shows a note instead.
264
+ */
265
+ export function servedPage(text, { blockOf = () => null } = {}) {
266
+ const own = withCardIds(text).text;
267
+ const splices = [];
268
+ for (const card of readPage(own).cards) {
269
+ const block = card.block ? blockOf(card.block) : null;
270
+ const values = { "data-ge-base": baseOf(own, card) };
271
+ if (block?.fit === "content") values["data-ge-fit"] = "content";
272
+ if (block?.bare) values["data-ge-bare"] = "";
273
+ const state = card.block === null ? null : block?.state ?? "missing";
274
+ if (state && state !== "page") values["data-ge-state"] = state;
275
+ splices.push(...attributeSplices(own, card.node, values));
276
+ if (card.instance && block && state !== "page" && state !== "missing") {
277
+ const { startOffset, endOffset } = card.instance.sourceCodeLocation;
278
+ splices.push({ start: startOffset, end: startOffset, text: "<template data-ge-held>" }, { start: endOffset, end: endOffset, text: "</template>" });
279
+ }
280
+ }
281
+ return spliced(own, splices);
282
+ }
283
+
284
+ // A card's markup read on a board of its own: { text, card, from, to } (where the markup is in the text).
285
+ function alone(markup) {
286
+ const before = `<!doctype html><html><head></head><body><div class="${BOARD_CLASS}">`;
287
+ const text = `${before}${markup}</div></body></html>`;
288
+ const [board] = readPage(text).boards;
289
+ return { text, board, from: before.length, to: before.length + markup.length };
290
+ }
291
+
292
+ /** Whether `markup` reads as one card and nothing else (a comment aside), closed by its own end tag, holding one instance of a block: its card, or null. */
293
+ export function oneCard(markup) {
294
+ const { board } = alone(markup);
295
+ if (!board || board.cards.length !== 1) return null;
296
+ const strays = elementsOf(board.node).length !== 1 || board.node.childNodes.some((node) => node.nodeName === "#text" && node.value.trim());
297
+ const [card] = board.cards;
298
+ return strays || !card.closed || !card.instance || card.instance.parentNode !== card.node ? null : card;
299
+ }
300
+
301
+ /** A card's `markup` (oneCard's) with its id and cells set: { id, x, y, w, h }. */
302
+ export function cardWith(markup, { id, x, y, w, h }) {
303
+ const { text, board, from, to } = alone(markup);
304
+ const values = { "data-card-id": id, "data-x": x, "data-y": y, "data-w": w, "data-h": h };
305
+ const splices = attributeSplices(text, board.cards[0].node, values);
306
+ const grown = splices.reduce((sum, { start, end, text: put }) => sum + put.length - (end - start), 0);
307
+ return spliced(text, splices).slice(from, to + grown);
308
+ }
@@ -5,8 +5,14 @@
5
5
  // one title need nothing to tell them apart.
6
6
  //
7
7
  // A page id has the look of a block id (shared/ids.mjs) and is worked out from the folder name, the
8
- // document's identity, which a title never changes. So nothing is kept anywhere: no file, no list to
9
- // keep in step, and a page alone in a tab or with no list read yet can always say its own address.
8
+ // document's identity, which a title never changes: a hash of the name, but for a name of the shape
9
+ // doc-<eight> (DOC_SLUG), which has those eight as its id. The workbench names a new document so
10
+ // (shared/workspace.mjs newDocSlug: doc- and a random id no name of the workspace has), so that the
11
+ // folder and the address read alike (doc-tacti90g, #反馈文档-tacti90g); every name made before has the
12
+ // id it had, but for one of that very shape (an Agent's slug may be doc-overview), which keeps the
13
+ // address it had besides: its hash opens it too (earlierId, pageOfLink). So nothing is kept anywhere:
14
+ // no file, no list to keep in step, and a page alone in a tab or with no list read yet can always say
15
+ // its own address.
10
16
  // The folder name opens its document too, for what was written by it. A document in the trash has its
11
17
  // id, and has its address back when it is restored; one restored under another folder name goes by
12
18
  // that name's id, as the links of files to it change too.
@@ -19,11 +25,17 @@
19
25
  const NOT_WORDS = /(?:[^\p{L}\p{M}\p{N}_]\p{M}*)+/gu;
20
26
 
21
27
  /**
22
- * A document's page id: eight letters and digits, a letter first, from a 53-bit hash of its folder
23
- * name (cyrb53).
28
+ * A folder name that is a page id's own: "doc-" and the eight characters of an id, a lowercase letter
29
+ * first and lowercase letters or digits after it. Its group is the id (pageId).
30
+ */
31
+ export const DOC_SLUG = /^doc-([a-z][a-z0-9]{7})$/;
32
+
33
+ /**
34
+ * The id a name has from a 53-bit hash of it (cyrb53): eight letters and digits, a letter first. Every
35
+ * name had it before the folders of the shape DOC_SLUG had their own (pageId, earlierId).
24
36
  * @param {string} slug
25
37
  */
26
- export function pageId(slug) {
38
+ function hashId(slug) {
27
39
  let one = 0xdeadbeef;
28
40
  let two = 0x41c6ce57;
29
41
  for (let at = 0; at < slug.length; at++) {
@@ -36,6 +48,40 @@ export function pageId(slug) {
36
48
  return String.fromCharCode(97 + hash % 26) + Math.floor(hash / 26).toString(36).padStart(7, "0").slice(-7);
37
49
  }
38
50
 
51
+ /**
52
+ * A document's page id: eight letters and digits, a letter first. A folder named doc-<eight> (DOC_SLUG)
53
+ * has those eight; any other name, a hash of it. So only a name of that one shape reads otherwise than
54
+ * it did, and it keeps the address it had besides (earlierId).
55
+ * @param {string} slug
56
+ */
57
+ export const pageId = (slug) => DOC_SLUG.exec(slug)?.[1] ?? hashId(slug);
58
+
59
+ /**
60
+ * The id a name of the shape DOC_SLUG went by before its own eight were its id, its hash, or null for
61
+ * any other name, whose id has not changed. An Agent's slug may have that shape (doc-overview was
62
+ * #Overview-f3md3kg4 before), and an address written down then opens it still (pageOfLink, earlierLink).
63
+ * @param {string} slug
64
+ */
65
+ export const earlierId = (slug) => (DOC_SLUG.test(slug) ? hashId(slug) : null);
66
+
67
+ const ID_FIRST = "abcdefghijklmnopqrstuvwxyz";
68
+ const ID_REST = `${ID_FIRST}0123456789`;
69
+
70
+ /**
71
+ * A new page id, one `taken` (a Set of ids) does not hold: eight characters of the shape DOC_SLUG has,
72
+ * each picked by `random` (a function giving a number from 0 up to 1, Math.random's way: the tests give
73
+ * their own), another picked while it is held.
74
+ * @param {Set<string>} taken
75
+ * @param {() => number} [random]
76
+ */
77
+ export function newPageId(taken, random = Math.random) {
78
+ for (;;) {
79
+ let id = ID_FIRST[Math.min(25, Math.floor(random() * 26))];
80
+ for (let at = 1; at < 8; at++) id += ID_REST[Math.min(35, Math.floor(random() * 36))];
81
+ if (!taken.has(id)) return id;
82
+ }
83
+ }
84
+
39
85
  /**
40
86
  * A document's link, what stands after # in its address: its title's words and its page id, the id
41
87
  * alone for a title that leaves no words or one not known here.
@@ -46,6 +92,20 @@ export function pageLink({ slug, title }) {
46
92
  return words ? `${words}-${pageId(slug)}` : pageId(slug);
47
93
  }
48
94
 
95
+ /**
96
+ * The link a document had before its own eight were its id, if it has an earlier id (earlierId): its
97
+ * `link` of now with the id at its end swapped for that one, its words as they are; else null. Only
98
+ * an address on another server is held to be a document's by its words (addressOn), and one written
99
+ * for such a document before reads so.
100
+ * @param {string} slug
101
+ * @param {string | undefined} link the link the document has now (pageLink)
102
+ */
103
+ export function earlierLink(slug, link) {
104
+ const was = earlierId(slug);
105
+ const now = pageId(slug);
106
+ return was !== null && link?.endsWith(now) ? link.slice(0, link.length - now.length) + was : null;
107
+ }
108
+
49
109
  /**
50
110
  * Each document's link: a Map of slug to link, which is also the list of documents an address is read
51
111
  * against (pageOfLink).
@@ -56,7 +116,9 @@ export const pageLinks = (pages) => new Map(pages.map((page) => [page.slug, page
56
116
 
57
117
  /**
58
118
  * The document `value` names of those in `links`: by its folder name, else by the page id after the
59
- * last dash of a link, or that id alone, whatever words stand before it. Its slug, or null.
119
+ * last dash of a link, or that id alone, whatever words stand before it; else, for a folder of the
120
+ * shape DOC_SLUG, by the id it went by before (earlierId), which never takes a document that has the
121
+ * id for its own. Its slug, or null.
60
122
  * @param {Map<string, string>} links
61
123
  * @param {string} value
62
124
  */
@@ -64,6 +126,7 @@ export function pageOfLink(links, value) {
64
126
  if (links.has(value)) return value;
65
127
  const id = value.slice(value.lastIndexOf("-") + 1);
66
128
  for (const slug of links.keys()) if (pageId(slug) === id) return slug;
129
+ for (const slug of links.keys()) if (earlierId(slug) === id) return slug;
67
130
  return null;
68
131
  }
69
132