@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/site/site.ts CHANGED
@@ -1,76 +1,76 @@
1
- // Name, title, phone, email, address and CVR number: contact.json; the texts of "Book en tid": booking.json (the calendar
2
- // is the app Calendly's, src/apps/calendly/); the menus: menu.json and mobile-menu.json; the shared texts of the other blocks: their shared.ts, with those saved in
3
- // blocks.json over them (`blockTexts`).
4
- // The site's owner edits them in the editor (/editor/); what the editor does not edit is the site's config
5
- // (src/site/config.ts).
6
- import contact from '@data/contact.json';
7
- import booking from '@data/booking.json';
8
- import menu from '@data/menu.json';
9
- import mobileMenu from '@data/mobile-menu.json';
10
- import blocks from '@data/blocks.json';
11
- import standardPages from '@data/standard-pages.json';
12
- import { config } from '@site/config';
13
- import { sharedTexts, type SharedTexts } from '@morphemecms/cms/src/shared';
14
- import { standardShared } from '@morphemecms/cms/src/standard/sharedTexts';
15
-
16
- // The number with its country code: +45 when it has none (a number in Denmark, saved without it), else
17
- // its own ("+46 70 12 34 56", picked in the editor).
18
- const phoneIntl = `${contact.phone.trim().startsWith('+') ? '+' : '+45'}${contact.phone.replace(/\D/g, '')}`;
19
- // The CVR number, when it is filled in ("Virksomheden" › "Kontakt").
20
- const { cvr = '' } = contact as typeof contact & { cvr?: string };
21
-
22
- export const site = {
23
- name: contact.name,
24
- role: contact.role,
25
- /** The site's own address, https://<domain> (config.ts). */
26
- url: `https://${config.domain}`,
27
- /** The site's language (config.ts, BCP 47: "da-DK"). */
28
- locale: config.locale,
29
- description: config.siteDescription,
30
- phone: contact.phone,
31
- phoneHref: `tel:${phoneIntl}`,
32
- /** For structured data: the country code and the digits. */
33
- phoneIntl,
34
- email: contact.email,
35
- address: { street: contact.street, city: contact.city },
36
- /** The CVR number, or empty: at the bottom of every page (the theme's Footer.astro) and in the structured data. */
37
- cvr,
38
- mapsUrl: `https://www.google.com/maps/search/?api=1&query=${`${contact.street}, ${contact.city}`.replace(/ /g, '+')}`,
39
- bookingPath: config.booking.path,
40
- /** The pages a booking or an order ends on (config.ts): no action bar there. */
41
- thanks: config.booking.thanks,
42
- /** The page about the owner, or '' (config.ts). */
43
- aboutPath: config.aboutPath,
44
- /** The block after every blog post, by its type, or '' (config.ts). */
45
- postEnd: config.postEnd,
46
- /** The page chosen as the contact page ("Indstillinger" › "Udseende" › "Standardsider", standard-pages.json). */
47
- contactPath: standardPages.contact,
48
- /** The shared texts of "Book en tid" (an app's booking block). */
49
- booking: { heading: booking.heading, text: booking.text },
50
- /** The labels of the buttons "Book en tid" and "Ring" (the number comes after). */
51
- labels: { book: booking.book, call: booking.call },
52
- /** The owner's picture (config.ts), or '' when the site has none. */
53
- portrait: config.picture?.src ?? '',
54
- portraitAlt: config.picture?.alt ?? '',
55
- };
56
-
57
- // Primary navigation (menu.json, "Hovedmenu"). Labels, URLs and sub-items started out as the old site's menu.
58
- export type NavItem = { label: string; href: string; children?: { label: string; href: string }[] };
59
- export const nav: NavItem[] = menu.items;
60
- /** Whether the header has the menu and its button ("Aktiveret" under "Hovedmenu"). */
61
- export const navShown = menu.enabled !== false;
62
- /** The links in the bar under the header on a phone (mobile-menu.json, "Mobilmenu"); none when it is turned off. */
63
- export const mobileNav: { label: string; href: string }[] = mobileMenu.enabled ? mobileMenu.items : [];
64
- // Sub-items in alphabetical order (Danish: æ, ø, å last), in both the desktop and the mobile menu.
65
- for (const item of nav) item.children?.sort((a, b) => a.label.localeCompare(b.label, 'da'));
66
-
67
- /** The texts every copy of a block has ("Blokke" in the editor), with {…} for what differs, by
68
- * the block's type: those written in its shared.ts, with the saved ones (blocks.json) over them. The
69
- * standard blocks' first, so an app's block (src/apps/<app>/blocks/) by the same name has its own. */
70
- export const blockTexts = sharedTexts(
71
- {
72
- ...standardShared,
73
- ...import.meta.glob<SharedTexts>('/src/apps/*/blocks/*/shared.ts', { eager: true, import: 'default' }),
74
- },
75
- blocks,
76
- );
1
+ // Name, title, phone, email, address and CVR number: contact.json; the texts of "Book en tid": booking.json (the calendar
2
+ // is the app Calendly's, src/apps/calendly/); the menus: menu.json and mobile-menu.json; the shared texts of the other blocks: their shared.ts, with those saved in
3
+ // blocks.json over them (`blockTexts`).
4
+ // The site's owner edits them in the editor (/editor/); what the editor does not edit is the site's config
5
+ // (src/site/config.ts).
6
+ import contact from '@data/contact.json';
7
+ import booking from '@data/booking.json';
8
+ import menu from '@data/menu.json';
9
+ import mobileMenu from '@data/mobile-menu.json';
10
+ import blocks from '@data/blocks.json';
11
+ import standardPages from '@data/standard-pages.json';
12
+ import { config } from '@site/config';
13
+ import { sharedTexts, type SharedTexts } from '@morphemecms/cms/src/shared';
14
+ import { standardShared } from '@morphemecms/cms/src/standard/sharedTexts';
15
+
16
+ // The number with its country code: +45 when it has none (a number in Denmark, saved without it), else
17
+ // its own ("+46 70 12 34 56", picked in the editor).
18
+ const phoneIntl = `${contact.phone.trim().startsWith('+') ? '+' : '+45'}${contact.phone.replace(/\D/g, '')}`;
19
+ // The CVR number, when it is filled in ("Virksomheden" › "Kontakt").
20
+ const { cvr = '' } = contact as typeof contact & { cvr?: string };
21
+
22
+ export const site = {
23
+ name: contact.name,
24
+ role: contact.role,
25
+ /** The site's own address, https://<domain> (config.ts). */
26
+ url: `https://${config.domain}`,
27
+ /** The site's language (config.ts, BCP 47: "da-DK"). */
28
+ locale: config.locale,
29
+ description: config.siteDescription,
30
+ phone: contact.phone,
31
+ phoneHref: `tel:${phoneIntl}`,
32
+ /** For structured data: the country code and the digits. */
33
+ phoneIntl,
34
+ email: contact.email,
35
+ address: { street: contact.street, city: contact.city },
36
+ /** The CVR number, or empty: at the bottom of every page (the theme's Footer.astro) and in the structured data. */
37
+ cvr,
38
+ mapsUrl: `https://www.google.com/maps/search/?api=1&query=${`${contact.street}, ${contact.city}`.replace(/ /g, '+')}`,
39
+ bookingPath: config.booking.path,
40
+ /** The pages a booking or an order ends on (config.ts): no action bar there. */
41
+ thanks: config.booking.thanks,
42
+ /** The page about the owner, or '' (config.ts). */
43
+ aboutPath: config.aboutPath,
44
+ /** The block after every blog post, by its type, or '' (config.ts). */
45
+ postEnd: config.postEnd,
46
+ /** The page chosen as the contact page ("Indstillinger" › "Udseende" › "Standardsider", standard-pages.json). */
47
+ contactPath: standardPages.contact,
48
+ /** The shared texts of "Book en tid" (an app's booking block). */
49
+ booking: { heading: booking.heading, text: booking.text },
50
+ /** The labels of the buttons "Book en tid" and "Ring" (the number comes after). */
51
+ labels: { book: booking.book, call: booking.call },
52
+ /** The owner's picture (config.ts), or '' when the site has none. */
53
+ portrait: config.picture?.src ?? '',
54
+ portraitAlt: config.picture?.alt ?? '',
55
+ };
56
+
57
+ // Primary navigation (menu.json, "Hovedmenu"). Labels, URLs and sub-items started out as the old site's menu.
58
+ export type NavItem = { label: string; href: string; children?: { label: string; href: string }[] };
59
+ export const nav: NavItem[] = menu.items;
60
+ /** Whether the header has the menu and its button ("Aktiveret" under "Hovedmenu"). */
61
+ export const navShown = menu.enabled !== false;
62
+ /** The links in the bar under the header on a phone (mobile-menu.json, "Mobilmenu"); none when it is turned off. */
63
+ export const mobileNav: { label: string; href: string }[] = mobileMenu.enabled ? mobileMenu.items : [];
64
+ // Sub-items in alphabetical order (Danish: æ, ø, å last), in both the desktop and the mobile menu.
65
+ for (const item of nav) item.children?.sort((a, b) => a.label.localeCompare(b.label, 'da'));
66
+
67
+ /** The texts every copy of a block has ("Blokke" in the editor), with {…} for what differs, by
68
+ * the block's type: those written in its shared.ts, with the saved ones (blocks.json) over them. The
69
+ * standard blocks' first, so an app's block (src/apps/<app>/blocks/) by the same name has its own. */
70
+ export const blockTexts = sharedTexts(
71
+ {
72
+ ...standardShared,
73
+ ...import.meta.glob<SharedTexts>('/src/apps/*/blocks/*/shared.ts', { eager: true, import: 'default' }),
74
+ },
75
+ blocks,
76
+ );
@@ -1,8 +1,8 @@
1
- // The site's settings (src/site/config.ts, `@site/config`) for this package's modules that also run outside Vite, where
2
- // @site is no alias (astro.mjs and the scripts): loaded from the site's root, the working directory, as Node loads
3
- // TypeScript. Its imports must be ones Node can follow (defineSite.mjs, not @site).
4
- import { join } from 'node:path';
5
- import { pathToFileURL } from 'node:url';
6
-
7
- /** @type {{ config: import('./defineSite.mjs').SiteConfig }} */
8
- export const { config } = await import(/* @vite-ignore */ pathToFileURL(join(process.cwd(), 'src/site/config.ts')).href);
1
+ // The site's settings (src/site/config.ts, `@site/config`) for this package's modules that also run outside Vite, where
2
+ // @site is no alias (astro.mjs and the scripts): loaded from the site's root, the working directory, as Node loads
3
+ // TypeScript. Its imports must be ones Node can follow (defineSite.mjs, not @site).
4
+ import { join } from 'node:path';
5
+ import { pathToFileURL } from 'node:url';
6
+
7
+ /** @type {{ config: import('./defineSite.mjs').SiteConfig }} */
8
+ export const { config } = await import(/* @vite-ignore */ pathToFileURL(join(process.cwd(), 'src/site/config.ts')).href);
package/site/siteCsp.mjs CHANGED
@@ -1,75 +1,75 @@
1
- // What this site's pages may load from elsewhere, besides what the editor's package allows on every site (the
2
- // videos, packages/editor/lib/csp.mjs, which writes the policy into the pages): what each installed app needs
3
- // (src/apps/<app>/csp.json, src/data/apps.json), Google Analytics, Google Ads and Google Tag Manager too, which load
4
- // Google's tag once the visitor has said yes (src/scripts/tracking.ts), and the addresses allowed in the editor after
5
- // the policy stopped them (src/data/csp.json, config.csp: the app "Cookiescanner"'s "Blokeret adresse").
6
- // Read by the build (packages/editor/astro.mjs) and by npm run check:content (appCspProblems), so no TypeScript here.
7
- import { existsSync, readdirSync, readFileSync } from 'node:fs';
8
- import { pathToFileURL } from 'node:url';
9
- import { allows, sourcesProblems } from '../lib/csp.mjs';
10
-
11
- // The site's src/, from its root (the working directory).
12
- const SRC = pathToFileURL(`${process.cwd()}/src/`);
13
-
14
- const json = (file) => JSON.parse(readFileSync(new URL(file, SRC), 'utf8'));
15
-
16
- const appSources = (app) => {
17
- const file = new URL(`apps/${app}/csp.json`, SRC);
18
- return existsSync(file) ? JSON.parse(readFileSync(file, 'utf8')) : {};
19
- };
20
-
21
- // The addresses allowed in the editor (config.csp), as an app's csp.json.
22
- const ALLOWED = new URL('data/csp.json', SRC);
23
- const allowedSources = () => (existsSync(ALLOWED) ? JSON.parse(readFileSync(ALLOWED, 'utf8')) : {});
24
-
25
- /** What the site's installed apps load from elsewhere, and the addresses allowed in the editor.
26
- * @returns {import('../lib/csp.mjs').Sources[]} */
27
- export function siteSources() {
28
- return [...(json('data/apps.json').installed ?? []).map(appSources), allowedSources()];
29
- }
30
-
31
- /** What is wrong with the addresses allowed in the editor (src/data/csp.json): not JSON, or not written as an app's
32
- * csp.json must be (npm run check:content). */
33
- export function allowedCspProblems() {
34
- try {
35
- return sourcesProblems(allowedSources(), 'src/data/csp.json');
36
- } catch {
37
- return ['src/data/csp.json: er ikke JSON.'];
38
- }
39
- }
40
-
41
- // A line of code that loads from an address (not a link to it): a script's or a frame's src, fetch, import …
42
- const LOADS = /\bsrc\b|\bsrcset\b|\bfetch\(|\bimport\(|\bsendBeacon\(|\bEventSource\(|\bWebSocket\(|\bXMLHttpRequest\b/;
43
- const ADDRESS = /https:\/\/[a-z0-9-]+(?:\.[a-z0-9-]+)+/gi;
44
- // An app's files that do not run in a browser on the site: its part of the Worker and its step after the build
45
- // (packages/editor/lib/apps.mjs).
46
- const OFF_SITE = new Set(['worker.js', 'build.mjs']);
47
-
48
- /** What is wrong with what the apps (all of them, installed or not) say they load from elsewhere: a csp.json not
49
- * written as it must be, or an address the app's code on the site loads from that its csp.json does not have (npm run
50
- * check:content). */
51
- export function appCspProblems() {
52
- const apps = new URL('apps/', SRC);
53
- if (!existsSync(apps)) return [];
54
- return readdirSync(apps, { withFileTypes: true })
55
- .filter((d) => d.isDirectory())
56
- .flatMap(({ name: app }) => {
57
- const dir = `src/apps/${app}`;
58
- let sources;
59
- try {
60
- sources = appSources(app);
61
- } catch {
62
- return [`${dir}/csp.json: er ikke JSON.`];
63
- }
64
- const problems = sourcesProblems(sources, `${dir}/csp.json`);
65
- if (problems.length) return problems;
66
- const missing = new Set();
67
- for (const file of readdirSync(new URL(`${app}/`, apps), { recursive: true, encoding: 'utf8' }))
68
- if (/\.(tsx?|mjs|js|astro)$/.test(file) && !OFF_SITE.has(file))
69
- for (const line of readFileSync(new URL(`${app}/${file}`, apps), 'utf8').split('\n'))
70
- if (LOADS.test(line)) for (const [url] of line.matchAll(ADDRESS)) if (!allows(sources, url)) missing.add(new URL(url).origin);
71
- return [...missing].map(
72
- (origin) => `${dir}: henter fra ${origin}, men csp.json har det ikke, så sidernes Content-Security-Policy stopper det.`,
73
- );
74
- });
75
- }
1
+ // What this site's pages may load from elsewhere, besides what the editor's package allows on every site (the
2
+ // videos, packages/editor/lib/csp.mjs, which writes the policy into the pages): what each installed app needs
3
+ // (src/apps/<app>/csp.json, src/data/apps.json), Google Analytics, Google Ads and Google Tag Manager too, which load
4
+ // Google's tag once the visitor has said yes (src/scripts/tracking.ts), and the addresses allowed in the editor after
5
+ // the policy stopped them (src/data/csp.json, config.csp: the app "Cookiescanner"'s "Blokeret adresse").
6
+ // Read by the build (packages/editor/astro.mjs) and by npm run check:content (appCspProblems), so no TypeScript here.
7
+ import { existsSync, readdirSync, readFileSync } from 'node:fs';
8
+ import { pathToFileURL } from 'node:url';
9
+ import { allows, sourcesProblems } from '../lib/csp.mjs';
10
+
11
+ // The site's src/, from its root (the working directory).
12
+ const SRC = pathToFileURL(`${process.cwd()}/src/`);
13
+
14
+ const json = (file) => JSON.parse(readFileSync(new URL(file, SRC), 'utf8'));
15
+
16
+ const appSources = (app) => {
17
+ const file = new URL(`apps/${app}/csp.json`, SRC);
18
+ return existsSync(file) ? JSON.parse(readFileSync(file, 'utf8')) : {};
19
+ };
20
+
21
+ // The addresses allowed in the editor (config.csp), as an app's csp.json.
22
+ const ALLOWED = new URL('data/csp.json', SRC);
23
+ const allowedSources = () => (existsSync(ALLOWED) ? JSON.parse(readFileSync(ALLOWED, 'utf8')) : {});
24
+
25
+ /** What the site's installed apps load from elsewhere, and the addresses allowed in the editor.
26
+ * @returns {import('../lib/csp.mjs').Sources[]} */
27
+ export function siteSources() {
28
+ return [...(json('data/apps.json').installed ?? []).map(appSources), allowedSources()];
29
+ }
30
+
31
+ /** What is wrong with the addresses allowed in the editor (src/data/csp.json): not JSON, or not written as an app's
32
+ * csp.json must be (npm run check:content). */
33
+ export function allowedCspProblems() {
34
+ try {
35
+ return sourcesProblems(allowedSources(), 'src/data/csp.json');
36
+ } catch {
37
+ return ['src/data/csp.json: er ikke JSON.'];
38
+ }
39
+ }
40
+
41
+ // A line of code that loads from an address (not a link to it): a script's or a frame's src, fetch, import …
42
+ const LOADS = /\bsrc\b|\bsrcset\b|\bfetch\(|\bimport\(|\bsendBeacon\(|\bEventSource\(|\bWebSocket\(|\bXMLHttpRequest\b/;
43
+ const ADDRESS = /https:\/\/[a-z0-9-]+(?:\.[a-z0-9-]+)+/gi;
44
+ // An app's files that do not run in a browser on the site: its part of the Worker and its step after the build
45
+ // (packages/editor/lib/apps.mjs).
46
+ const OFF_SITE = new Set(['worker.js', 'build.mjs']);
47
+
48
+ /** What is wrong with what the apps (all of them, installed or not) say they load from elsewhere: a csp.json not
49
+ * written as it must be, or an address the app's code on the site loads from that its csp.json does not have (npm run
50
+ * check:content). */
51
+ export function appCspProblems() {
52
+ const apps = new URL('apps/', SRC);
53
+ if (!existsSync(apps)) return [];
54
+ return readdirSync(apps, { withFileTypes: true })
55
+ .filter((d) => d.isDirectory())
56
+ .flatMap(({ name: app }) => {
57
+ const dir = `src/apps/${app}`;
58
+ let sources;
59
+ try {
60
+ sources = appSources(app);
61
+ } catch {
62
+ return [`${dir}/csp.json: er ikke JSON.`];
63
+ }
64
+ const problems = sourcesProblems(sources, `${dir}/csp.json`);
65
+ if (problems.length) return problems;
66
+ const missing = new Set();
67
+ for (const file of readdirSync(new URL(`${app}/`, apps), { recursive: true, encoding: 'utf8' }))
68
+ if (/\.(tsx?|mjs|js|astro)$/.test(file) && !OFF_SITE.has(file))
69
+ for (const line of readFileSync(new URL(`${app}/${file}`, apps), 'utf8').split('\n'))
70
+ if (LOADS.test(line)) for (const [url] of line.matchAll(ADDRESS)) if (!allows(sources, url)) missing.add(new URL(url).origin);
71
+ return [...missing].map(
72
+ (origin) => `${dir}: henter fra ${origin}, men csp.json har det ikke, så sidernes Content-Security-Policy stopper det.`,
73
+ );
74
+ });
75
+ }
@@ -1,27 +1,27 @@
1
- // The site's TypeScript loaded with Vite, as the build has it (its @site, @theme and apps), for the scripts that run
2
- // outside the build: Node itself loads no TypeScript from a package in node_modules, and follows no @site.
3
- import { createServer } from 'vite';
4
- import { appFoldersPlugin } from '../lib/apps.mjs';
5
- import { aliases, themePlugin } from './theme.mjs';
6
-
7
- /**
8
- * Runs `use` with a loader of the site's modules (`@site/collections`, `/src/apps/<id>/index.ts`), then closes it.
9
- * @template T
10
- * @param {(load: (path: string) => Promise<any>) => Promise<T>} use
11
- * @returns {Promise<T>}
12
- */
13
- export async function withSiteModules(use) {
14
- const server = await createServer({
15
- configFile: false,
16
- logLevel: 'error',
17
- appType: 'custom',
18
- plugins: [themePlugin(), appFoldersPlugin(`${process.cwd()}/`)],
19
- resolve: { alias: aliases() },
20
- server: { middlewareMode: true, hmr: false, ws: false },
21
- });
22
- try {
23
- return await use((path) => server.ssrLoadModule(path));
24
- } finally {
25
- await server.close();
26
- }
27
- }
1
+ // The site's TypeScript loaded with Vite, as the build has it (its @site, @theme and apps), for the scripts that run
2
+ // outside the build: Node itself loads no TypeScript from a package in node_modules, and follows no @site.
3
+ import { createServer } from 'vite';
4
+ import { appFoldersPlugin } from '../lib/apps.mjs';
5
+ import { aliases, themePlugin } from './theme.mjs';
6
+
7
+ /**
8
+ * Runs `use` with a loader of the site's modules (`@site/collections`, `/src/apps/<id>/index.ts`), then closes it.
9
+ * @template T
10
+ * @param {(load: (path: string) => Promise<any>) => Promise<T>} use
11
+ * @returns {Promise<T>}
12
+ */
13
+ export async function withSiteModules(use) {
14
+ const server = await createServer({
15
+ configFile: false,
16
+ logLevel: 'error',
17
+ appType: 'custom',
18
+ plugins: [themePlugin(), appFoldersPlugin(`${process.cwd()}/`)],
19
+ resolve: { alias: aliases() },
20
+ server: { middlewareMode: true, hmr: false, ws: false },
21
+ });
22
+ try {
23
+ return await use((path) => server.ssrLoadModule(path));
24
+ } finally {
25
+ await server.close();
26
+ }
27
+ }
@@ -1,59 +1,59 @@
1
- // The blog page, the 404 page and the cookie policy: the pages chosen under "Indstillinger" › "Udseende" › "Standardsider"
2
- // (src/data/standard-pages.json, packages/editor/defaults/standardPages.ts), read for the theme's templates/Blog.astro (at /blog/) and
3
- // templates/NotFound.astro (the page for an address that does not exist): the page, its heading (the H1 at the top of
4
- // its text, else its title), its introduction (the first paragraph of the text before its first heading or block) and the
5
- // rest, shown, as sections: text ("text": a heading and Markdown) and each block by its type, with its fields; and where
6
- // the cookie banner's "Læs mere" goes (cookiesHref).
7
- import { slug } from 'github-slugger';
8
- import paths from '@data/standard-pages.json';
9
- import { getPages, type Page } from './content';
10
- import { pageH1, partsOfMarkdown, sectionsFromParts } from '@morphemecms/cms/src/sections.mjs';
11
-
12
- /** The addresses of the pages that are the front page, the blog page, the 404 page, the contact page, the privacy policy
13
- * and the cookie policy (their own addresses: the front page is shown at /, the blog page at /blog/, the 404 page at none,
14
- * the others at their own). */
15
- export const standardPaths: {
16
- front: string;
17
- blog: string;
18
- notFound: string;
19
- contact: string;
20
- privacy: string;
21
- cookies: string;
22
- } = paths;
23
-
24
- export type PageSection = { type: string; hidden?: boolean; heading?: string; body?: string } & Record<string, any>;
25
- export type StandardPageView = { page: Page; heading: string; intro?: string; sections: PageSection[] };
26
-
27
- async function read(key: 'blog' | 'notFound'): Promise<StandardPageView> {
28
- const page = (await getPages({ previews: false })).find((p) => p.data.path === standardPaths[key]);
29
- if (!page) throw new Error(`src/data/standard-pages.json: siden ${standardPaths[key]} findes ikke, eller den er en kladde.`);
30
- const sections = (sectionsFromParts(partsOfMarkdown(page.body ?? '')) as PageSection[]).filter((s) => !s.hidden);
31
- // The introduction: the first paragraph of a text without a heading at the top; the rest of that text stays a section.
32
- let intro: string | undefined;
33
- const first = sections[0];
34
- if (first?.type === 'text' && !first.heading && first.body) {
35
- const [paragraph, ...rest] = first.body.trim().split(/\n\s*\n/);
36
- intro = paragraph.trim();
37
- if (rest.length) first.body = rest.join('\n\n');
38
- else sections.shift();
39
- }
40
- return { page, heading: pageH1(page.body).heading || page.data.title, intro, sections };
41
- }
42
-
43
- /** The blog page, shown at /blog/. */
44
- export const blogPage = () => read('blog');
45
- /** The 404 page, shown for an address that does not exist. */
46
- export const notFoundPage = () => read('notFound');
47
-
48
- /** The addresses the standard pages are shown at, by their own: the front page's at /, the blog page's at /blog/. */
49
- export const shownAt = (path: string) => (path === standardPaths.front ? '/' : path === standardPaths.blog ? '/blog/' : path);
50
-
51
- /** Where the cookie banner's "Læs mere" goes: the cookie policy, and when it is the privacy policy, its first heading about
52
- * cookies (its id, as Astro gives it: github-slugger), if it has one. */
53
- export async function cookiesHref(): Promise<string> {
54
- const path = standardPaths.cookies;
55
- if (path !== standardPaths.privacy) return path;
56
- const page = (await getPages({ previews: false })).find((p) => p.data.path === path);
57
- const heading = (page?.body ?? '').match(/^#{2,6}\s+(.*cookie.*?)\s*#*\s*$/im)?.[1];
58
- return heading ? `${path}#${slug(heading)}` : path;
59
- }
1
+ // The blog page, the 404 page and the cookie policy: the pages chosen under "Indstillinger" › "Udseende" › "Standardsider"
2
+ // (src/data/standard-pages.json, packages/editor/defaults/standardPages.ts), read for the theme's templates/Blog.astro (at /blog/) and
3
+ // templates/NotFound.astro (the page for an address that does not exist): the page, its heading (the H1 at the top of
4
+ // its text, else its title), its introduction (the first paragraph of the text before its first heading or block) and the
5
+ // rest, shown, as sections: text ("text": a heading and Markdown) and each block by its type, with its fields; and where
6
+ // the cookie banner's "Læs mere" goes (cookiesHref).
7
+ import { slug } from 'github-slugger';
8
+ import paths from '@data/standard-pages.json';
9
+ import { getPages, type Page } from './content';
10
+ import { pageH1, partsOfMarkdown, sectionsFromParts } from '@morphemecms/cms/src/sections.mjs';
11
+
12
+ /** The addresses of the pages that are the front page, the blog page, the 404 page, the contact page, the privacy policy
13
+ * and the cookie policy (their own addresses: the front page is shown at /, the blog page at /blog/, the 404 page at none,
14
+ * the others at their own). */
15
+ export const standardPaths: {
16
+ front: string;
17
+ blog: string;
18
+ notFound: string;
19
+ contact: string;
20
+ privacy: string;
21
+ cookies: string;
22
+ } = paths;
23
+
24
+ export type PageSection = { type: string; hidden?: boolean; heading?: string; body?: string } & Record<string, any>;
25
+ export type StandardPageView = { page: Page; heading: string; intro?: string; sections: PageSection[] };
26
+
27
+ async function read(key: 'blog' | 'notFound'): Promise<StandardPageView> {
28
+ const page = (await getPages({ previews: false })).find((p) => p.data.path === standardPaths[key]);
29
+ if (!page) throw new Error(`src/data/standard-pages.json: siden ${standardPaths[key]} findes ikke, eller den er en kladde.`);
30
+ const sections = (sectionsFromParts(partsOfMarkdown(page.body ?? '')) as PageSection[]).filter((s) => !s.hidden);
31
+ // The introduction: the first paragraph of a text without a heading at the top; the rest of that text stays a section.
32
+ let intro: string | undefined;
33
+ const first = sections[0];
34
+ if (first?.type === 'text' && !first.heading && first.body) {
35
+ const [paragraph, ...rest] = first.body.trim().split(/\n\s*\n/);
36
+ intro = paragraph.trim();
37
+ if (rest.length) first.body = rest.join('\n\n');
38
+ else sections.shift();
39
+ }
40
+ return { page, heading: pageH1(page.body).heading || page.data.title, intro, sections };
41
+ }
42
+
43
+ /** The blog page, shown at /blog/. */
44
+ export const blogPage = () => read('blog');
45
+ /** The 404 page, shown for an address that does not exist. */
46
+ export const notFoundPage = () => read('notFound');
47
+
48
+ /** The addresses the standard pages are shown at, by their own: the front page's at /, the blog page's at /blog/. */
49
+ export const shownAt = (path: string) => (path === standardPaths.front ? '/' : path === standardPaths.blog ? '/blog/' : path);
50
+
51
+ /** Where the cookie banner's "Læs mere" goes: the cookie policy, and when it is the privacy policy, its first heading about
52
+ * cookies (its id, as Astro gives it: github-slugger), if it has one. */
53
+ export async function cookiesHref(): Promise<string> {
54
+ const path = standardPaths.cookies;
55
+ if (path !== standardPaths.privacy) return path;
56
+ const page = (await getPages({ previews: false })).find((p) => p.data.path === path);
57
+ const heading = (page?.body ?? '').match(/^#{2,6}\s+(.*cookie.*?)\s*#*\s*$/im)?.[1];
58
+ return heading ? `${path}#${slug(heading)}` : path;
59
+ }
@@ -0,0 +1,6 @@
1
+ /** What is wrong with the imports in a store theme's CSS file.
2
+ * @param {string} css the file's text
3
+ * @param {string} file its path in the theme, e.g. 'styles/global.css'
4
+ * @returns {string[]}
5
+ */
6
+ export function storeImportProblems(css: string, file: string): string[];
@@ -0,0 +1,29 @@
1
+ // Keeps a store theme's CSS to imports from the CMS and its own files, which is all that is there on a site that
2
+ // installs it. Exposes storeImportProblems, the problems in one CSS file's imports. Depends on node:path only.
3
+ import { posix } from 'node:path';
4
+
5
+ /** What is wrong with the imports in a store theme's CSS file.
6
+ * @param {string} css the file's text
7
+ * @param {string} file its path in the theme, e.g. 'styles/global.css'
8
+ * @returns {string[]}
9
+ */
10
+ export function storeImportProblems(css, file) {
11
+ const text = css.replace(/\/\*[\s\S]*?\*\//g, '');
12
+ // One pass over both forms, so the targets come in the order they appear in the text.
13
+ const targets = [];
14
+ const targetRe = /@import\s+(['"])(.*?)\1|url\(\s*(['"]?)(.*?)\3\s*\)/g;
15
+ let match;
16
+ while ((match = targetRe.exec(text))) targets.push(match[2] !== undefined ? match[2] : match[4].trim());
17
+
18
+ return targets
19
+ .filter((target) => {
20
+ if (target.startsWith('data:')) return false;
21
+ if (target.startsWith('@morphemecms/cms/')) return false;
22
+ if (target.startsWith('./') || target.startsWith('../')) {
23
+ const joined = posix.normalize(posix.join(posix.dirname(file), target));
24
+ if (joined !== '..' && !joined.startsWith('../')) return false;
25
+ }
26
+ return true;
27
+ })
28
+ .map((target) => `${file}: et tema i butikken må kun importere fra @morphemecms/cms og sine egne filer, ikke "${target}".`);
29
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,53 @@
1
+ // What is wrong with a store theme's CSS imports: only the CMS and its own files are allowed.
2
+ // Run with `node --test packages/editor/site/*.test.mjs` (part of npm run check).
3
+ import { strict as assert } from 'node:assert';
4
+ import { test } from 'node:test';
5
+ import { storeImportProblems } from './storeTheme.mjs';
6
+
7
+ const F = 'styles/global.css';
8
+ const expected = (target) => `${F}: et tema i butikken må kun importere fra @morphemecms/cms og sine egne filer, ikke "${target}".`;
9
+
10
+ test('an import of the CMS is allowed', () => {
11
+ const css = `@import '@morphemecms/cms/theme/styles/base.css';`;
12
+ assert.deepEqual(storeImportProblems(css, F), []);
13
+ });
14
+
15
+ test('an npm package is not there', () => {
16
+ const css = `@import '@fontsource-variable/outfit';`;
17
+ assert.deepEqual(storeImportProblems(css, F), [expected('@fontsource-variable/outfit')]);
18
+ });
19
+
20
+ test('a font in the theme is allowed', () => {
21
+ const css = `@font-face { src: url('../fonts/a.woff2') format('woff2'); }`;
22
+ assert.deepEqual(storeImportProblems(css, F), []);
23
+ });
24
+
25
+ test('a path that leaves the theme is not there', () => {
26
+ const css = `@font-face { src: url('../../x.woff2'); }`;
27
+ assert.deepEqual(storeImportProblems(css, F), [expected('../../x.woff2')]);
28
+ });
29
+
30
+ test('a font from another host is not there', () => {
31
+ const css = `@font-face { src: url(https://fonts.example/a.woff2); }`;
32
+ assert.deepEqual(storeImportProblems(css, F), [expected('https://fonts.example/a.woff2')]);
33
+ });
34
+
35
+ test('a data URI is allowed', () => {
36
+ const css = `@font-face { src: url(data:font/woff2;base64,AA); }`;
37
+ assert.deepEqual(storeImportProblems(css, F), []);
38
+ });
39
+
40
+ test('two targets outside the theme are two problems', () => {
41
+ const css = `@import 'https://a.example/x.css';\n@import url("other-package/x.css");`;
42
+ assert.deepEqual(storeImportProblems(css, F), [expected('https://a.example/x.css'), expected('other-package/x.css')]);
43
+ });
44
+
45
+ test('the problems come in the order of the text', () => {
46
+ const css = `@font-face { src: url(https://a.example/x); }\n@import 'b';`;
47
+ assert.deepEqual(storeImportProblems(css, F), [expected('https://a.example/x'), expected('b')]);
48
+ });
49
+
50
+ test('an import in a comment is not there', () => {
51
+ const css = `/* @import 'left-out'; */ @import './ui.css';`;
52
+ assert.deepEqual(storeImportProblems(css, F), []);
53
+ });