@morphemecms/cms 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1106) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +51 -3
  3. package/astro.d.mts +2 -0
  4. package/astro.mjs +162 -0
  5. package/bin/morpheme.mjs +38 -0
  6. package/client.d.ts +10 -0
  7. package/defaults/blockTexts.ts +33 -0
  8. package/defaults/collections.ts +774 -0
  9. package/defaults/colors.ts +125 -0
  10. package/defaults/company.ts +20 -0
  11. package/defaults/editor.ts +178 -0
  12. package/defaults/internalLinks.ts +30 -0
  13. package/defaults/opens.ts +18 -0
  14. package/defaults/popup.tsx +93 -0
  15. package/defaults/privacy.ts +79 -0
  16. package/defaults/rules.ts +450 -0
  17. package/defaults/schema.ts +16 -0
  18. package/defaults/sitedata.ts +129 -0
  19. package/defaults/standard.ts +106 -0
  20. package/defaults/standardPages.ts +87 -0
  21. package/defaults/texts.ts +481 -0
  22. package/demo/README.md +26 -0
  23. package/demo/public/apple-touch-icon.png +0 -0
  24. package/demo/public/editor/apple-touch-icon.png +0 -0
  25. package/demo/public/editor/icon-192.png +0 -0
  26. package/demo/public/editor/icon-512.png +0 -0
  27. package/demo/public/editor/icon-maskable-512.png +0 -0
  28. package/demo/public/favicon.ico +0 -0
  29. package/demo/public/favicon.svg +1 -0
  30. package/demo/public/images/uploads/2026/10/andromeda.webp +0 -0
  31. package/demo/public/images/uploads/2026/10/earth-from-space.webp +0 -0
  32. package/demo/public/images/uploads/2026/10/editor-blog.webp +0 -0
  33. package/demo/public/images/uploads/2026/10/editor-colors.webp +0 -0
  34. package/demo/public/images/uploads/2026/10/editor-home.webp +0 -0
  35. package/demo/public/images/uploads/2026/10/editor-page.webp +0 -0
  36. package/demo/public/images/uploads/2026/10/editor-pages.webp +0 -0
  37. package/demo/public/images/uploads/2026/10/editor-seo.webp +0 -0
  38. package/demo/public/images/uploads/2026/10/editor-start.webp +0 -0
  39. package/demo/public/images/uploads/2026/10/editor-themes.webp +0 -0
  40. package/demo/public/images/uploads/2026/10/moon.webp +0 -0
  41. package/demo/public/images/uploads/2026/10/saturn.webp +0 -0
  42. package/demo/public/logo.svg +1 -0
  43. package/demo/src/content/blog/build-a-page-from-blocks.md +19 -0
  44. package/demo/src/content/blog/colors-everyone-can-read.md +19 -0
  45. package/demo/src/content/blog/edit-your-website-from-your-phone.md +21 -0
  46. package/demo/src/content/blog/every-save-is-a-version.md +21 -0
  47. package/demo/src/content/blog/schedule-a-post.md +17 -0
  48. package/demo/src/content/blog/secure-from-day-one.md +17 -0
  49. package/demo/src/content/blog/seo-without-the-guesswork.md +23 -0
  50. package/demo/src/content/blog/switch-themes-without-losing-anything.md +23 -0
  51. package/demo/src/content/blog/the-app-store.md +21 -0
  52. package/demo/src/content/pages/about.md +22 -0
  53. package/demo/src/content/pages/app-store.md +30 -0
  54. package/demo/src/content/pages/blocks.md +98 -0
  55. package/demo/src/content/pages/blog-page.md +11 -0
  56. package/demo/src/content/pages/contact.md +16 -0
  57. package/demo/src/content/pages/get-started.md +20 -0
  58. package/demo/src/content/pages/home.md +26 -0
  59. package/demo/src/content/pages/page-not-found.md +11 -0
  60. package/demo/src/content/pages/privacy-policy.md +24 -0
  61. package/demo/src/data/blocks.json +25 -0
  62. package/demo/src/data/booking.json +6 -0
  63. package/demo/src/data/categories/apps.json +6 -0
  64. package/demo/src/data/categories/design.json +6 -0
  65. package/demo/src/data/categories/editing.json +6 -0
  66. package/demo/src/data/categories/security.json +6 -0
  67. package/demo/src/data/categories/seo.json +6 -0
  68. package/demo/src/data/colors.json +75 -0
  69. package/demo/src/data/contact.json +8 -0
  70. package/demo/src/data/cookies.json +21 -0
  71. package/demo/src/data/footer.json +27 -0
  72. package/demo/src/data/menu.json +35 -0
  73. package/demo/src/data/mobile-menu.json +25 -0
  74. package/demo/src/data/popups/booking-bar.json +13 -0
  75. package/demo/src/data/popups/try-the-editor.json +16 -0
  76. package/demo/src/data/standard-pages.json +8 -0
  77. package/demo/src/data/testimonials/sample-bakery.json +10 -0
  78. package/demo/src/data/testimonials/sample-clinic.json +10 -0
  79. package/demo/src/data/testimonials/sample-studio.json +10 -0
  80. package/demo/src/site/colors.ts +11 -0
  81. package/demo/src/site/config.ts +19 -0
  82. package/icons/lucide/LICENSE +43 -0
  83. package/icons/lucide/LICENSE-material-design-icons +20 -0
  84. package/icons/lucide/address-book.svg +1 -0
  85. package/icons/lucide/app-window.svg +1 -0
  86. package/icons/lucide/arrow-counter-clockwise.svg +1 -0
  87. package/icons/lucide/arrow-down.svg +1 -0
  88. package/icons/lucide/arrow-left.svg +1 -0
  89. package/icons/lucide/arrow-right.svg +1 -0
  90. package/icons/lucide/arrow-square-out.svg +1 -0
  91. package/icons/lucide/arrow-u-up-left.svg +1 -0
  92. package/icons/lucide/arrow-u-up-right.svg +1 -0
  93. package/icons/lucide/arrow-up-right.svg +1 -0
  94. package/icons/lucide/arrow-up.svg +1 -0
  95. package/icons/lucide/arrows-down-up.svg +1 -0
  96. package/icons/lucide/arrows-in-line-horizontal.svg +1 -0
  97. package/icons/lucide/arrows-out-line-horizontal.svg +1 -0
  98. package/icons/lucide/article.svg +1 -0
  99. package/icons/lucide/bank.svg +1 -0
  100. package/icons/lucide/bell.svg +1 -0
  101. package/icons/lucide/bicycle.svg +1 -0
  102. package/icons/lucide/binoculars.svg +1 -0
  103. package/icons/lucide/book-open-text.svg +1 -0
  104. package/icons/lucide/book-open.svg +1 -0
  105. package/icons/lucide/browser.svg +1 -0
  106. package/icons/lucide/buildings.svg +1 -0
  107. package/icons/lucide/bus.svg +1 -0
  108. package/icons/lucide/calendar-blank.svg +1 -0
  109. package/icons/lucide/calendar-check.svg +1 -0
  110. package/icons/lucide/car.svg +1 -0
  111. package/icons/lucide/cards.svg +1 -0
  112. package/icons/lucide/caret-down.svg +1 -0
  113. package/icons/lucide/caret-left.svg +1 -0
  114. package/icons/lucide/caret-right.svg +1 -0
  115. package/icons/lucide/caret-up.svg +1 -0
  116. package/icons/lucide/certificate.svg +1 -0
  117. package/icons/lucide/chart-line-up.svg +1 -0
  118. package/icons/lucide/chats.svg +1 -0
  119. package/icons/lucide/check-circle.svg +1 -0
  120. package/icons/lucide/check.svg +1 -0
  121. package/icons/lucide/circle-half.svg +1 -0
  122. package/icons/lucide/circle.svg +1 -0
  123. package/icons/lucide/clock-counter-clockwise.svg +1 -0
  124. package/icons/lucide/clock.svg +1 -0
  125. package/icons/lucide/code.svg +1 -0
  126. package/icons/lucide/coffee.svg +1 -0
  127. package/icons/lucide/columns.svg +1 -0
  128. package/icons/lucide/cookie.svg +1 -0
  129. package/icons/lucide/copy.svg +1 -0
  130. package/icons/lucide/credit-card.svg +1 -0
  131. package/icons/lucide/currency-circle-dollar.svg +1 -0
  132. package/icons/lucide/cursor-click.svg +1 -0
  133. package/icons/lucide/database.svg +1 -0
  134. package/icons/lucide/desktop.svg +1 -0
  135. package/icons/lucide/device-mobile.svg +1 -0
  136. package/icons/lucide/door-open.svg +1 -0
  137. package/icons/lucide/download-simple.svg +1 -0
  138. package/icons/lucide/envelope-simple.svg +1 -0
  139. package/icons/lucide/eye-slash.svg +1 -0
  140. package/icons/lucide/eye.svg +1 -0
  141. package/icons/lucide/file-pdf.svg +1 -0
  142. package/icons/lucide/file-text.svg +1 -0
  143. package/icons/lucide/file-video.svg +1 -0
  144. package/icons/lucide/file-zip.svg +1 -0
  145. package/icons/lucide/flower-lotus.svg +1 -0
  146. package/icons/lucide/folder-simple.svg +1 -0
  147. package/icons/lucide/funnel.svg +1 -0
  148. package/icons/lucide/gauge.svg +1 -0
  149. package/icons/lucide/gear.svg +1 -0
  150. package/icons/lucide/github-logo.svg +1 -0
  151. package/icons/lucide/globe.svg +1 -0
  152. package/icons/lucide/google-logo.svg +1 -0
  153. package/icons/lucide/graduation-cap.svg +1 -0
  154. package/icons/lucide/hammer.svg +1 -0
  155. package/icons/lucide/hand-heart.svg +1 -0
  156. package/icons/lucide/handshake.svg +1 -0
  157. package/icons/lucide/hard-drives.svg +1 -0
  158. package/icons/lucide/heart.svg +1 -0
  159. package/icons/lucide/house.svg +1 -0
  160. package/icons/lucide/image-square.svg +1 -0
  161. package/icons/lucide/image.svg +1 -0
  162. package/icons/lucide/info.svg +1 -0
  163. package/icons/lucide/keyboard.svg +1 -0
  164. package/icons/lucide/leaf.svg +1 -0
  165. package/icons/lucide/lifebuoy.svg +1 -0
  166. package/icons/lucide/lightbulb.svg +1 -0
  167. package/icons/lucide/link-break.svg +1 -0
  168. package/icons/lucide/link-simple.svg +1 -0
  169. package/icons/lucide/list-bullets.svg +1 -0
  170. package/icons/lucide/list-checks.svg +1 -0
  171. package/icons/lucide/list-numbers.svg +1 -0
  172. package/icons/lucide/list.svg +1 -0
  173. package/icons/lucide/lock-simple-open.svg +1 -0
  174. package/icons/lucide/lock-simple.svg +1 -0
  175. package/icons/lucide/magnifying-glass.svg +1 -0
  176. package/icons/lucide/map-pin.svg +1 -0
  177. package/icons/lucide/map-trifold.svg +1 -0
  178. package/icons/lucide/medal.svg +1 -0
  179. package/icons/lucide/megaphone.svg +1 -0
  180. package/icons/lucide/minus.svg +1 -0
  181. package/icons/lucide/moon.svg +1 -0
  182. package/icons/lucide/newspaper.svg +1 -0
  183. package/icons/lucide/pack.json +23 -0
  184. package/icons/lucide/paint-brush-broad.svg +1 -0
  185. package/icons/lucide/palette.svg +1 -0
  186. package/icons/lucide/paper-plane-tilt.svg +1 -0
  187. package/icons/lucide/pencil-simple.svg +1 -0
  188. package/icons/lucide/phone.svg +1 -0
  189. package/icons/lucide/play-fill.svg +1 -0
  190. package/icons/lucide/plus.svg +1 -0
  191. package/icons/lucide/prohibit.svg +1 -0
  192. package/icons/lucide/puzzle-piece.svg +1 -0
  193. package/icons/lucide/question.svg +1 -0
  194. package/icons/lucide/quotes.svg +1 -0
  195. package/icons/lucide/rows.svg +1 -0
  196. package/icons/lucide/ruler.svg +1 -0
  197. package/icons/lucide/scan.svg +1 -0
  198. package/icons/lucide/shapes.svg +1 -0
  199. package/icons/lucide/share-network.svg +1 -0
  200. package/icons/lucide/shield-check.svg +1 -0
  201. package/icons/lucide/sidebar-simple.svg +1 -0
  202. package/icons/lucide/sign-out.svg +1 -0
  203. package/icons/lucide/signpost.svg +1 -0
  204. package/icons/lucide/sliders-horizontal.svg +1 -0
  205. package/icons/lucide/smiley.svg +1 -0
  206. package/icons/lucide/sparkle.svg +1 -0
  207. package/icons/lucide/square-half-bottom.svg +1 -0
  208. package/icons/lucide/square.svg +1 -0
  209. package/icons/lucide/squares-four.svg +1 -0
  210. package/icons/lucide/sticker.svg +1 -0
  211. package/icons/lucide/storefront.svg +1 -0
  212. package/icons/lucide/sun.svg +1 -0
  213. package/icons/lucide/swatches.svg +1 -0
  214. package/icons/lucide/tag.svg +1 -0
  215. package/icons/lucide/text-aa.svg +1 -0
  216. package/icons/lucide/text-align-left.svg +1 -0
  217. package/icons/lucide/text-b.svg +1 -0
  218. package/icons/lucide/text-h-one.svg +1 -0
  219. package/icons/lucide/text-h-three.svg +1 -0
  220. package/icons/lucide/text-h-two.svg +1 -0
  221. package/icons/lucide/text-italic.svg +1 -0
  222. package/icons/lucide/text-t.svg +1 -0
  223. package/icons/lucide/ticket.svg +1 -0
  224. package/icons/lucide/toggle-right.svg +1 -0
  225. package/icons/lucide/train.svg +1 -0
  226. package/icons/lucide/trash.svg +1 -0
  227. package/icons/lucide/upload-simple.svg +1 -0
  228. package/icons/lucide/user-circle.svg +1 -0
  229. package/icons/lucide/user.svg +1 -0
  230. package/icons/lucide/users-three.svg +1 -0
  231. package/icons/lucide/users.svg +1 -0
  232. package/icons/lucide/video-camera.svg +1 -0
  233. package/icons/lucide/warning-circle.svg +1 -0
  234. package/icons/lucide/warning.svg +1 -0
  235. package/icons/lucide/wave-sine.svg +1 -0
  236. package/icons/lucide/wheelchair.svg +1 -0
  237. package/icons/lucide/wrench.svg +1 -0
  238. package/icons/lucide/x.svg +1 -0
  239. package/icons/material-symbols/LICENSE +201 -0
  240. package/icons/material-symbols/LICENSE-material-design-icons +20 -0
  241. package/icons/material-symbols/address-book.svg +1 -0
  242. package/icons/material-symbols/app-window.svg +1 -0
  243. package/icons/material-symbols/arrow-counter-clockwise.svg +1 -0
  244. package/icons/material-symbols/arrow-down.svg +1 -0
  245. package/icons/material-symbols/arrow-left.svg +1 -0
  246. package/icons/material-symbols/arrow-right.svg +1 -0
  247. package/icons/material-symbols/arrow-square-out.svg +1 -0
  248. package/icons/material-symbols/arrow-u-up-left.svg +1 -0
  249. package/icons/material-symbols/arrow-u-up-right.svg +1 -0
  250. package/icons/material-symbols/arrow-up-right.svg +1 -0
  251. package/icons/material-symbols/arrow-up.svg +1 -0
  252. package/icons/material-symbols/arrows-down-up.svg +1 -0
  253. package/icons/material-symbols/arrows-in-line-horizontal.svg +1 -0
  254. package/icons/material-symbols/arrows-out-line-horizontal.svg +1 -0
  255. package/icons/material-symbols/article.svg +1 -0
  256. package/icons/material-symbols/bank.svg +1 -0
  257. package/icons/material-symbols/bell.svg +1 -0
  258. package/icons/material-symbols/bicycle.svg +1 -0
  259. package/icons/material-symbols/binoculars.svg +1 -0
  260. package/icons/material-symbols/book-open-text.svg +1 -0
  261. package/icons/material-symbols/book-open.svg +1 -0
  262. package/icons/material-symbols/browser.svg +1 -0
  263. package/icons/material-symbols/buildings.svg +1 -0
  264. package/icons/material-symbols/bus.svg +1 -0
  265. package/icons/material-symbols/calendar-blank.svg +1 -0
  266. package/icons/material-symbols/calendar-check.svg +1 -0
  267. package/icons/material-symbols/car.svg +1 -0
  268. package/icons/material-symbols/cards.svg +1 -0
  269. package/icons/material-symbols/caret-down.svg +1 -0
  270. package/icons/material-symbols/caret-left.svg +1 -0
  271. package/icons/material-symbols/caret-right.svg +1 -0
  272. package/icons/material-symbols/caret-up.svg +1 -0
  273. package/icons/material-symbols/certificate.svg +1 -0
  274. package/icons/material-symbols/chart-line-up.svg +1 -0
  275. package/icons/material-symbols/chats.svg +1 -0
  276. package/icons/material-symbols/check-circle.svg +1 -0
  277. package/icons/material-symbols/check.svg +1 -0
  278. package/icons/material-symbols/circle-half.svg +1 -0
  279. package/icons/material-symbols/circle.svg +1 -0
  280. package/icons/material-symbols/clock-counter-clockwise.svg +1 -0
  281. package/icons/material-symbols/clock.svg +1 -0
  282. package/icons/material-symbols/code.svg +1 -0
  283. package/icons/material-symbols/coffee.svg +1 -0
  284. package/icons/material-symbols/columns.svg +1 -0
  285. package/icons/material-symbols/cookie.svg +1 -0
  286. package/icons/material-symbols/copy.svg +1 -0
  287. package/icons/material-symbols/credit-card.svg +1 -0
  288. package/icons/material-symbols/currency-circle-dollar.svg +1 -0
  289. package/icons/material-symbols/cursor-click.svg +1 -0
  290. package/icons/material-symbols/database.svg +1 -0
  291. package/icons/material-symbols/desktop.svg +1 -0
  292. package/icons/material-symbols/device-mobile.svg +1 -0
  293. package/icons/material-symbols/door-open.svg +1 -0
  294. package/icons/material-symbols/download-simple.svg +1 -0
  295. package/icons/material-symbols/envelope-simple.svg +1 -0
  296. package/icons/material-symbols/eye-slash.svg +1 -0
  297. package/icons/material-symbols/eye.svg +1 -0
  298. package/icons/material-symbols/file-pdf.svg +1 -0
  299. package/icons/material-symbols/file-text.svg +1 -0
  300. package/icons/material-symbols/file-video.svg +1 -0
  301. package/icons/material-symbols/file-zip.svg +1 -0
  302. package/icons/material-symbols/flower-lotus.svg +1 -0
  303. package/icons/material-symbols/folder-simple.svg +1 -0
  304. package/icons/material-symbols/funnel.svg +1 -0
  305. package/icons/material-symbols/gauge.svg +1 -0
  306. package/icons/material-symbols/gear.svg +1 -0
  307. package/icons/material-symbols/github-logo.svg +1 -0
  308. package/icons/material-symbols/globe.svg +1 -0
  309. package/icons/material-symbols/google-logo.svg +1 -0
  310. package/icons/material-symbols/graduation-cap.svg +1 -0
  311. package/icons/material-symbols/hammer.svg +1 -0
  312. package/icons/material-symbols/hand-heart.svg +1 -0
  313. package/icons/material-symbols/handshake.svg +1 -0
  314. package/icons/material-symbols/hard-drives.svg +1 -0
  315. package/icons/material-symbols/heart.svg +1 -0
  316. package/icons/material-symbols/house.svg +1 -0
  317. package/icons/material-symbols/image-square.svg +1 -0
  318. package/icons/material-symbols/image.svg +1 -0
  319. package/icons/material-symbols/info.svg +1 -0
  320. package/icons/material-symbols/keyboard.svg +1 -0
  321. package/icons/material-symbols/leaf.svg +1 -0
  322. package/icons/material-symbols/lifebuoy.svg +1 -0
  323. package/icons/material-symbols/lightbulb.svg +1 -0
  324. package/icons/material-symbols/link-break.svg +1 -0
  325. package/icons/material-symbols/link-simple.svg +1 -0
  326. package/icons/material-symbols/list-bullets.svg +1 -0
  327. package/icons/material-symbols/list-checks.svg +1 -0
  328. package/icons/material-symbols/list-numbers.svg +1 -0
  329. package/icons/material-symbols/list.svg +1 -0
  330. package/icons/material-symbols/lock-simple-open.svg +1 -0
  331. package/icons/material-symbols/lock-simple.svg +1 -0
  332. package/icons/material-symbols/magnifying-glass.svg +1 -0
  333. package/icons/material-symbols/map-pin.svg +1 -0
  334. package/icons/material-symbols/map-trifold.svg +1 -0
  335. package/icons/material-symbols/medal.svg +1 -0
  336. package/icons/material-symbols/megaphone.svg +1 -0
  337. package/icons/material-symbols/minus.svg +1 -0
  338. package/icons/material-symbols/moon.svg +1 -0
  339. package/icons/material-symbols/newspaper.svg +1 -0
  340. package/icons/material-symbols/pack.json +29 -0
  341. package/icons/material-symbols/paint-brush-broad.svg +1 -0
  342. package/icons/material-symbols/palette.svg +1 -0
  343. package/icons/material-symbols/paper-plane-tilt.svg +1 -0
  344. package/icons/material-symbols/pencil-simple.svg +1 -0
  345. package/icons/material-symbols/phone.svg +1 -0
  346. package/icons/material-symbols/play-fill.svg +1 -0
  347. package/icons/material-symbols/plus.svg +1 -0
  348. package/icons/material-symbols/prohibit.svg +1 -0
  349. package/icons/material-symbols/puzzle-piece.svg +1 -0
  350. package/icons/material-symbols/question.svg +1 -0
  351. package/icons/material-symbols/quotes.svg +1 -0
  352. package/icons/material-symbols/rows.svg +1 -0
  353. package/icons/material-symbols/ruler.svg +1 -0
  354. package/icons/material-symbols/scan.svg +1 -0
  355. package/icons/material-symbols/shapes.svg +1 -0
  356. package/icons/material-symbols/share-network.svg +1 -0
  357. package/icons/material-symbols/shield-check.svg +1 -0
  358. package/icons/material-symbols/sidebar-simple.svg +1 -0
  359. package/icons/material-symbols/sign-out.svg +1 -0
  360. package/icons/material-symbols/signpost.svg +1 -0
  361. package/icons/material-symbols/sliders-horizontal.svg +1 -0
  362. package/icons/material-symbols/smiley.svg +1 -0
  363. package/icons/material-symbols/sparkle.svg +1 -0
  364. package/icons/material-symbols/square-half-bottom.svg +1 -0
  365. package/icons/material-symbols/square.svg +1 -0
  366. package/icons/material-symbols/squares-four.svg +1 -0
  367. package/icons/material-symbols/sticker.svg +1 -0
  368. package/icons/material-symbols/storefront.svg +1 -0
  369. package/icons/material-symbols/sun.svg +1 -0
  370. package/icons/material-symbols/swatches.svg +1 -0
  371. package/icons/material-symbols/tag.svg +1 -0
  372. package/icons/material-symbols/text-aa.svg +1 -0
  373. package/icons/material-symbols/text-align-left.svg +1 -0
  374. package/icons/material-symbols/text-b.svg +1 -0
  375. package/icons/material-symbols/text-h-one.svg +1 -0
  376. package/icons/material-symbols/text-h-three.svg +1 -0
  377. package/icons/material-symbols/text-h-two.svg +1 -0
  378. package/icons/material-symbols/text-italic.svg +1 -0
  379. package/icons/material-symbols/text-t.svg +1 -0
  380. package/icons/material-symbols/ticket.svg +1 -0
  381. package/icons/material-symbols/toggle-right.svg +1 -0
  382. package/icons/material-symbols/train.svg +1 -0
  383. package/icons/material-symbols/trash.svg +1 -0
  384. package/icons/material-symbols/upload-simple.svg +1 -0
  385. package/icons/material-symbols/user-circle.svg +1 -0
  386. package/icons/material-symbols/user.svg +1 -0
  387. package/icons/material-symbols/users-three.svg +1 -0
  388. package/icons/material-symbols/users.svg +1 -0
  389. package/icons/material-symbols/video-camera.svg +1 -0
  390. package/icons/material-symbols/warning-circle.svg +1 -0
  391. package/icons/material-symbols/warning.svg +1 -0
  392. package/icons/material-symbols/wave-sine.svg +1 -0
  393. package/icons/material-symbols/wheelchair.svg +1 -0
  394. package/icons/material-symbols/wrench.svg +1 -0
  395. package/icons/material-symbols/x.svg +1 -0
  396. package/icons/phosphor/LICENSE +21 -0
  397. package/icons/phosphor/address-book.svg +1 -0
  398. package/icons/phosphor/app-window.svg +1 -0
  399. package/icons/phosphor/arrow-counter-clockwise.svg +1 -0
  400. package/icons/phosphor/arrow-down.svg +1 -0
  401. package/icons/phosphor/arrow-left.svg +1 -0
  402. package/icons/phosphor/arrow-right.svg +1 -0
  403. package/icons/phosphor/arrow-square-out.svg +1 -0
  404. package/icons/phosphor/arrow-u-up-left.svg +1 -0
  405. package/icons/phosphor/arrow-u-up-right.svg +1 -0
  406. package/icons/phosphor/arrow-up-right.svg +1 -0
  407. package/icons/phosphor/arrow-up.svg +1 -0
  408. package/icons/phosphor/arrows-down-up.svg +1 -0
  409. package/icons/phosphor/arrows-in-line-horizontal.svg +1 -0
  410. package/icons/phosphor/arrows-out-line-horizontal.svg +1 -0
  411. package/icons/phosphor/article.svg +1 -0
  412. package/icons/phosphor/bank.svg +1 -0
  413. package/icons/phosphor/bell.svg +1 -0
  414. package/icons/phosphor/bicycle.svg +1 -0
  415. package/icons/phosphor/binoculars.svg +1 -0
  416. package/icons/phosphor/book-open-text.svg +1 -0
  417. package/icons/phosphor/book-open.svg +1 -0
  418. package/icons/phosphor/browser.svg +1 -0
  419. package/icons/phosphor/buildings.svg +1 -0
  420. package/icons/phosphor/bus.svg +1 -0
  421. package/icons/phosphor/calendar-blank.svg +1 -0
  422. package/icons/phosphor/calendar-check.svg +1 -0
  423. package/icons/phosphor/car.svg +1 -0
  424. package/icons/phosphor/cards.svg +1 -0
  425. package/icons/phosphor/caret-down.svg +1 -0
  426. package/icons/phosphor/caret-left.svg +1 -0
  427. package/icons/phosphor/caret-right.svg +1 -0
  428. package/icons/phosphor/caret-up.svg +1 -0
  429. package/icons/phosphor/certificate.svg +1 -0
  430. package/icons/phosphor/chart-line-up.svg +1 -0
  431. package/icons/phosphor/chats.svg +1 -0
  432. package/icons/phosphor/check-circle.svg +1 -0
  433. package/icons/phosphor/check.svg +1 -0
  434. package/icons/phosphor/circle-half.svg +1 -0
  435. package/icons/phosphor/circle.svg +1 -0
  436. package/icons/phosphor/clock-counter-clockwise.svg +1 -0
  437. package/icons/phosphor/clock.svg +1 -0
  438. package/icons/phosphor/code.svg +1 -0
  439. package/icons/phosphor/coffee.svg +1 -0
  440. package/icons/phosphor/columns.svg +1 -0
  441. package/icons/phosphor/cookie.svg +1 -0
  442. package/icons/phosphor/copy.svg +1 -0
  443. package/icons/phosphor/credit-card.svg +1 -0
  444. package/icons/phosphor/currency-circle-dollar.svg +1 -0
  445. package/icons/phosphor/cursor-click.svg +1 -0
  446. package/icons/phosphor/database.svg +1 -0
  447. package/icons/phosphor/desktop.svg +1 -0
  448. package/icons/phosphor/device-mobile.svg +1 -0
  449. package/icons/phosphor/door-open.svg +1 -0
  450. package/icons/phosphor/download-simple.svg +1 -0
  451. package/icons/phosphor/envelope-simple.svg +1 -0
  452. package/icons/phosphor/eye-slash.svg +1 -0
  453. package/icons/phosphor/eye.svg +1 -0
  454. package/icons/phosphor/file-pdf.svg +1 -0
  455. package/icons/phosphor/file-text.svg +1 -0
  456. package/icons/phosphor/file-video.svg +1 -0
  457. package/icons/phosphor/file-zip.svg +1 -0
  458. package/icons/phosphor/flower-lotus.svg +1 -0
  459. package/icons/phosphor/folder-simple.svg +1 -0
  460. package/icons/phosphor/funnel.svg +1 -0
  461. package/icons/phosphor/gauge.svg +1 -0
  462. package/icons/phosphor/gear.svg +1 -0
  463. package/icons/phosphor/github-logo.svg +1 -0
  464. package/icons/phosphor/globe.svg +1 -0
  465. package/icons/phosphor/google-logo.svg +1 -0
  466. package/icons/phosphor/graduation-cap.svg +1 -0
  467. package/icons/phosphor/hammer.svg +1 -0
  468. package/icons/phosphor/hand-heart.svg +1 -0
  469. package/icons/phosphor/handshake.svg +1 -0
  470. package/icons/phosphor/hard-drives.svg +1 -0
  471. package/icons/phosphor/heart.svg +1 -0
  472. package/icons/phosphor/house.svg +1 -0
  473. package/icons/phosphor/image-square.svg +1 -0
  474. package/icons/phosphor/image.svg +1 -0
  475. package/icons/phosphor/info.svg +1 -0
  476. package/icons/phosphor/keyboard.svg +1 -0
  477. package/icons/phosphor/leaf.svg +1 -0
  478. package/icons/phosphor/lifebuoy.svg +1 -0
  479. package/icons/phosphor/lightbulb.svg +1 -0
  480. package/icons/phosphor/link-break.svg +1 -0
  481. package/icons/phosphor/link-simple.svg +1 -0
  482. package/icons/phosphor/list-bullets.svg +1 -0
  483. package/icons/phosphor/list-checks.svg +1 -0
  484. package/icons/phosphor/list-numbers.svg +1 -0
  485. package/icons/phosphor/list.svg +1 -0
  486. package/icons/phosphor/lock-simple-open.svg +1 -0
  487. package/icons/phosphor/lock-simple.svg +1 -0
  488. package/icons/phosphor/magnifying-glass.svg +1 -0
  489. package/icons/phosphor/map-pin.svg +1 -0
  490. package/icons/phosphor/map-trifold.svg +1 -0
  491. package/icons/phosphor/medal.svg +1 -0
  492. package/icons/phosphor/megaphone.svg +1 -0
  493. package/icons/phosphor/minus.svg +1 -0
  494. package/icons/phosphor/moon.svg +1 -0
  495. package/icons/phosphor/newspaper.svg +1 -0
  496. package/icons/phosphor/pack.json +8 -0
  497. package/icons/phosphor/paint-brush-broad.svg +1 -0
  498. package/icons/phosphor/palette.svg +1 -0
  499. package/icons/phosphor/paper-plane-tilt.svg +1 -0
  500. package/icons/phosphor/pencil-simple.svg +1 -0
  501. package/icons/phosphor/phone.svg +1 -0
  502. package/icons/phosphor/play-fill.svg +1 -0
  503. package/icons/phosphor/plus.svg +1 -0
  504. package/icons/phosphor/prohibit.svg +1 -0
  505. package/icons/phosphor/puzzle-piece.svg +1 -0
  506. package/icons/phosphor/question.svg +1 -0
  507. package/icons/phosphor/quotes.svg +1 -0
  508. package/icons/phosphor/rows.svg +1 -0
  509. package/icons/phosphor/ruler.svg +1 -0
  510. package/icons/phosphor/scan.svg +1 -0
  511. package/icons/phosphor/shapes.svg +1 -0
  512. package/icons/phosphor/share-network.svg +1 -0
  513. package/icons/phosphor/shield-check.svg +1 -0
  514. package/icons/phosphor/sidebar-simple.svg +1 -0
  515. package/icons/phosphor/sign-out.svg +1 -0
  516. package/icons/phosphor/signpost.svg +1 -0
  517. package/icons/phosphor/sliders-horizontal.svg +1 -0
  518. package/icons/phosphor/smiley.svg +1 -0
  519. package/icons/phosphor/sparkle.svg +1 -0
  520. package/icons/phosphor/square-half-bottom.svg +1 -0
  521. package/icons/phosphor/square.svg +1 -0
  522. package/icons/phosphor/squares-four.svg +1 -0
  523. package/icons/phosphor/sticker.svg +1 -0
  524. package/icons/phosphor/storefront.svg +1 -0
  525. package/icons/phosphor/sun.svg +1 -0
  526. package/icons/phosphor/swatches.svg +1 -0
  527. package/icons/phosphor/tag.svg +1 -0
  528. package/icons/phosphor/text-aa.svg +1 -0
  529. package/icons/phosphor/text-align-left.svg +1 -0
  530. package/icons/phosphor/text-b.svg +1 -0
  531. package/icons/phosphor/text-h-one.svg +1 -0
  532. package/icons/phosphor/text-h-three.svg +1 -0
  533. package/icons/phosphor/text-h-two.svg +1 -0
  534. package/icons/phosphor/text-italic.svg +1 -0
  535. package/icons/phosphor/text-t.svg +1 -0
  536. package/icons/phosphor/ticket.svg +1 -0
  537. package/icons/phosphor/toggle-right.svg +1 -0
  538. package/icons/phosphor/train.svg +1 -0
  539. package/icons/phosphor/trash.svg +1 -0
  540. package/icons/phosphor/upload-simple.svg +1 -0
  541. package/icons/phosphor/user-circle.svg +1 -0
  542. package/icons/phosphor/user.svg +1 -0
  543. package/icons/phosphor/users-three.svg +1 -0
  544. package/icons/phosphor/users.svg +1 -0
  545. package/icons/phosphor/video-camera.svg +1 -0
  546. package/icons/phosphor/warning-circle.svg +1 -0
  547. package/icons/phosphor/warning.svg +1 -0
  548. package/icons/phosphor/wave-sine.svg +1 -0
  549. package/icons/phosphor/wheelchair.svg +1 -0
  550. package/icons/phosphor/wrench.svg +1 -0
  551. package/icons/phosphor/x.svg +1 -0
  552. package/lib/apps.d.mts +28 -0
  553. package/lib/apps.mjs +139 -0
  554. package/lib/blocks.d.mts +23 -0
  555. package/lib/blocks.mjs +90 -0
  556. package/lib/colors.ts +86 -0
  557. package/lib/contactBar.ts +18 -0
  558. package/lib/cookieCategories.d.mts +17 -0
  559. package/lib/cookieCategories.mjs +28 -0
  560. package/lib/crop.d.mts +34 -0
  561. package/lib/crop.mjs +83 -0
  562. package/lib/csp.d.mts +22 -0
  563. package/lib/csp.mjs +130 -0
  564. package/lib/cspSources.d.mts +24 -0
  565. package/lib/cspSources.mjs +60 -0
  566. package/lib/dynamic-colors.ts +426 -0
  567. package/lib/git.d.mts +24 -0
  568. package/lib/git.mjs +64 -0
  569. package/lib/hooks.ts +51 -0
  570. package/lib/inline.ts +20 -0
  571. package/lib/license-texts/Apache-2.0.txt +191 -0
  572. package/lib/license-texts/BSD-2-Clause.txt +24 -0
  573. package/lib/license-texts/BSD-3-Clause.txt +28 -0
  574. package/lib/license-texts/ISC.txt +15 -0
  575. package/lib/license-texts/MIT.txt +21 -0
  576. package/lib/licenses.d.mts +190 -0
  577. package/lib/licenses.mjs +683 -0
  578. package/lib/markdown.ts +42 -0
  579. package/lib/motion-schemes.d.mts +2 -0
  580. package/lib/motion-schemes.mjs +5 -0
  581. package/lib/motion.ts +131 -0
  582. package/lib/notice.d.mts +3 -0
  583. package/lib/notice.mjs +34 -0
  584. package/lib/scheduled.d.mts +15 -0
  585. package/lib/scheduled.mjs +37 -0
  586. package/lib/snackbar.ts +149 -0
  587. package/lib/status.d.mts +7 -0
  588. package/lib/status.mjs +18 -0
  589. package/lib/svg.d.mts +22 -0
  590. package/lib/svg.mjs +231 -0
  591. package/lib/text-colors.d.mts +11 -0
  592. package/lib/text-colors.mjs +43 -0
  593. package/lib/video-id.d.mts +14 -0
  594. package/lib/video-id.mjs +72 -0
  595. package/lib/video.d.mts +20 -0
  596. package/lib/video.mjs +91 -0
  597. package/package.json +131 -6
  598. package/pages/404.astro +10 -0
  599. package/pages/[...slug].astro +51 -0
  600. package/pages/_headers.txt +31 -0
  601. package/pages/blog/index.astro +10 -0
  602. package/pages/blog/kategori/[category].astro +18 -0
  603. package/pages/editor/code-images.json.js +25 -0
  604. package/pages/editor/index.astro +75 -0
  605. package/pages/editor/manifest.webmanifest.js +23 -0
  606. package/pages/editor/sw.js +33 -0
  607. package/pages/editor/sw.js.js +4 -0
  608. package/pages/editor/thumbnails.json.js +21 -0
  609. package/pages/editor/version.json.js +22 -0
  610. package/pages/headers.js +4 -0
  611. package/pages/index.astro +10 -0
  612. package/pages/ny.astro +6 -0
  613. package/pages/robots.txt.js +3 -0
  614. package/pages/rss.xml.js +20 -0
  615. package/scripts/app-screenshots.mjs +164 -0
  616. package/scripts/app-workers.mjs +6 -0
  617. package/scripts/bin.mjs +12 -0
  618. package/scripts/built-site.mjs +99 -0
  619. package/scripts/check-consent.mjs +113 -0
  620. package/scripts/check-content.mjs +149 -0
  621. package/scripts/check-demo.mjs +24 -0
  622. package/scripts/check-themes.mjs +45 -0
  623. package/scripts/check-worker.mjs +569 -0
  624. package/scripts/compare-html.mjs +81 -0
  625. package/scripts/demo-site.mjs +42 -0
  626. package/scripts/editor-icons.mjs +56 -0
  627. package/scripts/editor-roundtrip.mjs +134 -0
  628. package/scripts/editor-screens.mjs +101 -0
  629. package/scripts/git-env.mjs +9 -0
  630. package/scripts/icon-packs.mjs +151 -0
  631. package/scripts/link-counts.mjs +22 -0
  632. package/scripts/page-colors.mjs +42 -0
  633. package/scripts/releases.d.mts +10 -0
  634. package/scripts/releases.mjs +80 -0
  635. package/scripts/responsive-images.mjs +94 -0
  636. package/scripts/scheduled-list.mjs +15 -0
  637. package/scripts/theme-screenshots.mjs +88 -0
  638. package/scripts/types.mjs +21 -0
  639. package/scripts/video-thumbnails.mjs +89 -0
  640. package/scripts/worker-modules.mjs +34 -0
  641. package/site/appCookies.d.mts +9 -0
  642. package/site/appCookies.mjs +74 -0
  643. package/site/apps.ts +21 -0
  644. package/site/autolinks.d.mts +11 -0
  645. package/site/autolinks.mjs +200 -0
  646. package/site/blockScripts.ts +31 -0
  647. package/site/categories.ts +16 -0
  648. package/site/consent.ts +26 -0
  649. package/site/content.config.ts +84 -0
  650. package/site/content.ts +104 -0
  651. package/site/cookieList.ts +17 -0
  652. package/site/defineSite.d.mts +142 -0
  653. package/site/defineSite.mjs +136 -0
  654. package/site/directives/interact.d.mts +2 -0
  655. package/site/directives/interact.mjs +31 -0
  656. package/site/editor-version.d.mts +1 -0
  657. package/site/editor-version.mjs +26 -0
  658. package/site/fill.ts +13 -0
  659. package/site/format.ts +11 -0
  660. package/site/home.ts +66 -0
  661. package/site/iconPacks.d.mts +20 -0
  662. package/site/iconPacks.mjs +43 -0
  663. package/site/icons.d.mts +693 -0
  664. package/site/icons.mjs +605 -0
  665. package/site/images.d.mts +43 -0
  666. package/site/images.mjs +157 -0
  667. package/site/motion.ts +13 -0
  668. package/site/noindex.d.mts +6 -0
  669. package/site/noindex.mjs +21 -0
  670. package/site/pageColors.ts +110 -0
  671. package/site/popups.ts +98 -0
  672. package/site/schema.ts +189 -0
  673. package/site/sections.ts +3 -0
  674. package/site/seo.ts +28 -0
  675. package/site/site.ts +76 -0
  676. package/site/siteConfig.d.mts +1 -0
  677. package/site/siteConfig.mjs +8 -0
  678. package/site/siteCsp.d.mts +10 -0
  679. package/site/siteCsp.mjs +75 -0
  680. package/site/siteModules.d.mts +7 -0
  681. package/site/siteModules.mjs +27 -0
  682. package/site/standardPages.ts +59 -0
  683. package/site/testimonials.ts +48 -0
  684. package/site/text.ts +43 -0
  685. package/site/theme.d.mts +83 -0
  686. package/site/theme.mjs +472 -0
  687. package/site/tracking.client.ts +225 -0
  688. package/site/tracking.ts +9 -0
  689. package/src/ActionParts.tsx +205 -0
  690. package/src/Advanced.tsx +152 -0
  691. package/src/App.tsx +904 -0
  692. package/src/AppList.tsx +1345 -0
  693. package/src/BlockDialog.tsx +360 -0
  694. package/src/BlockParts.tsx +652 -0
  695. package/src/BlockSettings.tsx +533 -0
  696. package/src/BrandForm.tsx +164 -0
  697. package/src/Colors.tsx +476 -0
  698. package/src/CommunicationParts.tsx +199 -0
  699. package/src/CompanyForm.tsx +209 -0
  700. package/src/Consents.tsx +175 -0
  701. package/src/ContainmentParts.tsx +185 -0
  702. package/src/Crop.tsx +152 -0
  703. package/src/DataForm.tsx +434 -0
  704. package/src/Deleted.tsx +177 -0
  705. package/src/EntryForm.tsx +740 -0
  706. package/src/FileView.tsx +30 -0
  707. package/src/FormFrame.tsx +237 -0
  708. package/src/Keywords.tsx +225 -0
  709. package/src/Library.tsx +1563 -0
  710. package/src/Licenses.tsx +336 -0
  711. package/src/LinkSheet.tsx +138 -0
  712. package/src/MarkdownEditor.tsx +1075 -0
  713. package/src/Media.tsx +677 -0
  714. package/src/NavigationParts.tsx +350 -0
  715. package/src/NavigationRestParts.tsx +247 -0
  716. package/src/Notifications.tsx +59 -0
  717. package/src/PagePicker.tsx +136 -0
  718. package/src/Parts.tsx +991 -0
  719. package/src/PartsShown.tsx +168 -0
  720. package/src/PickerParts.tsx +183 -0
  721. package/src/Redirects.tsx +450 -0
  722. package/src/Screen.tsx +184 -0
  723. package/src/SectionsField.tsx +65 -0
  724. package/src/SelectionParts.tsx +134 -0
  725. package/src/SeoScores.tsx +184 -0
  726. package/src/Sheet.tsx +35 -0
  727. package/src/ThemeStore.tsx +376 -0
  728. package/src/Tokens.tsx +346 -0
  729. package/src/Versions.tsx +214 -0
  730. package/src/addresses.ts +75 -0
  731. package/src/allIcons.ts +7 -0
  732. package/src/appFiles.ts +29 -0
  733. package/src/apps.ts +281 -0
  734. package/src/ask.tsx +123 -0
  735. package/src/blocks.ts +251 -0
  736. package/src/brand.ts +153 -0
  737. package/src/cache.ts +42 -0
  738. package/src/check.ts +285 -0
  739. package/src/checkSite.ts +256 -0
  740. package/src/consents.ts +26 -0
  741. package/src/cookieList.ts +70 -0
  742. package/src/countries.ts +59 -0
  743. package/src/deploy.ts +155 -0
  744. package/src/editor.css +602 -0
  745. package/src/examples.ts +85 -0
  746. package/src/fields.tsx +942 -0
  747. package/src/frontmatter.d.mts +6 -0
  748. package/src/frontmatter.mjs +42 -0
  749. package/src/github.ts +376 -0
  750. package/src/i18n/da-DK/advanced.ts +28 -0
  751. package/src/i18n/da-DK/app.ts +71 -0
  752. package/src/i18n/da-DK/apps.ts +90 -0
  753. package/src/i18n/da-DK/blockSettings.ts +38 -0
  754. package/src/i18n/da-DK/blocks.ts +408 -0
  755. package/src/i18n/da-DK/check.ts +25 -0
  756. package/src/i18n/da-DK/colors.ts +64 -0
  757. package/src/i18n/da-DK/common.ts +118 -0
  758. package/src/i18n/da-DK/company.ts +24 -0
  759. package/src/i18n/da-DK/consents.ts +23 -0
  760. package/src/i18n/da-DK/forms.ts +116 -0
  761. package/src/i18n/da-DK/history.ts +35 -0
  762. package/src/i18n/da-DK/index.ts +49 -0
  763. package/src/i18n/da-DK/keywords.ts +19 -0
  764. package/src/i18n/da-DK/library.ts +135 -0
  765. package/src/i18n/da-DK/licenses.ts +25 -0
  766. package/src/i18n/da-DK/media.ts +79 -0
  767. package/src/i18n/da-DK/parts.ts +696 -0
  768. package/src/i18n/da-DK/preview.ts +13 -0
  769. package/src/i18n/da-DK/redirects.ts +51 -0
  770. package/src/i18n/da-DK/seo.ts +20 -0
  771. package/src/i18n/da-DK/text.ts +35 -0
  772. package/src/i18n/da-DK/theme.ts +41 -0
  773. package/src/i18n/en-US/advanced.ts +32 -0
  774. package/src/i18n/en-US/app.ts +84 -0
  775. package/src/i18n/en-US/apps.ts +134 -0
  776. package/src/i18n/en-US/blockSettings.ts +48 -0
  777. package/src/i18n/en-US/blocks.ts +441 -0
  778. package/src/i18n/en-US/check.ts +31 -0
  779. package/src/i18n/en-US/colors.ts +82 -0
  780. package/src/i18n/en-US/common.ts +144 -0
  781. package/src/i18n/en-US/company.ts +25 -0
  782. package/src/i18n/en-US/consents.ts +25 -0
  783. package/src/i18n/en-US/forms.ts +145 -0
  784. package/src/i18n/en-US/history.ts +43 -0
  785. package/src/i18n/en-US/index.ts +51 -0
  786. package/src/i18n/en-US/keywords.ts +24 -0
  787. package/src/i18n/en-US/library.ts +176 -0
  788. package/src/i18n/en-US/licenses.ts +36 -0
  789. package/src/i18n/en-US/media.ts +80 -0
  790. package/src/i18n/en-US/parts.ts +718 -0
  791. package/src/i18n/en-US/preview.ts +15 -0
  792. package/src/i18n/en-US/redirects.ts +66 -0
  793. package/src/i18n/en-US/seo.ts +26 -0
  794. package/src/i18n/en-US/text.ts +41 -0
  795. package/src/i18n/en-US/theme.ts +41 -0
  796. package/src/i18n/index.ts +124 -0
  797. package/src/icon.tsx +160 -0
  798. package/src/iconPacks.ts +89 -0
  799. package/src/images.ts +163 -0
  800. package/src/licenses.ts +79 -0
  801. package/src/markdown.d.mts +12 -0
  802. package/src/markdown.mjs +204 -0
  803. package/src/nav.ts +68 -0
  804. package/src/notFound.ts +28 -0
  805. package/src/notifications.ts +223 -0
  806. package/src/pagePreview.tsx +204 -0
  807. package/src/r2Caching.ts +55 -0
  808. package/src/redirects.ts +149 -0
  809. package/src/registry.tsx +188 -0
  810. package/src/schema.ts +417 -0
  811. package/src/sections.d.mts +45 -0
  812. package/src/sections.mjs +303 -0
  813. package/src/seo.ts +333 -0
  814. package/src/shared.ts +44 -0
  815. package/src/sidebar.ts +31 -0
  816. package/src/site.ts +317 -0
  817. package/src/standard/Block.astro +19 -0
  818. package/src/standard/BlockSite.astro +18 -0
  819. package/src/standard/accordion/index.tsx +47 -0
  820. package/src/standard/accordion/load.ts +23 -0
  821. package/src/standard/accordion/shared.ts +15 -0
  822. package/src/standard/accordion/view.ts +32 -0
  823. package/src/standard/buttons/fields.ts +98 -0
  824. package/src/standard/buttons/index.tsx +23 -0
  825. package/src/standard/buttons/load.ts +34 -0
  826. package/src/standard/buttons/shared.ts +12 -0
  827. package/src/standard/buttons/view.ts +30 -0
  828. package/src/standard/cards/index.tsx +71 -0
  829. package/src/standard/cards/load.ts +17 -0
  830. package/src/standard/cards/shared.ts +27 -0
  831. package/src/standard/cards/view.ts +29 -0
  832. package/src/standard/checklist/index.tsx +27 -0
  833. package/src/standard/checklist/load.ts +5 -0
  834. package/src/standard/checklist/view.ts +13 -0
  835. package/src/standard/cookies/index.tsx +17 -0
  836. package/src/standard/cookies/list.ts +56 -0
  837. package/src/standard/cookies/load.ts +11 -0
  838. package/src/standard/cookies/shared.ts +20 -0
  839. package/src/standard/cookies/view.ts +28 -0
  840. package/src/standard/faq/index.tsx +29 -0
  841. package/src/standard/faq/load.ts +14 -0
  842. package/src/standard/faq/view.ts +21 -0
  843. package/src/standard/head.ts +23 -0
  844. package/src/standard/hero/fields.ts +48 -0
  845. package/src/standard/hero/index.tsx +57 -0
  846. package/src/standard/hero/load.ts +23 -0
  847. package/src/standard/hero/view.ts +38 -0
  848. package/src/standard/links/index.tsx +41 -0
  849. package/src/standard/links/load.ts +17 -0
  850. package/src/standard/links/view.ts +25 -0
  851. package/src/standard/list/index.tsx +50 -0
  852. package/src/standard/list/load.ts +5 -0
  853. package/src/standard/list/view.ts +18 -0
  854. package/src/standard/load.ts +7 -0
  855. package/src/standard/notice/index.tsx +30 -0
  856. package/src/standard/notice/load.ts +16 -0
  857. package/src/standard/notice/view.ts +10 -0
  858. package/src/standard/points/index.tsx +42 -0
  859. package/src/standard/points/load.ts +5 -0
  860. package/src/standard/points/view.ts +12 -0
  861. package/src/standard/posts/index.tsx +132 -0
  862. package/src/standard/posts/load.ts +36 -0
  863. package/src/standard/posts/shared.ts +21 -0
  864. package/src/standard/posts/view.ts +63 -0
  865. package/src/standard/pricecards/index.tsx +57 -0
  866. package/src/standard/pricecards/load.ts +11 -0
  867. package/src/standard/pricecards/view.ts +50 -0
  868. package/src/standard/sharedTexts.ts +6 -0
  869. package/src/standard/site.ts +124 -0
  870. package/src/standard/siteLooks.ts +19 -0
  871. package/src/standard/sites.ts +13 -0
  872. package/src/standard/steps/index.tsx +28 -0
  873. package/src/standard/steps/load.ts +5 -0
  874. package/src/standard/steps/view.ts +11 -0
  875. package/src/standard/testimonials/index.tsx +87 -0
  876. package/src/standard/testimonials/list.ts +43 -0
  877. package/src/standard/testimonials/load.ts +58 -0
  878. package/src/standard/testimonials/shared.ts +13 -0
  879. package/src/standard/testimonials/view.ts +76 -0
  880. package/src/standard/themeBlocks.ts +13 -0
  881. package/src/standard/video/index.tsx +23 -0
  882. package/src/standard/video/load.ts +10 -0
  883. package/src/standard/video/view.ts +42 -0
  884. package/src/standard/view.tsx +105 -0
  885. package/src/standard/views.ts +37 -0
  886. package/src/store.ts +499 -0
  887. package/src/theme.ts +90 -0
  888. package/src/themeUi.ts +97 -0
  889. package/src/themes.ts +91 -0
  890. package/src/ui.tsx +3402 -0
  891. package/src/virtual.d.ts +5 -0
  892. package/src/when.ts +22 -0
  893. package/starter/.githooks/pre-push +4 -0
  894. package/starter/.nvmrc +1 -0
  895. package/starter/.prettierignore +11 -0
  896. package/starter/.prettierrc.json +7 -0
  897. package/starter/README.md +26 -0
  898. package/starter/astro.config.mjs +5 -0
  899. package/starter/package.json +67 -0
  900. package/starter/public/_redirects +1 -0
  901. package/starter/public/apple-touch-icon.png +0 -0
  902. package/starter/public/editor/apple-touch-icon.png +0 -0
  903. package/starter/public/editor/icon-192.png +0 -0
  904. package/starter/public/editor/icon-512.png +0 -0
  905. package/starter/public/editor/icon-maskable-512.png +0 -0
  906. package/starter/public/favicon.ico +0 -0
  907. package/starter/public/favicon.svg +1 -0
  908. package/starter/public/logo.svg +1 -0
  909. package/starter/src/content/pages/blog.md +8 -0
  910. package/starter/src/content/pages/forside.md +9 -0
  911. package/starter/src/content/pages/kontakt.md +7 -0
  912. package/starter/src/content/pages/privatlivspolitik.md +9 -0
  913. package/starter/src/content/pages/siden-findes-ikke.md +7 -0
  914. package/starter/src/content.config.ts +2 -0
  915. package/starter/src/data/apps.json +1 -0
  916. package/starter/src/data/block-settings.json +3 -0
  917. package/starter/src/data/blocks.json +1 -0
  918. package/starter/src/data/booking.json +6 -0
  919. package/starter/src/data/colors.json +70 -0
  920. package/starter/src/data/contact.json +8 -0
  921. package/starter/src/data/cookies.json +21 -0
  922. package/starter/src/data/csp.json +1 -0
  923. package/starter/src/data/footer.json +15 -0
  924. package/starter/src/data/internal-links.json +4 -0
  925. package/starter/src/data/menu.json +4 -0
  926. package/starter/src/data/mobile-menu.json +4 -0
  927. package/starter/src/data/old-addresses.json +1 -0
  928. package/starter/src/data/redirects.json +1 -0
  929. package/starter/src/data/standard-pages.json +8 -0
  930. package/starter/src/data/theme.json +1 -0
  931. package/starter/src/env.d.ts +2 -0
  932. package/starter/src/site/config.ts +13 -0
  933. package/starter/src/site/worker.js +14 -0
  934. package/starter/tsconfig.json +17 -0
  935. package/starter/worker/apps.js +6 -0
  936. package/starter/wrangler.jsonc +39 -0
  937. package/theme/LICENSE +21 -0
  938. package/theme/blocks/ArrowLink.tsx +14 -0
  939. package/theme/blocks/BlockHead.tsx +26 -0
  940. package/theme/blocks/Panel.tsx +32 -0
  941. package/theme/blocks/Person.tsx +26 -0
  942. package/theme/blocks/accordion/PageRow.tsx +25 -0
  943. package/theme/blocks/accordion/View.tsx +17 -0
  944. package/theme/blocks/buttons/Buttons.tsx +28 -0
  945. package/theme/blocks/buttons/View.tsx +12 -0
  946. package/theme/blocks/cards/LinkCards.tsx +72 -0
  947. package/theme/blocks/cards/View.tsx +20 -0
  948. package/theme/blocks/checklist/Checks.tsx +15 -0
  949. package/theme/blocks/checklist/View.tsx +14 -0
  950. package/theme/blocks/cookies/View.tsx +36 -0
  951. package/theme/blocks/faq/Accordion.tsx +34 -0
  952. package/theme/blocks/faq/View.tsx +16 -0
  953. package/theme/blocks/faq/script.ts +56 -0
  954. package/theme/blocks/hero/View.tsx +44 -0
  955. package/theme/blocks/links/LinkGroups.tsx +24 -0
  956. package/theme/blocks/links/View.tsx +17 -0
  957. package/theme/blocks/list/Rows.tsx +24 -0
  958. package/theme/blocks/list/View.tsx +14 -0
  959. package/theme/blocks/notice/View.tsx +13 -0
  960. package/theme/blocks/points/PointList.tsx +34 -0
  961. package/theme/blocks/points/View.tsx +14 -0
  962. package/theme/blocks/posts/View.tsx +26 -0
  963. package/theme/blocks/pricecards/View.tsx +40 -0
  964. package/theme/blocks/steps/StepList.tsx +23 -0
  965. package/theme/blocks/steps/View.tsx +14 -0
  966. package/theme/blocks/testimonials/List.tsx +46 -0
  967. package/theme/blocks/testimonials/Slider.tsx +44 -0
  968. package/theme/blocks/testimonials/Testimonial.tsx +124 -0
  969. package/theme/blocks/testimonials/View.tsx +21 -0
  970. package/theme/blocks/testimonials/script.ts +52 -0
  971. package/theme/blocks/video/View.tsx +41 -0
  972. package/theme/components/ActionBar.astro +63 -0
  973. package/theme/components/AppSlot.astro +21 -0
  974. package/theme/components/ArrowLink.tsx +21 -0
  975. package/theme/components/BlogIndex.astro +48 -0
  976. package/theme/components/BlogPosts.astro +18 -0
  977. package/theme/components/BlogPosts.tsx +45 -0
  978. package/theme/components/BookButton.tsx +22 -0
  979. package/theme/components/Container.astro +11 -0
  980. package/theme/components/CookieConsent.astro +121 -0
  981. package/theme/components/EndBlock.astro +21 -0
  982. package/theme/components/FontPreload.astro +6 -0
  983. package/theme/components/Footer.astro +85 -0
  984. package/theme/components/Header.astro +186 -0
  985. package/theme/components/Icon.astro +16 -0
  986. package/theme/components/Img.astro +29 -0
  987. package/theme/components/Img.tsx +33 -0
  988. package/theme/components/Inline.astro +11 -0
  989. package/theme/components/Logo.astro +23 -0
  990. package/theme/components/LogoMark.astro +10 -0
  991. package/theme/components/Markdown.astro +17 -0
  992. package/theme/components/MobileMenu.tsx +224 -0
  993. package/theme/components/MobileNav.astro +33 -0
  994. package/theme/components/PageHeader.astro +22 -0
  995. package/theme/components/PageSection.astro +24 -0
  996. package/theme/components/PhoneButton.tsx +11 -0
  997. package/theme/components/Popup.astro +145 -0
  998. package/theme/components/PopupButton.tsx +24 -0
  999. package/theme/components/PopupView.tsx +48 -0
  1000. package/theme/components/PostList.tsx +58 -0
  1001. package/theme/components/PostMeta.tsx +17 -0
  1002. package/theme/components/RichText.astro +28 -0
  1003. package/theme/components/Section.astro +29 -0
  1004. package/theme/components/SectionHeading.tsx +8 -0
  1005. package/theme/components/TextSection.astro +16 -0
  1006. package/theme/components/home/PageBlock.astro +19 -0
  1007. package/theme/components/home/Text.astro +13 -0
  1008. package/theme/components/loadPopup.ts +22 -0
  1009. package/theme/components/loadPosts.ts +16 -0
  1010. package/theme/components/posts.ts +15 -0
  1011. package/theme/editor/looks.mjs +7 -0
  1012. package/theme/editor/previews.tsx +56 -0
  1013. package/theme/layouts/Base.astro +273 -0
  1014. package/theme/layouts/PageLayout.astro +126 -0
  1015. package/theme/layouts/PostLayout.astro +137 -0
  1016. package/theme/screenshots/1-front.jpg +0 -0
  1017. package/theme/screenshots/2-front-dark.jpg +0 -0
  1018. package/theme/screenshots/3-blog.jpg +0 -0
  1019. package/theme/screenshots/4-contact.jpg +0 -0
  1020. package/theme/scripts/motion.ts +29 -0
  1021. package/theme/styles/base.css +320 -0
  1022. package/theme/styles/blocks.css +1808 -0
  1023. package/theme/styles/components.css +206 -0
  1024. package/theme/styles/global.css +1302 -0
  1025. package/theme/styles/ui.css +6544 -0
  1026. package/theme/templates/Blog.astro +38 -0
  1027. package/theme/templates/Category.astro +19 -0
  1028. package/theme/templates/Home.astro +36 -0
  1029. package/theme/templates/New.astro +68 -0
  1030. package/theme/templates/NotFound.astro +117 -0
  1031. package/theme/theme.json +28 -0
  1032. package/theme/ui/Badge.tsx +45 -0
  1033. package/theme/ui/BottomSheet.tsx +148 -0
  1034. package/theme/ui/Button.tsx +79 -0
  1035. package/theme/ui/ButtonGroup.tsx +31 -0
  1036. package/theme/ui/Card.tsx +45 -0
  1037. package/theme/ui/Carousel.tsx +124 -0
  1038. package/theme/ui/Checkbox.tsx +59 -0
  1039. package/theme/ui/Chip.tsx +101 -0
  1040. package/theme/ui/ChipSet.tsx +27 -0
  1041. package/theme/ui/DatePicker.tsx +149 -0
  1042. package/theme/ui/DatePickerContainer.tsx +316 -0
  1043. package/theme/ui/Dialog.tsx +100 -0
  1044. package/theme/ui/Divider.tsx +27 -0
  1045. package/theme/ui/ExposedDropdownMenu.tsx +77 -0
  1046. package/theme/ui/Fab.tsx +88 -0
  1047. package/theme/ui/FabMenu.tsx +67 -0
  1048. package/theme/ui/IconButton.tsx +78 -0
  1049. package/theme/ui/List.tsx +287 -0
  1050. package/theme/ui/LoadingIndicator.tsx +29 -0
  1051. package/theme/ui/Menu.tsx +278 -0
  1052. package/theme/ui/NavigationBar.tsx +62 -0
  1053. package/theme/ui/NavigationDrawer.tsx +80 -0
  1054. package/theme/ui/NavigationRail.tsx +154 -0
  1055. package/theme/ui/ProgressIndicator.tsx +162 -0
  1056. package/theme/ui/RadioButton.tsx +50 -0
  1057. package/theme/ui/Search.tsx +129 -0
  1058. package/theme/ui/SegmentedButton.tsx +49 -0
  1059. package/theme/ui/SideSheet.tsx +54 -0
  1060. package/theme/ui/Slider.tsx +155 -0
  1061. package/theme/ui/Snackbar.tsx +67 -0
  1062. package/theme/ui/SplitButton.tsx +67 -0
  1063. package/theme/ui/Switch.tsx +60 -0
  1064. package/theme/ui/Tabs.tsx +114 -0
  1065. package/theme/ui/TextField.tsx +278 -0
  1066. package/theme/ui/TimePicker.tsx +128 -0
  1067. package/theme/ui/TimePickerContainer.tsx +234 -0
  1068. package/theme/ui/Toolbar.tsx +67 -0
  1069. package/theme/ui/Tooltip.tsx +58 -0
  1070. package/theme/ui/TopAppBar.tsx +77 -0
  1071. package/theme/ui/bottomSheet.script.ts +8 -0
  1072. package/theme/ui/bottomSheet.ts +211 -0
  1073. package/theme/ui/carousel.script.ts +28 -0
  1074. package/theme/ui/carouselLayout.ts +229 -0
  1075. package/theme/ui/checkbox.script.ts +8 -0
  1076. package/theme/ui/datePicker.script.ts +302 -0
  1077. package/theme/ui/dates.ts +185 -0
  1078. package/theme/ui/dialog.ts +48 -0
  1079. package/theme/ui/dropdownMenu.script.ts +166 -0
  1080. package/theme/ui/fabMenu.script.ts +57 -0
  1081. package/theme/ui/navigationRail.script.ts +47 -0
  1082. package/theme/ui/ripple.script.ts +159 -0
  1083. package/theme/ui/search.script.ts +92 -0
  1084. package/theme/ui/sideSheet.ts +48 -0
  1085. package/theme/ui/slider.script.ts +12 -0
  1086. package/theme/ui/sliderUpdate.ts +52 -0
  1087. package/theme/ui/snackbar.script.ts +16 -0
  1088. package/theme/ui/splitButton.script.ts +63 -0
  1089. package/theme/ui/tabs.script.ts +48 -0
  1090. package/theme/ui/textField.script.ts +17 -0
  1091. package/theme/ui/textFieldUpdate.ts +44 -0
  1092. package/theme/ui/timePicker.script.ts +248 -0
  1093. package/theme/ui/toolbar.script.ts +43 -0
  1094. package/theme/ui/tooltip.script.ts +68 -0
  1095. package/worker/consent.js +141 -0
  1096. package/worker/editor-github.js +167 -0
  1097. package/worker/editor-host.js +74 -0
  1098. package/worker/files.js +401 -0
  1099. package/worker/github.js +36 -0
  1100. package/worker/index.js +184 -0
  1101. package/worker/not-found.js +97 -0
  1102. package/worker/oauth.js +95 -0
  1103. package/worker/publish.js +52 -0
  1104. package/worker/push.js +270 -0
  1105. package/worker/r2-status.js +50 -0
  1106. package/worker/session.js +58 -0
@@ -0,0 +1,42 @@
1
+ // The CMS's demo site: a made-up site about Morpheme itself, with pages, blog posts, pictures and settings of its
2
+ // own, and nothing of any real site's. It is the starter (starter/, the site a new site begins with) with demo/ laid on
3
+ // top: demo/ holds only what differs (its pages and posts, the data files it changes, its src/site/ parts, its logo,
4
+ // icons and pictures), so the two cannot drift apart. demoSite() puts it in a folder of its own with one of the site's
5
+ // themes, ready to build: the pictures of the themes are taken of it (theme-screenshots.mjs), so a theme is never shown
6
+ // with a site's own content. `morpheme check:demo` builds it with the standard theme and checks its content
7
+ // (check-demo.mjs), so it keeps up with the CMS.
8
+ import { cpSync, mkdirSync, mkdtempSync, symlinkSync, writeFileSync } from 'node:fs';
9
+ import { join, relative, sep } from 'node:path';
10
+ import { fileURLToPath } from 'node:url';
11
+ import { execFileSync } from 'node:child_process';
12
+ import { STANDARD_THEME, themeFolder } from '@morphemecms/cms/site/theme.mjs';
13
+
14
+ const STARTER = fileURLToPath(new URL('../starter/', import.meta.url));
15
+ const DEMO = fileURLToPath(new URL('../demo/', import.meta.url));
16
+
17
+ /** The demo site in a new folder, with the theme (a folder in the site's src/themes/, or the standard theme) as its theme,
18
+ * the site's packages and its pictures' smaller sizes (`morpheme images`), from the site at `root`. Its folder;
19
+ * the caller deletes it. */
20
+ export function demoSite(theme = STANDARD_THEME, root = process.cwd()) {
21
+ // In the site's .morpheme/ (git-ignored), not the system's temporary folder: Astro takes a file in a folder that has
22
+ // no folder in common with the site's root (the CMS's theme) as one in the root. Not in node_modules/ either, where Node
23
+ // runs no TypeScript.
24
+ const cache = join(root, '.morpheme/demo');
25
+ mkdirSync(cache, { recursive: true });
26
+ const dir = mkdtempSync(join(cache, `${theme}-`));
27
+ // The starter's site without its pages (the demo has its own, at other addresses), then the demo over it.
28
+ const content = join(STARTER, 'src/content');
29
+ cpSync(STARTER, dir, {
30
+ recursive: true,
31
+ filter: (from) => !(from + sep).startsWith(content + sep) && !relative(STARTER, from).startsWith('node_modules'),
32
+ });
33
+ cpSync(DEMO, dir, { recursive: true });
34
+ if (theme !== STANDARD_THEME) cpSync(join(root, themeFolder(theme)), join(dir, 'src/themes', theme), { recursive: true });
35
+ writeFileSync(join(dir, 'src/data/theme.json'), `${JSON.stringify({ theme }, null, 2)}\n`);
36
+ // The site's packages: its node_modules/ (a junction, which Windows makes without the rights a symbolic link needs). The
37
+ // starter's package.json names them, as a site's does, which Astro reads to know which packages to build with the site.
38
+ symlinkSync(join(root, 'node_modules'), join(dir, 'node_modules'), 'junction');
39
+ for (const script of ['responsive-images', 'video-thumbnails'])
40
+ execFileSync(process.execPath, [fileURLToPath(new URL(`${script}.mjs`, import.meta.url))], { cwd: dir, stdio: 'inherit' });
41
+ return dir;
42
+ }
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+ // The PNG icons (the editor's app icons in public/editor/, the site's public/apple-touch-icon.png and
3
+ // public/favicon.ico), made from the mark in public/favicon.svg on the site's background colour
4
+ // (light mode, src/data/colors.json). Run again only if the favicon changes:
5
+ // npx morpheme editor-icons
6
+ // icon-192/512: the icon on Android and in the browser; maskable: Android may crop it to a circle,
7
+ // so the mark keeps inside the middle 60 %; apple-touch-icon: the iPhone home screen (the editor's
8
+ // and the site's); favicon.ico: for browsers and programs that ask for /favicon.ico, not the SVG.
9
+ import fs from 'node:fs/promises';
10
+ import path from 'node:path';
11
+ import sharp from 'sharp';
12
+
13
+ const ROOT = process.cwd();
14
+ const OUT = path.join(ROOT, 'public');
15
+ const favicon = await fs.readFile(path.join(ROOT, 'public/favicon.svg'), 'utf8');
16
+ const mark = favicon.match(/<svg x="[^>]*viewBox="([^"]+)">([\s\S]*?)<\/svg>/);
17
+ const BG = JSON.parse(await fs.readFile(path.join(ROOT, 'src/data/colors.json'), 'utf8')).light.bg;
18
+
19
+ // size: the mark's share of the icon's width.
20
+ const icon = (size) => {
21
+ const [, , vw, vh] = mark[1].split(/[\s,]+/).map(Number);
22
+ const w = 64 * size;
23
+ const h = w * (vh / vw);
24
+ return Buffer.from(
25
+ `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect width="64" height="64" fill="${BG}"/>` +
26
+ `<svg x="${(64 - w) / 2}" y="${(64 - h) / 2}" width="${w}" height="${h}" viewBox="${mark[1]}">${mark[2]}</svg></svg>`,
27
+ );
28
+ };
29
+
30
+ const png = (px, size) =>
31
+ sharp(icon(size), { density: 72 * (px / 64) * 2 })
32
+ .resize(px, px)
33
+ .png()
34
+ .toBuffer();
35
+
36
+ for (const [name, px, size] of [
37
+ ['editor/icon-192.png', 192, 0.7],
38
+ ['editor/icon-512.png', 512, 0.7],
39
+ ['editor/icon-maskable-512.png', 512, 0.5],
40
+ ['editor/apple-touch-icon.png', 180, 0.66],
41
+ ['apple-touch-icon.png', 180, 0.66],
42
+ ]) {
43
+ await fs.writeFile(path.join(OUT, name), await png(px, size));
44
+ }
45
+
46
+ // An ICO file with one 32 px PNG in it (as packages/editor/src/brand.ts makes it).
47
+ const image = await png(32, 0.75);
48
+ const head = Buffer.alloc(22);
49
+ head.writeUInt16LE(1, 2); // an icon
50
+ head.writeUInt16LE(1, 4); // one picture
51
+ head[6] = head[7] = 32; // width and height
52
+ head.writeUInt16LE(1, 10); // colour planes
53
+ head.writeUInt16LE(32, 12); // bits per pixel
54
+ head.writeUInt32LE(image.length, 14);
55
+ head.writeUInt32LE(22, 18); // where the picture starts
56
+ await fs.writeFile(path.join(OUT, 'favicon.ico'), Buffer.concat([head, image]));
@@ -0,0 +1,134 @@
1
+ // Checks that the editor (/editor/) can save every page and blog post without changing the site:
2
+ // each body is loaded into Milkdown and written back, and both versions are rendered with Astro's
3
+ // Markdown pipeline. The HTML must be the same. The front matter, written back without changes, must
4
+ // be the same text. The fixed pages (src/data/*.json with sections) are loaded as their text with the
5
+ // sections as blocks (packages/editor/src/sections.mjs) and read back: the sections must be the same, a section
6
+ // of text with the same heading and the same HTML. Every page is also read into sections as the front page (as the
7
+ // site reads the page that is the front page without the editor, partsOfMarkdown in sections.mjs, packages/editor/site/home.ts):
8
+ // they must be those the editor reads. Run: npm run check:editor [files...]
9
+ // Milkdown needs a DOM; jsdom stands in for the browser.
10
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
11
+ import { join } from 'node:path';
12
+ import { JSDOM } from 'jsdom';
13
+
14
+ const dom = new JSDOM('<!doctype html><html><body></body></html>', { pretendToBeVisual: true });
15
+ globalThis.window = dom.window;
16
+ for (const key of [
17
+ 'document',
18
+ 'Node',
19
+ 'Element',
20
+ 'HTMLElement',
21
+ 'MutationObserver',
22
+ 'getComputedStyle',
23
+ 'requestAnimationFrame',
24
+ 'DOMParser',
25
+ 'Event',
26
+ 'CustomEvent',
27
+ ])
28
+ globalThis[key] = dom.window[key];
29
+ for (const key of ['addEventListener', 'removeEventListener', 'dispatchEvent']) globalThis[key] = dom.window[key].bind(dom.window);
30
+
31
+ const { editorViewCtx } = await import('@milkdown/kit/core');
32
+ const { createMarkdownProcessor } = await import('@astrojs/markdown-remark');
33
+ const { makeEditor, markdownOf, partsOf, spacing } = await import('@morphemecms/cms/src/markdown.mjs');
34
+ const { introOf, partsOfMarkdown, sectionsFromParts, sectionsToMarkdown } = await import('@morphemecms/cms/src/sections.mjs');
35
+ const { withSiteModules } = await import('../site/siteModules.mjs');
36
+ // The field of the sections of each fixed page (@site/collections): the sections whose text is written
37
+ // above their card (their lead), and the page's introduction above them (intro).
38
+ const [{ frontLeads }, { collections }] = await withSiteModules((load) =>
39
+ Promise.all([load('@site/standardPages'), load('@site/collections')]),
40
+ );
41
+ const { leadsOfField } = await import('@morphemecms/cms/src/sections.mjs');
42
+ const textOf = Object.fromEntries(
43
+ collections
44
+ .filter((c) => c.kind === 'files')
45
+ .flatMap((c) => c.files)
46
+ .map((f) => [f.file, f.fields.find((x) => x.type === 'blocks')]),
47
+ );
48
+ const { splitFrontmatter, writeFields } = await import('@morphemecms/cms/src/frontmatter.mjs');
49
+
50
+ const walk = (dir) =>
51
+ (existsSync(dir) ? readdirSync(dir, { withFileTypes: true }) : []).flatMap((e) =>
52
+ e.isDirectory() ? walk(join(dir, e.name)) : e.name.endsWith('.md') ? [join(dir, e.name)] : [],
53
+ );
54
+ const fixed = readdirSync('src/data')
55
+ .filter((f) => f.endsWith('.json') && JSON.parse(readFileSync(join('src/data', f), 'utf8')).sections)
56
+ .map((f) => join('src/data', f));
57
+ const files = process.argv.length > 2 ? process.argv.slice(2) : [...walk('src/content/blog'), ...walk('src/content/pages'), ...fixed];
58
+
59
+ const processor = await createMarkdownProcessor();
60
+ const render = async (md) => (await processor.render(md)).code.replace(/\s+/g, ' ').trim();
61
+
62
+ let failed = 0;
63
+ // A fixed page's introduction and sections, as the editor reads them back.
64
+ async function sectionsBack(sections, intro, field) {
65
+ const leads = leadsOfField(field);
66
+ const editor = await makeEditor(
67
+ document.createElement('div'),
68
+ sectionsToMarkdown(sections, leads, field?.intro ? intro : undefined),
69
+ ).create();
70
+ let parts = editor.action(partsOf);
71
+ let back = '';
72
+ if (field?.intro) [back, parts] = introOf(parts);
73
+ await editor.destroy();
74
+ return [back, sectionsFromParts(parts, leads)];
75
+ }
76
+ // The text of a section of text, and of the front page's top, as HTML.
77
+ const comparable = async (intro, sections) =>
78
+ JSON.stringify([
79
+ intro ?? '',
80
+ ...(await Promise.all(
81
+ sections.map(async (s) =>
82
+ s.type === 'text' ? { ...s, body: await render(s.body) } : s.type === 'hero' ? { ...s, text: await render(s.text) } : s,
83
+ ),
84
+ )),
85
+ ]);
86
+
87
+ for (const file of files) {
88
+ if (file.endsWith('.json')) {
89
+ const { sections, intro } = JSON.parse(readFileSync(file, 'utf8'));
90
+ const field = textOf[file];
91
+ const [before, after] = [
92
+ await comparable(field?.intro ? intro : '', sections),
93
+ await comparable(...(await sectionsBack(sections, intro, field))),
94
+ ];
95
+ if (before === after) continue;
96
+ failed++;
97
+ console.log(`\n✗ ${file}\n før: ${before.slice(0, 300)}\n efter: ${after.slice(0, 300)}`);
98
+ continue;
99
+ }
100
+ const { yaml, body } = splitFrontmatter(readFileSync(file, 'utf8'));
101
+ if (writeFields(yaml, {}) !== yaml) {
102
+ failed++;
103
+ console.log(`\n✗ ${file}\n front matter skrives ikke tilbage uændret`);
104
+ continue;
105
+ }
106
+ const root = document.createElement('div');
107
+ // As in the editor: with the free lines between the blocks, written without them.
108
+ const editor = await makeEditor(root, body).use(spacing).create();
109
+ editor.action((ctx) => ctx.get(editorViewCtx).dispatch(ctx.get(editorViewCtx).state.tr));
110
+ const saved = editor.action(markdownOf);
111
+ const parts = editor.action(partsOf);
112
+ await editor.destroy();
113
+ if (file.includes('src/content/pages/')) {
114
+ const [editors, site] = [
115
+ await comparable('', sectionsFromParts(parts, frontLeads)),
116
+ await comparable('', sectionsFromParts(partsOfMarkdown(body), frontLeads)),
117
+ ];
118
+ if (editors !== site) {
119
+ failed++;
120
+ console.log(`\n✗ ${file} som forside\n editoren: ${editors.slice(0, 300)}\n sitet: ${site.slice(0, 300)}`);
121
+ continue;
122
+ }
123
+ }
124
+ const [before, after] = [await render(body), await render(saved)];
125
+ if (before === after) continue;
126
+ failed++;
127
+ let i = 0;
128
+ while (before[i] === after[i]) i++;
129
+ console.log(
130
+ `\n✗ ${file}\n før: …${before.slice(Math.max(0, i - 80), i + 120)}\n efter: …${after.slice(Math.max(0, i - 80), i + 120)}`,
131
+ );
132
+ }
133
+ console.log(`\n${files.length - failed} af ${files.length} filer giver samme side efter en gem i editoren.`);
134
+ process.exit(failed ? 1 : 0);
@@ -0,0 +1,101 @@
1
+ // Opens every screen of the editor (/editor/) in a browser, on a phone and on a computer, and fails
2
+ // when one breaks: an error on the page, something its Content-Security-Policy stopped, an empty app, or a link to an
3
+ // address with nothing on it, or an icon that is not found (drawn as the question mark, data-icon-missing: Svg in
4
+ // packages/editor/src/icon.tsx), there or on one of the built site's pages.
5
+ // The screens are found as the editor's own links: from the start screen (and "Indstillinger", #indstillinger, "Dele", #udseende/dele, "Temaer",
6
+ // #udseende/temaer, "Søgemaskineoptimering", #seo, and "Appstore", #indstillinger/appstore), and
7
+ // from each screen it opens, two steps down. GitHub is answered from the files in this repository, so it needs no login
8
+ // and changes nothing. It runs on the built site: npm run build && npm run check:screens (or on another
9
+ // folder with a built site, its path after the command: packages/editor/scripts/check-themes.mjs).
10
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
11
+ import { join, relative, resolve } from 'node:path';
12
+ import { chromium } from 'playwright';
13
+ import { openEditor, serveBuilt } from './built-site.mjs';
14
+
15
+ const ROOT = `${process.cwd()}/`;
16
+ const DIST = resolve(ROOT, process.argv[2] ?? 'dist');
17
+ if (!existsSync(join(DIST, 'editor/index.html'))) {
18
+ console.error(`Der er intet bygget site i ${DIST}. Kør npm run build først.`);
19
+ process.exit(1);
20
+ }
21
+
22
+ const missingIcon = (name) =>
23
+ name
24
+ ? `ikonet "${name}" findes ikke (et spørgsmålstegn i stedet): skriv det i packages/editor/src/icon.tsx`
25
+ : 'et ikon er ikke en SVG-fil (et spørgsmålstegn i stedet)';
26
+
27
+ // The icons not found on the built site's pages: each one once, with the pages it is on.
28
+ const problems = [];
29
+ const missingOn = new Map();
30
+ for (const entry of readdirSync(DIST, { recursive: true, withFileTypes: true })) {
31
+ if (!entry.isFile() || !entry.name.endsWith('.html')) continue;
32
+ const file = join(entry.parentPath, entry.name);
33
+ for (const [, name] of readFileSync(file, 'utf8').matchAll(/data-icon-missing="([^"]*)"/g))
34
+ missingOn.set(name, new Set([...(missingOn.get(name) ?? []), `/${relative(DIST, file)}`]));
35
+ }
36
+ for (const [name, pages] of missingOn) {
37
+ const shown = [...pages].slice(0, 3).join(', ');
38
+ problems.push(`${shown}${pages.size > 3 ? ` og ${pages.size - 3} sider til` : ''}: ${missingIcon(name)}`);
39
+ }
40
+
41
+ const { server, site } = await serveBuilt(DIST);
42
+
43
+ // CHROMIUM_PATH: another Chromium than Playwright's own (one installed for another version of Playwright).
44
+ const browser = await chromium.launch({ executablePath: process.env.CHROMIUM_PATH || undefined });
45
+ // The screens opened (each on both).
46
+ const opened = new Set();
47
+
48
+ for (const [width, height] of [
49
+ [390, 844],
50
+ [1280, 900],
51
+ ]) {
52
+ const page = await browser.newPage({ viewport: { width, height }, locale: 'da-DK' });
53
+ let route = '';
54
+ page.on('pageerror', (e) => problems.push(`${width}px #${route}: ${e.message}`));
55
+ // Something the page's Content-Security-Policy stopped (packages/editor/lib/csp.mjs).
56
+ page.on('console', (m) => {
57
+ if (m.type() === 'error' && /Content Security Policy/i.test(m.text())) problems.push(`${width}px #${route}: ${m.text()}`);
58
+ });
59
+ await openEditor(page, site);
60
+
61
+ // From the start screen, and from "Indstillinger" (the gear in the top bar), "Dele", "Temaer",
62
+ // "Søgemaskineoptimering" and "Appstore" (the apps' pages and their developers'), whose screens are a step further
63
+ // down than the others.
64
+ const starts = ['', 'indstillinger', 'udseende/dele', 'udseende/temaer', 'seo', 'indstillinger/appstore'];
65
+ const seen = new Set(starts);
66
+ let next = starts;
67
+ for (let depth = 0; depth <= 2 && next.length; depth++) {
68
+ const found = [];
69
+ for (const hash of next) {
70
+ route = hash;
71
+ await page.evaluate((h) => (location.hash = h), hash);
72
+ await page.waitForTimeout(150);
73
+ opened.add(hash);
74
+ const state = await page.evaluate(() => ({
75
+ empty: !document.querySelector('astro-island')?.textContent?.trim(),
76
+ text: document.body.innerText,
77
+ links: [...document.querySelectorAll('a[href^="#"]')].map((a) => a.getAttribute('href').slice(1)),
78
+ missing: [...document.querySelectorAll('[data-icon-missing]')].map((e) => e.getAttribute('data-icon-missing')),
79
+ }));
80
+ for (const name of new Set(state.missing)) problems.push(`${width}px #${hash}: ${missingIcon(name)}`);
81
+ if (state.empty) problems.push(`${width}px #${hash}: skærmen er tom`);
82
+ if (state.text.includes(`Der er ikke noget på adressen ${hash}.`))
83
+ problems.push(`${width}px #${hash}: der er ikke noget på adressen`);
84
+ for (const link of state.links) {
85
+ if (seen.has(link)) continue;
86
+ seen.add(link);
87
+ found.push(link);
88
+ }
89
+ }
90
+ next = found;
91
+ }
92
+ await page.close();
93
+ }
94
+
95
+ await browser.close();
96
+ server.close();
97
+ if (problems.length) {
98
+ console.error(`${problems.length} fejl i editoren eller på sitet:\n${[...new Set(problems)].join('\n')}`);
99
+ process.exit(1);
100
+ }
101
+ console.log(`${opened.size} skærme i editoren åbner uden fejl, på en telefon og på en computer, og alle ikoner findes.`);
@@ -0,0 +1,9 @@
1
+ // The environment for git in a repository a script makes for itself. Git gives its hooks the variables that point a
2
+ // command at a repository (GIT_DIR, GIT_INDEX_FILE, GIT_WORK_TREE …; in a worktree always), so a check run from the
3
+ // pre-push hook would otherwise init, add and commit in the repository being pushed instead of its own.
4
+ import { execFileSync } from 'node:child_process';
5
+
6
+ // The variables, as this git names them.
7
+ const local = execFileSync('git', ['rev-parse', '--local-env-vars'], { encoding: 'utf8' }).split('\n').filter(Boolean);
8
+
9
+ export const ownRepoEnv = (env = process.env) => Object.fromEntries(Object.entries(env).filter(([name]) => !local.includes(name)));
@@ -0,0 +1,151 @@
1
+ // Writes the system's own icon packs (packages/editor/icons/<pack>/: Material Symbols, Phosphor and Lucide; SYSTEM_PACKS in
2
+ // packages/editor/site/iconPacks.mjs) from their sets' packages at the versions in PACK_SOURCES (packages/editor/site/icons.mjs): for each icon the
3
+ // site and the editor draw, by its Phosphor name (usedIcons: the site's in packages/editor/src/icon.tsx, which the
4
+ // content stores; the editor's as it imports them from @phosphor-icons/react and @phosphor-icons/core, found in the
5
+ // code; the app store's), the set's icon its map names (MATERIAL_SYMBOLS, LUCIDE; one the set has none of from
6
+ // Pictogrammers' Material Design Icons, MATERIAL_DESIGN_ICONS), as one <svg> with its viewBox, without a size or a colour
7
+ // of its own: Svg and the theme's Vite plugin (themePlugin in packages/editor/site/theme.mjs) give it those. Phosphor's are its files
8
+ // as they are (so a site with Phosphor's pack draws Phosphor's own icons, unchanged); Lucide's lines in a <g> with
9
+ // Lucide's stroke (`-fill`: filled in). Beside them the pack's manifest (pack.json: name, author, licence, and the icons
10
+ // from Material Design Icons under `includes`) and the licences (LICENSE, LICENSE-material-design-icons), from the
11
+ // packages. The files are committed, so neither an install nor the site's build needs the sets' packages.
12
+ //
13
+ // npm run icons (npm run icons)
14
+ //
15
+ // Run it after a new icon on the site or in the editor (check:content says which a pack has none for) or a new version
16
+ // of a set (PACK_SOURCES). It fetches the sets' packages at those versions itself, once, into node_modules/.cache/ (they
17
+ // are not in package.json, and large); Phosphor's is the site's own dependency.
18
+ import { execFileSync } from 'node:child_process';
19
+ import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
20
+ import { ICON_PACK_FILE, ICON_PACK_LICENSE, SYSTEM_PACKS } from '@morphemecms/cms/site/iconPacks.mjs';
21
+ import { packFolder } from '@morphemecms/cms/site/icons.mjs';
22
+ import { MATERIAL_DESIGN_ICONS, PACK_MAPS, PACK_SOURCES, phosphorFile, usedIcons } from '@morphemecms/cms/site/icons.mjs';
23
+
24
+ const MDI = 'material-design-icons';
25
+ const version = (spec) => spec.replace(/^.*@/, '');
26
+
27
+ // A set's package at its version, in a folder of its own, so the site's node_modules stays as package.json has it.
28
+ function fetched(spec) {
29
+ const cache = `node_modules/.cache/${spec.replace(/[/@]/g, '_')}`;
30
+ const pkg = `${cache}/node_modules/${spec.replace(/@[^@]*$/, '')}/`;
31
+ if (!existsSync(`${pkg}package.json`)) {
32
+ console.log(`Henter ${spec} til ${cache} …`);
33
+ mkdirSync(cache, { recursive: true });
34
+ // npm is npm.cmd on Windows, which execFileSync cannot start without a shell: npm's own script with Node, when npm
35
+ // runs this.
36
+ const npm = process.env.npm_execpath ? [process.execPath, process.env.npm_execpath] : ['npm'];
37
+ execFileSync(
38
+ npm[0],
39
+ [...npm.slice(1), 'install', '--prefix', cache, '--no-save', '--no-package-lock', '--no-audit', '--no-fund', spec],
40
+ {
41
+ stdio: 'inherit',
42
+ },
43
+ );
44
+ }
45
+ return pkg;
46
+ }
47
+
48
+ const used = [...usedIcons()].sort();
49
+ const phosphorPkg = 'node_modules/@phosphor-icons/core/';
50
+ const phosphorVersion = JSON.parse(readFileSync(`${phosphorPkg}package.json`, 'utf8')).version;
51
+ if (`@phosphor-icons/core@${phosphorVersion}` !== PACK_SOURCES.phosphor.package) {
52
+ console.error(
53
+ `@phosphor-icons/core er ${phosphorVersion}, ikke ${PACK_SOURCES.phosphor.package}: ret versionen i PACK_SOURCES (packages/editor/site/icons.mjs), eller installer den.`,
54
+ );
55
+ process.exit(1);
56
+ }
57
+ const pkgs = { phosphor: phosphorPkg };
58
+ for (const id of [...SYSTEM_PACKS, MDI]) pkgs[id] ??= fetched(PACK_SOURCES[id].package);
59
+
60
+ // An icon's file of a set by the set's own name.
61
+ const sourceFile = {
62
+ 'material-symbols': (icon) => `${pkgs['material-symbols']}outlined/${icon}.svg`,
63
+ lucide: (icon) => `${pkgs.lucide}icons/${icon.replace(/-fill$/, '')}.svg`,
64
+ [MDI]: (icon) => `${pkgs[MDI]}svg/${icon}.svg`,
65
+ };
66
+
67
+ // One <svg> with the file's viewBox and what is in it, without comments, a size or a class of its own.
68
+ function bare(file, wrap = (inner) => inner) {
69
+ const svg = readFileSync(file, 'utf8').replace(/<!--[\s\S]*?-->/g, '');
70
+ const viewBox = svg.match(/\bviewBox="([^"]*)"/)?.[1];
71
+ const inner = svg.match(/^\s*<svg\b[^>]*>([\s\S]*)<\/svg>\s*$/)?.[1];
72
+ if (!viewBox || !inner) throw new Error(`${file} er ikke ét <svg> med en viewBox.`);
73
+ return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBox}">${wrap(inner)}</svg>\n`;
74
+ }
75
+ // Lucide's lines, in the text's colour as lines (its own <svg> has the stroke); `-fill` filled in.
76
+ const lines = (fill) => (inner) =>
77
+ `<g fill="${fill ? 'currentColor' : 'none'}" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${inner.replace(/\s+/g, ' ').trim()}</g>`;
78
+
79
+ // What each pack's files are, by Phosphor's name: its set's, and those from Material Design Icons.
80
+ function sourcesOf(id) {
81
+ if (id === 'phosphor') return used.map((name) => ({ name, text: () => phosphorFile(name) }));
82
+ const map = PACK_MAPS[id];
83
+ const mdi = MATERIAL_DESIGN_ICONS[id] ?? {};
84
+ return [
85
+ ...Object.entries(map).map(([name, icon]) => {
86
+ const file = sourceFile[id](icon);
87
+ return { name, icon, file, text: () => bare(file, id === 'lucide' ? lines(icon.endsWith('-fill')) : undefined) };
88
+ }),
89
+ ...Object.entries(mdi).map(([name, icon]) => {
90
+ const file = sourceFile[MDI](icon);
91
+ return { name, icon, file, text: () => bare(file) };
92
+ }),
93
+ ];
94
+ }
95
+
96
+ const problems = [];
97
+ for (const id of SYSTEM_PACKS) {
98
+ const sources = sourcesOf(id);
99
+ const names = sources.map((s) => s.name);
100
+ const missing = used.filter((name) => !names.includes(name));
101
+ if (missing.length)
102
+ problems.push(
103
+ `${PACK_SOURCES[id].name} har intet ikon for ${missing.join(', ')} i packages/editor/site/icons.mjs: skriv det, der passer (et, sættet intet har af, i MATERIAL_DESIGN_ICONS).`,
104
+ );
105
+ for (const { name, icon, file } of sources)
106
+ if (file && !existsSync(file)) problems.push(`${PACK_SOURCES[id].name} har intet "${icon}" (for ${name}).`);
107
+ if (id === 'phosphor') for (const name of used) if (!phosphorFile(name)) problems.push(`Phosphor har intet "${name}".`);
108
+ }
109
+ if (problems.length) {
110
+ for (const p of problems) console.error(p);
111
+ process.exit(1);
112
+ }
113
+
114
+ for (const id of SYSTEM_PACKS) {
115
+ const dir = `${packFolder(id)}/`;
116
+ rmSync(dir, { recursive: true, force: true });
117
+ mkdirSync(dir, { recursive: true });
118
+ for (const { name, text } of sourcesOf(id)) writeFileSync(`${dir}${name}.svg`, text());
119
+ const { name, author, license, url, package: spec } = PACK_SOURCES[id];
120
+ const mdi = Object.keys(MATERIAL_DESIGN_ICONS[id] ?? {}).sort();
121
+ const manifest = {
122
+ name,
123
+ author,
124
+ license,
125
+ url,
126
+ version: version(spec),
127
+ source: spec,
128
+ ...(mdi.length
129
+ ? {
130
+ includes: [
131
+ {
132
+ name: PACK_SOURCES[MDI].name,
133
+ author: PACK_SOURCES[MDI].author,
134
+ license: PACK_SOURCES[MDI].license,
135
+ url: PACK_SOURCES[MDI].url,
136
+ version: version(PACK_SOURCES[MDI].package),
137
+ source: PACK_SOURCES[MDI].package,
138
+ licenseFile: `${ICON_PACK_LICENSE}-${MDI}`,
139
+ icons: mdi,
140
+ },
141
+ ],
142
+ }
143
+ : {}),
144
+ };
145
+ writeFileSync(`${dir}${ICON_PACK_FILE}`, `${JSON.stringify(manifest, null, 2)}\n`);
146
+ writeFileSync(`${dir}${ICON_PACK_LICENSE}`, `${readFileSync(`${pkgs[id]}LICENSE`, 'utf8').trim()}\n`);
147
+ if (mdi.length) writeFileSync(`${dir}${ICON_PACK_LICENSE}-${MDI}`, `${readFileSync(`${pkgs[MDI]}LICENSE`, 'utf8').trim()}\n`);
148
+ console.log(
149
+ `${readdirSync(dir).filter((f) => f.endsWith('.svg')).length} ikoner fra ${spec}${mdi.length ? ` og ${PACK_SOURCES[MDI].package}` : ''} i ${dir}.`,
150
+ );
151
+ }
@@ -0,0 +1,22 @@
1
+ // After the build: how many pages and posts each keyword links from (packages/editor/site/autolinks.mjs gives its links
2
+ // data-link="auto"), in dist/editor/links.json, for "Søgeord" under "Interne links" in the editor (Keywords.tsx):
3
+ // { words: { "<word in lower case>": { href, pages } } }, counted in the built pages, without the new versions under
4
+ // /ny/ and the editor. A keyword without links is not in it.
5
+ import { readFileSync, readdirSync, writeFileSync } from 'node:fs';
6
+ import { join } from 'node:path';
7
+ import { isPreview } from '@morphemecms/cms/site/noindex.mjs';
8
+
9
+ const ROOT = `${process.cwd()}/`;
10
+ const DIST = join(ROOT, process.argv[2] ?? 'dist');
11
+ const LINK = /<a href="([^"]+)" data-link="auto">([^<]+)<\/a>/g;
12
+ const words = {};
13
+ for (const file of readdirSync(DIST, { recursive: true, encoding: 'utf8' }).filter((f) => f.endsWith('index.html'))) {
14
+ const path = `/${file.replace(/index\.html$/, '')}`;
15
+ if (path.startsWith('/editor/') || isPreview(path)) continue;
16
+ for (const [, href, text] of readFileSync(join(DIST, file), 'utf8').matchAll(LINK)) {
17
+ const word = text.toLowerCase();
18
+ words[word] ??= { href, pages: 0 };
19
+ words[word].pages++;
20
+ }
21
+ }
22
+ writeFileSync(join(DIST, 'editor', 'links.json'), `${JSON.stringify({ words })}\n`);
@@ -0,0 +1,42 @@
1
+ // After the build: each page's colours as it was built, in dist/editor/page-colors.json, for "Farver" › "Sider" in the
2
+ // editor (Colors.tsx), while an app changes the pages' colours (hooks/page-colors.ts):
3
+ // { pages: [{ path, light: { bg, … }, dark: { … }, app?, picture? }] }, by address, read from the <style> Base.astro
4
+ // writes them in (data-page-colors, colorsCss in packages/editor/lib/colors.ts: light mode on :root, dark mode on
5
+ // :root[data-theme='dark']), with the app that changed them and the picture they came from (data-app, data-picture;
6
+ // packages/editor/site/pageColors.ts), without them for a page with the site's own. Without the new versions under /ny/ and the editor.
7
+ import { readFileSync, readdirSync, writeFileSync } from 'node:fs';
8
+ import { join } from 'node:path';
9
+ import { isPreview } from '@morphemecms/cms/site/noindex.mjs';
10
+
11
+ const ROOT = `${process.cwd()}/`;
12
+ const DIST = join(ROOT, process.argv[2] ?? 'dist');
13
+ const STYLE = /<style\b([^>]*\bdata-page-colors\b[^>]*)>([^<]*)<\/style>/;
14
+ const LIGHT = /:root\{([^}]*)\}/;
15
+ const DARK = /:root\[data-theme='dark'\]\{([^}]*)\}/;
16
+
17
+ const attribute = (attributes, name) => {
18
+ const value = new RegExp(`\\b${name}="([^"]*)"`).exec(attributes)?.[1];
19
+ return value && value.replaceAll('&amp;', '&').replaceAll('&quot;', '"').replaceAll('&#39;', "'");
20
+ };
21
+ const declarations = (css) =>
22
+ Object.fromEntries([...(css ?? '').matchAll(/--([a-z][a-z0-9-]*):(#[0-9a-f]{6});/gi)].map(([, name, value]) => [name, value]));
23
+
24
+ const pages = [];
25
+ for (const file of readdirSync(DIST, { recursive: true, encoding: 'utf8' }).filter((f) => f.endsWith('index.html'))) {
26
+ const path = `/${file.replace(/index\.html$/, '')}`;
27
+ if (path.startsWith('/editor/') || isPreview(path)) continue;
28
+ const style = STYLE.exec(readFileSync(join(DIST, file), 'utf8'));
29
+ if (!style) continue;
30
+ const [, attributes, css] = style;
31
+ const app = attribute(attributes, 'data-app');
32
+ const picture = attribute(attributes, 'data-picture');
33
+ pages.push({
34
+ path,
35
+ light: declarations(LIGHT.exec(css)?.[1]),
36
+ dark: declarations(DARK.exec(css)?.[1]),
37
+ ...(app && { app }),
38
+ ...(picture && { picture }),
39
+ });
40
+ }
41
+ pages.sort((a, b) => a.path.localeCompare(b.path));
42
+ writeFileSync(join(DIST, 'editor', 'page-colors.json'), `${JSON.stringify({ pages })}\n`);
@@ -0,0 +1,10 @@
1
+ /** The versions that can follow one: its next patch, minor and major release ("1.2.1": 1.2.2, 1.3.0, 2.0.0). */
2
+ export function nextVersions(version: any): string[];
3
+ /** Whether a folder is not as its entry in the catalog has it (another file, one more or one less). */
4
+ export function changedSince(folder: any, entry: any): any;
5
+ /** What is wrong with the version of an app or a theme of the store against what the catalog has released of it.
6
+ * `item`: `kind` ('apps' or 'themes'), `id`, `folder`, `version`, `notes` (its release notes by version, one object
7
+ * for each language it writes them in, by the language: [[null, notes]] for an app) and `where` (the file with its
8
+ * version). One never released can have any version. */
9
+ export function releaseProblems(catalog: any, item: any): string[];
10
+ export function notesOf(releaseNotes: any, byLanguage: any): any[][];