@morphemecms/cms 0.1.0 → 0.2.0-next-20261104150211

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 (908) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE +21 -21
  3. package/README.md +51 -51
  4. package/astro.mjs +162 -162
  5. package/bin/morpheme.mjs +38 -38
  6. package/client.d.ts +10 -10
  7. package/defaults/blockTexts.ts +33 -33
  8. package/defaults/collections.ts +774 -774
  9. package/defaults/colors.ts +125 -125
  10. package/defaults/company.ts +20 -20
  11. package/defaults/editor.ts +178 -178
  12. package/defaults/internalLinks.ts +30 -30
  13. package/defaults/opens.ts +18 -18
  14. package/defaults/popup.tsx +93 -93
  15. package/defaults/privacy.ts +79 -79
  16. package/defaults/rules.ts +450 -450
  17. package/defaults/schema.ts +16 -16
  18. package/defaults/sitedata.ts +129 -129
  19. package/defaults/standard.ts +106 -106
  20. package/defaults/standardPages.ts +87 -87
  21. package/defaults/texts.ts +481 -481
  22. package/demo/README.md +26 -26
  23. package/demo/src/content/blog/build-a-page-from-blocks.md +19 -19
  24. package/demo/src/content/blog/colors-everyone-can-read.md +19 -19
  25. package/demo/src/content/blog/edit-your-website-from-your-phone.md +21 -21
  26. package/demo/src/content/blog/every-save-is-a-version.md +21 -21
  27. package/demo/src/content/blog/schedule-a-post.md +17 -17
  28. package/demo/src/content/blog/secure-from-day-one.md +17 -17
  29. package/demo/src/content/blog/seo-without-the-guesswork.md +23 -23
  30. package/demo/src/content/blog/switch-themes-without-losing-anything.md +23 -23
  31. package/demo/src/content/blog/the-app-store.md +21 -21
  32. package/demo/src/content/pages/about.md +22 -22
  33. package/demo/src/content/pages/app-store.md +30 -30
  34. package/demo/src/content/pages/blocks.md +98 -98
  35. package/demo/src/content/pages/blog-page.md +11 -11
  36. package/demo/src/content/pages/contact.md +16 -16
  37. package/demo/src/content/pages/get-started.md +20 -20
  38. package/demo/src/content/pages/home.md +26 -26
  39. package/demo/src/content/pages/page-not-found.md +11 -11
  40. package/demo/src/content/pages/privacy-policy.md +24 -24
  41. package/demo/src/data/blocks.json +25 -25
  42. package/demo/src/data/booking.json +6 -6
  43. package/demo/src/data/categories/apps.json +6 -6
  44. package/demo/src/data/categories/design.json +6 -6
  45. package/demo/src/data/categories/editing.json +6 -6
  46. package/demo/src/data/categories/security.json +6 -6
  47. package/demo/src/data/categories/seo.json +6 -6
  48. package/demo/src/data/colors.json +75 -75
  49. package/demo/src/data/contact.json +8 -8
  50. package/demo/src/data/cookies.json +21 -21
  51. package/demo/src/data/footer.json +27 -27
  52. package/demo/src/data/menu.json +35 -35
  53. package/demo/src/data/mobile-menu.json +25 -25
  54. package/demo/src/data/popups/booking-bar.json +13 -13
  55. package/demo/src/data/popups/try-the-editor.json +16 -16
  56. package/demo/src/data/standard-pages.json +8 -8
  57. package/demo/src/data/testimonials/sample-bakery.json +10 -10
  58. package/demo/src/data/testimonials/sample-clinic.json +10 -10
  59. package/demo/src/data/testimonials/sample-studio.json +10 -10
  60. package/demo/src/site/colors.ts +11 -11
  61. package/demo/src/site/config.ts +19 -19
  62. package/icons/lucide/LICENSE +43 -43
  63. package/icons/lucide/address-book.svg +1 -1
  64. package/icons/lucide/app-window.svg +1 -1
  65. package/icons/lucide/arrow-counter-clockwise.svg +1 -1
  66. package/icons/lucide/arrow-down.svg +1 -1
  67. package/icons/lucide/arrow-left.svg +1 -1
  68. package/icons/lucide/arrow-right.svg +1 -1
  69. package/icons/lucide/arrow-square-out.svg +1 -1
  70. package/icons/lucide/arrow-u-up-left.svg +1 -1
  71. package/icons/lucide/arrow-u-up-right.svg +1 -1
  72. package/icons/lucide/arrow-up-right.svg +1 -1
  73. package/icons/lucide/arrow-up.svg +1 -1
  74. package/icons/lucide/arrows-down-up.svg +1 -1
  75. package/icons/lucide/arrows-in-line-horizontal.svg +1 -1
  76. package/icons/lucide/arrows-out-line-horizontal.svg +1 -1
  77. package/icons/lucide/article.svg +1 -1
  78. package/icons/lucide/bank.svg +1 -1
  79. package/icons/lucide/bell.svg +1 -1
  80. package/icons/lucide/bicycle.svg +1 -1
  81. package/icons/lucide/binoculars.svg +1 -1
  82. package/icons/lucide/book-open-text.svg +1 -1
  83. package/icons/lucide/book-open.svg +1 -1
  84. package/icons/lucide/browser.svg +1 -1
  85. package/icons/lucide/buildings.svg +1 -1
  86. package/icons/lucide/bus.svg +1 -1
  87. package/icons/lucide/calendar-blank.svg +1 -1
  88. package/icons/lucide/calendar-check.svg +1 -1
  89. package/icons/lucide/car.svg +1 -1
  90. package/icons/lucide/cards.svg +1 -1
  91. package/icons/lucide/caret-down.svg +1 -1
  92. package/icons/lucide/caret-left.svg +1 -1
  93. package/icons/lucide/caret-right.svg +1 -1
  94. package/icons/lucide/caret-up.svg +1 -1
  95. package/icons/lucide/certificate.svg +1 -1
  96. package/icons/lucide/chart-line-up.svg +1 -1
  97. package/icons/lucide/chats.svg +1 -1
  98. package/icons/lucide/check-circle.svg +1 -1
  99. package/icons/lucide/check.svg +1 -1
  100. package/icons/lucide/circle-half.svg +1 -1
  101. package/icons/lucide/circle.svg +1 -1
  102. package/icons/lucide/clock-counter-clockwise.svg +1 -1
  103. package/icons/lucide/clock.svg +1 -1
  104. package/icons/lucide/code.svg +1 -1
  105. package/icons/lucide/coffee.svg +1 -1
  106. package/icons/lucide/columns.svg +1 -1
  107. package/icons/lucide/cookie.svg +1 -1
  108. package/icons/lucide/copy.svg +1 -1
  109. package/icons/lucide/credit-card.svg +1 -1
  110. package/icons/lucide/currency-circle-dollar.svg +1 -1
  111. package/icons/lucide/cursor-click.svg +1 -1
  112. package/icons/lucide/database.svg +1 -1
  113. package/icons/lucide/desktop.svg +1 -1
  114. package/icons/lucide/device-mobile.svg +1 -1
  115. package/icons/lucide/door-open.svg +1 -1
  116. package/icons/lucide/download-simple.svg +1 -1
  117. package/icons/lucide/envelope-simple.svg +1 -1
  118. package/icons/lucide/eye-slash.svg +1 -1
  119. package/icons/lucide/eye.svg +1 -1
  120. package/icons/lucide/file-pdf.svg +1 -1
  121. package/icons/lucide/file-text.svg +1 -1
  122. package/icons/lucide/file-video.svg +1 -1
  123. package/icons/lucide/file-zip.svg +1 -1
  124. package/icons/lucide/flower-lotus.svg +1 -1
  125. package/icons/lucide/folder-simple.svg +1 -1
  126. package/icons/lucide/funnel.svg +1 -1
  127. package/icons/lucide/gauge.svg +1 -1
  128. package/icons/lucide/gear.svg +1 -1
  129. package/icons/lucide/github-logo.svg +1 -1
  130. package/icons/lucide/globe.svg +1 -1
  131. package/icons/lucide/google-logo.svg +1 -1
  132. package/icons/lucide/graduation-cap.svg +1 -1
  133. package/icons/lucide/hammer.svg +1 -1
  134. package/icons/lucide/hand-heart.svg +1 -1
  135. package/icons/lucide/handshake.svg +1 -1
  136. package/icons/lucide/hard-drives.svg +1 -1
  137. package/icons/lucide/heart.svg +1 -1
  138. package/icons/lucide/house.svg +1 -1
  139. package/icons/lucide/image-square.svg +1 -1
  140. package/icons/lucide/image.svg +1 -1
  141. package/icons/lucide/info.svg +1 -1
  142. package/icons/lucide/keyboard.svg +1 -1
  143. package/icons/lucide/leaf.svg +1 -1
  144. package/icons/lucide/lifebuoy.svg +1 -1
  145. package/icons/lucide/lightbulb.svg +1 -1
  146. package/icons/lucide/link-break.svg +1 -1
  147. package/icons/lucide/link-simple.svg +1 -1
  148. package/icons/lucide/list-bullets.svg +1 -1
  149. package/icons/lucide/list-checks.svg +1 -1
  150. package/icons/lucide/list-numbers.svg +1 -1
  151. package/icons/lucide/list.svg +1 -1
  152. package/icons/lucide/lock-simple-open.svg +1 -1
  153. package/icons/lucide/lock-simple.svg +1 -1
  154. package/icons/lucide/magnifying-glass.svg +1 -1
  155. package/icons/lucide/map-pin.svg +1 -1
  156. package/icons/lucide/map-trifold.svg +1 -1
  157. package/icons/lucide/medal.svg +1 -1
  158. package/icons/lucide/megaphone.svg +1 -1
  159. package/icons/lucide/minus.svg +1 -1
  160. package/icons/lucide/moon.svg +1 -1
  161. package/icons/lucide/newspaper.svg +1 -1
  162. package/icons/lucide/pack.json +23 -23
  163. package/icons/lucide/paint-brush-broad.svg +1 -1
  164. package/icons/lucide/palette.svg +1 -1
  165. package/icons/lucide/paper-plane-tilt.svg +1 -1
  166. package/icons/lucide/pencil-simple.svg +1 -1
  167. package/icons/lucide/phone.svg +1 -1
  168. package/icons/lucide/play-fill.svg +1 -1
  169. package/icons/lucide/plus.svg +1 -1
  170. package/icons/lucide/prohibit.svg +1 -1
  171. package/icons/lucide/puzzle-piece.svg +1 -1
  172. package/icons/lucide/question.svg +1 -1
  173. package/icons/lucide/quotes.svg +1 -1
  174. package/icons/lucide/rows.svg +1 -1
  175. package/icons/lucide/ruler.svg +1 -1
  176. package/icons/lucide/scan.svg +1 -1
  177. package/icons/lucide/shapes.svg +1 -1
  178. package/icons/lucide/share-network.svg +1 -1
  179. package/icons/lucide/shield-check.svg +1 -1
  180. package/icons/lucide/sidebar-simple.svg +1 -1
  181. package/icons/lucide/sign-out.svg +1 -1
  182. package/icons/lucide/signpost.svg +1 -1
  183. package/icons/lucide/sliders-horizontal.svg +1 -1
  184. package/icons/lucide/smiley.svg +1 -1
  185. package/icons/lucide/sparkle.svg +1 -1
  186. package/icons/lucide/square-half-bottom.svg +1 -1
  187. package/icons/lucide/square.svg +1 -1
  188. package/icons/lucide/squares-four.svg +1 -1
  189. package/icons/lucide/sticker.svg +1 -1
  190. package/icons/lucide/storefront.svg +1 -1
  191. package/icons/lucide/sun.svg +1 -1
  192. package/icons/lucide/swatches.svg +1 -1
  193. package/icons/lucide/tag.svg +1 -1
  194. package/icons/lucide/text-aa.svg +1 -1
  195. package/icons/lucide/text-align-left.svg +1 -1
  196. package/icons/lucide/text-b.svg +1 -1
  197. package/icons/lucide/text-h-one.svg +1 -1
  198. package/icons/lucide/text-h-three.svg +1 -1
  199. package/icons/lucide/text-h-two.svg +1 -1
  200. package/icons/lucide/text-italic.svg +1 -1
  201. package/icons/lucide/text-t.svg +1 -1
  202. package/icons/lucide/ticket.svg +1 -1
  203. package/icons/lucide/toggle-right.svg +1 -1
  204. package/icons/lucide/train.svg +1 -1
  205. package/icons/lucide/trash.svg +1 -1
  206. package/icons/lucide/upload-simple.svg +1 -1
  207. package/icons/lucide/user-circle.svg +1 -1
  208. package/icons/lucide/user.svg +1 -1
  209. package/icons/lucide/users-three.svg +1 -1
  210. package/icons/lucide/users.svg +1 -1
  211. package/icons/lucide/video-camera.svg +1 -1
  212. package/icons/lucide/warning-circle.svg +1 -1
  213. package/icons/lucide/warning.svg +1 -1
  214. package/icons/lucide/wave-sine.svg +1 -1
  215. package/icons/lucide/wheelchair.svg +1 -1
  216. package/icons/lucide/wrench.svg +1 -1
  217. package/icons/lucide/x.svg +1 -1
  218. package/icons/material-symbols/LICENSE +201 -201
  219. package/icons/material-symbols/address-book.svg +1 -1
  220. package/icons/material-symbols/app-window.svg +1 -1
  221. package/icons/material-symbols/arrow-counter-clockwise.svg +1 -1
  222. package/icons/material-symbols/arrow-down.svg +1 -1
  223. package/icons/material-symbols/arrow-left.svg +1 -1
  224. package/icons/material-symbols/arrow-right.svg +1 -1
  225. package/icons/material-symbols/arrow-square-out.svg +1 -1
  226. package/icons/material-symbols/arrow-u-up-left.svg +1 -1
  227. package/icons/material-symbols/arrow-u-up-right.svg +1 -1
  228. package/icons/material-symbols/arrow-up-right.svg +1 -1
  229. package/icons/material-symbols/arrow-up.svg +1 -1
  230. package/icons/material-symbols/arrows-down-up.svg +1 -1
  231. package/icons/material-symbols/arrows-in-line-horizontal.svg +1 -1
  232. package/icons/material-symbols/arrows-out-line-horizontal.svg +1 -1
  233. package/icons/material-symbols/article.svg +1 -1
  234. package/icons/material-symbols/bank.svg +1 -1
  235. package/icons/material-symbols/bell.svg +1 -1
  236. package/icons/material-symbols/bicycle.svg +1 -1
  237. package/icons/material-symbols/binoculars.svg +1 -1
  238. package/icons/material-symbols/book-open-text.svg +1 -1
  239. package/icons/material-symbols/book-open.svg +1 -1
  240. package/icons/material-symbols/browser.svg +1 -1
  241. package/icons/material-symbols/buildings.svg +1 -1
  242. package/icons/material-symbols/bus.svg +1 -1
  243. package/icons/material-symbols/calendar-blank.svg +1 -1
  244. package/icons/material-symbols/calendar-check.svg +1 -1
  245. package/icons/material-symbols/car.svg +1 -1
  246. package/icons/material-symbols/cards.svg +1 -1
  247. package/icons/material-symbols/caret-down.svg +1 -1
  248. package/icons/material-symbols/caret-left.svg +1 -1
  249. package/icons/material-symbols/caret-right.svg +1 -1
  250. package/icons/material-symbols/caret-up.svg +1 -1
  251. package/icons/material-symbols/certificate.svg +1 -1
  252. package/icons/material-symbols/chart-line-up.svg +1 -1
  253. package/icons/material-symbols/chats.svg +1 -1
  254. package/icons/material-symbols/check-circle.svg +1 -1
  255. package/icons/material-symbols/check.svg +1 -1
  256. package/icons/material-symbols/circle-half.svg +1 -1
  257. package/icons/material-symbols/circle.svg +1 -1
  258. package/icons/material-symbols/clock-counter-clockwise.svg +1 -1
  259. package/icons/material-symbols/clock.svg +1 -1
  260. package/icons/material-symbols/code.svg +1 -1
  261. package/icons/material-symbols/coffee.svg +1 -1
  262. package/icons/material-symbols/columns.svg +1 -1
  263. package/icons/material-symbols/cookie.svg +1 -1
  264. package/icons/material-symbols/copy.svg +1 -1
  265. package/icons/material-symbols/credit-card.svg +1 -1
  266. package/icons/material-symbols/currency-circle-dollar.svg +1 -1
  267. package/icons/material-symbols/cursor-click.svg +1 -1
  268. package/icons/material-symbols/database.svg +1 -1
  269. package/icons/material-symbols/desktop.svg +1 -1
  270. package/icons/material-symbols/device-mobile.svg +1 -1
  271. package/icons/material-symbols/door-open.svg +1 -1
  272. package/icons/material-symbols/download-simple.svg +1 -1
  273. package/icons/material-symbols/envelope-simple.svg +1 -1
  274. package/icons/material-symbols/eye-slash.svg +1 -1
  275. package/icons/material-symbols/eye.svg +1 -1
  276. package/icons/material-symbols/file-pdf.svg +1 -1
  277. package/icons/material-symbols/file-text.svg +1 -1
  278. package/icons/material-symbols/file-video.svg +1 -1
  279. package/icons/material-symbols/file-zip.svg +1 -1
  280. package/icons/material-symbols/flower-lotus.svg +1 -1
  281. package/icons/material-symbols/folder-simple.svg +1 -1
  282. package/icons/material-symbols/funnel.svg +1 -1
  283. package/icons/material-symbols/gauge.svg +1 -1
  284. package/icons/material-symbols/gear.svg +1 -1
  285. package/icons/material-symbols/github-logo.svg +1 -1
  286. package/icons/material-symbols/globe.svg +1 -1
  287. package/icons/material-symbols/google-logo.svg +1 -1
  288. package/icons/material-symbols/graduation-cap.svg +1 -1
  289. package/icons/material-symbols/hammer.svg +1 -1
  290. package/icons/material-symbols/hand-heart.svg +1 -1
  291. package/icons/material-symbols/handshake.svg +1 -1
  292. package/icons/material-symbols/hard-drives.svg +1 -1
  293. package/icons/material-symbols/heart.svg +1 -1
  294. package/icons/material-symbols/house.svg +1 -1
  295. package/icons/material-symbols/image-square.svg +1 -1
  296. package/icons/material-symbols/image.svg +1 -1
  297. package/icons/material-symbols/info.svg +1 -1
  298. package/icons/material-symbols/keyboard.svg +1 -1
  299. package/icons/material-symbols/leaf.svg +1 -1
  300. package/icons/material-symbols/lifebuoy.svg +1 -1
  301. package/icons/material-symbols/lightbulb.svg +1 -1
  302. package/icons/material-symbols/link-break.svg +1 -1
  303. package/icons/material-symbols/link-simple.svg +1 -1
  304. package/icons/material-symbols/list-bullets.svg +1 -1
  305. package/icons/material-symbols/list-checks.svg +1 -1
  306. package/icons/material-symbols/list-numbers.svg +1 -1
  307. package/icons/material-symbols/list.svg +1 -1
  308. package/icons/material-symbols/lock-simple-open.svg +1 -1
  309. package/icons/material-symbols/lock-simple.svg +1 -1
  310. package/icons/material-symbols/magnifying-glass.svg +1 -1
  311. package/icons/material-symbols/map-pin.svg +1 -1
  312. package/icons/material-symbols/map-trifold.svg +1 -1
  313. package/icons/material-symbols/medal.svg +1 -1
  314. package/icons/material-symbols/megaphone.svg +1 -1
  315. package/icons/material-symbols/minus.svg +1 -1
  316. package/icons/material-symbols/moon.svg +1 -1
  317. package/icons/material-symbols/newspaper.svg +1 -1
  318. package/icons/material-symbols/pack.json +29 -29
  319. package/icons/material-symbols/paint-brush-broad.svg +1 -1
  320. package/icons/material-symbols/palette.svg +1 -1
  321. package/icons/material-symbols/paper-plane-tilt.svg +1 -1
  322. package/icons/material-symbols/pencil-simple.svg +1 -1
  323. package/icons/material-symbols/phone.svg +1 -1
  324. package/icons/material-symbols/play-fill.svg +1 -1
  325. package/icons/material-symbols/plus.svg +1 -1
  326. package/icons/material-symbols/prohibit.svg +1 -1
  327. package/icons/material-symbols/puzzle-piece.svg +1 -1
  328. package/icons/material-symbols/question.svg +1 -1
  329. package/icons/material-symbols/quotes.svg +1 -1
  330. package/icons/material-symbols/rows.svg +1 -1
  331. package/icons/material-symbols/ruler.svg +1 -1
  332. package/icons/material-symbols/scan.svg +1 -1
  333. package/icons/material-symbols/shapes.svg +1 -1
  334. package/icons/material-symbols/share-network.svg +1 -1
  335. package/icons/material-symbols/shield-check.svg +1 -1
  336. package/icons/material-symbols/sidebar-simple.svg +1 -1
  337. package/icons/material-symbols/sign-out.svg +1 -1
  338. package/icons/material-symbols/signpost.svg +1 -1
  339. package/icons/material-symbols/sliders-horizontal.svg +1 -1
  340. package/icons/material-symbols/smiley.svg +1 -1
  341. package/icons/material-symbols/sparkle.svg +1 -1
  342. package/icons/material-symbols/square-half-bottom.svg +1 -1
  343. package/icons/material-symbols/square.svg +1 -1
  344. package/icons/material-symbols/squares-four.svg +1 -1
  345. package/icons/material-symbols/sticker.svg +1 -1
  346. package/icons/material-symbols/storefront.svg +1 -1
  347. package/icons/material-symbols/sun.svg +1 -1
  348. package/icons/material-symbols/swatches.svg +1 -1
  349. package/icons/material-symbols/tag.svg +1 -1
  350. package/icons/material-symbols/text-aa.svg +1 -1
  351. package/icons/material-symbols/text-align-left.svg +1 -1
  352. package/icons/material-symbols/text-b.svg +1 -1
  353. package/icons/material-symbols/text-h-one.svg +1 -1
  354. package/icons/material-symbols/text-h-three.svg +1 -1
  355. package/icons/material-symbols/text-h-two.svg +1 -1
  356. package/icons/material-symbols/text-italic.svg +1 -1
  357. package/icons/material-symbols/text-t.svg +1 -1
  358. package/icons/material-symbols/ticket.svg +1 -1
  359. package/icons/material-symbols/toggle-right.svg +1 -1
  360. package/icons/material-symbols/train.svg +1 -1
  361. package/icons/material-symbols/trash.svg +1 -1
  362. package/icons/material-symbols/upload-simple.svg +1 -1
  363. package/icons/material-symbols/user-circle.svg +1 -1
  364. package/icons/material-symbols/user.svg +1 -1
  365. package/icons/material-symbols/users-three.svg +1 -1
  366. package/icons/material-symbols/users.svg +1 -1
  367. package/icons/material-symbols/video-camera.svg +1 -1
  368. package/icons/material-symbols/warning-circle.svg +1 -1
  369. package/icons/material-symbols/warning.svg +1 -1
  370. package/icons/material-symbols/wave-sine.svg +1 -1
  371. package/icons/material-symbols/wheelchair.svg +1 -1
  372. package/icons/material-symbols/wrench.svg +1 -1
  373. package/icons/material-symbols/x.svg +1 -1
  374. package/icons/phosphor/pack.json +8 -8
  375. package/lib/apps.mjs +142 -139
  376. package/lib/apps.test.d.mts +1 -0
  377. package/lib/apps.test.mjs +50 -0
  378. package/lib/blocks.mjs +90 -90
  379. package/lib/caseCollisions.d.mts +4 -0
  380. package/lib/caseCollisions.mjs +62 -0
  381. package/lib/caseCollisions.test.d.mts +1 -0
  382. package/lib/caseCollisions.test.mjs +74 -0
  383. package/lib/colors.ts +86 -86
  384. package/lib/contactBar.ts +18 -18
  385. package/lib/contracts.d.mts +15 -0
  386. package/lib/contracts.mjs +17 -0
  387. package/lib/cookieCategories.mjs +28 -28
  388. package/lib/crop.mjs +83 -83
  389. package/lib/csp.mjs +130 -130
  390. package/lib/cspSources.mjs +60 -60
  391. package/lib/dynamic-colors.ts +426 -426
  392. package/lib/git.mjs +64 -64
  393. package/lib/hooks.ts +51 -51
  394. package/lib/inline.ts +20 -20
  395. package/lib/license-texts/Apache-2.0.txt +190 -190
  396. package/lib/license-texts/BSD-2-Clause.txt +24 -24
  397. package/lib/license-texts/BSD-3-Clause.txt +28 -28
  398. package/lib/license-texts/ISC.txt +15 -15
  399. package/lib/license-texts/MIT.txt +21 -21
  400. package/lib/licenses.d.mts +1 -1
  401. package/lib/licenses.mjs +683 -683
  402. package/lib/markdown.ts +42 -42
  403. package/lib/motion-schemes.mjs +5 -5
  404. package/lib/motion.ts +131 -131
  405. package/lib/notice.mjs +34 -34
  406. package/lib/scheduled.mjs +37 -37
  407. package/lib/snackbar.ts +149 -149
  408. package/lib/status.mjs +18 -18
  409. package/lib/storeEntries.d.mts +18 -0
  410. package/lib/storeEntries.mjs +64 -0
  411. package/lib/storeEntries.test.d.mts +1 -0
  412. package/lib/storeEntries.test.mjs +71 -0
  413. package/lib/svg.mjs +231 -231
  414. package/lib/text-colors.mjs +43 -43
  415. package/lib/video-id.mjs +72 -72
  416. package/lib/video.mjs +91 -91
  417. package/package.json +136 -131
  418. package/pages/404.astro +10 -10
  419. package/pages/[...slug].astro +51 -51
  420. package/pages/_headers.txt +31 -31
  421. package/pages/blog/index.astro +10 -10
  422. package/pages/blog/kategori/[category].astro +18 -18
  423. package/pages/editor/code-images.json.js +25 -25
  424. package/pages/editor/index.astro +75 -75
  425. package/pages/editor/manifest.webmanifest.js +23 -23
  426. package/pages/editor/sw.js +33 -33
  427. package/pages/editor/sw.js.js +4 -4
  428. package/pages/editor/thumbnails.json.js +21 -21
  429. package/pages/editor/version.json.js +22 -22
  430. package/pages/headers.js +4 -4
  431. package/pages/index.astro +10 -10
  432. package/pages/ny.astro +6 -6
  433. package/pages/robots.txt.js +3 -3
  434. package/pages/rss.xml.js +20 -20
  435. package/scripts/app-screenshots.mjs +164 -164
  436. package/scripts/app-workers.mjs +6 -6
  437. package/scripts/bin.mjs +12 -12
  438. package/scripts/built-site.mjs +134 -99
  439. package/scripts/check-consent.mjs +113 -113
  440. package/scripts/check-content.mjs +151 -149
  441. package/scripts/check-demo.mjs +24 -24
  442. package/scripts/check-store.mjs +160 -0
  443. package/scripts/check-themes.mjs +45 -45
  444. package/scripts/check-worker.mjs +569 -569
  445. package/scripts/compare-html.mjs +81 -81
  446. package/scripts/declarations.mjs +10 -0
  447. package/scripts/declarations.test.mjs +32 -0
  448. package/scripts/demo-site.mjs +42 -42
  449. package/scripts/editor-icons.mjs +56 -56
  450. package/scripts/editor-roundtrip.mjs +134 -134
  451. package/scripts/editor-screens.mjs +101 -101
  452. package/scripts/git-env.mjs +9 -9
  453. package/scripts/icon-packs.mjs +151 -151
  454. package/scripts/link-counts.mjs +22 -22
  455. package/scripts/page-colors.mjs +42 -42
  456. package/scripts/releases.mjs +80 -80
  457. package/scripts/responsive-images.mjs +94 -94
  458. package/scripts/scheduled-list.mjs +15 -15
  459. package/scripts/theme-screenshots.mjs +88 -88
  460. package/scripts/types.mjs +17 -21
  461. package/scripts/video-thumbnails.mjs +89 -89
  462. package/scripts/worker-modules.mjs +34 -34
  463. package/site/appCookies.mjs +74 -74
  464. package/site/apps.ts +21 -21
  465. package/site/autolinks.mjs +200 -200
  466. package/site/blockScripts.ts +31 -31
  467. package/site/categories.ts +16 -16
  468. package/site/consent.ts +26 -26
  469. package/site/content.config.ts +84 -84
  470. package/site/content.ts +104 -104
  471. package/site/cookieList.ts +17 -17
  472. package/site/defineSite.d.mts +2 -14
  473. package/site/defineSite.mjs +131 -136
  474. package/site/directives/interact.mjs +31 -31
  475. package/site/editor-version.mjs +26 -26
  476. package/site/fill.ts +13 -13
  477. package/site/format.ts +11 -11
  478. package/site/home.ts +66 -66
  479. package/site/iconPacks.mjs +43 -43
  480. package/site/icons.mjs +605 -605
  481. package/site/images.mjs +157 -157
  482. package/site/motion.ts +13 -13
  483. package/site/noindex.mjs +21 -21
  484. package/site/pageColors.ts +110 -110
  485. package/site/popups.ts +98 -98
  486. package/site/schema.ts +189 -189
  487. package/site/sections.ts +3 -3
  488. package/site/seo.ts +28 -28
  489. package/site/site.ts +76 -76
  490. package/site/siteConfig.mjs +8 -8
  491. package/site/siteCsp.mjs +75 -75
  492. package/site/siteModules.mjs +27 -27
  493. package/site/standardPages.ts +59 -59
  494. package/site/storeTheme.d.mts +6 -0
  495. package/site/storeTheme.mjs +29 -0
  496. package/site/storeTheme.test.d.mts +1 -0
  497. package/site/storeTheme.test.mjs +53 -0
  498. package/site/testimonials.ts +48 -48
  499. package/site/text.ts +43 -43
  500. package/site/theme.mjs +483 -472
  501. package/site/tracking.client.ts +225 -225
  502. package/site/tracking.ts +9 -9
  503. package/src/ActionParts.tsx +205 -205
  504. package/src/Advanced.tsx +152 -152
  505. package/src/App.tsx +901 -904
  506. package/src/AppList.tsx +1362 -1345
  507. package/src/BlockDialog.tsx +360 -360
  508. package/src/BlockParts.tsx +652 -652
  509. package/src/BlockSettings.tsx +533 -533
  510. package/src/BrandForm.tsx +164 -164
  511. package/src/Colors.tsx +476 -476
  512. package/src/CommunicationParts.tsx +199 -199
  513. package/src/CompanyForm.tsx +209 -209
  514. package/src/Consents.tsx +175 -175
  515. package/src/ContainmentParts.tsx +185 -185
  516. package/src/Crop.tsx +152 -152
  517. package/src/DataForm.tsx +434 -434
  518. package/src/Deleted.tsx +177 -177
  519. package/src/EntryForm.tsx +740 -740
  520. package/src/FileView.tsx +30 -30
  521. package/src/FormFrame.tsx +237 -237
  522. package/src/Keywords.tsx +225 -225
  523. package/src/Library.tsx +1563 -1563
  524. package/src/Licenses.tsx +336 -336
  525. package/src/LinkSheet.tsx +138 -138
  526. package/src/MarkdownEditor.tsx +1075 -1075
  527. package/src/Media.tsx +677 -677
  528. package/src/NavigationParts.tsx +350 -350
  529. package/src/NavigationRestParts.tsx +247 -247
  530. package/src/Notifications.tsx +59 -59
  531. package/src/PagePicker.tsx +136 -136
  532. package/src/Parts.tsx +991 -991
  533. package/src/PartsShown.tsx +168 -168
  534. package/src/PickerParts.tsx +183 -183
  535. package/src/Redirects.tsx +450 -450
  536. package/src/Screen.tsx +184 -184
  537. package/src/SectionsField.tsx +65 -65
  538. package/src/SelectionParts.tsx +134 -134
  539. package/src/SeoScores.tsx +184 -184
  540. package/src/Sheet.tsx +35 -35
  541. package/src/ThemeStore.tsx +376 -376
  542. package/src/Tokens.tsx +346 -346
  543. package/src/Versions.tsx +214 -214
  544. package/src/addresses.ts +75 -75
  545. package/src/allIcons.ts +7 -7
  546. package/src/appFiles.ts +29 -29
  547. package/src/apps.ts +281 -281
  548. package/src/ask.tsx +123 -123
  549. package/src/blocks.ts +251 -251
  550. package/src/brand.ts +153 -153
  551. package/src/cache.ts +42 -42
  552. package/src/check.ts +285 -285
  553. package/src/checkSite.ts +256 -256
  554. package/src/{consents.ts → consentData.ts} +26 -26
  555. package/src/cookieList.ts +70 -70
  556. package/src/countries.ts +59 -59
  557. package/src/deploy.ts +155 -155
  558. package/src/editor.css +602 -602
  559. package/src/examples.ts +85 -85
  560. package/src/fields.tsx +942 -942
  561. package/src/frontmatter.mjs +42 -42
  562. package/src/github.ts +376 -376
  563. package/src/i18n/da-DK/advanced.ts +28 -28
  564. package/src/i18n/da-DK/app.ts +71 -71
  565. package/src/i18n/da-DK/apps.ts +90 -90
  566. package/src/i18n/da-DK/blockSettings.ts +38 -38
  567. package/src/i18n/da-DK/blocks.ts +408 -408
  568. package/src/i18n/da-DK/check.ts +25 -25
  569. package/src/i18n/da-DK/colors.ts +64 -64
  570. package/src/i18n/da-DK/common.ts +118 -118
  571. package/src/i18n/da-DK/company.ts +24 -24
  572. package/src/i18n/da-DK/consents.ts +23 -23
  573. package/src/i18n/da-DK/forms.ts +116 -116
  574. package/src/i18n/da-DK/history.ts +35 -35
  575. package/src/i18n/da-DK/index.ts +49 -49
  576. package/src/i18n/da-DK/keywords.ts +19 -19
  577. package/src/i18n/da-DK/library.ts +135 -135
  578. package/src/i18n/da-DK/licenses.ts +25 -25
  579. package/src/i18n/da-DK/media.ts +79 -79
  580. package/src/i18n/da-DK/parts.ts +696 -696
  581. package/src/i18n/da-DK/preview.ts +13 -13
  582. package/src/i18n/da-DK/redirects.ts +51 -51
  583. package/src/i18n/da-DK/seo.ts +20 -20
  584. package/src/i18n/da-DK/text.ts +35 -35
  585. package/src/i18n/da-DK/theme.ts +41 -41
  586. package/src/i18n/en-US/advanced.ts +32 -32
  587. package/src/i18n/en-US/app.ts +84 -84
  588. package/src/i18n/en-US/apps.ts +134 -134
  589. package/src/i18n/en-US/blockSettings.ts +48 -48
  590. package/src/i18n/en-US/blocks.ts +441 -441
  591. package/src/i18n/en-US/check.ts +31 -31
  592. package/src/i18n/en-US/colors.ts +82 -82
  593. package/src/i18n/en-US/common.ts +144 -144
  594. package/src/i18n/en-US/company.ts +25 -25
  595. package/src/i18n/en-US/consents.ts +25 -25
  596. package/src/i18n/en-US/forms.ts +145 -145
  597. package/src/i18n/en-US/history.ts +43 -43
  598. package/src/i18n/en-US/index.ts +51 -51
  599. package/src/i18n/en-US/keywords.ts +24 -24
  600. package/src/i18n/en-US/library.ts +176 -176
  601. package/src/i18n/en-US/licenses.ts +36 -36
  602. package/src/i18n/en-US/media.ts +80 -80
  603. package/src/i18n/en-US/parts.ts +718 -718
  604. package/src/i18n/en-US/preview.ts +15 -15
  605. package/src/i18n/en-US/redirects.ts +66 -66
  606. package/src/i18n/en-US/seo.ts +26 -26
  607. package/src/i18n/en-US/text.ts +41 -41
  608. package/src/i18n/en-US/theme.ts +41 -41
  609. package/src/i18n/index.ts +124 -124
  610. package/src/icon.tsx +160 -160
  611. package/src/iconPacks.ts +89 -89
  612. package/src/images.ts +163 -163
  613. package/src/{licenses.ts → licenseData.ts} +79 -79
  614. package/src/markdown.mjs +204 -204
  615. package/src/nav.ts +68 -68
  616. package/src/notFound.ts +28 -28
  617. package/src/{notifications.ts → notificationData.ts} +223 -223
  618. package/src/pagePreview.tsx +204 -204
  619. package/src/r2Caching.ts +55 -55
  620. package/src/{redirects.ts → redirectData.ts} +149 -149
  621. package/src/registry.tsx +188 -188
  622. package/src/schema.ts +417 -417
  623. package/src/sections.mjs +303 -303
  624. package/src/seo.ts +333 -333
  625. package/src/shared.ts +44 -44
  626. package/src/sidebar.ts +31 -31
  627. package/src/site.ts +317 -317
  628. package/src/standard/Block.astro +19 -19
  629. package/src/standard/BlockSite.astro +18 -18
  630. package/src/standard/accordion/index.tsx +47 -47
  631. package/src/standard/accordion/load.ts +23 -23
  632. package/src/standard/accordion/shared.ts +15 -15
  633. package/src/standard/accordion/view.ts +32 -32
  634. package/src/standard/buttons/fields.ts +98 -98
  635. package/src/standard/buttons/index.tsx +23 -23
  636. package/src/standard/buttons/load.ts +34 -34
  637. package/src/standard/buttons/shared.ts +12 -12
  638. package/src/standard/buttons/view.ts +30 -30
  639. package/src/standard/cards/index.tsx +71 -71
  640. package/src/standard/cards/load.ts +17 -17
  641. package/src/standard/cards/shared.ts +27 -27
  642. package/src/standard/cards/view.ts +29 -29
  643. package/src/standard/checklist/index.tsx +27 -27
  644. package/src/standard/checklist/load.ts +5 -5
  645. package/src/standard/checklist/view.ts +13 -13
  646. package/src/standard/cookies/index.tsx +17 -17
  647. package/src/standard/cookies/list.ts +56 -56
  648. package/src/standard/cookies/load.ts +11 -11
  649. package/src/standard/cookies/shared.ts +20 -20
  650. package/src/standard/cookies/view.ts +28 -28
  651. package/src/standard/faq/index.tsx +29 -29
  652. package/src/standard/faq/load.ts +14 -14
  653. package/src/standard/faq/view.ts +21 -21
  654. package/src/standard/head.ts +23 -23
  655. package/src/standard/hero/fields.ts +48 -48
  656. package/src/standard/hero/index.tsx +57 -57
  657. package/src/standard/hero/load.ts +23 -23
  658. package/src/standard/hero/view.ts +38 -38
  659. package/src/standard/links/index.tsx +41 -41
  660. package/src/standard/links/load.ts +17 -17
  661. package/src/standard/links/view.ts +25 -25
  662. package/src/standard/list/index.tsx +50 -50
  663. package/src/standard/list/load.ts +5 -5
  664. package/src/standard/list/view.ts +18 -18
  665. package/src/standard/load.ts +7 -7
  666. package/src/standard/notice/index.tsx +30 -30
  667. package/src/standard/notice/load.ts +16 -16
  668. package/src/standard/notice/view.ts +10 -10
  669. package/src/standard/points/index.tsx +42 -42
  670. package/src/standard/points/load.ts +5 -5
  671. package/src/standard/points/view.ts +12 -12
  672. package/src/standard/posts/index.tsx +132 -132
  673. package/src/standard/posts/load.ts +36 -36
  674. package/src/standard/posts/shared.ts +21 -21
  675. package/src/standard/posts/view.ts +63 -63
  676. package/src/standard/pricecards/index.tsx +57 -57
  677. package/src/standard/pricecards/load.ts +11 -11
  678. package/src/standard/pricecards/view.ts +50 -50
  679. package/src/standard/sharedTexts.ts +6 -6
  680. package/src/standard/site.ts +124 -124
  681. package/src/standard/siteLooks.ts +19 -19
  682. package/src/standard/sites.ts +13 -13
  683. package/src/standard/steps/index.tsx +28 -28
  684. package/src/standard/steps/load.ts +5 -5
  685. package/src/standard/steps/view.ts +11 -11
  686. package/src/standard/testimonials/index.tsx +87 -87
  687. package/src/standard/testimonials/list.ts +43 -43
  688. package/src/standard/testimonials/load.ts +58 -58
  689. package/src/standard/testimonials/shared.ts +13 -13
  690. package/src/standard/testimonials/view.ts +76 -76
  691. package/src/standard/themeBlocks.ts +13 -13
  692. package/src/standard/video/index.tsx +23 -23
  693. package/src/standard/video/load.ts +10 -10
  694. package/src/standard/video/view.ts +42 -42
  695. package/src/standard/view.tsx +105 -105
  696. package/src/standard/views.ts +37 -37
  697. package/src/store.ts +479 -499
  698. package/src/theme.ts +90 -90
  699. package/src/themeUi.ts +97 -97
  700. package/src/themes.ts +91 -91
  701. package/src/ui.tsx +3402 -3402
  702. package/src/virtual.d.ts +5 -5
  703. package/src/when.ts +22 -22
  704. package/starter/.githooks/pre-push +4 -4
  705. package/starter/.nvmrc +1 -1
  706. package/starter/.prettierignore +11 -11
  707. package/starter/.prettierrc.json +7 -7
  708. package/starter/README.md +27 -26
  709. package/starter/astro.config.mjs +5 -5
  710. package/starter/package.json +67 -67
  711. package/starter/public/_redirects +1 -1
  712. package/starter/public/favicon.svg +1 -1
  713. package/starter/public/logo.svg +1 -1
  714. package/starter/src/content/pages/blog.md +8 -8
  715. package/starter/src/content/pages/forside.md +9 -9
  716. package/starter/src/content/pages/kontakt.md +7 -7
  717. package/starter/src/content/pages/privatlivspolitik.md +9 -9
  718. package/starter/src/content/pages/siden-findes-ikke.md +7 -7
  719. package/starter/src/content.config.ts +2 -2
  720. package/starter/src/data/apps.json +1 -1
  721. package/starter/src/data/block-settings.json +3 -3
  722. package/starter/src/data/blocks.json +1 -1
  723. package/starter/src/data/booking.json +6 -6
  724. package/starter/src/data/colors.json +70 -70
  725. package/starter/src/data/contact.json +8 -8
  726. package/starter/src/data/cookies.json +21 -21
  727. package/starter/src/data/csp.json +1 -1
  728. package/starter/src/data/footer.json +15 -15
  729. package/starter/src/data/internal-links.json +4 -4
  730. package/starter/src/data/menu.json +4 -4
  731. package/starter/src/data/mobile-menu.json +4 -4
  732. package/starter/src/data/old-addresses.json +1 -1
  733. package/starter/src/data/redirects.json +1 -1
  734. package/starter/src/data/standard-pages.json +8 -8
  735. package/starter/src/data/theme.json +1 -1
  736. package/starter/src/env.d.ts +2 -2
  737. package/starter/src/site/config.ts +13 -13
  738. package/starter/src/site/worker.js +14 -14
  739. package/starter/tsconfig.json +17 -17
  740. package/starter/worker/apps.js +6 -6
  741. package/starter/wrangler.jsonc +39 -39
  742. package/theme/LICENSE +21 -21
  743. package/theme/blocks/ArrowLink.tsx +14 -14
  744. package/theme/blocks/BlockHead.tsx +26 -26
  745. package/theme/blocks/Panel.tsx +32 -32
  746. package/theme/blocks/Person.tsx +26 -26
  747. package/theme/blocks/accordion/PageRow.tsx +25 -25
  748. package/theme/blocks/accordion/View.tsx +17 -17
  749. package/theme/blocks/buttons/Buttons.tsx +28 -28
  750. package/theme/blocks/buttons/View.tsx +12 -12
  751. package/theme/blocks/cards/LinkCards.tsx +72 -72
  752. package/theme/blocks/cards/View.tsx +20 -20
  753. package/theme/blocks/checklist/Checks.tsx +15 -15
  754. package/theme/blocks/checklist/View.tsx +14 -14
  755. package/theme/blocks/cookies/View.tsx +36 -36
  756. package/theme/blocks/faq/Accordion.tsx +34 -34
  757. package/theme/blocks/faq/View.tsx +16 -16
  758. package/theme/blocks/faq/script.ts +56 -56
  759. package/theme/blocks/hero/View.tsx +44 -44
  760. package/theme/blocks/links/LinkGroups.tsx +24 -24
  761. package/theme/blocks/links/View.tsx +17 -17
  762. package/theme/blocks/list/Rows.tsx +24 -24
  763. package/theme/blocks/list/View.tsx +14 -14
  764. package/theme/blocks/notice/View.tsx +13 -13
  765. package/theme/blocks/points/PointList.tsx +34 -34
  766. package/theme/blocks/points/View.tsx +14 -14
  767. package/theme/blocks/posts/View.tsx +26 -26
  768. package/theme/blocks/pricecards/View.tsx +40 -40
  769. package/theme/blocks/steps/StepList.tsx +23 -23
  770. package/theme/blocks/steps/View.tsx +14 -14
  771. package/theme/blocks/testimonials/List.tsx +46 -46
  772. package/theme/blocks/testimonials/Slider.tsx +44 -44
  773. package/theme/blocks/testimonials/Testimonial.tsx +124 -124
  774. package/theme/blocks/testimonials/View.tsx +21 -21
  775. package/theme/blocks/testimonials/script.ts +52 -52
  776. package/theme/blocks/video/View.tsx +41 -41
  777. package/theme/components/ActionBar.astro +63 -63
  778. package/theme/components/AppSlot.astro +21 -21
  779. package/theme/components/ArrowLink.tsx +21 -21
  780. package/theme/components/BlogIndex.astro +48 -48
  781. package/theme/components/BlogPosts.astro +18 -18
  782. package/theme/components/BlogPosts.tsx +45 -45
  783. package/theme/components/BookButton.tsx +22 -22
  784. package/theme/components/Container.astro +11 -11
  785. package/theme/components/CookieConsent.astro +121 -121
  786. package/theme/components/EndBlock.astro +21 -21
  787. package/theme/components/FontPreload.astro +6 -6
  788. package/theme/components/Footer.astro +85 -85
  789. package/theme/components/Header.astro +186 -186
  790. package/theme/components/Icon.astro +16 -16
  791. package/theme/components/Img.astro +29 -29
  792. package/theme/components/Img.tsx +33 -33
  793. package/theme/components/Inline.astro +11 -11
  794. package/theme/components/Logo.astro +23 -23
  795. package/theme/components/LogoMark.astro +10 -10
  796. package/theme/components/Markdown.astro +17 -17
  797. package/theme/components/MobileMenu.tsx +224 -224
  798. package/theme/components/MobileNav.astro +33 -33
  799. package/theme/components/PageHeader.astro +22 -22
  800. package/theme/components/PageSection.astro +24 -24
  801. package/theme/components/PhoneButton.tsx +11 -11
  802. package/theme/components/Popup.astro +145 -145
  803. package/theme/components/PopupButton.tsx +24 -24
  804. package/theme/components/PopupView.tsx +48 -48
  805. package/theme/components/PostList.tsx +58 -58
  806. package/theme/components/PostMeta.tsx +17 -17
  807. package/theme/components/RichText.astro +28 -28
  808. package/theme/components/Section.astro +29 -29
  809. package/theme/components/SectionHeading.tsx +8 -8
  810. package/theme/components/TextSection.astro +16 -16
  811. package/theme/components/home/PageBlock.astro +19 -19
  812. package/theme/components/home/Text.astro +13 -13
  813. package/theme/components/loadPopup.ts +22 -22
  814. package/theme/components/loadPosts.ts +16 -16
  815. package/theme/components/posts.ts +15 -15
  816. package/theme/editor/looks.mjs +7 -7
  817. package/theme/editor/previews.tsx +56 -56
  818. package/theme/layouts/Base.astro +273 -273
  819. package/theme/layouts/PageLayout.astro +126 -126
  820. package/theme/layouts/PostLayout.astro +137 -137
  821. package/theme/scripts/motion.ts +29 -29
  822. package/theme/styles/base.css +320 -320
  823. package/theme/styles/blocks.css +1808 -1808
  824. package/theme/styles/components.css +206 -206
  825. package/theme/styles/global.css +1302 -1302
  826. package/theme/styles/ui.css +6544 -6544
  827. package/theme/templates/Blog.astro +38 -38
  828. package/theme/templates/Category.astro +19 -19
  829. package/theme/templates/Home.astro +36 -36
  830. package/theme/templates/New.astro +68 -68
  831. package/theme/templates/NotFound.astro +117 -117
  832. package/theme/theme.json +28 -28
  833. package/theme/ui/Badge.tsx +45 -45
  834. package/theme/ui/BottomSheet.tsx +148 -148
  835. package/theme/ui/Button.tsx +79 -79
  836. package/theme/ui/ButtonGroup.tsx +31 -31
  837. package/theme/ui/Card.tsx +45 -45
  838. package/theme/ui/Carousel.tsx +124 -124
  839. package/theme/ui/Checkbox.tsx +59 -59
  840. package/theme/ui/Chip.tsx +101 -101
  841. package/theme/ui/ChipSet.tsx +27 -27
  842. package/theme/ui/DatePicker.tsx +149 -149
  843. package/theme/ui/DatePickerContainer.tsx +316 -316
  844. package/theme/ui/Dialog.tsx +100 -100
  845. package/theme/ui/Divider.tsx +27 -27
  846. package/theme/ui/ExposedDropdownMenu.tsx +77 -77
  847. package/theme/ui/Fab.tsx +88 -88
  848. package/theme/ui/FabMenu.tsx +67 -67
  849. package/theme/ui/IconButton.tsx +78 -78
  850. package/theme/ui/List.tsx +287 -287
  851. package/theme/ui/LoadingIndicator.tsx +29 -29
  852. package/theme/ui/Menu.tsx +278 -278
  853. package/theme/ui/NavigationBar.tsx +62 -62
  854. package/theme/ui/NavigationDrawer.tsx +80 -80
  855. package/theme/ui/NavigationRail.tsx +154 -154
  856. package/theme/ui/ProgressIndicator.tsx +162 -162
  857. package/theme/ui/RadioButton.tsx +50 -50
  858. package/theme/ui/Search.tsx +129 -129
  859. package/theme/ui/SegmentedButton.tsx +49 -49
  860. package/theme/ui/SideSheet.tsx +54 -54
  861. package/theme/ui/Slider.tsx +155 -155
  862. package/theme/ui/Snackbar.tsx +67 -67
  863. package/theme/ui/SplitButton.tsx +67 -67
  864. package/theme/ui/Switch.tsx +60 -60
  865. package/theme/ui/Tabs.tsx +114 -114
  866. package/theme/ui/TextField.tsx +278 -278
  867. package/theme/ui/TimePicker.tsx +128 -128
  868. package/theme/ui/TimePickerContainer.tsx +234 -234
  869. package/theme/ui/Toolbar.tsx +67 -67
  870. package/theme/ui/Tooltip.tsx +58 -58
  871. package/theme/ui/TopAppBar.tsx +77 -77
  872. package/theme/ui/bottomSheet.script.ts +8 -8
  873. package/theme/ui/{bottomSheet.ts → bottomSheetControl.ts} +211 -211
  874. package/theme/ui/carousel.script.ts +28 -28
  875. package/theme/ui/carouselLayout.ts +229 -229
  876. package/theme/ui/checkbox.script.ts +8 -8
  877. package/theme/ui/datePicker.script.ts +302 -302
  878. package/theme/ui/dates.ts +185 -185
  879. package/theme/ui/{dialog.ts → dialogControl.ts} +48 -48
  880. package/theme/ui/dropdownMenu.script.ts +166 -166
  881. package/theme/ui/fabMenu.script.ts +57 -57
  882. package/theme/ui/navigationRail.script.ts +47 -47
  883. package/theme/ui/ripple.script.ts +159 -159
  884. package/theme/ui/search.script.ts +92 -92
  885. package/theme/ui/{sideSheet.ts → sideSheetControl.ts} +48 -48
  886. package/theme/ui/slider.script.ts +12 -12
  887. package/theme/ui/sliderUpdate.ts +52 -52
  888. package/theme/ui/snackbar.script.ts +16 -16
  889. package/theme/ui/splitButton.script.ts +63 -63
  890. package/theme/ui/tabs.script.ts +48 -48
  891. package/theme/ui/textField.script.ts +17 -17
  892. package/theme/ui/textFieldUpdate.ts +44 -44
  893. package/theme/ui/timePicker.script.ts +248 -248
  894. package/theme/ui/toolbar.script.ts +43 -43
  895. package/theme/ui/tooltip.script.ts +68 -68
  896. package/worker/consent.js +141 -141
  897. package/worker/editor-github.js +167 -167
  898. package/worker/editor-host.js +74 -74
  899. package/worker/files.js +401 -401
  900. package/worker/github.js +36 -36
  901. package/worker/index.js +188 -184
  902. package/worker/not-found.js +97 -97
  903. package/worker/oauth.js +95 -95
  904. package/worker/publish.js +52 -52
  905. package/worker/push.js +270 -270
  906. package/worker/r2-status.js +50 -50
  907. package/worker/session.js +58 -58
  908. package/worker/store.js +46 -0
package/src/cookieList.ts CHANGED
@@ -1,70 +1,70 @@
1
- // The site's cookie list, "Cookies" under "Lister" (the list the standard block "Cookieliste" brings,
2
- // standard/cookies/list.ts): a file per cookie in config.cookieList, each with its name (`*` for the rest of it), who
3
- // sets it, what for, how long it lasts and its category (necessary, or one the visitor says yes to in the cookie banner,
4
- // lib/cookieCategories.mjs). An app's cookies (its
5
- // cookies.json, those with a name) are added to it in the commit that installs the app, and those it added (`app`, its
6
- // id, kept in the file but not shown) are taken out in the one that uninstalls it; an update adds its new ones and takes
7
- // out those it no longer sets. One already in the list by its name and provider is left as it is, so what was written
8
- // over an app's text stays. The app "Cookiescanner" adds those its scan finds besides (its worker.js), and more can be
9
- // added by hand.
10
- import { config } from '@site/config';
11
- import type { Change, RepoFile } from './github';
12
- import { slugify } from './schema';
13
- import { categoryOf, type CookieCategory } from '../lib/cookieCategories.mjs';
14
- import type { AppCookie } from './store';
15
-
16
- /** A cookie in the list, as its file has it; `app`: the app that added it; `new`: added by the app "Cookiescanner" and not
17
- * yet looked through (first in the list, marked, until it is saved: FolderCollection.fresh); `scanned`: added by it, kept
18
- * when saved (its tab "Problemer" says when the site no longer sets it). */
19
- export type CookieEntry = {
20
- name: string;
21
- provider: string;
22
- purpose: string;
23
- lasts?: string;
24
- category: CookieCategory;
25
- app?: string;
26
- new?: boolean;
27
- scanned?: boolean;
28
- };
29
-
30
- /** Whether a file is one of the list's. */
31
- export const inCookieList = (path: string) => path.startsWith(`${config.cookieList}/`) && path.endsWith('.json');
32
-
33
- function entryOf(file: RepoFile): Partial<CookieEntry> {
34
- try {
35
- return JSON.parse(file.text) ?? {};
36
- } catch {
37
- return {};
38
- }
39
- }
40
-
41
- const same = (a: { name?: string; provider?: string }, b: { name?: string; provider?: string }) =>
42
- a.name === b.name && (a.provider ?? '') === (b.provider ?? '');
43
-
44
- /** The changes to the list when an app is installed or updated with `cookies` (its cookies.json, in the site's
45
- * language), or uninstalled (null), from the site's files now (see above). */
46
- export function cookieChanges(app: string, cookies: AppCookie[] | null, files: RepoFile[]): Change[] {
47
- const list = files.filter((f) => inCookieList(f.path)).map((file) => ({ file, entry: entryOf(file) }));
48
- const wanted = (cookies ?? []).filter((c) => c.name?.trim());
49
- const changes: Change[] = list
50
- .filter(({ entry }) => entry.app === app && !wanted.some((c) => same(c, entry)))
51
- .map(({ file }) => ({ path: file.path, content: null, oid: file.oid }));
52
- const taken = new Set(list.map(({ file }) => file.path));
53
- for (const c of wanted) {
54
- if (list.some(({ entry }) => same(c, entry))) continue;
55
- const slug = slugify(`${c.name!.replace(/\*/g, ' x ')} ${c.provider ?? ''}`) || 'cookie';
56
- let path = `${config.cookieList}/${slug}.json`;
57
- for (let n = 2; taken.has(path); n++) path = `${config.cookieList}/${slug}-${n}.json`;
58
- taken.add(path);
59
- const entry: CookieEntry = {
60
- name: c.name!,
61
- provider: c.provider ?? '',
62
- purpose: c.purpose,
63
- ...(c.lasts ? { lasts: c.lasts } : {}),
64
- category: categoryOf(c),
65
- app,
66
- };
67
- changes.push({ path, content: `${JSON.stringify(entry, null, 2)}\n`, oid: null });
68
- }
69
- return changes;
70
- }
1
+ // The site's cookie list, "Cookies" under "Lister" (the list the standard block "Cookieliste" brings,
2
+ // standard/cookies/list.ts): a file per cookie in config.cookieList, each with its name (`*` for the rest of it), who
3
+ // sets it, what for, how long it lasts and its category (necessary, or one the visitor says yes to in the cookie banner,
4
+ // lib/cookieCategories.mjs). An app's cookies (its
5
+ // cookies.json, those with a name) are added to it in the commit that installs the app, and those it added (`app`, its
6
+ // id, kept in the file but not shown) are taken out in the one that uninstalls it; an update adds its new ones and takes
7
+ // out those it no longer sets. One already in the list by its name and provider is left as it is, so what was written
8
+ // over an app's text stays. The app "Cookiescanner" adds those its scan finds besides (its worker.js), and more can be
9
+ // added by hand.
10
+ import { config } from '@site/config';
11
+ import type { Change, RepoFile } from './github';
12
+ import { slugify } from './schema';
13
+ import { categoryOf, type CookieCategory } from '../lib/cookieCategories.mjs';
14
+ import type { AppCookie } from './store';
15
+
16
+ /** A cookie in the list, as its file has it; `app`: the app that added it; `new`: added by the app "Cookiescanner" and not
17
+ * yet looked through (first in the list, marked, until it is saved: FolderCollection.fresh); `scanned`: added by it, kept
18
+ * when saved (its tab "Problemer" says when the site no longer sets it). */
19
+ export type CookieEntry = {
20
+ name: string;
21
+ provider: string;
22
+ purpose: string;
23
+ lasts?: string;
24
+ category: CookieCategory;
25
+ app?: string;
26
+ new?: boolean;
27
+ scanned?: boolean;
28
+ };
29
+
30
+ /** Whether a file is one of the list's. */
31
+ export const inCookieList = (path: string) => path.startsWith(`${config.cookieList}/`) && path.endsWith('.json');
32
+
33
+ function entryOf(file: RepoFile): Partial<CookieEntry> {
34
+ try {
35
+ return JSON.parse(file.text) ?? {};
36
+ } catch {
37
+ return {};
38
+ }
39
+ }
40
+
41
+ const same = (a: { name?: string; provider?: string }, b: { name?: string; provider?: string }) =>
42
+ a.name === b.name && (a.provider ?? '') === (b.provider ?? '');
43
+
44
+ /** The changes to the list when an app is installed or updated with `cookies` (its cookies.json, in the site's
45
+ * language), or uninstalled (null), from the site's files now (see above). */
46
+ export function cookieChanges(app: string, cookies: AppCookie[] | null, files: RepoFile[]): Change[] {
47
+ const list = files.filter((f) => inCookieList(f.path)).map((file) => ({ file, entry: entryOf(file) }));
48
+ const wanted = (cookies ?? []).filter((c) => c.name?.trim());
49
+ const changes: Change[] = list
50
+ .filter(({ entry }) => entry.app === app && !wanted.some((c) => same(c, entry)))
51
+ .map(({ file }) => ({ path: file.path, content: null, oid: file.oid }));
52
+ const taken = new Set(list.map(({ file }) => file.path));
53
+ for (const c of wanted) {
54
+ if (list.some(({ entry }) => same(c, entry))) continue;
55
+ const slug = slugify(`${c.name!.replace(/\*/g, ' x ')} ${c.provider ?? ''}`) || 'cookie';
56
+ let path = `${config.cookieList}/${slug}.json`;
57
+ for (let n = 2; taken.has(path); n++) path = `${config.cookieList}/${slug}-${n}.json`;
58
+ taken.add(path);
59
+ const entry: CookieEntry = {
60
+ name: c.name!,
61
+ provider: c.provider ?? '',
62
+ purpose: c.purpose,
63
+ ...(c.lasts ? { lasts: c.lasts } : {}),
64
+ category: categoryOf(c),
65
+ app,
66
+ };
67
+ changes.push({ path, content: `${JSON.stringify(entry, null, 2)}\n`, oid: null });
68
+ }
69
+ return changes;
70
+ }
package/src/countries.ts CHANGED
@@ -1,59 +1,59 @@
1
- // The countries a phone number can be in, by their code (ISO 3166, "DK") and their country code
2
- // ("+45"), for the sheet the code is picked in (PhoneField in ui.tsx) and for reading a number typed
3
- // with its code (phoneParts in check.ts). Their names are the browser's own, in the editor's language
4
- // (Intl.DisplayNames). Countries that share a code (+1: the USA, Canada and the islands with an area
5
- // code of their own) have it each; the first with a code is the one shown for it until another is picked.
6
- import { locale } from './i18n';
7
-
8
- const list =
9
- 'US1 CA1 AG1 AI1 AS1 BB1 BM1 BS1 DM1 DO1 GD1 GU1 JM1 KN1 KY1 LC1 MP1 MS1 PR1 SX1 TC1 TT1 VC1 VG1 VI1 RU7 KZ7 ' +
10
- 'EG20 ZA27 GR30 NL31 BE32 FR33 ES34 HU36 IT39 VA39 RO40 CH41 AT43 GB44 GG44 IM44 JE44 DK45 SE46 NO47 SJ47 PL48 ' +
11
- 'DE49 PE51 MX52 CU53 AR54 BR55 CL56 CO57 VE58 MY60 AU61 CX61 CC61 ID62 PH63 NZ64 SG65 TH66 JP81 KR82 VN84 CN86 ' +
12
- 'TR90 IN91 PK92 AF93 LK94 MM95 IR98 SS211 MA212 EH212 DZ213 TN216 LY218 GM220 SN221 MR222 ML223 GN224 CI225 ' +
13
- 'BF226 NE227 TG228 BJ229 MU230 LR231 SL232 GH233 NG234 TD235 CF236 CM237 CV238 ST239 GQ240 GA241 CG242 CD243 ' +
14
- 'AO244 GW245 IO246 SC248 SD249 RW250 ET251 SO252 DJ253 KE254 TZ255 UG256 BI257 MZ258 ZM260 MG261 RE262 YT262 ' +
15
- 'ZW263 NA264 MW265 LS266 BW267 SZ268 KM269 SH290 ER291 AW297 FO298 GL299 GI350 PT351 LU352 IE353 IS354 AL355 ' +
16
- 'MT356 CY357 FI358 AX358 BG359 LT370 LV371 EE372 MD373 AM374 BY375 AD376 MC377 SM378 UA380 RS381 ME382 XK383 ' +
17
- 'HR385 SI386 BA387 MK389 CZ420 SK421 LI423 FK500 BZ501 GT502 SV503 HN504 NI505 CR506 PA507 PM508 HT509 GP590 ' +
18
- 'BL590 MF590 BO591 GY592 EC593 GF594 PY595 MQ596 SR597 UY598 CW599 BQ599 TL670 NF672 BN673 NR674 PG675 TO676 ' +
19
- 'SB677 VU678 FJ679 PW680 WF681 CK682 NU683 WS685 KI686 NC687 TV688 PF689 TK690 FM691 MH692 KP850 HK852 MO853 ' +
20
- 'KH855 LA856 BD880 TW886 MV960 LB961 JO962 SY963 IQ964 KW965 SA966 YE967 OM968 PS970 AE971 IL972 BH973 QA974 ' +
21
- 'BT975 MN976 NP977 TJ992 TM993 AZ994 GE995 KG996 UZ998';
22
-
23
- /** Each country's code and its country code, "+45". */
24
- export const dialCodes: Record<string, string> = Object.fromEntries(list.split(' ').map((c) => [c.slice(0, 2), `+${c.slice(2)}`]));
25
-
26
- /** The country shown for a country code: the first with it, or undefined when no country has it. */
27
- export const regionOf = (code: string) => Object.keys(dialCodes).find((r) => dialCodes[r] === code);
28
-
29
- const codes = new Set(Object.values(dialCodes));
30
-
31
- /** The country code at the start of a number's digits, with digits after it (the longest that is one:
32
- * +358 before +35), or undefined. */
33
- export const codeAt = (digits: string) =>
34
- [3, 2, 1]
35
- .filter((n) => digits.length > n)
36
- .map((n) => `+${digits.slice(0, n)}`)
37
- .find((c) => codes.has(c));
38
-
39
- /** A country's flag, of the two letters of its code. */
40
- export const flagOf = (region: string) => String.fromCodePoint(...[...region].map((c) => 0x1f1e6 + c.charCodeAt(0) - 65));
41
-
42
- const names = typeof Intl.DisplayNames === 'function' ? new Intl.DisplayNames([locale], { type: 'region' }) : null;
43
- const english = typeof Intl.DisplayNames === 'function' ? new Intl.DisplayNames(['en'], { type: 'region' }) : null;
44
-
45
- /** A country's name in the editor's language. */
46
- export const countryName = (region: string) => names?.of(region) ?? region;
47
-
48
- /** The countries in the order of their names, each with its name, its code and the words it is also
49
- * found by in a search (its country code, its code, its name in English). */
50
- export function countries() {
51
- return Object.keys(dialCodes)
52
- .map((region) => ({
53
- region,
54
- name: countryName(region),
55
- code: dialCodes[region],
56
- words: `${dialCodes[region]} ${region} ${english?.of(region) ?? ''}`,
57
- }))
58
- .sort((a, b) => a.name.localeCompare(b.name, locale));
59
- }
1
+ // The countries a phone number can be in, by their code (ISO 3166, "DK") and their country code
2
+ // ("+45"), for the sheet the code is picked in (PhoneField in ui.tsx) and for reading a number typed
3
+ // with its code (phoneParts in check.ts). Their names are the browser's own, in the editor's language
4
+ // (Intl.DisplayNames). Countries that share a code (+1: the USA, Canada and the islands with an area
5
+ // code of their own) have it each; the first with a code is the one shown for it until another is picked.
6
+ import { locale } from './i18n';
7
+
8
+ const list =
9
+ 'US1 CA1 AG1 AI1 AS1 BB1 BM1 BS1 DM1 DO1 GD1 GU1 JM1 KN1 KY1 LC1 MP1 MS1 PR1 SX1 TC1 TT1 VC1 VG1 VI1 RU7 KZ7 ' +
10
+ 'EG20 ZA27 GR30 NL31 BE32 FR33 ES34 HU36 IT39 VA39 RO40 CH41 AT43 GB44 GG44 IM44 JE44 DK45 SE46 NO47 SJ47 PL48 ' +
11
+ 'DE49 PE51 MX52 CU53 AR54 BR55 CL56 CO57 VE58 MY60 AU61 CX61 CC61 ID62 PH63 NZ64 SG65 TH66 JP81 KR82 VN84 CN86 ' +
12
+ 'TR90 IN91 PK92 AF93 LK94 MM95 IR98 SS211 MA212 EH212 DZ213 TN216 LY218 GM220 SN221 MR222 ML223 GN224 CI225 ' +
13
+ 'BF226 NE227 TG228 BJ229 MU230 LR231 SL232 GH233 NG234 TD235 CF236 CM237 CV238 ST239 GQ240 GA241 CG242 CD243 ' +
14
+ 'AO244 GW245 IO246 SC248 SD249 RW250 ET251 SO252 DJ253 KE254 TZ255 UG256 BI257 MZ258 ZM260 MG261 RE262 YT262 ' +
15
+ 'ZW263 NA264 MW265 LS266 BW267 SZ268 KM269 SH290 ER291 AW297 FO298 GL299 GI350 PT351 LU352 IE353 IS354 AL355 ' +
16
+ 'MT356 CY357 FI358 AX358 BG359 LT370 LV371 EE372 MD373 AM374 BY375 AD376 MC377 SM378 UA380 RS381 ME382 XK383 ' +
17
+ 'HR385 SI386 BA387 MK389 CZ420 SK421 LI423 FK500 BZ501 GT502 SV503 HN504 NI505 CR506 PA507 PM508 HT509 GP590 ' +
18
+ 'BL590 MF590 BO591 GY592 EC593 GF594 PY595 MQ596 SR597 UY598 CW599 BQ599 TL670 NF672 BN673 NR674 PG675 TO676 ' +
19
+ 'SB677 VU678 FJ679 PW680 WF681 CK682 NU683 WS685 KI686 NC687 TV688 PF689 TK690 FM691 MH692 KP850 HK852 MO853 ' +
20
+ 'KH855 LA856 BD880 TW886 MV960 LB961 JO962 SY963 IQ964 KW965 SA966 YE967 OM968 PS970 AE971 IL972 BH973 QA974 ' +
21
+ 'BT975 MN976 NP977 TJ992 TM993 AZ994 GE995 KG996 UZ998';
22
+
23
+ /** Each country's code and its country code, "+45". */
24
+ export const dialCodes: Record<string, string> = Object.fromEntries(list.split(' ').map((c) => [c.slice(0, 2), `+${c.slice(2)}`]));
25
+
26
+ /** The country shown for a country code: the first with it, or undefined when no country has it. */
27
+ export const regionOf = (code: string) => Object.keys(dialCodes).find((r) => dialCodes[r] === code);
28
+
29
+ const codes = new Set(Object.values(dialCodes));
30
+
31
+ /** The country code at the start of a number's digits, with digits after it (the longest that is one:
32
+ * +358 before +35), or undefined. */
33
+ export const codeAt = (digits: string) =>
34
+ [3, 2, 1]
35
+ .filter((n) => digits.length > n)
36
+ .map((n) => `+${digits.slice(0, n)}`)
37
+ .find((c) => codes.has(c));
38
+
39
+ /** A country's flag, of the two letters of its code. */
40
+ export const flagOf = (region: string) => String.fromCodePoint(...[...region].map((c) => 0x1f1e6 + c.charCodeAt(0) - 65));
41
+
42
+ const names = typeof Intl.DisplayNames === 'function' ? new Intl.DisplayNames([locale], { type: 'region' }) : null;
43
+ const english = typeof Intl.DisplayNames === 'function' ? new Intl.DisplayNames(['en'], { type: 'region' }) : null;
44
+
45
+ /** A country's name in the editor's language. */
46
+ export const countryName = (region: string) => names?.of(region) ?? region;
47
+
48
+ /** The countries in the order of their names, each with its name, its code and the words it is also
49
+ * found by in a search (its country code, its code, its name in English). */
50
+ export function countries() {
51
+ return Object.keys(dialCodes)
52
+ .map((region) => ({
53
+ region,
54
+ name: countryName(region),
55
+ code: dialCodes[region],
56
+ words: `${dialCodes[region]} ${region} ${english?.of(region) ?? ''}`,
57
+ }))
58
+ .sort((a, b) => a.name.localeCompare(b.name, locale));
59
+ }
package/src/deploy.ts CHANGED
@@ -1,155 +1,155 @@
1
- // After a save: tells when the site has been rebuilt with it. Each build writes the commit it was
2
- // made from to /editor/version.json (packages/editor/pages/editor/version.json.js), and the editor asks for that
3
- // until it is the saved commit or a later one. The message is a notification of the type `site` (notifications.ts),
4
- // which also comes on the phone or computer when the editor is not on screen.
5
- // Each save says what it changed ("farver ændret", "side “Om” ændret", t.app.changes): right after it (savedText),
6
- // and, with the other saves since, when the website has been updated with them (changesText, App.tsx save).
7
- import { graphql, REPO } from './github';
8
- import { entryName, type Collection } from './schema';
9
- import { readFields, splitFrontmatter } from './frontmatter.mjs';
10
- import { locale, t } from './i18n';
11
-
12
- const fileName = (path: string) => path.split('/').pop() ?? path;
13
-
14
- /** What a file of a list is called: a page's or post's title, an entry's name as its list shows it, else (a picture)
15
- * its file name. */
16
- export function nameOf(collection: Collection | undefined, file: { path: string; text: string }): string {
17
- try {
18
- if (collection?.kind === 'markdown') return String(readFields(splitFrontmatter(file.text).yaml).title ?? fileName(file.path));
19
- if (collection?.kind === 'folder') return entryName(collection, JSON.parse(file.text)) || fileName(file.path);
20
- } catch {}
21
- return fileName(file.path);
22
- }
23
-
24
- /** A kind or a label inside a sentence: "Side" as "side", but "SEO" as it is. */
25
- export const lower = (s: string) => (/^\p{Lu}\p{Lu}/u.test(s) ? s : s.charAt(0).toLocaleLowerCase(locale) + s.slice(1));
26
- const capital = (s: string) => s.charAt(0).toLocaleUpperCase(locale) + s.slice(1);
27
-
28
- /** A thing by its kind and name, as a change says it: side “Om”. */
29
- export const kindAndName = (kind: string, name: string) => t.app.changes.named(lower(kind), name);
30
-
31
- /** The message right after a save, with what it changed; the site is rebuilt in 1-2 minutes. */
32
- export const savedText = (change: string) => t.common.saved(capital(change));
33
-
34
- /** What the saves since the last update changed, as a list: the first three and how many more. */
35
- export function changesText(changes: string[]): string {
36
- const shown = changes.slice(0, 3);
37
- const rest = changes.length - shown.length;
38
- return new Intl.ListFormat(locale, { type: 'conjunction' }).format(rest ? [...shown, t.app.changes.more(rest)] : shown);
39
- }
40
-
41
- const EVERY = 10_000;
42
- const GIVE_UP = 10 * 60_000;
43
-
44
- // What the site was last built from: the commit, the fingerprint of the editor's code and when.
45
- type Version = { commit?: string; editor?: string; builtAt?: string };
46
- async function version(): Promise<Version> {
47
- try {
48
- const res = await fetch('/editor/version.json', { cache: 'no-store' });
49
- return res.ok ? await res.json() : {};
50
- } catch {
51
- return {};
52
- }
53
- }
54
-
55
- const built = async () => (await version()).commit ?? null;
56
-
57
- // Whether `commit` is among the last commits up to `build` (the site may be built from a later one).
58
- async function includes(build: string, commit: string): Promise<boolean> {
59
- const data = await graphql<{ repository: { object: { history?: { nodes: { oid: string }[] } } | null } }>(
60
- `
61
- query ($owner: String!, $name: String!, $oid: GitObjectID!) {
62
- repository(owner: $owner, name: $name) {
63
- object(oid: $oid) {
64
- ... on Commit {
65
- history(first: 50) {
66
- nodes {
67
- oid
68
- }
69
- }
70
- }
71
- }
72
- }
73
- }
74
- `,
75
- { owner: REPO.owner, name: REPO.name, oid: build },
76
- );
77
- return data.repository.object?.history?.nodes.some((n) => n.oid === commit) ?? false;
78
- }
79
-
80
- // Waits for `commit` to be on the site: done(true) when it is, done(false) when it is not after
81
- // 10 minutes. Returns a function that stops waiting (a newer save takes over).
82
- export function waitForSite(commit: string, done: (online: boolean) => void): () => void {
83
- const until = Date.now() + GIVE_UP;
84
- // The build last looked at, so GitHub is asked about each build once.
85
- let seen: string | null = null;
86
- let stopped = false;
87
- let timer: ReturnType<typeof setTimeout>;
88
-
89
- async function check() {
90
- const build = await built();
91
- if (stopped) return;
92
- if (build && build !== seen) {
93
- seen = build;
94
- const online = build === commit || (await includes(build, commit).catch(() => false));
95
- if (stopped) return;
96
- if (online) return done(true);
97
- }
98
- if (Date.now() > until) {
99
- // Without any version file (a build from before it existed) there is nothing to tell.
100
- if (seen) done(false);
101
- return;
102
- }
103
- timer = setTimeout(check, EVERY);
104
- }
105
-
106
- timer = setTimeout(check, EVERY);
107
- return () => {
108
- stopped = true;
109
- clearTimeout(timer);
110
- };
111
- }
112
-
113
- // Whether a form has changes that are not saved (set by FormFrame).
114
- let unsaved = false;
115
- export const setUnsaved = (yes: boolean) => void (unsaved = yes);
116
- export const hasUnsaved = () => unsaved;
117
-
118
- // Keeps an open editor up to date. The installed app can stay open for days, and it reads the files
119
- // straight from GitHub, so after a change to the editor and its files (like the front page becoming
120
- // sections) an old editor would show them as empty forms. When the site has an editor with other
121
- // code (the fingerprint in /editor/version.json is not the one in this page,
122
- // packages/editor/site/editor-version.mjs), the page reloads, as soon as nothing is unsaved: checked when the
123
- // editor opens, when it comes back on screen, and every minute while it is on screen. onSite: what the
124
- // site was last built from, at each check (when it was updated, on the start screen).
125
- export function keepCurrent(onSite?: (v: Version) => void) {
126
- const own = document.querySelector<HTMLMetaElement>('meta[name="editor-version"]')?.content;
127
- async function check() {
128
- if (document.visibilityState !== 'visible') return;
129
- const v = await version();
130
- onSite?.(v);
131
- const { editor } = v;
132
- if (!own || unsaved || !editor || editor === own) return;
133
- // Once for each newer editor, so a page that comes back old (from a cache) does not reload again
134
- // and again.
135
- try {
136
- if (sessionStorage.getItem('editor-reloaded-for') === editor) return;
137
- sessionStorage.setItem('editor-reloaded-for', editor);
138
- } catch {
139
- return;
140
- }
141
- location.reload();
142
- }
143
- check();
144
- const timer = setInterval(check, 60_000);
145
- document.addEventListener('visibilitychange', check);
146
- return () => {
147
- clearInterval(timer);
148
- document.removeEventListener('visibilitychange', check);
149
- };
150
- }
151
-
152
- // Notifications go through the service worker (packages/editor/pages/editor/sw.js); registered when the editor opens.
153
- export function registerWorker() {
154
- navigator.serviceWorker?.register('/editor/sw.js').catch(() => {});
155
- }
1
+ // After a save: tells when the site has been rebuilt with it. Each build writes the commit it was
2
+ // made from to /editor/version.json (packages/editor/pages/editor/version.json.js), and the editor asks for that
3
+ // until it is the saved commit or a later one. The message is a notification of the type `site` (notificationData.ts),
4
+ // which also comes on the phone or computer when the editor is not on screen.
5
+ // Each save says what it changed ("farver ændret", "side “Om” ændret", t.app.changes): right after it (savedText),
6
+ // and, with the other saves since, when the website has been updated with them (changesText, App.tsx save).
7
+ import { graphql, REPO } from './github';
8
+ import { entryName, type Collection } from './schema';
9
+ import { readFields, splitFrontmatter } from './frontmatter.mjs';
10
+ import { locale, t } from './i18n';
11
+
12
+ const fileName = (path: string) => path.split('/').pop() ?? path;
13
+
14
+ /** What a file of a list is called: a page's or post's title, an entry's name as its list shows it, else (a picture)
15
+ * its file name. */
16
+ export function nameOf(collection: Collection | undefined, file: { path: string; text: string }): string {
17
+ try {
18
+ if (collection?.kind === 'markdown') return String(readFields(splitFrontmatter(file.text).yaml).title ?? fileName(file.path));
19
+ if (collection?.kind === 'folder') return entryName(collection, JSON.parse(file.text)) || fileName(file.path);
20
+ } catch {}
21
+ return fileName(file.path);
22
+ }
23
+
24
+ /** A kind or a label inside a sentence: "Side" as "side", but "SEO" as it is. */
25
+ export const lower = (s: string) => (/^\p{Lu}\p{Lu}/u.test(s) ? s : s.charAt(0).toLocaleLowerCase(locale) + s.slice(1));
26
+ const capital = (s: string) => s.charAt(0).toLocaleUpperCase(locale) + s.slice(1);
27
+
28
+ /** A thing by its kind and name, as a change says it: side “Om”. */
29
+ export const kindAndName = (kind: string, name: string) => t.app.changes.named(lower(kind), name);
30
+
31
+ /** The message right after a save, with what it changed; the site is rebuilt in 1-2 minutes. */
32
+ export const savedText = (change: string) => t.common.saved(capital(change));
33
+
34
+ /** What the saves since the last update changed, as a list: the first three and how many more. */
35
+ export function changesText(changes: string[]): string {
36
+ const shown = changes.slice(0, 3);
37
+ const rest = changes.length - shown.length;
38
+ return new Intl.ListFormat(locale, { type: 'conjunction' }).format(rest ? [...shown, t.app.changes.more(rest)] : shown);
39
+ }
40
+
41
+ const EVERY = 10_000;
42
+ const GIVE_UP = 10 * 60_000;
43
+
44
+ // What the site was last built from: the commit, the fingerprint of the editor's code and when.
45
+ type Version = { commit?: string; editor?: string; builtAt?: string };
46
+ async function version(): Promise<Version> {
47
+ try {
48
+ const res = await fetch('/editor/version.json', { cache: 'no-store' });
49
+ return res.ok ? await res.json() : {};
50
+ } catch {
51
+ return {};
52
+ }
53
+ }
54
+
55
+ const built = async () => (await version()).commit ?? null;
56
+
57
+ // Whether `commit` is among the last commits up to `build` (the site may be built from a later one).
58
+ async function includes(build: string, commit: string): Promise<boolean> {
59
+ const data = await graphql<{ repository: { object: { history?: { nodes: { oid: string }[] } } | null } }>(
60
+ `
61
+ query ($owner: String!, $name: String!, $oid: GitObjectID!) {
62
+ repository(owner: $owner, name: $name) {
63
+ object(oid: $oid) {
64
+ ... on Commit {
65
+ history(first: 50) {
66
+ nodes {
67
+ oid
68
+ }
69
+ }
70
+ }
71
+ }
72
+ }
73
+ }
74
+ `,
75
+ { owner: REPO.owner, name: REPO.name, oid: build },
76
+ );
77
+ return data.repository.object?.history?.nodes.some((n) => n.oid === commit) ?? false;
78
+ }
79
+
80
+ // Waits for `commit` to be on the site: done(true) when it is, done(false) when it is not after
81
+ // 10 minutes. Returns a function that stops waiting (a newer save takes over).
82
+ export function waitForSite(commit: string, done: (online: boolean) => void): () => void {
83
+ const until = Date.now() + GIVE_UP;
84
+ // The build last looked at, so GitHub is asked about each build once.
85
+ let seen: string | null = null;
86
+ let stopped = false;
87
+ let timer: ReturnType<typeof setTimeout>;
88
+
89
+ async function check() {
90
+ const build = await built();
91
+ if (stopped) return;
92
+ if (build && build !== seen) {
93
+ seen = build;
94
+ const online = build === commit || (await includes(build, commit).catch(() => false));
95
+ if (stopped) return;
96
+ if (online) return done(true);
97
+ }
98
+ if (Date.now() > until) {
99
+ // Without any version file (a build from before it existed) there is nothing to tell.
100
+ if (seen) done(false);
101
+ return;
102
+ }
103
+ timer = setTimeout(check, EVERY);
104
+ }
105
+
106
+ timer = setTimeout(check, EVERY);
107
+ return () => {
108
+ stopped = true;
109
+ clearTimeout(timer);
110
+ };
111
+ }
112
+
113
+ // Whether a form has changes that are not saved (set by FormFrame).
114
+ let unsaved = false;
115
+ export const setUnsaved = (yes: boolean) => void (unsaved = yes);
116
+ export const hasUnsaved = () => unsaved;
117
+
118
+ // Keeps an open editor up to date. The installed app can stay open for days, and it reads the files
119
+ // straight from GitHub, so after a change to the editor and its files (like the front page becoming
120
+ // sections) an old editor would show them as empty forms. When the site has an editor with other
121
+ // code (the fingerprint in /editor/version.json is not the one in this page,
122
+ // packages/editor/site/editor-version.mjs), the page reloads, as soon as nothing is unsaved: checked when the
123
+ // editor opens, when it comes back on screen, and every minute while it is on screen. onSite: what the
124
+ // site was last built from, at each check (when it was updated, on the start screen).
125
+ export function keepCurrent(onSite?: (v: Version) => void) {
126
+ const own = document.querySelector<HTMLMetaElement>('meta[name="editor-version"]')?.content;
127
+ async function check() {
128
+ if (document.visibilityState !== 'visible') return;
129
+ const v = await version();
130
+ onSite?.(v);
131
+ const { editor } = v;
132
+ if (!own || unsaved || !editor || editor === own) return;
133
+ // Once for each newer editor, so a page that comes back old (from a cache) does not reload again
134
+ // and again.
135
+ try {
136
+ if (sessionStorage.getItem('editor-reloaded-for') === editor) return;
137
+ sessionStorage.setItem('editor-reloaded-for', editor);
138
+ } catch {
139
+ return;
140
+ }
141
+ location.reload();
142
+ }
143
+ check();
144
+ const timer = setInterval(check, 60_000);
145
+ document.addEventListener('visibilitychange', check);
146
+ return () => {
147
+ clearInterval(timer);
148
+ document.removeEventListener('visibilitychange', check);
149
+ };
150
+ }
151
+
152
+ // Notifications go through the service worker (packages/editor/pages/editor/sw.js); registered when the editor opens.
153
+ export function registerWorker() {
154
+ navigator.serviceWorker?.register('/editor/sw.js').catch(() => {});
155
+ }