@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/icons.mjs CHANGED
@@ -1,605 +1,605 @@
1
- // The icons the site and the editor draw, by Phosphor's names (usedIcons), and the icon packs that draw them (the
2
- // folders, packages/editor/site/iconPacks.mjs): which packs there are (installedPacks), each one's icons (packIcons) and what is
3
- // wrong with one (packProblems). The system's own packs (SYSTEM_PACKS: Material Symbols, Phosphor and Lucide, in
4
- // packages/editor/icons/<pack>/) are written by packages/editor/scripts/icon-packs.mjs (`npm run icons`) from their sets' packages at the versions in
5
- // PACK_SOURCES, by the maps here: Phosphor's name → the set's icon, chosen for what it means where it is used (by its own
6
- // name in the set, else by what it shows: Phosphor's `browser`, a window with a bar at the top, is Material Symbols'
7
- // `web`). An icon a set has none of (a brand's logo; Lucide has none) is Pictogrammers' Material Design Icons'
8
- // (MATERIAL_DESIGN_ICONS), with its licence beside the pack's own. check:content stops at a pack without an icon the
9
- // site or the editor draws (themeProblems and iconPackProblems in packages/editor/site/theme.mjs).
10
- import { existsSync, readdirSync, readFileSync } from 'node:fs';
11
- import { join, relative } from 'node:path';
12
- import { fileURLToPath, pathToFileURL } from 'node:url';
13
- import { cleanSvg } from '@morphemecms/cms/lib/svg.mjs';
14
- import { ICON_PACK_FILE, ICON_PACK_LICENSE, SYSTEM_PACKS, THEME_PACKS_FOLDER, themePackId } from './iconPacks.mjs';
15
-
16
- // The site's root (the working directory) and this package's.
17
- const root = pathToFileURL(`${process.cwd()}/`);
18
- const pkg = new URL('../', import.meta.url);
19
- /** Whether the system packs are written here (`npm run icons`, where the CMS is made: this package is the site's own
20
- * packages/editor/, not in node_modules/ and not outside the site, as for the CMS's demo): only there can it be said that
21
- * a pack has icons nothing draws, since the apps of the store and the site that makes the CMS draw them too. */
22
- const packsWrittenHere = (() => {
23
- const path = relative(fileURLToPath(root), fileURLToPath(pkg));
24
- return !path.startsWith('..') && !path.split(/[\\/]/).includes('node_modules');
25
- })();
26
-
27
- /** Where the system's own packs are, one folder each (this package's icons/), from the site's root. */
28
- export const SYSTEM_PACKS_FOLDER = relative(process.cwd(), fileURLToPath(new URL('icons', pkg)));
29
-
30
- /** A pack's folder, from its id, from the site's root: a system pack's in this package, a theme's in its folder. */
31
- export const packFolder = (id) => {
32
- const [theme, pack] = id.split('/');
33
- return pack ? `src/themes/${theme}/${THEME_PACKS_FOLDER}/${pack}` : `${SYSTEM_PACKS_FOLDER}/${theme}`;
34
- };
35
- const PHOSPHOR = 'node_modules/@phosphor-icons/core/assets/';
36
- const has = (path) => existsSync(new URL(path, root));
37
-
38
- /** The packages the system's packs are written from, at the versions they are (not in package.json, so neither an
39
- * install nor the site's build fetches them; packages/editor/scripts/icon-packs.mjs fetches them into node_modules/.cache/), and what
40
- * their packs' manifests say of them. Phosphor's is the site's own dependency (the names, and its React icons), at the
41
- * version package-lock.json has; check:content stops when it is another. */
42
- export const PACK_SOURCES = {
43
- 'material-symbols': {
44
- package: '@material-symbols/svg-400@0.48.2',
45
- name: 'Material Symbols',
46
- author: 'Google',
47
- license: 'Apache-2.0',
48
- url: 'https://fonts.google.com/icons',
49
- },
50
- phosphor: {
51
- package: '@phosphor-icons/core@2.1.1',
52
- name: 'Phosphor',
53
- author: 'Phosphor Icons',
54
- license: 'MIT',
55
- url: 'https://phosphoricons.com',
56
- },
57
- lucide: {
58
- package: 'lucide-static@1.63.0',
59
- name: 'Lucide',
60
- author: 'Lucide Contributors',
61
- license: 'ISC',
62
- url: 'https://lucide.dev',
63
- },
64
- 'material-design-icons': {
65
- package: '@mdi/svg@7.4.47',
66
- name: 'Material Design Icons',
67
- author: 'Pictogrammers',
68
- license: 'Apache-2.0',
69
- url: 'https://pictogrammers.com/library/mdi/',
70
- },
71
- };
72
-
73
- /** For each system pack but Phosphor's (whose names they are): Phosphor's name → Material Design Icons' (the package in
74
- * PACK_SOURCES), for an icon the site or the editor draws that its set has none of. Material Symbols: a brand's logo (the
75
- * account logged in at GitHub, the SEO choices' Google) and the
76
- * things it has nothing that shows (binoculars, a hard disk, swatches, a scan frame, the arrows that widen and narrow
77
- * the Hero). Lucide, which draws no brands: the logos. */
78
- export const MATERIAL_DESIGN_ICONS = {
79
- 'material-symbols': {
80
- 'arrows-in-line-horizontal': 'arrow-collapse-horizontal',
81
- 'arrows-out-line-horizontal': 'arrow-expand-horizontal',
82
- binoculars: 'binoculars',
83
- 'github-logo': 'github',
84
- 'google-logo': 'google',
85
- 'hard-drives': 'harddisk',
86
- scan: 'scan-helper',
87
- swatches: 'palette-swatch',
88
- },
89
- lucide: {
90
- 'github-logo': 'github',
91
- 'google-logo': 'google',
92
- },
93
- };
94
-
95
- /** Phosphor's name → Material Symbols' (Outlined, weight 400; `-fill` the filled one), for every icon the site and the
96
- * editor draw (usedIcons) but those in MATERIAL_DESIGN_ICONS['material-symbols']. */
97
- export const MATERIAL_SYMBOLS = {
98
- 'address-book': 'contacts',
99
- 'app-window': 'web_asset',
100
- 'arrow-counter-clockwise': 'replay',
101
- 'arrow-down': 'arrow_downward',
102
- 'arrow-left': 'arrow_back',
103
- 'arrow-right': 'arrow_forward',
104
- 'arrow-square-out': 'open_in_new',
105
- 'arrow-u-up-left': 'undo',
106
- 'arrow-u-up-right': 'redo',
107
- 'arrow-up': 'arrow_upward',
108
- 'arrow-up-right': 'arrow_outward',
109
- 'arrows-down-up': 'swap_vert',
110
- article: 'article',
111
- bank: 'account_balance',
112
- bell: 'notifications',
113
- bicycle: 'pedal_bike',
114
- 'book-open': 'import_contacts',
115
- 'book-open-text': 'menu_book',
116
- browser: 'web',
117
- buildings: 'domain',
118
- bus: 'directions_bus',
119
- 'calendar-blank': 'calendar_today',
120
- 'calendar-check': 'event_available',
121
- car: 'directions_car',
122
- cards: 'cards_stack',
123
- 'caret-down': 'keyboard_arrow_down',
124
- 'caret-left': 'chevron_left',
125
- 'caret-right': 'chevron_right',
126
- 'caret-up': 'keyboard_arrow_up',
127
- certificate: 'license',
128
- 'chart-line-up': 'monitoring',
129
- chats: 'forum',
130
- check: 'check',
131
- 'check-circle': 'check_circle',
132
- circle: 'circle',
133
- 'circle-half': 'contrast',
134
- clock: 'schedule',
135
- 'clock-counter-clockwise': 'history',
136
- code: 'code',
137
- coffee: 'local_cafe',
138
- columns: 'view_column_2',
139
- cookie: 'cookie',
140
- copy: 'content_copy',
141
- 'credit-card': 'credit_card',
142
- 'currency-circle-dollar': 'paid',
143
- 'cursor-click': 'ads_click',
144
- database: 'database',
145
- desktop: 'desktop_windows',
146
- 'device-mobile': 'mobile',
147
- 'door-open': 'door_open',
148
- 'download-simple': 'download',
149
- 'envelope-simple': 'mail',
150
- eye: 'visibility',
151
- 'eye-slash': 'visibility_off',
152
- 'file-pdf': 'picture_as_pdf',
153
- 'file-text': 'description',
154
- 'file-video': 'video_file',
155
- 'file-zip': 'folder_zip',
156
- 'flower-lotus': 'spa',
157
- 'folder-simple': 'folder',
158
- funnel: 'filter_alt',
159
- gauge: 'speed',
160
- gear: 'settings',
161
- globe: 'language',
162
- 'graduation-cap': 'school',
163
- hammer: 'hardware',
164
- 'hand-heart': 'volunteer_activism',
165
- handshake: 'handshake',
166
- heart: 'favorite',
167
- house: 'home',
168
- image: 'image',
169
- 'image-square': 'image',
170
- info: 'info',
171
- keyboard: 'keyboard',
172
- leaf: 'eco',
173
- lifebuoy: 'support',
174
- lightbulb: 'lightbulb',
175
- 'link-break': 'link_off',
176
- 'link-simple': 'link',
177
- list: 'menu',
178
- 'list-bullets': 'format_list_bulleted',
179
- 'list-checks': 'checklist',
180
- 'list-numbers': 'format_list_numbered',
181
- 'lock-simple': 'lock',
182
- 'lock-simple-open': 'lock_open',
183
- 'magnifying-glass': 'search',
184
- 'map-pin': 'location_on',
185
- 'map-trifold': 'map',
186
- medal: 'military_tech',
187
- megaphone: 'campaign',
188
- minus: 'remove',
189
- moon: 'dark_mode',
190
- newspaper: 'newspaper',
191
- 'paint-brush-broad': 'brush',
192
- palette: 'palette',
193
- 'paper-plane-tilt': 'send',
194
- 'pencil-simple': 'edit',
195
- phone: 'call',
196
- 'play-fill': 'play_arrow-fill',
197
- plus: 'add',
198
- prohibit: 'block',
199
- 'puzzle-piece': 'extension',
200
- question: 'help',
201
- quotes: 'format_quote',
202
- rows: 'view_agenda',
203
- ruler: 'straighten',
204
- shapes: 'shapes',
205
- 'share-network': 'share',
206
- 'shield-check': 'verified_user',
207
- 'sidebar-simple': 'side_navigation',
208
- 'sign-out': 'logout',
209
- signpost: 'signpost',
210
- 'sliders-horizontal': 'tune',
211
- smiley: 'mood',
212
- sparkle: 'star_shine',
213
- square: 'square',
214
- 'square-half-bottom': 'call_to_action',
215
- 'squares-four': 'grid_view',
216
- sticker: 'brand_family',
217
- storefront: 'storefront',
218
- sun: 'light_mode',
219
- tag: 'sell',
220
- 'text-aa': 'match_case',
221
- 'text-align-left': 'format_align_left',
222
- 'text-b': 'format_bold',
223
- 'text-h-one': 'format_h1',
224
- 'text-h-three': 'format_h3',
225
- 'text-h-two': 'format_h2',
226
- 'text-italic': 'format_italic',
227
- 'text-t': 'title',
228
- ticket: 'confirmation_number',
229
- 'toggle-right': 'toggle_on',
230
- train: 'train',
231
- trash: 'delete',
232
- 'upload-simple': 'upload',
233
- user: 'person',
234
- 'user-circle': 'account_circle',
235
- users: 'group',
236
- 'users-three': 'groups',
237
- 'video-camera': 'videocam',
238
- warning: 'warning',
239
- 'warning-circle': 'error',
240
- 'wave-sine': 'animation',
241
- wheelchair: 'accessible',
242
- wrench: 'build',
243
- x: 'close',
244
- };
245
-
246
- /** Phosphor's name → Lucide's, for every icon the site and the editor draw (usedIcons) but those in
247
- * MATERIAL_DESIGN_ICONS.lucide. `-fill`: Lucide's outline filled in (Lucide has no filled icons). */
248
- export const LUCIDE = {
249
- 'address-book': 'book-user',
250
- 'app-window': 'app-window',
251
- 'arrow-counter-clockwise': 'rotate-ccw',
252
- 'arrow-down': 'arrow-down',
253
- 'arrow-left': 'arrow-left',
254
- 'arrow-right': 'arrow-right',
255
- 'arrow-square-out': 'external-link',
256
- 'arrow-u-up-left': 'undo-2',
257
- 'arrow-u-up-right': 'redo-2',
258
- 'arrow-up': 'arrow-up',
259
- 'arrow-up-right': 'arrow-up-right',
260
- 'arrows-down-up': 'arrow-down-up',
261
- 'arrows-in-line-horizontal': 'fold-horizontal',
262
- 'arrows-out-line-horizontal': 'unfold-horizontal',
263
- article: 'file-text',
264
- bank: 'landmark',
265
- bell: 'bell',
266
- bicycle: 'bike',
267
- binoculars: 'binoculars',
268
- 'book-open': 'book-open',
269
- 'book-open-text': 'book-open-text',
270
- browser: 'panel-top',
271
- buildings: 'building-2',
272
- bus: 'bus',
273
- 'calendar-blank': 'calendar',
274
- 'calendar-check': 'calendar-check',
275
- car: 'car',
276
- cards: 'gallery-vertical-end',
277
- 'caret-down': 'chevron-down',
278
- 'caret-left': 'chevron-left',
279
- 'caret-right': 'chevron-right',
280
- 'caret-up': 'chevron-up',
281
- certificate: 'award',
282
- 'chart-line-up': 'chart-line',
283
- chats: 'messages-square',
284
- check: 'check',
285
- 'check-circle': 'circle-check',
286
- circle: 'circle',
287
- 'circle-half': 'contrast',
288
- clock: 'clock',
289
- 'clock-counter-clockwise': 'history',
290
- code: 'code',
291
- coffee: 'coffee',
292
- columns: 'columns-2',
293
- cookie: 'cookie',
294
- copy: 'copy',
295
- 'credit-card': 'credit-card',
296
- 'currency-circle-dollar': 'circle-dollar-sign',
297
- 'cursor-click': 'mouse-pointer-click',
298
- database: 'database',
299
- desktop: 'monitor',
300
- 'device-mobile': 'smartphone',
301
- 'door-open': 'door-open',
302
- 'download-simple': 'download',
303
- 'envelope-simple': 'mail',
304
- eye: 'eye',
305
- 'eye-slash': 'eye-off',
306
- 'file-pdf': 'file-text',
307
- 'file-text': 'file-text',
308
- 'file-video': 'file-video-camera',
309
- 'file-zip': 'file-archive',
310
- 'flower-lotus': 'flower-2',
311
- 'folder-simple': 'folder',
312
- funnel: 'funnel',
313
- gauge: 'gauge',
314
- gear: 'settings',
315
- globe: 'globe',
316
- 'graduation-cap': 'graduation-cap',
317
- hammer: 'hammer',
318
- 'hand-heart': 'hand-heart',
319
- handshake: 'handshake',
320
- 'hard-drives': 'server',
321
- heart: 'heart',
322
- house: 'house',
323
- image: 'image',
324
- 'image-square': 'image',
325
- info: 'info',
326
- keyboard: 'keyboard',
327
- leaf: 'leaf',
328
- lifebuoy: 'life-buoy',
329
- lightbulb: 'lightbulb',
330
- 'link-break': 'unlink',
331
- 'link-simple': 'link',
332
- list: 'menu',
333
- 'list-bullets': 'list',
334
- 'list-checks': 'list-checks',
335
- 'list-numbers': 'list-ordered',
336
- 'lock-simple': 'lock',
337
- 'lock-simple-open': 'lock-open',
338
- 'magnifying-glass': 'search',
339
- 'map-pin': 'map-pin',
340
- 'map-trifold': 'map',
341
- medal: 'medal',
342
- megaphone: 'megaphone',
343
- minus: 'minus',
344
- moon: 'moon',
345
- newspaper: 'newspaper',
346
- 'paint-brush-broad': 'paintbrush',
347
- palette: 'palette',
348
- 'paper-plane-tilt': 'send',
349
- 'pencil-simple': 'pencil',
350
- phone: 'phone',
351
- 'play-fill': 'play-fill',
352
- plus: 'plus',
353
- prohibit: 'ban',
354
- 'puzzle-piece': 'puzzle',
355
- question: 'circle-question-mark',
356
- quotes: 'quote',
357
- rows: 'rows-2',
358
- ruler: 'ruler',
359
- scan: 'scan',
360
- shapes: 'shapes',
361
- 'share-network': 'share-2',
362
- 'shield-check': 'shield-check',
363
- 'sidebar-simple': 'panel-left',
364
- 'sign-out': 'log-out',
365
- signpost: 'signpost',
366
- 'sliders-horizontal': 'sliders-horizontal',
367
- smiley: 'smile',
368
- sparkle: 'sparkle',
369
- square: 'square',
370
- 'square-half-bottom': 'panel-bottom',
371
- 'squares-four': 'layout-grid',
372
- sticker: 'sticker',
373
- storefront: 'store',
374
- sun: 'sun',
375
- swatches: 'swatch-book',
376
- tag: 'tag',
377
- 'text-aa': 'case-sensitive',
378
- 'text-align-left': 'text-align-start',
379
- 'text-b': 'bold',
380
- 'text-h-one': 'heading-1',
381
- 'text-h-three': 'heading-3',
382
- 'text-h-two': 'heading-2',
383
- 'text-italic': 'italic',
384
- 'text-t': 'type',
385
- ticket: 'ticket',
386
- 'toggle-right': 'toggle-right',
387
- train: 'train-front',
388
- trash: 'trash-2',
389
- 'upload-simple': 'upload',
390
- user: 'user',
391
- 'user-circle': 'circle-user',
392
- users: 'users',
393
- 'users-three': 'users-round',
394
- 'video-camera': 'video',
395
- warning: 'triangle-alert',
396
- 'warning-circle': 'circle-alert',
397
- 'wave-sine': 'spline',
398
- wheelchair: 'accessibility',
399
- wrench: 'wrench',
400
- x: 'x',
401
- };
402
-
403
- /** Each system pack's map: Phosphor's name → its set's icon (Phosphor's: its own names, no map). */
404
- export const PACK_MAPS = { 'material-symbols': MATERIAL_SYMBOLS, lucide: LUCIDE };
405
-
406
- /** The names the system's pack has an icon by in its maps (its set's and Material Design Icons'); all for Phosphor's. */
407
- const mapped = (pack) => (PACK_MAPS[pack] ? [...Object.keys(PACK_MAPS[pack]), ...Object.keys(MATERIAL_DESIGN_ICONS[pack] ?? {})] : null);
408
-
409
- /** Whether a name is one the site and the editor draw an icon by: Phosphor's (regular, and the filled ones as
410
- * `<name>-fill`). A pack's file and a theme's own icon have one of them. */
411
- export const isIconName = (name) =>
412
- /^[a-z0-9-]+$/.test(name) && (has(`${PHOSPHOR}regular/${name}.svg`) || (name.endsWith('-fill') && has(`${PHOSPHOR}fill/${name}.svg`)));
413
-
414
- /** What is wrong with an icon's SVG file (`file` its path, for the message): one <svg> with a viewBox, with only what
415
- * draws in it (what cleanSvg keeps; the rest is left out where it is drawn). */
416
- export function svgProblems(file, svg) {
417
- const clean = cleanSvg(svg);
418
- if (!clean || svg.match(/<svg\b/gi).length > 1 || !clean.viewBox)
419
- return [`${file}: et ikon er ét <svg> med en viewBox og intet før eller efter.`];
420
- if (clean.removed.length)
421
- return [
422
- `${file}: ${clean.removed.join(', ')} tegner ikke og bliver ikke vist. Et ikon har kun tegning: ingen scripts, stil, hændelser (on…) eller noget, der hentes udefra.`,
423
- ];
424
- return [];
425
- }
426
-
427
- const folders = (dir) =>
428
- has(dir)
429
- ? readdirSync(new URL(dir, root), { withFileTypes: true })
430
- .filter((e) => e.isDirectory())
431
- .map((e) => e.name)
432
- : [];
433
-
434
- /** The icon packs there are, by id: the system's (packages/editor/icons/<pack>/) and those the themes installed bring
435
- * (src/themes/<theme>/icon-packs/<pack>/, as `<theme>/<pack>`), each a folder with its pack.json. */
436
- export function installedPacks() {
437
- const system = folders(`${SYSTEM_PACKS_FOLDER}/`).filter((p) => has(`${SYSTEM_PACKS_FOLDER}/${p}/${ICON_PACK_FILE}`));
438
- const themes = folders('src/themes/').flatMap((theme) =>
439
- folders(`src/themes/${theme}/${THEME_PACKS_FOLDER}/`)
440
- .filter((p) => has(`src/themes/${theme}/${THEME_PACKS_FOLDER}/${p}/${ICON_PACK_FILE}`))
441
- .map((p) => themePackId(theme, p)),
442
- );
443
- return [...system, ...themes];
444
- }
445
-
446
- /** A pack's icons as their files' text, by name (its <name>.svg). */
447
- export function packIcons(id) {
448
- const dir = `${packFolder(id)}/`;
449
- const icons = {};
450
- if (has(dir))
451
- for (const f of readdirSync(new URL(dir, root)))
452
- if (f.endsWith('.svg')) icons[f.slice(0, -'.svg'.length)] = readFileSync(new URL(dir + f, root), 'utf8');
453
- return icons;
454
- }
455
-
456
- /** Phosphor's own file of an icon by its name (regular, or `<name>-fill` filled), as its package has it; null for one it
457
- * does not have. */
458
- export function phosphorFile(name) {
459
- const file =
460
- name.endsWith('-fill') && has(`${PHOSPHOR}fill/${name}.svg`) ? `${PHOSPHOR}fill/${name}.svg` : `${PHOSPHOR}regular/${name}.svg`;
461
- return has(file) ? readFileSync(new URL(file, root), 'utf8') : null;
462
- }
463
-
464
- const isText = (x) => typeof x === 'string' && x.trim() !== '';
465
-
466
- /** What is wrong with an icon pack (`id`, as installedPacks gives it): its manifest (pack.json: name, author, license;
467
- * and for each set it takes icons from besides its own, `includes`, its name, author, license, licence file and icons),
468
- * its licences (LICENSE, and each `includes`' licenseFile), an icon the site or the editor draws (usedIcons) it has no
469
- * file for, a file that is not an icon by a name the site draws, and each icon's SVG (svgProblems). For a system pack,
470
- * also that it is written as its maps say (systemPackProblems). */
471
- export function packProblems(id, used = usedIcons()) {
472
- const dir = packFolder(id);
473
- const problems = [];
474
- let manifest = {};
475
- try {
476
- manifest = JSON.parse(readFileSync(new URL(`${dir}/${ICON_PACK_FILE}`, root), 'utf8'));
477
- } catch (e) {
478
- return [`${dir}/${ICON_PACK_FILE}: ${e.message}`];
479
- }
480
- for (const key of ['name', 'author', 'license'])
481
- if (!isText(manifest[key]))
482
- problems.push(`${dir}/${ICON_PACK_FILE}: "${key}" mangler (ikonpakkens navn, hvem der har lavet den, og dens licens).`);
483
- if (!has(`${dir}/${ICON_PACK_LICENSE}`)) problems.push(`${dir}/${ICON_PACK_LICENSE} mangler: ikonpakkens licens.`);
484
- const licences = new Set([ICON_PACK_LICENSE]);
485
- if (manifest.includes !== undefined && !Array.isArray(manifest.includes))
486
- problems.push(`${dir}/${ICON_PACK_FILE}: "includes" er en liste med de sæt, pakken har ikoner fra ud over sit eget.`);
487
- for (const x of Array.isArray(manifest.includes) ? manifest.includes : []) {
488
- const named = isText(x?.name) ? x.name : '?';
489
- if (!['name', 'author', 'license', 'licenseFile'].every((k) => isText(x?.[k])) || !Array.isArray(x.icons) || !x.icons.every(isText))
490
- problems.push(`${dir}/${ICON_PACK_FILE}: "includes" (${named}) skal have "name", "author", "license", "licenseFile" og "icons".`);
491
- else if (!/^LICENSE-[a-z0-9-]+$/.test(x.licenseFile) || !has(`${dir}/${x.licenseFile}`))
492
- problems.push(`${dir}/${x.licenseFile ?? ICON_PACK_LICENSE}: licensen for ${named} mangler (LICENSE-<sæt> i pakkens mappe).`);
493
- else licences.add(x.licenseFile);
494
- for (const name of Array.isArray(x?.icons) ? x.icons : [])
495
- if (!has(`${dir}/${name}.svg`)) problems.push(`${dir}/${ICON_PACK_FILE}: "includes" (${named}) nævner ${name}, som pakken ikke har.`);
496
- }
497
- const files = has(dir) ? readdirSync(new URL(`${dir}/`, root), { withFileTypes: true }) : [];
498
- for (const entry of files) {
499
- const file = `${dir}/${entry.name}`;
500
- if (entry.name === ICON_PACK_FILE || licences.has(entry.name)) continue;
501
- if (!entry.isFile() || !entry.name.endsWith('.svg')) {
502
- problems.push(`${file}: en ikonpakke har kun ${ICON_PACK_FILE}, sine licenser og ikoner (${dir}/<navn>.svg).`);
503
- continue;
504
- }
505
- const name = entry.name.slice(0, -'.svg'.length);
506
- if (!isIconName(name))
507
- problems.push(`${file}: sitet tegner intet ikon, der hedder "${name}". Et ikon hedder som i Phosphor (fx map-pin, play-fill).`);
508
- problems.push(...svgProblems(file, readFileSync(new URL(file, root), 'utf8')));
509
- }
510
- const missing = [...used].sort().filter((name) => !has(`${dir}/${name}.svg`));
511
- if (missing.length)
512
- problems.push(
513
- `Ikonpakken ${isText(manifest.name) ? manifest.name : id} (${dir}/) har intet ikon for ${missing.join(', ')}: ${
514
- SYSTEM_PACKS.includes(id)
515
- ? 'skriv det, der passer, i packages/editor/site/icons.mjs, og kør npm run icons.'
516
- : 'giv den et ikon ved hvert navn.'
517
- }`,
518
- );
519
- return [...problems, ...(SYSTEM_PACKS.includes(id) ? systemPackProblems(id, used) : [])];
520
- }
521
-
522
- /** What is wrong with a system pack beyond what every pack must be (packProblems): an icon the site or the editor draws
523
- * that its maps have none for (Phosphor's: one its package has none of), and where the packs are written, one they name
524
- * that is not written or a file they do not name (`npm run icons` writes it again), and Phosphor's package at another
525
- * version than its pack's. */
526
- function systemPackProblems(id, used) {
527
- const dir = packFolder(id);
528
- const problems = [];
529
- const names = mapped(id);
530
- if (!packsWrittenHere) {
531
- const unnamed = names ? [...used].sort().filter((name) => !names.includes(name)) : [];
532
- return unnamed.length ? [`${PACK_SOURCES[id].name} har intet ikon for ${unnamed.join(', ')}.`] : [];
533
- }
534
- if (names) {
535
- const map = id === 'material-symbols' ? 'MATERIAL_SYMBOLS' : 'LUCIDE';
536
- const unnamed = [...used].sort().filter((name) => !names.includes(name));
537
- if (unnamed.length)
538
- problems.push(
539
- `${PACK_SOURCES[id].name} har intet ikon for ${unnamed.join(', ')}: skriv det, der passer, i ${map} i packages/editor/site/icons.mjs (et, ${PACK_SOURCES[id].name} intet har af, i MATERIAL_DESIGN_ICONS), og kør npm run icons.`,
540
- );
541
- } else {
542
- const version = JSON.parse(readFileSync(new URL('node_modules/@phosphor-icons/core/package.json', root), 'utf8')).version;
543
- if (`@phosphor-icons/core@${version}` !== PACK_SOURCES.phosphor.package)
544
- problems.push(
545
- `@phosphor-icons/core er ${version}, men ikonpakken Phosphor er skrevet fra ${PACK_SOURCES.phosphor.package}: ret versionen i PACK_SOURCES i packages/editor/site/icons.mjs, og kør npm run icons.`,
546
- );
547
- }
548
- if (names) {
549
- const unused = names.filter((name) => !used.has(name)).sort();
550
- if (unused.length)
551
- problems.push(
552
- `packages/editor/site/icons.mjs: ${PACK_SOURCES[id].name}s kort har ${unused.join(', ')}, som sitet og editoren ikke tegner: tag dem ud, og kør npm run icons.`,
553
- );
554
- }
555
- const written = Object.keys(packIcons(id));
556
- const wanted = names ?? [...used];
557
- const unwritten = wanted.filter((name) => !written.includes(name)).sort();
558
- const stray = written.filter((name) => !wanted.includes(name)).sort();
559
- if (unwritten.length) problems.push(`${dir}/ mangler ${unwritten.join(', ')}: kør npm run icons.`);
560
- if (stray.length)
561
- problems.push(`${dir}/: ${stray.join(', ')} bruges ikke (eller står ikke i packages/editor/site/icons.mjs): kør npm run icons.`);
562
- return problems;
563
- }
564
-
565
- /** The Phosphor icons the site and the editor draw, by their file's name: the site's (Svg's import.meta.glob in
566
- * packages/editor/src/icon.tsx), the React icons imported from @phosphor-icons/react (`CaretRight` → caret-right) and
567
- * the SVG files imported as text (`…/core/assets/regular/eye.svg` with `?raw`), in packages/editor/ and src/; and the
568
- * icons of the apps in the app store and what they add (`icon` in store/catalog.json, drawn by AnyIcon in icon.tsx
569
- * before they are installed). */
570
- export function usedIcons() {
571
- const used = new Set();
572
- const has = (name) => existsSync(new URL(`${PHOSPHOR}regular/${name}.svg`, root));
573
- // The CMS's code (also when it is in node_modules/) and the site's, without the packages inside either.
574
- const files = [pkg, new URL('src/', root)].flatMap((dir) =>
575
- readdirSync(fileURLToPath(dir), { recursive: true, withFileTypes: true })
576
- .filter(
577
- (e) => e.isFile() && /\.(tsx?|mjs|astro)$/.test(e.name) && !relative(fileURLToPath(dir), e.parentPath).includes('node_modules'),
578
- )
579
- .map((e) => join(e.parentPath, e.name)),
580
- );
581
- for (const file of files) {
582
- const code = readFileSync(file, 'utf8');
583
- for (const [, names] of code.matchAll(/import\s*\{([^}]*)\}\s*from\s*'@phosphor-icons\/react'/g))
584
- for (const part of names.split(',')) {
585
- const name = part
586
- .trim()
587
- .split(/\s+as\s+/)[0]
588
- .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
589
- .replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')
590
- .toLowerCase();
591
- if (has(name)) used.add(name);
592
- }
593
- for (const [, name] of code.matchAll(/@phosphor-icons\/core\/assets\/(?:regular|fill)\/([a-z0-9-]+)\.svg\?raw/g)) used.add(name);
594
- for (const [, names] of code.matchAll(/\/node_modules\/@phosphor-icons\/core\/assets\/(?:regular|fill)\/\{([^}]*)\}\.svg/g))
595
- for (const name of names.split(',')) used.add(name);
596
- }
597
- // The store's catalog (until the real store exists, this repository's own: `store` in src/site/config.ts).
598
- const catalog = new URL('store/catalog.json', root);
599
- if (existsSync(catalog))
600
- JSON.parse(readFileSync(catalog, 'utf8'), (key, value) => {
601
- if (key === 'icon' && typeof value === 'string' && /^[a-z0-9-]+$/.test(value) && has(value)) used.add(value);
602
- return value;
603
- });
604
- return used;
605
- }
1
+ // The icons the site and the editor draw, by Phosphor's names (usedIcons), and the icon packs that draw them (the
2
+ // folders, packages/editor/site/iconPacks.mjs): which packs there are (installedPacks), each one's icons (packIcons) and what is
3
+ // wrong with one (packProblems). The system's own packs (SYSTEM_PACKS: Material Symbols, Phosphor and Lucide, in
4
+ // packages/editor/icons/<pack>/) are written by packages/editor/scripts/icon-packs.mjs (`npm run icons`) from their sets' packages at the versions in
5
+ // PACK_SOURCES, by the maps here: Phosphor's name → the set's icon, chosen for what it means where it is used (by its own
6
+ // name in the set, else by what it shows: Phosphor's `browser`, a window with a bar at the top, is Material Symbols'
7
+ // `web`). An icon a set has none of (a brand's logo; Lucide has none) is Pictogrammers' Material Design Icons'
8
+ // (MATERIAL_DESIGN_ICONS), with its licence beside the pack's own. check:content stops at a pack without an icon the
9
+ // site or the editor draws (themeProblems and iconPackProblems in packages/editor/site/theme.mjs).
10
+ import { existsSync, readdirSync, readFileSync } from 'node:fs';
11
+ import { join, relative } from 'node:path';
12
+ import { fileURLToPath, pathToFileURL } from 'node:url';
13
+ import { cleanSvg } from '@morphemecms/cms/lib/svg.mjs';
14
+ import { ICON_PACK_FILE, ICON_PACK_LICENSE, SYSTEM_PACKS, THEME_PACKS_FOLDER, themePackId } from './iconPacks.mjs';
15
+
16
+ // The site's root (the working directory) and this package's.
17
+ const root = pathToFileURL(`${process.cwd()}/`);
18
+ const pkg = new URL('../', import.meta.url);
19
+ /** Whether the system packs are written here (`npm run icons`, where the CMS is made: this package is the site's own
20
+ * packages/editor/, not in node_modules/ and not outside the site, as for the CMS's demo): only there can it be said that
21
+ * a pack has icons nothing draws, since the apps of the store and the site that makes the CMS draw them too. */
22
+ const packsWrittenHere = (() => {
23
+ const path = relative(fileURLToPath(root), fileURLToPath(pkg));
24
+ return !path.startsWith('..') && !path.split(/[\\/]/).includes('node_modules');
25
+ })();
26
+
27
+ /** Where the system's own packs are, one folder each (this package's icons/), from the site's root. */
28
+ export const SYSTEM_PACKS_FOLDER = relative(process.cwd(), fileURLToPath(new URL('icons', pkg)));
29
+
30
+ /** A pack's folder, from its id, from the site's root: a system pack's in this package, a theme's in its folder. */
31
+ export const packFolder = (id) => {
32
+ const [theme, pack] = id.split('/');
33
+ return pack ? `src/themes/${theme}/${THEME_PACKS_FOLDER}/${pack}` : `${SYSTEM_PACKS_FOLDER}/${theme}`;
34
+ };
35
+ const PHOSPHOR = 'node_modules/@phosphor-icons/core/assets/';
36
+ const has = (path) => existsSync(new URL(path, root));
37
+
38
+ /** The packages the system's packs are written from, at the versions they are (not in package.json, so neither an
39
+ * install nor the site's build fetches them; packages/editor/scripts/icon-packs.mjs fetches them into node_modules/.cache/), and what
40
+ * their packs' manifests say of them. Phosphor's is the site's own dependency (the names, and its React icons), at the
41
+ * version package-lock.json has; check:content stops when it is another. */
42
+ export const PACK_SOURCES = {
43
+ 'material-symbols': {
44
+ package: '@material-symbols/svg-400@0.48.2',
45
+ name: 'Material Symbols',
46
+ author: 'Google',
47
+ license: 'Apache-2.0',
48
+ url: 'https://fonts.google.com/icons',
49
+ },
50
+ phosphor: {
51
+ package: '@phosphor-icons/core@2.1.1',
52
+ name: 'Phosphor',
53
+ author: 'Phosphor Icons',
54
+ license: 'MIT',
55
+ url: 'https://phosphoricons.com',
56
+ },
57
+ lucide: {
58
+ package: 'lucide-static@1.63.0',
59
+ name: 'Lucide',
60
+ author: 'Lucide Contributors',
61
+ license: 'ISC',
62
+ url: 'https://lucide.dev',
63
+ },
64
+ 'material-design-icons': {
65
+ package: '@mdi/svg@7.4.47',
66
+ name: 'Material Design Icons',
67
+ author: 'Pictogrammers',
68
+ license: 'Apache-2.0',
69
+ url: 'https://pictogrammers.com/library/mdi/',
70
+ },
71
+ };
72
+
73
+ /** For each system pack but Phosphor's (whose names they are): Phosphor's name → Material Design Icons' (the package in
74
+ * PACK_SOURCES), for an icon the site or the editor draws that its set has none of. Material Symbols: a brand's logo (the
75
+ * account logged in at GitHub, the SEO choices' Google) and the
76
+ * things it has nothing that shows (binoculars, a hard disk, swatches, a scan frame, the arrows that widen and narrow
77
+ * the Hero). Lucide, which draws no brands: the logos. */
78
+ export const MATERIAL_DESIGN_ICONS = {
79
+ 'material-symbols': {
80
+ 'arrows-in-line-horizontal': 'arrow-collapse-horizontal',
81
+ 'arrows-out-line-horizontal': 'arrow-expand-horizontal',
82
+ binoculars: 'binoculars',
83
+ 'github-logo': 'github',
84
+ 'google-logo': 'google',
85
+ 'hard-drives': 'harddisk',
86
+ scan: 'scan-helper',
87
+ swatches: 'palette-swatch',
88
+ },
89
+ lucide: {
90
+ 'github-logo': 'github',
91
+ 'google-logo': 'google',
92
+ },
93
+ };
94
+
95
+ /** Phosphor's name → Material Symbols' (Outlined, weight 400; `-fill` the filled one), for every icon the site and the
96
+ * editor draw (usedIcons) but those in MATERIAL_DESIGN_ICONS['material-symbols']. */
97
+ export const MATERIAL_SYMBOLS = {
98
+ 'address-book': 'contacts',
99
+ 'app-window': 'web_asset',
100
+ 'arrow-counter-clockwise': 'replay',
101
+ 'arrow-down': 'arrow_downward',
102
+ 'arrow-left': 'arrow_back',
103
+ 'arrow-right': 'arrow_forward',
104
+ 'arrow-square-out': 'open_in_new',
105
+ 'arrow-u-up-left': 'undo',
106
+ 'arrow-u-up-right': 'redo',
107
+ 'arrow-up': 'arrow_upward',
108
+ 'arrow-up-right': 'arrow_outward',
109
+ 'arrows-down-up': 'swap_vert',
110
+ article: 'article',
111
+ bank: 'account_balance',
112
+ bell: 'notifications',
113
+ bicycle: 'pedal_bike',
114
+ 'book-open': 'import_contacts',
115
+ 'book-open-text': 'menu_book',
116
+ browser: 'web',
117
+ buildings: 'domain',
118
+ bus: 'directions_bus',
119
+ 'calendar-blank': 'calendar_today',
120
+ 'calendar-check': 'event_available',
121
+ car: 'directions_car',
122
+ cards: 'cards_stack',
123
+ 'caret-down': 'keyboard_arrow_down',
124
+ 'caret-left': 'chevron_left',
125
+ 'caret-right': 'chevron_right',
126
+ 'caret-up': 'keyboard_arrow_up',
127
+ certificate: 'license',
128
+ 'chart-line-up': 'monitoring',
129
+ chats: 'forum',
130
+ check: 'check',
131
+ 'check-circle': 'check_circle',
132
+ circle: 'circle',
133
+ 'circle-half': 'contrast',
134
+ clock: 'schedule',
135
+ 'clock-counter-clockwise': 'history',
136
+ code: 'code',
137
+ coffee: 'local_cafe',
138
+ columns: 'view_column_2',
139
+ cookie: 'cookie',
140
+ copy: 'content_copy',
141
+ 'credit-card': 'credit_card',
142
+ 'currency-circle-dollar': 'paid',
143
+ 'cursor-click': 'ads_click',
144
+ database: 'database',
145
+ desktop: 'desktop_windows',
146
+ 'device-mobile': 'mobile',
147
+ 'door-open': 'door_open',
148
+ 'download-simple': 'download',
149
+ 'envelope-simple': 'mail',
150
+ eye: 'visibility',
151
+ 'eye-slash': 'visibility_off',
152
+ 'file-pdf': 'picture_as_pdf',
153
+ 'file-text': 'description',
154
+ 'file-video': 'video_file',
155
+ 'file-zip': 'folder_zip',
156
+ 'flower-lotus': 'spa',
157
+ 'folder-simple': 'folder',
158
+ funnel: 'filter_alt',
159
+ gauge: 'speed',
160
+ gear: 'settings',
161
+ globe: 'language',
162
+ 'graduation-cap': 'school',
163
+ hammer: 'hardware',
164
+ 'hand-heart': 'volunteer_activism',
165
+ handshake: 'handshake',
166
+ heart: 'favorite',
167
+ house: 'home',
168
+ image: 'image',
169
+ 'image-square': 'image',
170
+ info: 'info',
171
+ keyboard: 'keyboard',
172
+ leaf: 'eco',
173
+ lifebuoy: 'support',
174
+ lightbulb: 'lightbulb',
175
+ 'link-break': 'link_off',
176
+ 'link-simple': 'link',
177
+ list: 'menu',
178
+ 'list-bullets': 'format_list_bulleted',
179
+ 'list-checks': 'checklist',
180
+ 'list-numbers': 'format_list_numbered',
181
+ 'lock-simple': 'lock',
182
+ 'lock-simple-open': 'lock_open',
183
+ 'magnifying-glass': 'search',
184
+ 'map-pin': 'location_on',
185
+ 'map-trifold': 'map',
186
+ medal: 'military_tech',
187
+ megaphone: 'campaign',
188
+ minus: 'remove',
189
+ moon: 'dark_mode',
190
+ newspaper: 'newspaper',
191
+ 'paint-brush-broad': 'brush',
192
+ palette: 'palette',
193
+ 'paper-plane-tilt': 'send',
194
+ 'pencil-simple': 'edit',
195
+ phone: 'call',
196
+ 'play-fill': 'play_arrow-fill',
197
+ plus: 'add',
198
+ prohibit: 'block',
199
+ 'puzzle-piece': 'extension',
200
+ question: 'help',
201
+ quotes: 'format_quote',
202
+ rows: 'view_agenda',
203
+ ruler: 'straighten',
204
+ shapes: 'shapes',
205
+ 'share-network': 'share',
206
+ 'shield-check': 'verified_user',
207
+ 'sidebar-simple': 'side_navigation',
208
+ 'sign-out': 'logout',
209
+ signpost: 'signpost',
210
+ 'sliders-horizontal': 'tune',
211
+ smiley: 'mood',
212
+ sparkle: 'star_shine',
213
+ square: 'square',
214
+ 'square-half-bottom': 'call_to_action',
215
+ 'squares-four': 'grid_view',
216
+ sticker: 'brand_family',
217
+ storefront: 'storefront',
218
+ sun: 'light_mode',
219
+ tag: 'sell',
220
+ 'text-aa': 'match_case',
221
+ 'text-align-left': 'format_align_left',
222
+ 'text-b': 'format_bold',
223
+ 'text-h-one': 'format_h1',
224
+ 'text-h-three': 'format_h3',
225
+ 'text-h-two': 'format_h2',
226
+ 'text-italic': 'format_italic',
227
+ 'text-t': 'title',
228
+ ticket: 'confirmation_number',
229
+ 'toggle-right': 'toggle_on',
230
+ train: 'train',
231
+ trash: 'delete',
232
+ 'upload-simple': 'upload',
233
+ user: 'person',
234
+ 'user-circle': 'account_circle',
235
+ users: 'group',
236
+ 'users-three': 'groups',
237
+ 'video-camera': 'videocam',
238
+ warning: 'warning',
239
+ 'warning-circle': 'error',
240
+ 'wave-sine': 'animation',
241
+ wheelchair: 'accessible',
242
+ wrench: 'build',
243
+ x: 'close',
244
+ };
245
+
246
+ /** Phosphor's name → Lucide's, for every icon the site and the editor draw (usedIcons) but those in
247
+ * MATERIAL_DESIGN_ICONS.lucide. `-fill`: Lucide's outline filled in (Lucide has no filled icons). */
248
+ export const LUCIDE = {
249
+ 'address-book': 'book-user',
250
+ 'app-window': 'app-window',
251
+ 'arrow-counter-clockwise': 'rotate-ccw',
252
+ 'arrow-down': 'arrow-down',
253
+ 'arrow-left': 'arrow-left',
254
+ 'arrow-right': 'arrow-right',
255
+ 'arrow-square-out': 'external-link',
256
+ 'arrow-u-up-left': 'undo-2',
257
+ 'arrow-u-up-right': 'redo-2',
258
+ 'arrow-up': 'arrow-up',
259
+ 'arrow-up-right': 'arrow-up-right',
260
+ 'arrows-down-up': 'arrow-down-up',
261
+ 'arrows-in-line-horizontal': 'fold-horizontal',
262
+ 'arrows-out-line-horizontal': 'unfold-horizontal',
263
+ article: 'file-text',
264
+ bank: 'landmark',
265
+ bell: 'bell',
266
+ bicycle: 'bike',
267
+ binoculars: 'binoculars',
268
+ 'book-open': 'book-open',
269
+ 'book-open-text': 'book-open-text',
270
+ browser: 'panel-top',
271
+ buildings: 'building-2',
272
+ bus: 'bus',
273
+ 'calendar-blank': 'calendar',
274
+ 'calendar-check': 'calendar-check',
275
+ car: 'car',
276
+ cards: 'gallery-vertical-end',
277
+ 'caret-down': 'chevron-down',
278
+ 'caret-left': 'chevron-left',
279
+ 'caret-right': 'chevron-right',
280
+ 'caret-up': 'chevron-up',
281
+ certificate: 'award',
282
+ 'chart-line-up': 'chart-line',
283
+ chats: 'messages-square',
284
+ check: 'check',
285
+ 'check-circle': 'circle-check',
286
+ circle: 'circle',
287
+ 'circle-half': 'contrast',
288
+ clock: 'clock',
289
+ 'clock-counter-clockwise': 'history',
290
+ code: 'code',
291
+ coffee: 'coffee',
292
+ columns: 'columns-2',
293
+ cookie: 'cookie',
294
+ copy: 'copy',
295
+ 'credit-card': 'credit-card',
296
+ 'currency-circle-dollar': 'circle-dollar-sign',
297
+ 'cursor-click': 'mouse-pointer-click',
298
+ database: 'database',
299
+ desktop: 'monitor',
300
+ 'device-mobile': 'smartphone',
301
+ 'door-open': 'door-open',
302
+ 'download-simple': 'download',
303
+ 'envelope-simple': 'mail',
304
+ eye: 'eye',
305
+ 'eye-slash': 'eye-off',
306
+ 'file-pdf': 'file-text',
307
+ 'file-text': 'file-text',
308
+ 'file-video': 'file-video-camera',
309
+ 'file-zip': 'file-archive',
310
+ 'flower-lotus': 'flower-2',
311
+ 'folder-simple': 'folder',
312
+ funnel: 'funnel',
313
+ gauge: 'gauge',
314
+ gear: 'settings',
315
+ globe: 'globe',
316
+ 'graduation-cap': 'graduation-cap',
317
+ hammer: 'hammer',
318
+ 'hand-heart': 'hand-heart',
319
+ handshake: 'handshake',
320
+ 'hard-drives': 'server',
321
+ heart: 'heart',
322
+ house: 'house',
323
+ image: 'image',
324
+ 'image-square': 'image',
325
+ info: 'info',
326
+ keyboard: 'keyboard',
327
+ leaf: 'leaf',
328
+ lifebuoy: 'life-buoy',
329
+ lightbulb: 'lightbulb',
330
+ 'link-break': 'unlink',
331
+ 'link-simple': 'link',
332
+ list: 'menu',
333
+ 'list-bullets': 'list',
334
+ 'list-checks': 'list-checks',
335
+ 'list-numbers': 'list-ordered',
336
+ 'lock-simple': 'lock',
337
+ 'lock-simple-open': 'lock-open',
338
+ 'magnifying-glass': 'search',
339
+ 'map-pin': 'map-pin',
340
+ 'map-trifold': 'map',
341
+ medal: 'medal',
342
+ megaphone: 'megaphone',
343
+ minus: 'minus',
344
+ moon: 'moon',
345
+ newspaper: 'newspaper',
346
+ 'paint-brush-broad': 'paintbrush',
347
+ palette: 'palette',
348
+ 'paper-plane-tilt': 'send',
349
+ 'pencil-simple': 'pencil',
350
+ phone: 'phone',
351
+ 'play-fill': 'play-fill',
352
+ plus: 'plus',
353
+ prohibit: 'ban',
354
+ 'puzzle-piece': 'puzzle',
355
+ question: 'circle-question-mark',
356
+ quotes: 'quote',
357
+ rows: 'rows-2',
358
+ ruler: 'ruler',
359
+ scan: 'scan',
360
+ shapes: 'shapes',
361
+ 'share-network': 'share-2',
362
+ 'shield-check': 'shield-check',
363
+ 'sidebar-simple': 'panel-left',
364
+ 'sign-out': 'log-out',
365
+ signpost: 'signpost',
366
+ 'sliders-horizontal': 'sliders-horizontal',
367
+ smiley: 'smile',
368
+ sparkle: 'sparkle',
369
+ square: 'square',
370
+ 'square-half-bottom': 'panel-bottom',
371
+ 'squares-four': 'layout-grid',
372
+ sticker: 'sticker',
373
+ storefront: 'store',
374
+ sun: 'sun',
375
+ swatches: 'swatch-book',
376
+ tag: 'tag',
377
+ 'text-aa': 'case-sensitive',
378
+ 'text-align-left': 'text-align-start',
379
+ 'text-b': 'bold',
380
+ 'text-h-one': 'heading-1',
381
+ 'text-h-three': 'heading-3',
382
+ 'text-h-two': 'heading-2',
383
+ 'text-italic': 'italic',
384
+ 'text-t': 'type',
385
+ ticket: 'ticket',
386
+ 'toggle-right': 'toggle-right',
387
+ train: 'train-front',
388
+ trash: 'trash-2',
389
+ 'upload-simple': 'upload',
390
+ user: 'user',
391
+ 'user-circle': 'circle-user',
392
+ users: 'users',
393
+ 'users-three': 'users-round',
394
+ 'video-camera': 'video',
395
+ warning: 'triangle-alert',
396
+ 'warning-circle': 'circle-alert',
397
+ 'wave-sine': 'spline',
398
+ wheelchair: 'accessibility',
399
+ wrench: 'wrench',
400
+ x: 'x',
401
+ };
402
+
403
+ /** Each system pack's map: Phosphor's name → its set's icon (Phosphor's: its own names, no map). */
404
+ export const PACK_MAPS = { 'material-symbols': MATERIAL_SYMBOLS, lucide: LUCIDE };
405
+
406
+ /** The names the system's pack has an icon by in its maps (its set's and Material Design Icons'); all for Phosphor's. */
407
+ const mapped = (pack) => (PACK_MAPS[pack] ? [...Object.keys(PACK_MAPS[pack]), ...Object.keys(MATERIAL_DESIGN_ICONS[pack] ?? {})] : null);
408
+
409
+ /** Whether a name is one the site and the editor draw an icon by: Phosphor's (regular, and the filled ones as
410
+ * `<name>-fill`). A pack's file and a theme's own icon have one of them. */
411
+ export const isIconName = (name) =>
412
+ /^[a-z0-9-]+$/.test(name) && (has(`${PHOSPHOR}regular/${name}.svg`) || (name.endsWith('-fill') && has(`${PHOSPHOR}fill/${name}.svg`)));
413
+
414
+ /** What is wrong with an icon's SVG file (`file` its path, for the message): one <svg> with a viewBox, with only what
415
+ * draws in it (what cleanSvg keeps; the rest is left out where it is drawn). */
416
+ export function svgProblems(file, svg) {
417
+ const clean = cleanSvg(svg);
418
+ if (!clean || svg.match(/<svg\b/gi).length > 1 || !clean.viewBox)
419
+ return [`${file}: et ikon er ét <svg> med en viewBox og intet før eller efter.`];
420
+ if (clean.removed.length)
421
+ return [
422
+ `${file}: ${clean.removed.join(', ')} tegner ikke og bliver ikke vist. Et ikon har kun tegning: ingen scripts, stil, hændelser (on…) eller noget, der hentes udefra.`,
423
+ ];
424
+ return [];
425
+ }
426
+
427
+ const folders = (dir) =>
428
+ has(dir)
429
+ ? readdirSync(new URL(dir, root), { withFileTypes: true })
430
+ .filter((e) => e.isDirectory())
431
+ .map((e) => e.name)
432
+ : [];
433
+
434
+ /** The icon packs there are, by id: the system's (packages/editor/icons/<pack>/) and those the themes installed bring
435
+ * (src/themes/<theme>/icon-packs/<pack>/, as `<theme>/<pack>`), each a folder with its pack.json. */
436
+ export function installedPacks() {
437
+ const system = folders(`${SYSTEM_PACKS_FOLDER}/`).filter((p) => has(`${SYSTEM_PACKS_FOLDER}/${p}/${ICON_PACK_FILE}`));
438
+ const themes = folders('src/themes/').flatMap((theme) =>
439
+ folders(`src/themes/${theme}/${THEME_PACKS_FOLDER}/`)
440
+ .filter((p) => has(`src/themes/${theme}/${THEME_PACKS_FOLDER}/${p}/${ICON_PACK_FILE}`))
441
+ .map((p) => themePackId(theme, p)),
442
+ );
443
+ return [...system, ...themes];
444
+ }
445
+
446
+ /** A pack's icons as their files' text, by name (its <name>.svg). */
447
+ export function packIcons(id) {
448
+ const dir = `${packFolder(id)}/`;
449
+ const icons = {};
450
+ if (has(dir))
451
+ for (const f of readdirSync(new URL(dir, root)))
452
+ if (f.endsWith('.svg')) icons[f.slice(0, -'.svg'.length)] = readFileSync(new URL(dir + f, root), 'utf8');
453
+ return icons;
454
+ }
455
+
456
+ /** Phosphor's own file of an icon by its name (regular, or `<name>-fill` filled), as its package has it; null for one it
457
+ * does not have. */
458
+ export function phosphorFile(name) {
459
+ const file =
460
+ name.endsWith('-fill') && has(`${PHOSPHOR}fill/${name}.svg`) ? `${PHOSPHOR}fill/${name}.svg` : `${PHOSPHOR}regular/${name}.svg`;
461
+ return has(file) ? readFileSync(new URL(file, root), 'utf8') : null;
462
+ }
463
+
464
+ const isText = (x) => typeof x === 'string' && x.trim() !== '';
465
+
466
+ /** What is wrong with an icon pack (`id`, as installedPacks gives it): its manifest (pack.json: name, author, license;
467
+ * and for each set it takes icons from besides its own, `includes`, its name, author, license, licence file and icons),
468
+ * its licences (LICENSE, and each `includes`' licenseFile), an icon the site or the editor draws (usedIcons) it has no
469
+ * file for, a file that is not an icon by a name the site draws, and each icon's SVG (svgProblems). For a system pack,
470
+ * also that it is written as its maps say (systemPackProblems). */
471
+ export function packProblems(id, used = usedIcons()) {
472
+ const dir = packFolder(id);
473
+ const problems = [];
474
+ let manifest = {};
475
+ try {
476
+ manifest = JSON.parse(readFileSync(new URL(`${dir}/${ICON_PACK_FILE}`, root), 'utf8'));
477
+ } catch (e) {
478
+ return [`${dir}/${ICON_PACK_FILE}: ${e.message}`];
479
+ }
480
+ for (const key of ['name', 'author', 'license'])
481
+ if (!isText(manifest[key]))
482
+ problems.push(`${dir}/${ICON_PACK_FILE}: "${key}" mangler (ikonpakkens navn, hvem der har lavet den, og dens licens).`);
483
+ if (!has(`${dir}/${ICON_PACK_LICENSE}`)) problems.push(`${dir}/${ICON_PACK_LICENSE} mangler: ikonpakkens licens.`);
484
+ const licences = new Set([ICON_PACK_LICENSE]);
485
+ if (manifest.includes !== undefined && !Array.isArray(manifest.includes))
486
+ problems.push(`${dir}/${ICON_PACK_FILE}: "includes" er en liste med de sæt, pakken har ikoner fra ud over sit eget.`);
487
+ for (const x of Array.isArray(manifest.includes) ? manifest.includes : []) {
488
+ const named = isText(x?.name) ? x.name : '?';
489
+ if (!['name', 'author', 'license', 'licenseFile'].every((k) => isText(x?.[k])) || !Array.isArray(x.icons) || !x.icons.every(isText))
490
+ problems.push(`${dir}/${ICON_PACK_FILE}: "includes" (${named}) skal have "name", "author", "license", "licenseFile" og "icons".`);
491
+ else if (!/^LICENSE-[a-z0-9-]+$/.test(x.licenseFile) || !has(`${dir}/${x.licenseFile}`))
492
+ problems.push(`${dir}/${x.licenseFile ?? ICON_PACK_LICENSE}: licensen for ${named} mangler (LICENSE-<sæt> i pakkens mappe).`);
493
+ else licences.add(x.licenseFile);
494
+ for (const name of Array.isArray(x?.icons) ? x.icons : [])
495
+ if (!has(`${dir}/${name}.svg`)) problems.push(`${dir}/${ICON_PACK_FILE}: "includes" (${named}) nævner ${name}, som pakken ikke har.`);
496
+ }
497
+ const files = has(dir) ? readdirSync(new URL(`${dir}/`, root), { withFileTypes: true }) : [];
498
+ for (const entry of files) {
499
+ const file = `${dir}/${entry.name}`;
500
+ if (entry.name === ICON_PACK_FILE || licences.has(entry.name)) continue;
501
+ if (!entry.isFile() || !entry.name.endsWith('.svg')) {
502
+ problems.push(`${file}: en ikonpakke har kun ${ICON_PACK_FILE}, sine licenser og ikoner (${dir}/<navn>.svg).`);
503
+ continue;
504
+ }
505
+ const name = entry.name.slice(0, -'.svg'.length);
506
+ if (!isIconName(name))
507
+ problems.push(`${file}: sitet tegner intet ikon, der hedder "${name}". Et ikon hedder som i Phosphor (fx map-pin, play-fill).`);
508
+ problems.push(...svgProblems(file, readFileSync(new URL(file, root), 'utf8')));
509
+ }
510
+ const missing = [...used].sort().filter((name) => !has(`${dir}/${name}.svg`));
511
+ if (missing.length)
512
+ problems.push(
513
+ `Ikonpakken ${isText(manifest.name) ? manifest.name : id} (${dir}/) har intet ikon for ${missing.join(', ')}: ${
514
+ SYSTEM_PACKS.includes(id)
515
+ ? 'skriv det, der passer, i packages/editor/site/icons.mjs, og kør npm run icons.'
516
+ : 'giv den et ikon ved hvert navn.'
517
+ }`,
518
+ );
519
+ return [...problems, ...(SYSTEM_PACKS.includes(id) ? systemPackProblems(id, used) : [])];
520
+ }
521
+
522
+ /** What is wrong with a system pack beyond what every pack must be (packProblems): an icon the site or the editor draws
523
+ * that its maps have none for (Phosphor's: one its package has none of), and where the packs are written, one they name
524
+ * that is not written or a file they do not name (`npm run icons` writes it again), and Phosphor's package at another
525
+ * version than its pack's. */
526
+ function systemPackProblems(id, used) {
527
+ const dir = packFolder(id);
528
+ const problems = [];
529
+ const names = mapped(id);
530
+ if (!packsWrittenHere) {
531
+ const unnamed = names ? [...used].sort().filter((name) => !names.includes(name)) : [];
532
+ return unnamed.length ? [`${PACK_SOURCES[id].name} har intet ikon for ${unnamed.join(', ')}.`] : [];
533
+ }
534
+ if (names) {
535
+ const map = id === 'material-symbols' ? 'MATERIAL_SYMBOLS' : 'LUCIDE';
536
+ const unnamed = [...used].sort().filter((name) => !names.includes(name));
537
+ if (unnamed.length)
538
+ problems.push(
539
+ `${PACK_SOURCES[id].name} har intet ikon for ${unnamed.join(', ')}: skriv det, der passer, i ${map} i packages/editor/site/icons.mjs (et, ${PACK_SOURCES[id].name} intet har af, i MATERIAL_DESIGN_ICONS), og kør npm run icons.`,
540
+ );
541
+ } else {
542
+ const version = JSON.parse(readFileSync(new URL('node_modules/@phosphor-icons/core/package.json', root), 'utf8')).version;
543
+ if (`@phosphor-icons/core@${version}` !== PACK_SOURCES.phosphor.package)
544
+ problems.push(
545
+ `@phosphor-icons/core er ${version}, men ikonpakken Phosphor er skrevet fra ${PACK_SOURCES.phosphor.package}: ret versionen i PACK_SOURCES i packages/editor/site/icons.mjs, og kør npm run icons.`,
546
+ );
547
+ }
548
+ if (names) {
549
+ const unused = names.filter((name) => !used.has(name)).sort();
550
+ if (unused.length)
551
+ problems.push(
552
+ `packages/editor/site/icons.mjs: ${PACK_SOURCES[id].name}s kort har ${unused.join(', ')}, som sitet og editoren ikke tegner: tag dem ud, og kør npm run icons.`,
553
+ );
554
+ }
555
+ const written = Object.keys(packIcons(id));
556
+ const wanted = names ?? [...used];
557
+ const unwritten = wanted.filter((name) => !written.includes(name)).sort();
558
+ const stray = written.filter((name) => !wanted.includes(name)).sort();
559
+ if (unwritten.length) problems.push(`${dir}/ mangler ${unwritten.join(', ')}: kør npm run icons.`);
560
+ if (stray.length)
561
+ problems.push(`${dir}/: ${stray.join(', ')} bruges ikke (eller står ikke i packages/editor/site/icons.mjs): kør npm run icons.`);
562
+ return problems;
563
+ }
564
+
565
+ /** The Phosphor icons the site and the editor draw, by their file's name: the site's (Svg's import.meta.glob in
566
+ * packages/editor/src/icon.tsx), the React icons imported from @phosphor-icons/react (`CaretRight` → caret-right) and
567
+ * the SVG files imported as text (`…/core/assets/regular/eye.svg` with `?raw`), in packages/editor/ and src/; and the
568
+ * icons of the apps in the app store and what they add (`icon` in store/catalog.json, drawn by AnyIcon in icon.tsx
569
+ * before they are installed). */
570
+ export function usedIcons() {
571
+ const used = new Set();
572
+ const has = (name) => existsSync(new URL(`${PHOSPHOR}regular/${name}.svg`, root));
573
+ // The CMS's code (also when it is in node_modules/) and the site's, without the packages inside either.
574
+ const files = [pkg, new URL('src/', root)].flatMap((dir) =>
575
+ readdirSync(fileURLToPath(dir), { recursive: true, withFileTypes: true })
576
+ .filter(
577
+ (e) => e.isFile() && /\.(tsx?|mjs|astro)$/.test(e.name) && !relative(fileURLToPath(dir), e.parentPath).includes('node_modules'),
578
+ )
579
+ .map((e) => join(e.parentPath, e.name)),
580
+ );
581
+ for (const file of files) {
582
+ const code = readFileSync(file, 'utf8');
583
+ for (const [, names] of code.matchAll(/import\s*\{([^}]*)\}\s*from\s*'@phosphor-icons\/react'/g))
584
+ for (const part of names.split(',')) {
585
+ const name = part
586
+ .trim()
587
+ .split(/\s+as\s+/)[0]
588
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
589
+ .replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')
590
+ .toLowerCase();
591
+ if (has(name)) used.add(name);
592
+ }
593
+ for (const [, name] of code.matchAll(/@phosphor-icons\/core\/assets\/(?:regular|fill)\/([a-z0-9-]+)\.svg\?raw/g)) used.add(name);
594
+ for (const [, names] of code.matchAll(/\/node_modules\/@phosphor-icons\/core\/assets\/(?:regular|fill)\/\{([^}]*)\}\.svg/g))
595
+ for (const name of names.split(',')) used.add(name);
596
+ }
597
+ // The store's catalog (until the real store exists, this repository's own: `store` in src/site/config.ts).
598
+ const catalog = new URL('store/catalog.json', root);
599
+ if (existsSync(catalog))
600
+ JSON.parse(readFileSync(catalog, 'utf8'), (key, value) => {
601
+ if (key === 'icon' && typeof value === 'string' && /^[a-z0-9-]+$/.test(value) && has(value)) used.add(value);
602
+ return value;
603
+ });
604
+ return used;
605
+ }