@morphemecms/cms 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1106) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +51 -3
  3. package/astro.d.mts +2 -0
  4. package/astro.mjs +162 -0
  5. package/bin/morpheme.mjs +38 -0
  6. package/client.d.ts +10 -0
  7. package/defaults/blockTexts.ts +33 -0
  8. package/defaults/collections.ts +774 -0
  9. package/defaults/colors.ts +125 -0
  10. package/defaults/company.ts +20 -0
  11. package/defaults/editor.ts +178 -0
  12. package/defaults/internalLinks.ts +30 -0
  13. package/defaults/opens.ts +18 -0
  14. package/defaults/popup.tsx +93 -0
  15. package/defaults/privacy.ts +79 -0
  16. package/defaults/rules.ts +450 -0
  17. package/defaults/schema.ts +16 -0
  18. package/defaults/sitedata.ts +129 -0
  19. package/defaults/standard.ts +106 -0
  20. package/defaults/standardPages.ts +87 -0
  21. package/defaults/texts.ts +481 -0
  22. package/demo/README.md +26 -0
  23. package/demo/public/apple-touch-icon.png +0 -0
  24. package/demo/public/editor/apple-touch-icon.png +0 -0
  25. package/demo/public/editor/icon-192.png +0 -0
  26. package/demo/public/editor/icon-512.png +0 -0
  27. package/demo/public/editor/icon-maskable-512.png +0 -0
  28. package/demo/public/favicon.ico +0 -0
  29. package/demo/public/favicon.svg +1 -0
  30. package/demo/public/images/uploads/2026/10/andromeda.webp +0 -0
  31. package/demo/public/images/uploads/2026/10/earth-from-space.webp +0 -0
  32. package/demo/public/images/uploads/2026/10/editor-blog.webp +0 -0
  33. package/demo/public/images/uploads/2026/10/editor-colors.webp +0 -0
  34. package/demo/public/images/uploads/2026/10/editor-home.webp +0 -0
  35. package/demo/public/images/uploads/2026/10/editor-page.webp +0 -0
  36. package/demo/public/images/uploads/2026/10/editor-pages.webp +0 -0
  37. package/demo/public/images/uploads/2026/10/editor-seo.webp +0 -0
  38. package/demo/public/images/uploads/2026/10/editor-start.webp +0 -0
  39. package/demo/public/images/uploads/2026/10/editor-themes.webp +0 -0
  40. package/demo/public/images/uploads/2026/10/moon.webp +0 -0
  41. package/demo/public/images/uploads/2026/10/saturn.webp +0 -0
  42. package/demo/public/logo.svg +1 -0
  43. package/demo/src/content/blog/build-a-page-from-blocks.md +19 -0
  44. package/demo/src/content/blog/colors-everyone-can-read.md +19 -0
  45. package/demo/src/content/blog/edit-your-website-from-your-phone.md +21 -0
  46. package/demo/src/content/blog/every-save-is-a-version.md +21 -0
  47. package/demo/src/content/blog/schedule-a-post.md +17 -0
  48. package/demo/src/content/blog/secure-from-day-one.md +17 -0
  49. package/demo/src/content/blog/seo-without-the-guesswork.md +23 -0
  50. package/demo/src/content/blog/switch-themes-without-losing-anything.md +23 -0
  51. package/demo/src/content/blog/the-app-store.md +21 -0
  52. package/demo/src/content/pages/about.md +22 -0
  53. package/demo/src/content/pages/app-store.md +30 -0
  54. package/demo/src/content/pages/blocks.md +98 -0
  55. package/demo/src/content/pages/blog-page.md +11 -0
  56. package/demo/src/content/pages/contact.md +16 -0
  57. package/demo/src/content/pages/get-started.md +20 -0
  58. package/demo/src/content/pages/home.md +26 -0
  59. package/demo/src/content/pages/page-not-found.md +11 -0
  60. package/demo/src/content/pages/privacy-policy.md +24 -0
  61. package/demo/src/data/blocks.json +25 -0
  62. package/demo/src/data/booking.json +6 -0
  63. package/demo/src/data/categories/apps.json +6 -0
  64. package/demo/src/data/categories/design.json +6 -0
  65. package/demo/src/data/categories/editing.json +6 -0
  66. package/demo/src/data/categories/security.json +6 -0
  67. package/demo/src/data/categories/seo.json +6 -0
  68. package/demo/src/data/colors.json +75 -0
  69. package/demo/src/data/contact.json +8 -0
  70. package/demo/src/data/cookies.json +21 -0
  71. package/demo/src/data/footer.json +27 -0
  72. package/demo/src/data/menu.json +35 -0
  73. package/demo/src/data/mobile-menu.json +25 -0
  74. package/demo/src/data/popups/booking-bar.json +13 -0
  75. package/demo/src/data/popups/try-the-editor.json +16 -0
  76. package/demo/src/data/standard-pages.json +8 -0
  77. package/demo/src/data/testimonials/sample-bakery.json +10 -0
  78. package/demo/src/data/testimonials/sample-clinic.json +10 -0
  79. package/demo/src/data/testimonials/sample-studio.json +10 -0
  80. package/demo/src/site/colors.ts +11 -0
  81. package/demo/src/site/config.ts +19 -0
  82. package/icons/lucide/LICENSE +43 -0
  83. package/icons/lucide/LICENSE-material-design-icons +20 -0
  84. package/icons/lucide/address-book.svg +1 -0
  85. package/icons/lucide/app-window.svg +1 -0
  86. package/icons/lucide/arrow-counter-clockwise.svg +1 -0
  87. package/icons/lucide/arrow-down.svg +1 -0
  88. package/icons/lucide/arrow-left.svg +1 -0
  89. package/icons/lucide/arrow-right.svg +1 -0
  90. package/icons/lucide/arrow-square-out.svg +1 -0
  91. package/icons/lucide/arrow-u-up-left.svg +1 -0
  92. package/icons/lucide/arrow-u-up-right.svg +1 -0
  93. package/icons/lucide/arrow-up-right.svg +1 -0
  94. package/icons/lucide/arrow-up.svg +1 -0
  95. package/icons/lucide/arrows-down-up.svg +1 -0
  96. package/icons/lucide/arrows-in-line-horizontal.svg +1 -0
  97. package/icons/lucide/arrows-out-line-horizontal.svg +1 -0
  98. package/icons/lucide/article.svg +1 -0
  99. package/icons/lucide/bank.svg +1 -0
  100. package/icons/lucide/bell.svg +1 -0
  101. package/icons/lucide/bicycle.svg +1 -0
  102. package/icons/lucide/binoculars.svg +1 -0
  103. package/icons/lucide/book-open-text.svg +1 -0
  104. package/icons/lucide/book-open.svg +1 -0
  105. package/icons/lucide/browser.svg +1 -0
  106. package/icons/lucide/buildings.svg +1 -0
  107. package/icons/lucide/bus.svg +1 -0
  108. package/icons/lucide/calendar-blank.svg +1 -0
  109. package/icons/lucide/calendar-check.svg +1 -0
  110. package/icons/lucide/car.svg +1 -0
  111. package/icons/lucide/cards.svg +1 -0
  112. package/icons/lucide/caret-down.svg +1 -0
  113. package/icons/lucide/caret-left.svg +1 -0
  114. package/icons/lucide/caret-right.svg +1 -0
  115. package/icons/lucide/caret-up.svg +1 -0
  116. package/icons/lucide/certificate.svg +1 -0
  117. package/icons/lucide/chart-line-up.svg +1 -0
  118. package/icons/lucide/chats.svg +1 -0
  119. package/icons/lucide/check-circle.svg +1 -0
  120. package/icons/lucide/check.svg +1 -0
  121. package/icons/lucide/circle-half.svg +1 -0
  122. package/icons/lucide/circle.svg +1 -0
  123. package/icons/lucide/clock-counter-clockwise.svg +1 -0
  124. package/icons/lucide/clock.svg +1 -0
  125. package/icons/lucide/code.svg +1 -0
  126. package/icons/lucide/coffee.svg +1 -0
  127. package/icons/lucide/columns.svg +1 -0
  128. package/icons/lucide/cookie.svg +1 -0
  129. package/icons/lucide/copy.svg +1 -0
  130. package/icons/lucide/credit-card.svg +1 -0
  131. package/icons/lucide/currency-circle-dollar.svg +1 -0
  132. package/icons/lucide/cursor-click.svg +1 -0
  133. package/icons/lucide/database.svg +1 -0
  134. package/icons/lucide/desktop.svg +1 -0
  135. package/icons/lucide/device-mobile.svg +1 -0
  136. package/icons/lucide/door-open.svg +1 -0
  137. package/icons/lucide/download-simple.svg +1 -0
  138. package/icons/lucide/envelope-simple.svg +1 -0
  139. package/icons/lucide/eye-slash.svg +1 -0
  140. package/icons/lucide/eye.svg +1 -0
  141. package/icons/lucide/file-pdf.svg +1 -0
  142. package/icons/lucide/file-text.svg +1 -0
  143. package/icons/lucide/file-video.svg +1 -0
  144. package/icons/lucide/file-zip.svg +1 -0
  145. package/icons/lucide/flower-lotus.svg +1 -0
  146. package/icons/lucide/folder-simple.svg +1 -0
  147. package/icons/lucide/funnel.svg +1 -0
  148. package/icons/lucide/gauge.svg +1 -0
  149. package/icons/lucide/gear.svg +1 -0
  150. package/icons/lucide/github-logo.svg +1 -0
  151. package/icons/lucide/globe.svg +1 -0
  152. package/icons/lucide/google-logo.svg +1 -0
  153. package/icons/lucide/graduation-cap.svg +1 -0
  154. package/icons/lucide/hammer.svg +1 -0
  155. package/icons/lucide/hand-heart.svg +1 -0
  156. package/icons/lucide/handshake.svg +1 -0
  157. package/icons/lucide/hard-drives.svg +1 -0
  158. package/icons/lucide/heart.svg +1 -0
  159. package/icons/lucide/house.svg +1 -0
  160. package/icons/lucide/image-square.svg +1 -0
  161. package/icons/lucide/image.svg +1 -0
  162. package/icons/lucide/info.svg +1 -0
  163. package/icons/lucide/keyboard.svg +1 -0
  164. package/icons/lucide/leaf.svg +1 -0
  165. package/icons/lucide/lifebuoy.svg +1 -0
  166. package/icons/lucide/lightbulb.svg +1 -0
  167. package/icons/lucide/link-break.svg +1 -0
  168. package/icons/lucide/link-simple.svg +1 -0
  169. package/icons/lucide/list-bullets.svg +1 -0
  170. package/icons/lucide/list-checks.svg +1 -0
  171. package/icons/lucide/list-numbers.svg +1 -0
  172. package/icons/lucide/list.svg +1 -0
  173. package/icons/lucide/lock-simple-open.svg +1 -0
  174. package/icons/lucide/lock-simple.svg +1 -0
  175. package/icons/lucide/magnifying-glass.svg +1 -0
  176. package/icons/lucide/map-pin.svg +1 -0
  177. package/icons/lucide/map-trifold.svg +1 -0
  178. package/icons/lucide/medal.svg +1 -0
  179. package/icons/lucide/megaphone.svg +1 -0
  180. package/icons/lucide/minus.svg +1 -0
  181. package/icons/lucide/moon.svg +1 -0
  182. package/icons/lucide/newspaper.svg +1 -0
  183. package/icons/lucide/pack.json +23 -0
  184. package/icons/lucide/paint-brush-broad.svg +1 -0
  185. package/icons/lucide/palette.svg +1 -0
  186. package/icons/lucide/paper-plane-tilt.svg +1 -0
  187. package/icons/lucide/pencil-simple.svg +1 -0
  188. package/icons/lucide/phone.svg +1 -0
  189. package/icons/lucide/play-fill.svg +1 -0
  190. package/icons/lucide/plus.svg +1 -0
  191. package/icons/lucide/prohibit.svg +1 -0
  192. package/icons/lucide/puzzle-piece.svg +1 -0
  193. package/icons/lucide/question.svg +1 -0
  194. package/icons/lucide/quotes.svg +1 -0
  195. package/icons/lucide/rows.svg +1 -0
  196. package/icons/lucide/ruler.svg +1 -0
  197. package/icons/lucide/scan.svg +1 -0
  198. package/icons/lucide/shapes.svg +1 -0
  199. package/icons/lucide/share-network.svg +1 -0
  200. package/icons/lucide/shield-check.svg +1 -0
  201. package/icons/lucide/sidebar-simple.svg +1 -0
  202. package/icons/lucide/sign-out.svg +1 -0
  203. package/icons/lucide/signpost.svg +1 -0
  204. package/icons/lucide/sliders-horizontal.svg +1 -0
  205. package/icons/lucide/smiley.svg +1 -0
  206. package/icons/lucide/sparkle.svg +1 -0
  207. package/icons/lucide/square-half-bottom.svg +1 -0
  208. package/icons/lucide/square.svg +1 -0
  209. package/icons/lucide/squares-four.svg +1 -0
  210. package/icons/lucide/sticker.svg +1 -0
  211. package/icons/lucide/storefront.svg +1 -0
  212. package/icons/lucide/sun.svg +1 -0
  213. package/icons/lucide/swatches.svg +1 -0
  214. package/icons/lucide/tag.svg +1 -0
  215. package/icons/lucide/text-aa.svg +1 -0
  216. package/icons/lucide/text-align-left.svg +1 -0
  217. package/icons/lucide/text-b.svg +1 -0
  218. package/icons/lucide/text-h-one.svg +1 -0
  219. package/icons/lucide/text-h-three.svg +1 -0
  220. package/icons/lucide/text-h-two.svg +1 -0
  221. package/icons/lucide/text-italic.svg +1 -0
  222. package/icons/lucide/text-t.svg +1 -0
  223. package/icons/lucide/ticket.svg +1 -0
  224. package/icons/lucide/toggle-right.svg +1 -0
  225. package/icons/lucide/train.svg +1 -0
  226. package/icons/lucide/trash.svg +1 -0
  227. package/icons/lucide/upload-simple.svg +1 -0
  228. package/icons/lucide/user-circle.svg +1 -0
  229. package/icons/lucide/user.svg +1 -0
  230. package/icons/lucide/users-three.svg +1 -0
  231. package/icons/lucide/users.svg +1 -0
  232. package/icons/lucide/video-camera.svg +1 -0
  233. package/icons/lucide/warning-circle.svg +1 -0
  234. package/icons/lucide/warning.svg +1 -0
  235. package/icons/lucide/wave-sine.svg +1 -0
  236. package/icons/lucide/wheelchair.svg +1 -0
  237. package/icons/lucide/wrench.svg +1 -0
  238. package/icons/lucide/x.svg +1 -0
  239. package/icons/material-symbols/LICENSE +201 -0
  240. package/icons/material-symbols/LICENSE-material-design-icons +20 -0
  241. package/icons/material-symbols/address-book.svg +1 -0
  242. package/icons/material-symbols/app-window.svg +1 -0
  243. package/icons/material-symbols/arrow-counter-clockwise.svg +1 -0
  244. package/icons/material-symbols/arrow-down.svg +1 -0
  245. package/icons/material-symbols/arrow-left.svg +1 -0
  246. package/icons/material-symbols/arrow-right.svg +1 -0
  247. package/icons/material-symbols/arrow-square-out.svg +1 -0
  248. package/icons/material-symbols/arrow-u-up-left.svg +1 -0
  249. package/icons/material-symbols/arrow-u-up-right.svg +1 -0
  250. package/icons/material-symbols/arrow-up-right.svg +1 -0
  251. package/icons/material-symbols/arrow-up.svg +1 -0
  252. package/icons/material-symbols/arrows-down-up.svg +1 -0
  253. package/icons/material-symbols/arrows-in-line-horizontal.svg +1 -0
  254. package/icons/material-symbols/arrows-out-line-horizontal.svg +1 -0
  255. package/icons/material-symbols/article.svg +1 -0
  256. package/icons/material-symbols/bank.svg +1 -0
  257. package/icons/material-symbols/bell.svg +1 -0
  258. package/icons/material-symbols/bicycle.svg +1 -0
  259. package/icons/material-symbols/binoculars.svg +1 -0
  260. package/icons/material-symbols/book-open-text.svg +1 -0
  261. package/icons/material-symbols/book-open.svg +1 -0
  262. package/icons/material-symbols/browser.svg +1 -0
  263. package/icons/material-symbols/buildings.svg +1 -0
  264. package/icons/material-symbols/bus.svg +1 -0
  265. package/icons/material-symbols/calendar-blank.svg +1 -0
  266. package/icons/material-symbols/calendar-check.svg +1 -0
  267. package/icons/material-symbols/car.svg +1 -0
  268. package/icons/material-symbols/cards.svg +1 -0
  269. package/icons/material-symbols/caret-down.svg +1 -0
  270. package/icons/material-symbols/caret-left.svg +1 -0
  271. package/icons/material-symbols/caret-right.svg +1 -0
  272. package/icons/material-symbols/caret-up.svg +1 -0
  273. package/icons/material-symbols/certificate.svg +1 -0
  274. package/icons/material-symbols/chart-line-up.svg +1 -0
  275. package/icons/material-symbols/chats.svg +1 -0
  276. package/icons/material-symbols/check-circle.svg +1 -0
  277. package/icons/material-symbols/check.svg +1 -0
  278. package/icons/material-symbols/circle-half.svg +1 -0
  279. package/icons/material-symbols/circle.svg +1 -0
  280. package/icons/material-symbols/clock-counter-clockwise.svg +1 -0
  281. package/icons/material-symbols/clock.svg +1 -0
  282. package/icons/material-symbols/code.svg +1 -0
  283. package/icons/material-symbols/coffee.svg +1 -0
  284. package/icons/material-symbols/columns.svg +1 -0
  285. package/icons/material-symbols/cookie.svg +1 -0
  286. package/icons/material-symbols/copy.svg +1 -0
  287. package/icons/material-symbols/credit-card.svg +1 -0
  288. package/icons/material-symbols/currency-circle-dollar.svg +1 -0
  289. package/icons/material-symbols/cursor-click.svg +1 -0
  290. package/icons/material-symbols/database.svg +1 -0
  291. package/icons/material-symbols/desktop.svg +1 -0
  292. package/icons/material-symbols/device-mobile.svg +1 -0
  293. package/icons/material-symbols/door-open.svg +1 -0
  294. package/icons/material-symbols/download-simple.svg +1 -0
  295. package/icons/material-symbols/envelope-simple.svg +1 -0
  296. package/icons/material-symbols/eye-slash.svg +1 -0
  297. package/icons/material-symbols/eye.svg +1 -0
  298. package/icons/material-symbols/file-pdf.svg +1 -0
  299. package/icons/material-symbols/file-text.svg +1 -0
  300. package/icons/material-symbols/file-video.svg +1 -0
  301. package/icons/material-symbols/file-zip.svg +1 -0
  302. package/icons/material-symbols/flower-lotus.svg +1 -0
  303. package/icons/material-symbols/folder-simple.svg +1 -0
  304. package/icons/material-symbols/funnel.svg +1 -0
  305. package/icons/material-symbols/gauge.svg +1 -0
  306. package/icons/material-symbols/gear.svg +1 -0
  307. package/icons/material-symbols/github-logo.svg +1 -0
  308. package/icons/material-symbols/globe.svg +1 -0
  309. package/icons/material-symbols/google-logo.svg +1 -0
  310. package/icons/material-symbols/graduation-cap.svg +1 -0
  311. package/icons/material-symbols/hammer.svg +1 -0
  312. package/icons/material-symbols/hand-heart.svg +1 -0
  313. package/icons/material-symbols/handshake.svg +1 -0
  314. package/icons/material-symbols/hard-drives.svg +1 -0
  315. package/icons/material-symbols/heart.svg +1 -0
  316. package/icons/material-symbols/house.svg +1 -0
  317. package/icons/material-symbols/image-square.svg +1 -0
  318. package/icons/material-symbols/image.svg +1 -0
  319. package/icons/material-symbols/info.svg +1 -0
  320. package/icons/material-symbols/keyboard.svg +1 -0
  321. package/icons/material-symbols/leaf.svg +1 -0
  322. package/icons/material-symbols/lifebuoy.svg +1 -0
  323. package/icons/material-symbols/lightbulb.svg +1 -0
  324. package/icons/material-symbols/link-break.svg +1 -0
  325. package/icons/material-symbols/link-simple.svg +1 -0
  326. package/icons/material-symbols/list-bullets.svg +1 -0
  327. package/icons/material-symbols/list-checks.svg +1 -0
  328. package/icons/material-symbols/list-numbers.svg +1 -0
  329. package/icons/material-symbols/list.svg +1 -0
  330. package/icons/material-symbols/lock-simple-open.svg +1 -0
  331. package/icons/material-symbols/lock-simple.svg +1 -0
  332. package/icons/material-symbols/magnifying-glass.svg +1 -0
  333. package/icons/material-symbols/map-pin.svg +1 -0
  334. package/icons/material-symbols/map-trifold.svg +1 -0
  335. package/icons/material-symbols/medal.svg +1 -0
  336. package/icons/material-symbols/megaphone.svg +1 -0
  337. package/icons/material-symbols/minus.svg +1 -0
  338. package/icons/material-symbols/moon.svg +1 -0
  339. package/icons/material-symbols/newspaper.svg +1 -0
  340. package/icons/material-symbols/pack.json +29 -0
  341. package/icons/material-symbols/paint-brush-broad.svg +1 -0
  342. package/icons/material-symbols/palette.svg +1 -0
  343. package/icons/material-symbols/paper-plane-tilt.svg +1 -0
  344. package/icons/material-symbols/pencil-simple.svg +1 -0
  345. package/icons/material-symbols/phone.svg +1 -0
  346. package/icons/material-symbols/play-fill.svg +1 -0
  347. package/icons/material-symbols/plus.svg +1 -0
  348. package/icons/material-symbols/prohibit.svg +1 -0
  349. package/icons/material-symbols/puzzle-piece.svg +1 -0
  350. package/icons/material-symbols/question.svg +1 -0
  351. package/icons/material-symbols/quotes.svg +1 -0
  352. package/icons/material-symbols/rows.svg +1 -0
  353. package/icons/material-symbols/ruler.svg +1 -0
  354. package/icons/material-symbols/scan.svg +1 -0
  355. package/icons/material-symbols/shapes.svg +1 -0
  356. package/icons/material-symbols/share-network.svg +1 -0
  357. package/icons/material-symbols/shield-check.svg +1 -0
  358. package/icons/material-symbols/sidebar-simple.svg +1 -0
  359. package/icons/material-symbols/sign-out.svg +1 -0
  360. package/icons/material-symbols/signpost.svg +1 -0
  361. package/icons/material-symbols/sliders-horizontal.svg +1 -0
  362. package/icons/material-symbols/smiley.svg +1 -0
  363. package/icons/material-symbols/sparkle.svg +1 -0
  364. package/icons/material-symbols/square-half-bottom.svg +1 -0
  365. package/icons/material-symbols/square.svg +1 -0
  366. package/icons/material-symbols/squares-four.svg +1 -0
  367. package/icons/material-symbols/sticker.svg +1 -0
  368. package/icons/material-symbols/storefront.svg +1 -0
  369. package/icons/material-symbols/sun.svg +1 -0
  370. package/icons/material-symbols/swatches.svg +1 -0
  371. package/icons/material-symbols/tag.svg +1 -0
  372. package/icons/material-symbols/text-aa.svg +1 -0
  373. package/icons/material-symbols/text-align-left.svg +1 -0
  374. package/icons/material-symbols/text-b.svg +1 -0
  375. package/icons/material-symbols/text-h-one.svg +1 -0
  376. package/icons/material-symbols/text-h-three.svg +1 -0
  377. package/icons/material-symbols/text-h-two.svg +1 -0
  378. package/icons/material-symbols/text-italic.svg +1 -0
  379. package/icons/material-symbols/text-t.svg +1 -0
  380. package/icons/material-symbols/ticket.svg +1 -0
  381. package/icons/material-symbols/toggle-right.svg +1 -0
  382. package/icons/material-symbols/train.svg +1 -0
  383. package/icons/material-symbols/trash.svg +1 -0
  384. package/icons/material-symbols/upload-simple.svg +1 -0
  385. package/icons/material-symbols/user-circle.svg +1 -0
  386. package/icons/material-symbols/user.svg +1 -0
  387. package/icons/material-symbols/users-three.svg +1 -0
  388. package/icons/material-symbols/users.svg +1 -0
  389. package/icons/material-symbols/video-camera.svg +1 -0
  390. package/icons/material-symbols/warning-circle.svg +1 -0
  391. package/icons/material-symbols/warning.svg +1 -0
  392. package/icons/material-symbols/wave-sine.svg +1 -0
  393. package/icons/material-symbols/wheelchair.svg +1 -0
  394. package/icons/material-symbols/wrench.svg +1 -0
  395. package/icons/material-symbols/x.svg +1 -0
  396. package/icons/phosphor/LICENSE +21 -0
  397. package/icons/phosphor/address-book.svg +1 -0
  398. package/icons/phosphor/app-window.svg +1 -0
  399. package/icons/phosphor/arrow-counter-clockwise.svg +1 -0
  400. package/icons/phosphor/arrow-down.svg +1 -0
  401. package/icons/phosphor/arrow-left.svg +1 -0
  402. package/icons/phosphor/arrow-right.svg +1 -0
  403. package/icons/phosphor/arrow-square-out.svg +1 -0
  404. package/icons/phosphor/arrow-u-up-left.svg +1 -0
  405. package/icons/phosphor/arrow-u-up-right.svg +1 -0
  406. package/icons/phosphor/arrow-up-right.svg +1 -0
  407. package/icons/phosphor/arrow-up.svg +1 -0
  408. package/icons/phosphor/arrows-down-up.svg +1 -0
  409. package/icons/phosphor/arrows-in-line-horizontal.svg +1 -0
  410. package/icons/phosphor/arrows-out-line-horizontal.svg +1 -0
  411. package/icons/phosphor/article.svg +1 -0
  412. package/icons/phosphor/bank.svg +1 -0
  413. package/icons/phosphor/bell.svg +1 -0
  414. package/icons/phosphor/bicycle.svg +1 -0
  415. package/icons/phosphor/binoculars.svg +1 -0
  416. package/icons/phosphor/book-open-text.svg +1 -0
  417. package/icons/phosphor/book-open.svg +1 -0
  418. package/icons/phosphor/browser.svg +1 -0
  419. package/icons/phosphor/buildings.svg +1 -0
  420. package/icons/phosphor/bus.svg +1 -0
  421. package/icons/phosphor/calendar-blank.svg +1 -0
  422. package/icons/phosphor/calendar-check.svg +1 -0
  423. package/icons/phosphor/car.svg +1 -0
  424. package/icons/phosphor/cards.svg +1 -0
  425. package/icons/phosphor/caret-down.svg +1 -0
  426. package/icons/phosphor/caret-left.svg +1 -0
  427. package/icons/phosphor/caret-right.svg +1 -0
  428. package/icons/phosphor/caret-up.svg +1 -0
  429. package/icons/phosphor/certificate.svg +1 -0
  430. package/icons/phosphor/chart-line-up.svg +1 -0
  431. package/icons/phosphor/chats.svg +1 -0
  432. package/icons/phosphor/check-circle.svg +1 -0
  433. package/icons/phosphor/check.svg +1 -0
  434. package/icons/phosphor/circle-half.svg +1 -0
  435. package/icons/phosphor/circle.svg +1 -0
  436. package/icons/phosphor/clock-counter-clockwise.svg +1 -0
  437. package/icons/phosphor/clock.svg +1 -0
  438. package/icons/phosphor/code.svg +1 -0
  439. package/icons/phosphor/coffee.svg +1 -0
  440. package/icons/phosphor/columns.svg +1 -0
  441. package/icons/phosphor/cookie.svg +1 -0
  442. package/icons/phosphor/copy.svg +1 -0
  443. package/icons/phosphor/credit-card.svg +1 -0
  444. package/icons/phosphor/currency-circle-dollar.svg +1 -0
  445. package/icons/phosphor/cursor-click.svg +1 -0
  446. package/icons/phosphor/database.svg +1 -0
  447. package/icons/phosphor/desktop.svg +1 -0
  448. package/icons/phosphor/device-mobile.svg +1 -0
  449. package/icons/phosphor/door-open.svg +1 -0
  450. package/icons/phosphor/download-simple.svg +1 -0
  451. package/icons/phosphor/envelope-simple.svg +1 -0
  452. package/icons/phosphor/eye-slash.svg +1 -0
  453. package/icons/phosphor/eye.svg +1 -0
  454. package/icons/phosphor/file-pdf.svg +1 -0
  455. package/icons/phosphor/file-text.svg +1 -0
  456. package/icons/phosphor/file-video.svg +1 -0
  457. package/icons/phosphor/file-zip.svg +1 -0
  458. package/icons/phosphor/flower-lotus.svg +1 -0
  459. package/icons/phosphor/folder-simple.svg +1 -0
  460. package/icons/phosphor/funnel.svg +1 -0
  461. package/icons/phosphor/gauge.svg +1 -0
  462. package/icons/phosphor/gear.svg +1 -0
  463. package/icons/phosphor/github-logo.svg +1 -0
  464. package/icons/phosphor/globe.svg +1 -0
  465. package/icons/phosphor/google-logo.svg +1 -0
  466. package/icons/phosphor/graduation-cap.svg +1 -0
  467. package/icons/phosphor/hammer.svg +1 -0
  468. package/icons/phosphor/hand-heart.svg +1 -0
  469. package/icons/phosphor/handshake.svg +1 -0
  470. package/icons/phosphor/hard-drives.svg +1 -0
  471. package/icons/phosphor/heart.svg +1 -0
  472. package/icons/phosphor/house.svg +1 -0
  473. package/icons/phosphor/image-square.svg +1 -0
  474. package/icons/phosphor/image.svg +1 -0
  475. package/icons/phosphor/info.svg +1 -0
  476. package/icons/phosphor/keyboard.svg +1 -0
  477. package/icons/phosphor/leaf.svg +1 -0
  478. package/icons/phosphor/lifebuoy.svg +1 -0
  479. package/icons/phosphor/lightbulb.svg +1 -0
  480. package/icons/phosphor/link-break.svg +1 -0
  481. package/icons/phosphor/link-simple.svg +1 -0
  482. package/icons/phosphor/list-bullets.svg +1 -0
  483. package/icons/phosphor/list-checks.svg +1 -0
  484. package/icons/phosphor/list-numbers.svg +1 -0
  485. package/icons/phosphor/list.svg +1 -0
  486. package/icons/phosphor/lock-simple-open.svg +1 -0
  487. package/icons/phosphor/lock-simple.svg +1 -0
  488. package/icons/phosphor/magnifying-glass.svg +1 -0
  489. package/icons/phosphor/map-pin.svg +1 -0
  490. package/icons/phosphor/map-trifold.svg +1 -0
  491. package/icons/phosphor/medal.svg +1 -0
  492. package/icons/phosphor/megaphone.svg +1 -0
  493. package/icons/phosphor/minus.svg +1 -0
  494. package/icons/phosphor/moon.svg +1 -0
  495. package/icons/phosphor/newspaper.svg +1 -0
  496. package/icons/phosphor/pack.json +8 -0
  497. package/icons/phosphor/paint-brush-broad.svg +1 -0
  498. package/icons/phosphor/palette.svg +1 -0
  499. package/icons/phosphor/paper-plane-tilt.svg +1 -0
  500. package/icons/phosphor/pencil-simple.svg +1 -0
  501. package/icons/phosphor/phone.svg +1 -0
  502. package/icons/phosphor/play-fill.svg +1 -0
  503. package/icons/phosphor/plus.svg +1 -0
  504. package/icons/phosphor/prohibit.svg +1 -0
  505. package/icons/phosphor/puzzle-piece.svg +1 -0
  506. package/icons/phosphor/question.svg +1 -0
  507. package/icons/phosphor/quotes.svg +1 -0
  508. package/icons/phosphor/rows.svg +1 -0
  509. package/icons/phosphor/ruler.svg +1 -0
  510. package/icons/phosphor/scan.svg +1 -0
  511. package/icons/phosphor/shapes.svg +1 -0
  512. package/icons/phosphor/share-network.svg +1 -0
  513. package/icons/phosphor/shield-check.svg +1 -0
  514. package/icons/phosphor/sidebar-simple.svg +1 -0
  515. package/icons/phosphor/sign-out.svg +1 -0
  516. package/icons/phosphor/signpost.svg +1 -0
  517. package/icons/phosphor/sliders-horizontal.svg +1 -0
  518. package/icons/phosphor/smiley.svg +1 -0
  519. package/icons/phosphor/sparkle.svg +1 -0
  520. package/icons/phosphor/square-half-bottom.svg +1 -0
  521. package/icons/phosphor/square.svg +1 -0
  522. package/icons/phosphor/squares-four.svg +1 -0
  523. package/icons/phosphor/sticker.svg +1 -0
  524. package/icons/phosphor/storefront.svg +1 -0
  525. package/icons/phosphor/sun.svg +1 -0
  526. package/icons/phosphor/swatches.svg +1 -0
  527. package/icons/phosphor/tag.svg +1 -0
  528. package/icons/phosphor/text-aa.svg +1 -0
  529. package/icons/phosphor/text-align-left.svg +1 -0
  530. package/icons/phosphor/text-b.svg +1 -0
  531. package/icons/phosphor/text-h-one.svg +1 -0
  532. package/icons/phosphor/text-h-three.svg +1 -0
  533. package/icons/phosphor/text-h-two.svg +1 -0
  534. package/icons/phosphor/text-italic.svg +1 -0
  535. package/icons/phosphor/text-t.svg +1 -0
  536. package/icons/phosphor/ticket.svg +1 -0
  537. package/icons/phosphor/toggle-right.svg +1 -0
  538. package/icons/phosphor/train.svg +1 -0
  539. package/icons/phosphor/trash.svg +1 -0
  540. package/icons/phosphor/upload-simple.svg +1 -0
  541. package/icons/phosphor/user-circle.svg +1 -0
  542. package/icons/phosphor/user.svg +1 -0
  543. package/icons/phosphor/users-three.svg +1 -0
  544. package/icons/phosphor/users.svg +1 -0
  545. package/icons/phosphor/video-camera.svg +1 -0
  546. package/icons/phosphor/warning-circle.svg +1 -0
  547. package/icons/phosphor/warning.svg +1 -0
  548. package/icons/phosphor/wave-sine.svg +1 -0
  549. package/icons/phosphor/wheelchair.svg +1 -0
  550. package/icons/phosphor/wrench.svg +1 -0
  551. package/icons/phosphor/x.svg +1 -0
  552. package/lib/apps.d.mts +28 -0
  553. package/lib/apps.mjs +139 -0
  554. package/lib/blocks.d.mts +23 -0
  555. package/lib/blocks.mjs +90 -0
  556. package/lib/colors.ts +86 -0
  557. package/lib/contactBar.ts +18 -0
  558. package/lib/cookieCategories.d.mts +17 -0
  559. package/lib/cookieCategories.mjs +28 -0
  560. package/lib/crop.d.mts +34 -0
  561. package/lib/crop.mjs +83 -0
  562. package/lib/csp.d.mts +22 -0
  563. package/lib/csp.mjs +130 -0
  564. package/lib/cspSources.d.mts +24 -0
  565. package/lib/cspSources.mjs +60 -0
  566. package/lib/dynamic-colors.ts +426 -0
  567. package/lib/git.d.mts +24 -0
  568. package/lib/git.mjs +64 -0
  569. package/lib/hooks.ts +51 -0
  570. package/lib/inline.ts +20 -0
  571. package/lib/license-texts/Apache-2.0.txt +191 -0
  572. package/lib/license-texts/BSD-2-Clause.txt +24 -0
  573. package/lib/license-texts/BSD-3-Clause.txt +28 -0
  574. package/lib/license-texts/ISC.txt +15 -0
  575. package/lib/license-texts/MIT.txt +21 -0
  576. package/lib/licenses.d.mts +190 -0
  577. package/lib/licenses.mjs +683 -0
  578. package/lib/markdown.ts +42 -0
  579. package/lib/motion-schemes.d.mts +2 -0
  580. package/lib/motion-schemes.mjs +5 -0
  581. package/lib/motion.ts +131 -0
  582. package/lib/notice.d.mts +3 -0
  583. package/lib/notice.mjs +34 -0
  584. package/lib/scheduled.d.mts +15 -0
  585. package/lib/scheduled.mjs +37 -0
  586. package/lib/snackbar.ts +149 -0
  587. package/lib/status.d.mts +7 -0
  588. package/lib/status.mjs +18 -0
  589. package/lib/svg.d.mts +22 -0
  590. package/lib/svg.mjs +231 -0
  591. package/lib/text-colors.d.mts +11 -0
  592. package/lib/text-colors.mjs +43 -0
  593. package/lib/video-id.d.mts +14 -0
  594. package/lib/video-id.mjs +72 -0
  595. package/lib/video.d.mts +20 -0
  596. package/lib/video.mjs +91 -0
  597. package/package.json +131 -6
  598. package/pages/404.astro +10 -0
  599. package/pages/[...slug].astro +51 -0
  600. package/pages/_headers.txt +31 -0
  601. package/pages/blog/index.astro +10 -0
  602. package/pages/blog/kategori/[category].astro +18 -0
  603. package/pages/editor/code-images.json.js +25 -0
  604. package/pages/editor/index.astro +75 -0
  605. package/pages/editor/manifest.webmanifest.js +23 -0
  606. package/pages/editor/sw.js +33 -0
  607. package/pages/editor/sw.js.js +4 -0
  608. package/pages/editor/thumbnails.json.js +21 -0
  609. package/pages/editor/version.json.js +22 -0
  610. package/pages/headers.js +4 -0
  611. package/pages/index.astro +10 -0
  612. package/pages/ny.astro +6 -0
  613. package/pages/robots.txt.js +3 -0
  614. package/pages/rss.xml.js +20 -0
  615. package/scripts/app-screenshots.mjs +164 -0
  616. package/scripts/app-workers.mjs +6 -0
  617. package/scripts/bin.mjs +12 -0
  618. package/scripts/built-site.mjs +99 -0
  619. package/scripts/check-consent.mjs +113 -0
  620. package/scripts/check-content.mjs +149 -0
  621. package/scripts/check-demo.mjs +24 -0
  622. package/scripts/check-themes.mjs +45 -0
  623. package/scripts/check-worker.mjs +569 -0
  624. package/scripts/compare-html.mjs +81 -0
  625. package/scripts/demo-site.mjs +42 -0
  626. package/scripts/editor-icons.mjs +56 -0
  627. package/scripts/editor-roundtrip.mjs +134 -0
  628. package/scripts/editor-screens.mjs +101 -0
  629. package/scripts/git-env.mjs +9 -0
  630. package/scripts/icon-packs.mjs +151 -0
  631. package/scripts/link-counts.mjs +22 -0
  632. package/scripts/page-colors.mjs +42 -0
  633. package/scripts/releases.d.mts +10 -0
  634. package/scripts/releases.mjs +80 -0
  635. package/scripts/responsive-images.mjs +94 -0
  636. package/scripts/scheduled-list.mjs +15 -0
  637. package/scripts/theme-screenshots.mjs +88 -0
  638. package/scripts/types.mjs +21 -0
  639. package/scripts/video-thumbnails.mjs +89 -0
  640. package/scripts/worker-modules.mjs +34 -0
  641. package/site/appCookies.d.mts +9 -0
  642. package/site/appCookies.mjs +74 -0
  643. package/site/apps.ts +21 -0
  644. package/site/autolinks.d.mts +11 -0
  645. package/site/autolinks.mjs +200 -0
  646. package/site/blockScripts.ts +31 -0
  647. package/site/categories.ts +16 -0
  648. package/site/consent.ts +26 -0
  649. package/site/content.config.ts +84 -0
  650. package/site/content.ts +104 -0
  651. package/site/cookieList.ts +17 -0
  652. package/site/defineSite.d.mts +142 -0
  653. package/site/defineSite.mjs +136 -0
  654. package/site/directives/interact.d.mts +2 -0
  655. package/site/directives/interact.mjs +31 -0
  656. package/site/editor-version.d.mts +1 -0
  657. package/site/editor-version.mjs +26 -0
  658. package/site/fill.ts +13 -0
  659. package/site/format.ts +11 -0
  660. package/site/home.ts +66 -0
  661. package/site/iconPacks.d.mts +20 -0
  662. package/site/iconPacks.mjs +43 -0
  663. package/site/icons.d.mts +693 -0
  664. package/site/icons.mjs +605 -0
  665. package/site/images.d.mts +43 -0
  666. package/site/images.mjs +157 -0
  667. package/site/motion.ts +13 -0
  668. package/site/noindex.d.mts +6 -0
  669. package/site/noindex.mjs +21 -0
  670. package/site/pageColors.ts +110 -0
  671. package/site/popups.ts +98 -0
  672. package/site/schema.ts +189 -0
  673. package/site/sections.ts +3 -0
  674. package/site/seo.ts +28 -0
  675. package/site/site.ts +76 -0
  676. package/site/siteConfig.d.mts +1 -0
  677. package/site/siteConfig.mjs +8 -0
  678. package/site/siteCsp.d.mts +10 -0
  679. package/site/siteCsp.mjs +75 -0
  680. package/site/siteModules.d.mts +7 -0
  681. package/site/siteModules.mjs +27 -0
  682. package/site/standardPages.ts +59 -0
  683. package/site/testimonials.ts +48 -0
  684. package/site/text.ts +43 -0
  685. package/site/theme.d.mts +83 -0
  686. package/site/theme.mjs +472 -0
  687. package/site/tracking.client.ts +225 -0
  688. package/site/tracking.ts +9 -0
  689. package/src/ActionParts.tsx +205 -0
  690. package/src/Advanced.tsx +152 -0
  691. package/src/App.tsx +904 -0
  692. package/src/AppList.tsx +1345 -0
  693. package/src/BlockDialog.tsx +360 -0
  694. package/src/BlockParts.tsx +652 -0
  695. package/src/BlockSettings.tsx +533 -0
  696. package/src/BrandForm.tsx +164 -0
  697. package/src/Colors.tsx +476 -0
  698. package/src/CommunicationParts.tsx +199 -0
  699. package/src/CompanyForm.tsx +209 -0
  700. package/src/Consents.tsx +175 -0
  701. package/src/ContainmentParts.tsx +185 -0
  702. package/src/Crop.tsx +152 -0
  703. package/src/DataForm.tsx +434 -0
  704. package/src/Deleted.tsx +177 -0
  705. package/src/EntryForm.tsx +740 -0
  706. package/src/FileView.tsx +30 -0
  707. package/src/FormFrame.tsx +237 -0
  708. package/src/Keywords.tsx +225 -0
  709. package/src/Library.tsx +1563 -0
  710. package/src/Licenses.tsx +336 -0
  711. package/src/LinkSheet.tsx +138 -0
  712. package/src/MarkdownEditor.tsx +1075 -0
  713. package/src/Media.tsx +677 -0
  714. package/src/NavigationParts.tsx +350 -0
  715. package/src/NavigationRestParts.tsx +247 -0
  716. package/src/Notifications.tsx +59 -0
  717. package/src/PagePicker.tsx +136 -0
  718. package/src/Parts.tsx +991 -0
  719. package/src/PartsShown.tsx +168 -0
  720. package/src/PickerParts.tsx +183 -0
  721. package/src/Redirects.tsx +450 -0
  722. package/src/Screen.tsx +184 -0
  723. package/src/SectionsField.tsx +65 -0
  724. package/src/SelectionParts.tsx +134 -0
  725. package/src/SeoScores.tsx +184 -0
  726. package/src/Sheet.tsx +35 -0
  727. package/src/ThemeStore.tsx +376 -0
  728. package/src/Tokens.tsx +346 -0
  729. package/src/Versions.tsx +214 -0
  730. package/src/addresses.ts +75 -0
  731. package/src/allIcons.ts +7 -0
  732. package/src/appFiles.ts +29 -0
  733. package/src/apps.ts +281 -0
  734. package/src/ask.tsx +123 -0
  735. package/src/blocks.ts +251 -0
  736. package/src/brand.ts +153 -0
  737. package/src/cache.ts +42 -0
  738. package/src/check.ts +285 -0
  739. package/src/checkSite.ts +256 -0
  740. package/src/consents.ts +26 -0
  741. package/src/cookieList.ts +70 -0
  742. package/src/countries.ts +59 -0
  743. package/src/deploy.ts +155 -0
  744. package/src/editor.css +602 -0
  745. package/src/examples.ts +85 -0
  746. package/src/fields.tsx +942 -0
  747. package/src/frontmatter.d.mts +6 -0
  748. package/src/frontmatter.mjs +42 -0
  749. package/src/github.ts +376 -0
  750. package/src/i18n/da-DK/advanced.ts +28 -0
  751. package/src/i18n/da-DK/app.ts +71 -0
  752. package/src/i18n/da-DK/apps.ts +90 -0
  753. package/src/i18n/da-DK/blockSettings.ts +38 -0
  754. package/src/i18n/da-DK/blocks.ts +408 -0
  755. package/src/i18n/da-DK/check.ts +25 -0
  756. package/src/i18n/da-DK/colors.ts +64 -0
  757. package/src/i18n/da-DK/common.ts +118 -0
  758. package/src/i18n/da-DK/company.ts +24 -0
  759. package/src/i18n/da-DK/consents.ts +23 -0
  760. package/src/i18n/da-DK/forms.ts +116 -0
  761. package/src/i18n/da-DK/history.ts +35 -0
  762. package/src/i18n/da-DK/index.ts +49 -0
  763. package/src/i18n/da-DK/keywords.ts +19 -0
  764. package/src/i18n/da-DK/library.ts +135 -0
  765. package/src/i18n/da-DK/licenses.ts +25 -0
  766. package/src/i18n/da-DK/media.ts +79 -0
  767. package/src/i18n/da-DK/parts.ts +696 -0
  768. package/src/i18n/da-DK/preview.ts +13 -0
  769. package/src/i18n/da-DK/redirects.ts +51 -0
  770. package/src/i18n/da-DK/seo.ts +20 -0
  771. package/src/i18n/da-DK/text.ts +35 -0
  772. package/src/i18n/da-DK/theme.ts +41 -0
  773. package/src/i18n/en-US/advanced.ts +32 -0
  774. package/src/i18n/en-US/app.ts +84 -0
  775. package/src/i18n/en-US/apps.ts +134 -0
  776. package/src/i18n/en-US/blockSettings.ts +48 -0
  777. package/src/i18n/en-US/blocks.ts +441 -0
  778. package/src/i18n/en-US/check.ts +31 -0
  779. package/src/i18n/en-US/colors.ts +82 -0
  780. package/src/i18n/en-US/common.ts +144 -0
  781. package/src/i18n/en-US/company.ts +25 -0
  782. package/src/i18n/en-US/consents.ts +25 -0
  783. package/src/i18n/en-US/forms.ts +145 -0
  784. package/src/i18n/en-US/history.ts +43 -0
  785. package/src/i18n/en-US/index.ts +51 -0
  786. package/src/i18n/en-US/keywords.ts +24 -0
  787. package/src/i18n/en-US/library.ts +176 -0
  788. package/src/i18n/en-US/licenses.ts +36 -0
  789. package/src/i18n/en-US/media.ts +80 -0
  790. package/src/i18n/en-US/parts.ts +718 -0
  791. package/src/i18n/en-US/preview.ts +15 -0
  792. package/src/i18n/en-US/redirects.ts +66 -0
  793. package/src/i18n/en-US/seo.ts +26 -0
  794. package/src/i18n/en-US/text.ts +41 -0
  795. package/src/i18n/en-US/theme.ts +41 -0
  796. package/src/i18n/index.ts +124 -0
  797. package/src/icon.tsx +160 -0
  798. package/src/iconPacks.ts +89 -0
  799. package/src/images.ts +163 -0
  800. package/src/licenses.ts +79 -0
  801. package/src/markdown.d.mts +12 -0
  802. package/src/markdown.mjs +204 -0
  803. package/src/nav.ts +68 -0
  804. package/src/notFound.ts +28 -0
  805. package/src/notifications.ts +223 -0
  806. package/src/pagePreview.tsx +204 -0
  807. package/src/r2Caching.ts +55 -0
  808. package/src/redirects.ts +149 -0
  809. package/src/registry.tsx +188 -0
  810. package/src/schema.ts +417 -0
  811. package/src/sections.d.mts +45 -0
  812. package/src/sections.mjs +303 -0
  813. package/src/seo.ts +333 -0
  814. package/src/shared.ts +44 -0
  815. package/src/sidebar.ts +31 -0
  816. package/src/site.ts +317 -0
  817. package/src/standard/Block.astro +19 -0
  818. package/src/standard/BlockSite.astro +18 -0
  819. package/src/standard/accordion/index.tsx +47 -0
  820. package/src/standard/accordion/load.ts +23 -0
  821. package/src/standard/accordion/shared.ts +15 -0
  822. package/src/standard/accordion/view.ts +32 -0
  823. package/src/standard/buttons/fields.ts +98 -0
  824. package/src/standard/buttons/index.tsx +23 -0
  825. package/src/standard/buttons/load.ts +34 -0
  826. package/src/standard/buttons/shared.ts +12 -0
  827. package/src/standard/buttons/view.ts +30 -0
  828. package/src/standard/cards/index.tsx +71 -0
  829. package/src/standard/cards/load.ts +17 -0
  830. package/src/standard/cards/shared.ts +27 -0
  831. package/src/standard/cards/view.ts +29 -0
  832. package/src/standard/checklist/index.tsx +27 -0
  833. package/src/standard/checklist/load.ts +5 -0
  834. package/src/standard/checklist/view.ts +13 -0
  835. package/src/standard/cookies/index.tsx +17 -0
  836. package/src/standard/cookies/list.ts +56 -0
  837. package/src/standard/cookies/load.ts +11 -0
  838. package/src/standard/cookies/shared.ts +20 -0
  839. package/src/standard/cookies/view.ts +28 -0
  840. package/src/standard/faq/index.tsx +29 -0
  841. package/src/standard/faq/load.ts +14 -0
  842. package/src/standard/faq/view.ts +21 -0
  843. package/src/standard/head.ts +23 -0
  844. package/src/standard/hero/fields.ts +48 -0
  845. package/src/standard/hero/index.tsx +57 -0
  846. package/src/standard/hero/load.ts +23 -0
  847. package/src/standard/hero/view.ts +38 -0
  848. package/src/standard/links/index.tsx +41 -0
  849. package/src/standard/links/load.ts +17 -0
  850. package/src/standard/links/view.ts +25 -0
  851. package/src/standard/list/index.tsx +50 -0
  852. package/src/standard/list/load.ts +5 -0
  853. package/src/standard/list/view.ts +18 -0
  854. package/src/standard/load.ts +7 -0
  855. package/src/standard/notice/index.tsx +30 -0
  856. package/src/standard/notice/load.ts +16 -0
  857. package/src/standard/notice/view.ts +10 -0
  858. package/src/standard/points/index.tsx +42 -0
  859. package/src/standard/points/load.ts +5 -0
  860. package/src/standard/points/view.ts +12 -0
  861. package/src/standard/posts/index.tsx +132 -0
  862. package/src/standard/posts/load.ts +36 -0
  863. package/src/standard/posts/shared.ts +21 -0
  864. package/src/standard/posts/view.ts +63 -0
  865. package/src/standard/pricecards/index.tsx +57 -0
  866. package/src/standard/pricecards/load.ts +11 -0
  867. package/src/standard/pricecards/view.ts +50 -0
  868. package/src/standard/sharedTexts.ts +6 -0
  869. package/src/standard/site.ts +124 -0
  870. package/src/standard/siteLooks.ts +19 -0
  871. package/src/standard/sites.ts +13 -0
  872. package/src/standard/steps/index.tsx +28 -0
  873. package/src/standard/steps/load.ts +5 -0
  874. package/src/standard/steps/view.ts +11 -0
  875. package/src/standard/testimonials/index.tsx +87 -0
  876. package/src/standard/testimonials/list.ts +43 -0
  877. package/src/standard/testimonials/load.ts +58 -0
  878. package/src/standard/testimonials/shared.ts +13 -0
  879. package/src/standard/testimonials/view.ts +76 -0
  880. package/src/standard/themeBlocks.ts +13 -0
  881. package/src/standard/video/index.tsx +23 -0
  882. package/src/standard/video/load.ts +10 -0
  883. package/src/standard/video/view.ts +42 -0
  884. package/src/standard/view.tsx +105 -0
  885. package/src/standard/views.ts +37 -0
  886. package/src/store.ts +499 -0
  887. package/src/theme.ts +90 -0
  888. package/src/themeUi.ts +97 -0
  889. package/src/themes.ts +91 -0
  890. package/src/ui.tsx +3402 -0
  891. package/src/virtual.d.ts +5 -0
  892. package/src/when.ts +22 -0
  893. package/starter/.githooks/pre-push +4 -0
  894. package/starter/.nvmrc +1 -0
  895. package/starter/.prettierignore +11 -0
  896. package/starter/.prettierrc.json +7 -0
  897. package/starter/README.md +26 -0
  898. package/starter/astro.config.mjs +5 -0
  899. package/starter/package.json +67 -0
  900. package/starter/public/_redirects +1 -0
  901. package/starter/public/apple-touch-icon.png +0 -0
  902. package/starter/public/editor/apple-touch-icon.png +0 -0
  903. package/starter/public/editor/icon-192.png +0 -0
  904. package/starter/public/editor/icon-512.png +0 -0
  905. package/starter/public/editor/icon-maskable-512.png +0 -0
  906. package/starter/public/favicon.ico +0 -0
  907. package/starter/public/favicon.svg +1 -0
  908. package/starter/public/logo.svg +1 -0
  909. package/starter/src/content/pages/blog.md +8 -0
  910. package/starter/src/content/pages/forside.md +9 -0
  911. package/starter/src/content/pages/kontakt.md +7 -0
  912. package/starter/src/content/pages/privatlivspolitik.md +9 -0
  913. package/starter/src/content/pages/siden-findes-ikke.md +7 -0
  914. package/starter/src/content.config.ts +2 -0
  915. package/starter/src/data/apps.json +1 -0
  916. package/starter/src/data/block-settings.json +3 -0
  917. package/starter/src/data/blocks.json +1 -0
  918. package/starter/src/data/booking.json +6 -0
  919. package/starter/src/data/colors.json +70 -0
  920. package/starter/src/data/contact.json +8 -0
  921. package/starter/src/data/cookies.json +21 -0
  922. package/starter/src/data/csp.json +1 -0
  923. package/starter/src/data/footer.json +15 -0
  924. package/starter/src/data/internal-links.json +4 -0
  925. package/starter/src/data/menu.json +4 -0
  926. package/starter/src/data/mobile-menu.json +4 -0
  927. package/starter/src/data/old-addresses.json +1 -0
  928. package/starter/src/data/redirects.json +1 -0
  929. package/starter/src/data/standard-pages.json +8 -0
  930. package/starter/src/data/theme.json +1 -0
  931. package/starter/src/env.d.ts +2 -0
  932. package/starter/src/site/config.ts +13 -0
  933. package/starter/src/site/worker.js +14 -0
  934. package/starter/tsconfig.json +17 -0
  935. package/starter/worker/apps.js +6 -0
  936. package/starter/wrangler.jsonc +39 -0
  937. package/theme/LICENSE +21 -0
  938. package/theme/blocks/ArrowLink.tsx +14 -0
  939. package/theme/blocks/BlockHead.tsx +26 -0
  940. package/theme/blocks/Panel.tsx +32 -0
  941. package/theme/blocks/Person.tsx +26 -0
  942. package/theme/blocks/accordion/PageRow.tsx +25 -0
  943. package/theme/blocks/accordion/View.tsx +17 -0
  944. package/theme/blocks/buttons/Buttons.tsx +28 -0
  945. package/theme/blocks/buttons/View.tsx +12 -0
  946. package/theme/blocks/cards/LinkCards.tsx +72 -0
  947. package/theme/blocks/cards/View.tsx +20 -0
  948. package/theme/blocks/checklist/Checks.tsx +15 -0
  949. package/theme/blocks/checklist/View.tsx +14 -0
  950. package/theme/blocks/cookies/View.tsx +36 -0
  951. package/theme/blocks/faq/Accordion.tsx +34 -0
  952. package/theme/blocks/faq/View.tsx +16 -0
  953. package/theme/blocks/faq/script.ts +56 -0
  954. package/theme/blocks/hero/View.tsx +44 -0
  955. package/theme/blocks/links/LinkGroups.tsx +24 -0
  956. package/theme/blocks/links/View.tsx +17 -0
  957. package/theme/blocks/list/Rows.tsx +24 -0
  958. package/theme/blocks/list/View.tsx +14 -0
  959. package/theme/blocks/notice/View.tsx +13 -0
  960. package/theme/blocks/points/PointList.tsx +34 -0
  961. package/theme/blocks/points/View.tsx +14 -0
  962. package/theme/blocks/posts/View.tsx +26 -0
  963. package/theme/blocks/pricecards/View.tsx +40 -0
  964. package/theme/blocks/steps/StepList.tsx +23 -0
  965. package/theme/blocks/steps/View.tsx +14 -0
  966. package/theme/blocks/testimonials/List.tsx +46 -0
  967. package/theme/blocks/testimonials/Slider.tsx +44 -0
  968. package/theme/blocks/testimonials/Testimonial.tsx +124 -0
  969. package/theme/blocks/testimonials/View.tsx +21 -0
  970. package/theme/blocks/testimonials/script.ts +52 -0
  971. package/theme/blocks/video/View.tsx +41 -0
  972. package/theme/components/ActionBar.astro +63 -0
  973. package/theme/components/AppSlot.astro +21 -0
  974. package/theme/components/ArrowLink.tsx +21 -0
  975. package/theme/components/BlogIndex.astro +48 -0
  976. package/theme/components/BlogPosts.astro +18 -0
  977. package/theme/components/BlogPosts.tsx +45 -0
  978. package/theme/components/BookButton.tsx +22 -0
  979. package/theme/components/Container.astro +11 -0
  980. package/theme/components/CookieConsent.astro +121 -0
  981. package/theme/components/EndBlock.astro +21 -0
  982. package/theme/components/FontPreload.astro +6 -0
  983. package/theme/components/Footer.astro +85 -0
  984. package/theme/components/Header.astro +186 -0
  985. package/theme/components/Icon.astro +16 -0
  986. package/theme/components/Img.astro +29 -0
  987. package/theme/components/Img.tsx +33 -0
  988. package/theme/components/Inline.astro +11 -0
  989. package/theme/components/Logo.astro +23 -0
  990. package/theme/components/LogoMark.astro +10 -0
  991. package/theme/components/Markdown.astro +17 -0
  992. package/theme/components/MobileMenu.tsx +224 -0
  993. package/theme/components/MobileNav.astro +33 -0
  994. package/theme/components/PageHeader.astro +22 -0
  995. package/theme/components/PageSection.astro +24 -0
  996. package/theme/components/PhoneButton.tsx +11 -0
  997. package/theme/components/Popup.astro +145 -0
  998. package/theme/components/PopupButton.tsx +24 -0
  999. package/theme/components/PopupView.tsx +48 -0
  1000. package/theme/components/PostList.tsx +58 -0
  1001. package/theme/components/PostMeta.tsx +17 -0
  1002. package/theme/components/RichText.astro +28 -0
  1003. package/theme/components/Section.astro +29 -0
  1004. package/theme/components/SectionHeading.tsx +8 -0
  1005. package/theme/components/TextSection.astro +16 -0
  1006. package/theme/components/home/PageBlock.astro +19 -0
  1007. package/theme/components/home/Text.astro +13 -0
  1008. package/theme/components/loadPopup.ts +22 -0
  1009. package/theme/components/loadPosts.ts +16 -0
  1010. package/theme/components/posts.ts +15 -0
  1011. package/theme/editor/looks.mjs +7 -0
  1012. package/theme/editor/previews.tsx +56 -0
  1013. package/theme/layouts/Base.astro +273 -0
  1014. package/theme/layouts/PageLayout.astro +126 -0
  1015. package/theme/layouts/PostLayout.astro +137 -0
  1016. package/theme/screenshots/1-front.jpg +0 -0
  1017. package/theme/screenshots/2-front-dark.jpg +0 -0
  1018. package/theme/screenshots/3-blog.jpg +0 -0
  1019. package/theme/screenshots/4-contact.jpg +0 -0
  1020. package/theme/scripts/motion.ts +29 -0
  1021. package/theme/styles/base.css +320 -0
  1022. package/theme/styles/blocks.css +1808 -0
  1023. package/theme/styles/components.css +206 -0
  1024. package/theme/styles/global.css +1302 -0
  1025. package/theme/styles/ui.css +6544 -0
  1026. package/theme/templates/Blog.astro +38 -0
  1027. package/theme/templates/Category.astro +19 -0
  1028. package/theme/templates/Home.astro +36 -0
  1029. package/theme/templates/New.astro +68 -0
  1030. package/theme/templates/NotFound.astro +117 -0
  1031. package/theme/theme.json +28 -0
  1032. package/theme/ui/Badge.tsx +45 -0
  1033. package/theme/ui/BottomSheet.tsx +148 -0
  1034. package/theme/ui/Button.tsx +79 -0
  1035. package/theme/ui/ButtonGroup.tsx +31 -0
  1036. package/theme/ui/Card.tsx +45 -0
  1037. package/theme/ui/Carousel.tsx +124 -0
  1038. package/theme/ui/Checkbox.tsx +59 -0
  1039. package/theme/ui/Chip.tsx +101 -0
  1040. package/theme/ui/ChipSet.tsx +27 -0
  1041. package/theme/ui/DatePicker.tsx +149 -0
  1042. package/theme/ui/DatePickerContainer.tsx +316 -0
  1043. package/theme/ui/Dialog.tsx +100 -0
  1044. package/theme/ui/Divider.tsx +27 -0
  1045. package/theme/ui/ExposedDropdownMenu.tsx +77 -0
  1046. package/theme/ui/Fab.tsx +88 -0
  1047. package/theme/ui/FabMenu.tsx +67 -0
  1048. package/theme/ui/IconButton.tsx +78 -0
  1049. package/theme/ui/List.tsx +287 -0
  1050. package/theme/ui/LoadingIndicator.tsx +29 -0
  1051. package/theme/ui/Menu.tsx +278 -0
  1052. package/theme/ui/NavigationBar.tsx +62 -0
  1053. package/theme/ui/NavigationDrawer.tsx +80 -0
  1054. package/theme/ui/NavigationRail.tsx +154 -0
  1055. package/theme/ui/ProgressIndicator.tsx +162 -0
  1056. package/theme/ui/RadioButton.tsx +50 -0
  1057. package/theme/ui/Search.tsx +129 -0
  1058. package/theme/ui/SegmentedButton.tsx +49 -0
  1059. package/theme/ui/SideSheet.tsx +54 -0
  1060. package/theme/ui/Slider.tsx +155 -0
  1061. package/theme/ui/Snackbar.tsx +67 -0
  1062. package/theme/ui/SplitButton.tsx +67 -0
  1063. package/theme/ui/Switch.tsx +60 -0
  1064. package/theme/ui/Tabs.tsx +114 -0
  1065. package/theme/ui/TextField.tsx +278 -0
  1066. package/theme/ui/TimePicker.tsx +128 -0
  1067. package/theme/ui/TimePickerContainer.tsx +234 -0
  1068. package/theme/ui/Toolbar.tsx +67 -0
  1069. package/theme/ui/Tooltip.tsx +58 -0
  1070. package/theme/ui/TopAppBar.tsx +77 -0
  1071. package/theme/ui/bottomSheet.script.ts +8 -0
  1072. package/theme/ui/bottomSheet.ts +211 -0
  1073. package/theme/ui/carousel.script.ts +28 -0
  1074. package/theme/ui/carouselLayout.ts +229 -0
  1075. package/theme/ui/checkbox.script.ts +8 -0
  1076. package/theme/ui/datePicker.script.ts +302 -0
  1077. package/theme/ui/dates.ts +185 -0
  1078. package/theme/ui/dialog.ts +48 -0
  1079. package/theme/ui/dropdownMenu.script.ts +166 -0
  1080. package/theme/ui/fabMenu.script.ts +57 -0
  1081. package/theme/ui/navigationRail.script.ts +47 -0
  1082. package/theme/ui/ripple.script.ts +159 -0
  1083. package/theme/ui/search.script.ts +92 -0
  1084. package/theme/ui/sideSheet.ts +48 -0
  1085. package/theme/ui/slider.script.ts +12 -0
  1086. package/theme/ui/sliderUpdate.ts +52 -0
  1087. package/theme/ui/snackbar.script.ts +16 -0
  1088. package/theme/ui/splitButton.script.ts +63 -0
  1089. package/theme/ui/tabs.script.ts +48 -0
  1090. package/theme/ui/textField.script.ts +17 -0
  1091. package/theme/ui/textFieldUpdate.ts +44 -0
  1092. package/theme/ui/timePicker.script.ts +248 -0
  1093. package/theme/ui/toolbar.script.ts +43 -0
  1094. package/theme/ui/tooltip.script.ts +68 -0
  1095. package/worker/consent.js +141 -0
  1096. package/worker/editor-github.js +167 -0
  1097. package/worker/editor-host.js +74 -0
  1098. package/worker/files.js +401 -0
  1099. package/worker/github.js +36 -0
  1100. package/worker/index.js +184 -0
  1101. package/worker/not-found.js +97 -0
  1102. package/worker/oauth.js +95 -0
  1103. package/worker/publish.js +52 -0
  1104. package/worker/push.js +270 -0
  1105. package/worker/r2-status.js +50 -0
  1106. package/worker/session.js +58 -0
@@ -0,0 +1,6 @@
1
+ export function splitFrontmatter(text: any): {
2
+ yaml: any;
3
+ body: any;
4
+ };
5
+ export function readFields(yaml: any): any;
6
+ export function writeFields(yaml: any, changes: any): string;
@@ -0,0 +1,42 @@
1
+ // Front matter in the .md files: the YAML block between the "---" lines, and the Markdown after it.
2
+ // Only changed fields are written, in the style of the existing files: text in double quotes, lists
3
+ // inline (["a", "b"]), dates and true/false without quotes. Long lines are never folded, and a line
4
+ // break in a text stays \n on the same line (doubleQuotedAsJSON), as the files write it.
5
+ import { parseDocument } from 'yaml';
6
+
7
+ const FENCE = /^---\r?\n(?:([\s\S]*?)\r?\n)?---\r?\n?/;
8
+ const DATE = /^\d{4}-\d{2}-\d{2}$/;
9
+ // The fields that are dates (src/content.config.ts). Any other text is quoted, also one that looks
10
+ // like a date: unquoted, YAML reads it as a date, and the schema (a text) fails the build.
11
+ const DATE_FIELDS = new Set(['date', 'updated']);
12
+ const STRINGIFY = { lineWidth: 0, flowCollectionPadding: false, doubleQuotedAsJSON: true };
13
+
14
+ export function splitFrontmatter(text) {
15
+ const match = text.match(FENCE);
16
+ return match ? { yaml: match[1] ?? '', body: text.slice(match[0].length) } : { yaml: '', body: text };
17
+ }
18
+
19
+ export function readFields(yaml) {
20
+ return parseDocument(yaml).toJS() ?? {};
21
+ }
22
+
23
+ // changes: { field: value }. An empty text removes the field (the content schemas treat a missing
24
+ // field as empty); new fields are added at the end, in the order given.
25
+ export function writeFields(yaml, changes) {
26
+ const doc = parseDocument(yaml);
27
+ for (const [key, value] of Object.entries(changes)) {
28
+ if (value !== '' && value != null) doc.set(key, toNode(doc, key, value));
29
+ else if (doc.has(key)) doc.delete(key);
30
+ }
31
+ return doc.contents?.items?.length ? doc.toString(STRINGIFY).replace(/\n$/, '') : '';
32
+ }
33
+
34
+ function toNode(doc, key, value) {
35
+ const node = doc.createNode(value);
36
+ if (typeof value === 'string') node.type = DATE_FIELDS.has(key) && DATE.test(value) ? 'PLAIN' : 'QUOTE_DOUBLE';
37
+ if (Array.isArray(value)) {
38
+ node.flow = true;
39
+ for (const item of node.items) item.type = 'QUOTE_DOUBLE';
40
+ }
41
+ return node;
42
+ }
package/src/github.ts ADDED
@@ -0,0 +1,376 @@
1
+ // GitHub for the editor, through the site's Worker (packages/editor/worker/editor-github.js): the sign-in (packages/editor/worker/oauth.js) is a
2
+ // cookie only the Worker can read (packages/editor/worker/session.js), so the browser never has the token, and every question to GitHub
3
+ // goes through the Worker with it. The site's files come from the Worker's cache in R2 (packages/editor/worker/files.js) by their git
4
+ // ids, and from this browser when it has them: a file's text is asked for once. Only people with write access to the
5
+ // repository can save; GitHub checks that on every commit.
6
+
7
+ import { config } from '@site/config';
8
+ import { blobId } from '../lib/git.mjs';
9
+ import { t } from './i18n';
10
+
11
+ export const REPO = config.repo;
12
+
13
+ // Where the token was kept before the sign-in moved into the Worker's cookie: removed, so it is not left readable.
14
+ const OLD_TOKEN_KEY = 'editor-github-token';
15
+ try {
16
+ localStorage.removeItem(OLD_TOKEN_KEY);
17
+ } catch {}
18
+
19
+ // "Log ud": the Worker removes the cookie, and GitHub forgets the token.
20
+ export async function logout() {
21
+ await fetch('/api/github/logout', { method: 'POST' }).catch(() => {});
22
+ }
23
+
24
+ // Sign in: the Worker sends the browser to GitHub and back, keeps the token in its cookie and opens
25
+ // /editor/ again (packages/editor/worker/oauth.js). A redirect, not a popup, so it works in the installed app too.
26
+ export function login() {
27
+ location.assign('/oauth/auth?provider=github&scope=repo');
28
+ }
29
+
30
+ export class AuthError extends Error {}
31
+
32
+ export class ConflictError extends Error {}
33
+
34
+ // A question to the Worker's /api/github/<path>, and its answer in JSON.
35
+ async function api<T>(path: string, body?: unknown): Promise<T> {
36
+ const res = await fetch(`/api/github/${path}`, {
37
+ cache: 'no-store',
38
+ ...(body === undefined ? {} : { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body) }),
39
+ });
40
+ if (res.status === 401) throw new AuthError(t.app.loggedOut);
41
+ const json = await res.json().catch(() => ({}));
42
+ if (res.status === 409) throw new ConflictError(json.conflict === 'exists' ? t.app.fileExists : t.app.changedElsewhere);
43
+ if (!res.ok) throw new Error(json.error ?? t.app.githubAnswered(json.status ?? res.status));
44
+ return json;
45
+ }
46
+
47
+ export async function graphql<T>(query: string, variables: Record<string, unknown> = {}): Promise<T> {
48
+ const res = await fetch('/api/github/graphql', {
49
+ method: 'POST',
50
+ headers: { 'content-type': 'application/json' },
51
+ body: JSON.stringify({ query, variables }),
52
+ });
53
+ if (res.status === 401) throw new AuthError(t.app.loggedOut);
54
+ const json = await res.json().catch(() => ({}));
55
+ if (!res.ok || json.errors?.length) throw new Error(json.errors?.[0]?.message ?? t.app.githubAnswered(res.status));
56
+ return json.data;
57
+ }
58
+
59
+ export type Viewer = { login: string; name: string | null; canSave: boolean };
60
+
61
+ export async function viewer(): Promise<Viewer> {
62
+ const data = await graphql<{ viewer: { login: string; name: string | null }; repository: { viewerPermission: string } | null }>(
63
+ `
64
+ query ($owner: String!, $name: String!) {
65
+ viewer {
66
+ login
67
+ name
68
+ }
69
+ repository(owner: $owner, name: $name) {
70
+ viewerPermission
71
+ }
72
+ }
73
+ `,
74
+ { owner: REPO.owner, name: REPO.name },
75
+ );
76
+ const permission = data.repository?.viewerPermission ?? '';
77
+ return { ...data.viewer, canSave: ['ADMIN', 'MAINTAIN', 'WRITE'].includes(permission) };
78
+ }
79
+
80
+ // One file in the repository as the editor loaded it: its path, text and git blob id. The blob id
81
+ // tells whether the file has been changed elsewhere (another browser, a push) since.
82
+ export type RepoFile = { path: string; oid: string; text: string };
83
+
84
+ /** The commit the branch is at, and its root tree (the files in it). */
85
+ export type Head = { commit: string; tree: string };
86
+
87
+ // A file as the Worker lists it: its blob id, and whether GitHub calls it binary (a picture: no text).
88
+ type Listed = { path: string; oid: string; binary: boolean };
89
+
90
+ // The texts of the files this browser has, by their blob ids (a blob id's text never changes): those it loaded and
91
+ // saved, and those it kept (cache.ts), so a file's text is asked for once.
92
+ const known = new Map<string, string>();
93
+
94
+ /** Keeps the files' texts by their blob ids (the files from this browser's copy, cache.ts). */
95
+ export function rememberTexts(files: RepoFile[]) {
96
+ for (const f of files) known.set(f.oid, f.text);
97
+ }
98
+
99
+ // The files with their text: '' for a picture, the rest from this browser or the Worker, 100 at a time.
100
+ async function withTexts(listed: Listed[]): Promise<RepoFile[]> {
101
+ const wanted = [...new Set(listed.filter((f) => !f.binary && !known.has(f.oid)).map((f) => f.oid))];
102
+ const parts = [];
103
+ for (let i = 0; i < wanted.length; i += 100) parts.push(wanted.slice(i, i + 100));
104
+ await Promise.all(
105
+ parts.map(async (oids) => {
106
+ const { texts } = await api<{ texts: Record<string, string | null> }>('texts', { oids });
107
+ for (const [oid, text] of Object.entries(texts)) known.set(oid, text ?? '');
108
+ }),
109
+ );
110
+ return listed.map((f) => ({ path: f.path, oid: f.oid, text: f.binary ? '' : (known.get(f.oid) ?? '') }));
111
+ }
112
+
113
+ type Files = Head & { folders: Listed[][]; paths: (Listed | null)[] };
114
+
115
+ // The files in folders and at paths, at a root tree (`tree`), or at the branch's head.
116
+ const listFiles = (ask: { tree?: string; folders?: string[]; depth?: number; paths?: string[] }) => api<Files>('files', ask);
117
+
118
+ /** The commit the branch is at: a small request, to see whether the files have changed (cache.ts). */
119
+ export const head = () => api<Head>('head');
120
+
121
+ // All files in some folders, with their text, and the commit the branch is at. `depth`: how many
122
+ // levels of folders (an app's folder, store.ts, has more). `at`: the branch's head, when it was just asked.
123
+ export async function loadFolders<K extends string>(
124
+ folders: Record<K, string>,
125
+ depth = 3,
126
+ at?: Head,
127
+ ): Promise<{ folders: Record<K, RepoFile[]>; commit: string }> {
128
+ const keys = Object.keys(folders) as K[];
129
+ const listed = await listFiles({ tree: at?.tree, folders: keys.map((k) => folders[k]), depth });
130
+ const files = await withTexts(listed.folders.flat());
131
+ const byPath = new Map(files.map((f) => [f.path, f]));
132
+ return {
133
+ folders: Object.fromEntries(keys.map((k, i) => [k, listed.folders[i].map((f) => byPath.get(f.path)!)])) as Record<K, RepoFile[]>,
134
+ commit: at?.commit ?? listed.commit,
135
+ };
136
+ }
137
+
138
+ // Some single files at the branch's head (`tree`: at another root tree), with their text ('' for a picture). A file that
139
+ // is not there is left out.
140
+ export async function loadFiles(paths: string[], tree?: string): Promise<RepoFile[]> {
141
+ const listed = await listFiles({ tree, paths });
142
+ return withTexts(listed.paths.filter((f): f is Listed => !!f));
143
+ }
144
+
145
+ /** A repository on GitHub: the site's (REPO), or the app store's (store.ts). */
146
+ export type Repo = { owner: string; name: string };
147
+
148
+ // Some files of a repository at a branch or a commit (an app in the store, store.ts), in one request: their blob
149
+ // id and their text, or null when they are not text or GitHub gives only part of it (a big file). A file that is not
150
+ // there is left out.
151
+ export async function loadFrom(repo: Repo, ref: string, paths: string[]): Promise<{ path: string; oid: string; text: string | null }[]> {
152
+ if (!paths.length) return [];
153
+ const data = await graphql<{
154
+ repository: Record<
155
+ string,
156
+ { oid: string; text?: string | null; isBinary?: boolean | null; isTruncated?: boolean | null } | null
157
+ > | null;
158
+ }>(
159
+ `query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) {
160
+ ${paths.map((p, i) => `f${i}: object(expression: ${JSON.stringify(`${ref}:${p}`)}) { oid ... on Blob { text isBinary isTruncated } }`).join('\n')}
161
+ } }`,
162
+ { owner: repo.owner, name: repo.name },
163
+ );
164
+ return paths.flatMap((path, i) => {
165
+ const f = data.repository?.[`f${i}`];
166
+ return f ? [{ path, oid: f.oid, text: f.isBinary || f.isTruncated || f.text == null ? null : f.text }] : [];
167
+ });
168
+ }
169
+
170
+ // A file's bytes by its blob id: a picture, which GraphQL gives no content for (renaming one in
171
+ // Filer). Checked against the id, so a picture is never saved broken. `repo`: another repository than the site's
172
+ // (a picture of an app in the store).
173
+ export async function loadBytes(oid: string, address?: string, repo: Repo = REPO): Promise<Uint8Array> {
174
+ // First from the site itself (the same file, no request to the Worker), when it has it unchanged.
175
+ if (address) {
176
+ const res = await fetch(address).catch(() => null);
177
+ const bytes = res?.ok ? new Uint8Array(await res.arrayBuffer()) : null;
178
+ if (bytes && (await blobId(bytes)) === oid) return bytes;
179
+ }
180
+ const other = repo.owner !== REPO.owner || repo.name !== REPO.name;
181
+ const res = await fetch(`/api/github/blob/${oid}${other ? `?repo=${repo.owner}/${repo.name}` : ''}`).catch(() => {
182
+ throw new Error(t.app.pictureNotLoaded);
183
+ });
184
+ if (res.status === 401) throw new AuthError(t.app.loggedOut);
185
+ if (!res.ok) throw new Error(t.app.githubAnswered(res.status));
186
+ const bytes = new Uint8Array(await res.arrayBuffer());
187
+ if ((await blobId(bytes)) !== oid) throw new Error(t.app.pictureNotWhole);
188
+ return bytes;
189
+ }
190
+
191
+ // When some files were last saved: the time of the last commit that changed each, in one request. A
192
+ // new file (no commit yet) is left out.
193
+ export async function savedAt(paths: string[]): Promise<Record<string, Date>> {
194
+ if (!paths.length) return {};
195
+ type History = { nodes: { committedDate: string }[] };
196
+ const data = await graphql<{ repository: { ref: { target: Record<string, History> } } }>(
197
+ `query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) {
198
+ ref(qualifiedName: ${JSON.stringify(`refs/heads/${REPO.branch}`)}) { target { ... on Commit {
199
+ ${paths.map((p, i) => `f${i}: history(first: 1, path: ${JSON.stringify(p)}) { nodes { committedDate } }`).join('\n')}
200
+ } } }
201
+ } }`,
202
+ { owner: REPO.owner, name: REPO.name },
203
+ );
204
+ const target = data.repository.ref.target;
205
+ return Object.fromEntries(
206
+ paths.flatMap((path, i) => {
207
+ const last = target[`f${i}`]?.nodes[0];
208
+ return last ? [[path, new Date(last.committedDate)]] : [];
209
+ }),
210
+ );
211
+ }
212
+
213
+ // A file to save: text or bytes (null deletes it), and the blob id it had when loaded (null for a
214
+ // new file).
215
+ export type Change = { path: string; content: string | Uint8Array | null; oid: string | null };
216
+
217
+ // Saves files as one commit on the branch, through the Worker. Refuses (ConflictError) when one of them was changed or
218
+ // created elsewhere since it was loaded, so nobody's edit is overwritten. Returns the id of the new
219
+ // commit and the new blob ids.
220
+ export type Saved = { commit: string; blobs: Record<string, string> };
221
+
222
+ export async function commit(message: string, changes: Change[]): Promise<Saved> {
223
+ const saved = await api<Saved>('commit', {
224
+ message,
225
+ changes: changes.map((c) => ({
226
+ path: c.path,
227
+ oid: c.oid,
228
+ content: c.content === null ? null : base64(typeof c.content === 'string' ? new TextEncoder().encode(c.content) : c.content),
229
+ })),
230
+ });
231
+ // The texts saved are known by their new blob ids.
232
+ for (const c of changes) if (typeof c.content === 'string' && saved.blobs[c.path]) known.set(saved.blobs[c.path], c.content);
233
+ return saved;
234
+ }
235
+
236
+ function base64(bytes: Uint8Array): string {
237
+ let binary = '';
238
+ for (let i = 0; i < bytes.length; i += 0x8000) binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000));
239
+ return btoa(binary);
240
+ }
241
+
242
+ // ---------------------------------------------------------------------------------------------------
243
+ // The history: earlier versions of a file, and files that were deleted (Versions.tsx, Deleted.tsx). Which commits
244
+ // changed a file is asked of GitHub; the folders and files in them come through the Worker's cache, like the files now.
245
+
246
+ /** A commit that changed a file: its id, its root tree (the files in it), when, and who saved it (their name on GitHub). */
247
+ export type Version = { commit: string; tree: string; at: Date; by: string };
248
+
249
+ type HistoryNode = {
250
+ oid: string;
251
+ tree: { oid: string };
252
+ committedDate: string;
253
+ author: { name: string | null; user: { name: string | null; login: string } | null };
254
+ };
255
+
256
+ const NODE = 'oid tree { oid } committedDate author { name user { name login } }';
257
+
258
+ const versionOf = (n: HistoryNode): Version => ({
259
+ commit: n.oid,
260
+ tree: n.tree.oid,
261
+ at: new Date(n.committedDate),
262
+ by: n.author.user?.name || n.author.name || n.author.user?.login || '',
263
+ });
264
+
265
+ /** The commits that changed a file, newest first, a page at a time (`after`: where the last ended). */
266
+ export async function versionsOf(path: string, after?: string): Promise<{ versions: Version[]; more: string | null }> {
267
+ const data = await graphql<{
268
+ repository: {
269
+ ref: { target: { history: { nodes: HistoryNode[]; pageInfo: { hasNextPage: boolean; endCursor: string | null } } } };
270
+ };
271
+ }>(
272
+ `query($owner: String!, $name: String!, $path: String!, $after: String) { repository(owner: $owner, name: $name) {
273
+ ref(qualifiedName: ${JSON.stringify(`refs/heads/${REPO.branch}`)}) { target { ... on Commit {
274
+ history(first: 20, path: $path, after: $after) {
275
+ nodes { ${NODE} }
276
+ pageInfo { hasNextPage endCursor }
277
+ }
278
+ } } }
279
+ } }`,
280
+ { owner: REPO.owner, name: REPO.name, path, after: after ?? null },
281
+ );
282
+ const { nodes, pageInfo } = data.repository.ref.target.history;
283
+ return { versions: nodes.map(versionOf), more: pageInfo.hasNextPage ? pageInfo.endCursor : null };
284
+ }
285
+
286
+ /** A file's text as it was in a version; null when it was not there (deleted in that commit). */
287
+ export async function versionText(version: Version, path: string): Promise<string | null> {
288
+ const [file] = await loadFiles([path], version.tree);
289
+ return file ? file.text : null;
290
+ }
291
+
292
+ /** A file that was deleted: its path, its last content (blob id, and text unless it is a picture),
293
+ * and when and by whom it was deleted. */
294
+ export type DeletedFile = { path: string; oid: string; text: string; at: Date; by: string };
295
+
296
+ type Entry = { name: string; oid: string; type: string; binary: boolean };
297
+
298
+ // The folders at paths under root trees (`path` '' the root itself), 200 to a request: their ids and what is in them
299
+ // (names, ids and kinds), or null where there is none.
300
+ async function foldersAt(at: { root: string; path: string }[]): Promise<({ oid: string; entries: Entry[] } | null)[]> {
301
+ const parts = [];
302
+ for (let i = 0; i < at.length; i += 200) parts.push(at.slice(i, i + 200));
303
+ const answers = await Promise.all(
304
+ parts.map((part) => api<{ trees: ({ oid: string; entries: Entry[] } | null)[] }>('trees', { at: part })),
305
+ );
306
+ return answers.flatMap((a) => a.trees);
307
+ }
308
+
309
+ /** The files deleted from a folder (and the folders in it) in its last `last` commits, newest first,
310
+ * each once, and not one that is there again. A file that went in a commit that also added one to the
311
+ * folder moved (a new address, a picture's new name) and is not counted. `text`: whether to get the
312
+ * files' text (not for pictures). */
313
+ export async function deletedFiles(folder: string, { last = 40, text = true } = {}): Promise<DeletedFile[]> {
314
+ const history = await graphql<{
315
+ repository: { ref: { target: { history: { nodes: (HistoryNode & { parents: { nodes: { tree: { oid: string } }[] } })[] } } } };
316
+ }>(
317
+ `query($owner: String!, $name: String!, $path: String!) { repository(owner: $owner, name: $name) {
318
+ ref(qualifiedName: ${JSON.stringify(`refs/heads/${REPO.branch}`)}) { target { ... on Commit {
319
+ history(first: ${last}, path: $path) {
320
+ nodes { ${NODE} parents(first: 1) { nodes { tree { oid } } } }
321
+ }
322
+ } } }
323
+ } }`,
324
+ { owner: REPO.owner, name: REPO.name, path: folder },
325
+ );
326
+ const commits = history.repository.ref.target.history.nodes;
327
+ if (!commits.length) return [];
328
+ // The folder in each commit and in the commit before it.
329
+ const sides = commits.flatMap((c) => [c.tree.oid, c.parents.nodes[0]?.tree.oid]);
330
+ const roots = await foldersAt(sides.flatMap((root) => (root ? [{ root, path: folder }] : [])));
331
+ const found = new Map<string, Entry[]>(roots.flatMap((r) => (r ? [[r.oid, r.entries] as const] : [])));
332
+ let next = 0;
333
+ const rootOid = sides.map((root) => (root ? (roots[next++]?.oid ?? null) : null));
334
+
335
+ // What each commit changed in the folder, a level of folders at a time: the trees that differ are
336
+ // compared again, the same ones left alone.
337
+ type Pair = { commit: number; path: string; now: string | null; was: string | null };
338
+ const removed: { commit: number; path: string; oid: string; binary: boolean }[] = [];
339
+ const added = new Set<number>();
340
+ let pairs: Pair[] = commits.map((_, i) => ({ commit: i, path: folder, now: rootOid[2 * i], was: rootOid[2 * i + 1] }));
341
+ pairs = pairs.filter((p) => p.now !== p.was);
342
+ while (pairs.length) {
343
+ const wanted = [...new Set(pairs.flatMap((p) => [p.now, p.was].filter((o): o is string => !!o && !found.has(o))))];
344
+ for (const t of await foldersAt(wanted.map((root) => ({ root, path: '' })))) if (t) found.set(t.oid, t.entries);
345
+ const next: Pair[] = [];
346
+ for (const p of pairs) {
347
+ const now = new Map((p.now ? (found.get(p.now) ?? []) : []).map((e) => [e.name, e]));
348
+ const was = new Map((p.was ? (found.get(p.was) ?? []) : []).map((e) => [e.name, e]));
349
+ for (const [name, e] of was) {
350
+ const there = now.get(name);
351
+ if (there?.oid === e.oid) continue;
352
+ const path = `${p.path}/${name}`;
353
+ if (e.type === 'tree') next.push({ commit: p.commit, path, now: there?.type === 'tree' ? there.oid : null, was: e.oid });
354
+ else if (!there) removed.push({ commit: p.commit, path, oid: e.oid, binary: e.binary });
355
+ }
356
+ for (const [name, e] of now) if (!was.has(name) && (e.type === 'blob' || e.type === 'tree')) added.add(p.commit);
357
+ }
358
+ pairs = next;
359
+ }
360
+
361
+ // The newest deletion of each file (the commits are newest first), not one that moved.
362
+ const seen = new Set<string>();
363
+ const gone = removed.sort((a, b) => a.commit - b.commit).filter((r) => !added.has(r.commit) && !seen.has(r.path) && seen.add(r.path));
364
+ if (!gone.length) return [];
365
+ // Still there (put back since, or another file under the same name): not deleted.
366
+ const now = (await listFiles({ paths: gone.map((r) => r.path) })).paths;
367
+ const deleted = gone.filter((_, i) => !now[i]);
368
+ if (!deleted.length) return [];
369
+ const files = text
370
+ ? await withTexts(deleted.map((r) => ({ path: r.path, oid: r.oid, binary: r.binary })))
371
+ : deleted.map((r) => ({ text: '' }));
372
+ return deleted.map((r, i) => {
373
+ const { at, by } = versionOf(commits[r.commit]);
374
+ return { path: r.path, oid: r.oid, text: files[i].text, at, by };
375
+ });
376
+ }
@@ -0,0 +1,28 @@
1
+ import type { Messages } from '../en-US';
2
+
3
+ export const advanced: Messages['advanced'] = {
4
+ r2Caching: 'R2-caching',
5
+ r2CachingHint: 'Workeren giver editoren hjemmesidens filer fra Cloudflare R2 og spørger kun GitHub om det, der er ændret.',
6
+ checking: 'Spørger Cloudflare, om R2 er klar.',
7
+ bucket: {
8
+ ready: (bucket, jurisdiction) => `Bucket'en ${bucket} er klar hos Cloudflare${jurisdiction ? ` i ${jurisdiction}` : ''}.`,
9
+ 'no-bucket': (bucket, jurisdiction) =>
10
+ `Kan slås til, når bucket'en ${bucket} er lavet under R2 hos Cloudflare${jurisdiction ? ` med jurisdiktionen ${jurisdiction}` : ''}.`,
11
+ 'no-r2': () => 'Kan slås til, når R2 er slået til hos Cloudflare.',
12
+ 'no-key': () => 'Workeren har ingen nøgle til Cloudflare, så den kan ikke se, om R2 er slået til.',
13
+ refused: () => 'Cloudflare godtog ikke Workerens nøgle til R2.',
14
+ failed: () => 'Cloudflare svarede ikke på, om R2 er klar. Prøv igen senere.',
15
+ },
16
+ place: 'Placering',
17
+ placeHint: 'Kan kun skiftes, når R2-caching er slået fra.',
18
+ placeAuto: 'Automatisk',
19
+ onWhenBuilt: 'Slås til, når hjemmesiden er opdateret.',
20
+ offWhenBuilt: 'Slås fra, når hjemmesiden er opdateret.',
21
+ loading: 'Henter Workerens indstillinger',
22
+ notLoaded: (error) => `Workerens indstillinger kunne ikke hentes: ${error}`,
23
+ noSettings: 'Hjemmesiden har ingen indstillinger til Workeren (wrangler.jsonc).',
24
+ noLine: 'Workerens indstillinger (wrangler.jsonc) har ingen linje til R2-caching.',
25
+ r2CachingCommit: (on) => (on ? 'Editor: slå R2-caching til' : 'Editor: slå R2-caching fra'),
26
+ placeCommit: (jurisdiction) =>
27
+ jurisdiction ? `Editor: hold R2-cachingens bucket i ${jurisdiction}` : 'Editor: lad Cloudflare placere R2-cachingens bucket',
28
+ };
@@ -0,0 +1,71 @@
1
+ import type { Messages } from '../en-US';
2
+
3
+ export const app: Messages['app'] = {
4
+ logIn: 'Log ind med GitHub',
5
+ loading: 'Henter hjemmesidens indhold',
6
+ cannotSave: (login) => `${login} har ikke adgang til at gemme. Log ind med en anden GitHub-konto under Konto.`,
7
+ notFound: 'Findes ikke',
8
+ nothingAt: (route) => `Der er ikke noget på adressen ${route}.`,
9
+ siteUpdated: (changes) => `Hjemmesiden er opdateret: ${changes}.`,
10
+ siteNotUpdated: (changes) => `Hjemmesiden blev ikke opdateret (${changes}). Gendan den forrige version under Tidligere versioner.`,
11
+ changes: {
12
+ named: (kind, name) => `${kind} “${name}”`,
13
+ edited: (what) => `${what} ændret`,
14
+ created: (what) => `${what} oprettet`,
15
+ added: (what) => `${what} tilføjet`,
16
+ deleted: (what) => `${what} slettet`,
17
+ restored: (what) => `${what} gendannet`,
18
+ moved: (what, address) => `${what} flyttet til ${address}`,
19
+ renamed: (what, name) => `${what} omdøbt til “${name}”`,
20
+ order: (label) => `ny rækkefølge for ${label}`,
21
+ turnedOn: (what) => `${what} slået til`,
22
+ turnedOff: (what) => `${what} slået fra`,
23
+ chosen: (what) => `${what} valgt`,
24
+ installed: (what) => `${what} installeret`,
25
+ updated: (what, version) => `${what} opdateret til ${version}`,
26
+ uninstalled: (what) => `${what} afinstalleret`,
27
+ more: (count) => (count === 1 ? '1 ændring mere' : `${count} ændringer mere`),
28
+ block: 'blok',
29
+ app: 'app',
30
+ theme: 'tema',
31
+ iconPack: 'ikonpakke',
32
+ motion: 'bevægelse',
33
+ colors: 'farver',
34
+ redirect: (from) => `videresendelse fra ${from}`,
35
+ logo: 'logo',
36
+ icon: 'ikon',
37
+ r2Caching: 'R2-caching',
38
+ place: 'placering',
39
+ },
40
+ addressTaken: (address) => `Der findes allerede en side eller et blogindlæg med adressen ${address}.`,
41
+ addressRedirects: (address, name) => `Adressen ${address} sender i dag besøgende videre til ${name}.`,
42
+ addressLoop: (loop) => `Adressen kan ikke ændres, fordi videresendelserne ville gå i ring (${loop}).`,
43
+ deleteEntry: (singular) => `Slet ${singular}? Det kan gendannes under Slettede.`,
44
+ notDeleted: (error) => `Kunne ikke slette: ${error}`,
45
+ busy: { saving: 'Gemmer', deleting: 'Sletter' },
46
+ lastSaved: (when) => `Sidst ændret ${when}`,
47
+ notSavedYet: 'Ikke gemt endnu',
48
+ unsavedTitle: 'Gem ændringerne?',
49
+ unsaved: 'Du har ændringer, der ikke er gemt.',
50
+ discard: 'Kassér',
51
+ unsavedSheet: 'Du har ændringer, der ikke er gemt. Vil du beholde dem?',
52
+ viewOnSite: 'Se på hjemmesiden',
53
+ loggedOut: 'Du er blevet logget ud. Log ind igen.',
54
+ githubAnswered: (status) => `GitHub svarede ${status}.`,
55
+ pictureNotLoaded: 'Billedet kunne ikke hentes fra GitHub. Tjek forbindelsen og prøv igen.',
56
+ pictureNotWhole: 'Billedet kunne ikke hentes helt. Prøv igen.',
57
+ changedElsewhere: 'Filen er ændret et andet sted. Kopiér din tekst, og genindlæs siden.',
58
+ fileExists: 'Der findes allerede en fil med det navn. Prøv igen, eller vælg en anden titel.',
59
+ pictureNotOpened: 'Billedet kunne ikke åbnes. Brug et JPEG-, PNG- eller WebP-billede.',
60
+ pictureNotReady: 'Billedet kunne ikke klargøres.',
61
+ preparingPicture: 'Klargør billedet…',
62
+ invalidJson: 'Filen er ikke gyldig JSON.',
63
+ blocksOff: 'Slået fra',
64
+ block: 'Blok',
65
+ appsInstalled: 'Installeret',
66
+ app: 'App',
67
+ commit: {
68
+ delete: (singular, slug) => `Editor: slet ${singular} "${slug}"`,
69
+ reorder: (label) => `Editor: ny rækkefølge for ${label}`,
70
+ },
71
+ };
@@ -0,0 +1,90 @@
1
+ import type { Messages } from '../en-US';
2
+
3
+ export const apps: Messages['apps'] = {
4
+ installed: 'Installeret',
5
+ notInstalled: 'Ikke installeret',
6
+ publisher: (name) => `Udvikler: ${name}`,
7
+ screenshots: 'Skærmbilleder',
8
+ about: 'Om appen',
9
+ news: 'Det er nyt',
10
+ needs: 'Rettigheder',
11
+ needsPages: 'Sætter sin egen kode på alle sider',
12
+ needsLoads: 'Henter fra andre adresser',
13
+ needsSends: 'Sender formularer til andre adresser',
14
+ needsServer: 'Har sin egen del af hjemmesidens server',
15
+ needsBuild: 'Laver sine egne filer, når hjemmesiden bygges',
16
+ changes: { 'page-colors': 'Ændrer sidernes farver' },
17
+ unknownHook: (places) => `Filen er ikke et sted, en app kan ændre hjemmesiden: ${places}.`,
18
+ needsNothing: 'Ingen',
19
+ notifications: 'Notifikationer',
20
+ notifiesNone: 'Sender ingen notifikationer',
21
+ cookies: 'Cookies',
22
+ cookieLasts: (lasts) => `Varer ${lasts}`,
23
+ cookiesAsk: 'Sættes først, når den besøgende har sagt ja i cookiebanneret',
24
+ noCookies: 'Sætter ingen cookies',
25
+ developer: 'Udvikler',
26
+ developerApps: 'Apps',
27
+ appCount: (n) => (n === 1 ? '1 app' : `${n} apps`),
28
+ noDeveloper: 'Der er ingen apps fra den udvikler.',
29
+ unknownScreenshot: (shows) =>
30
+ `Billedet "${shows}" viser intet, appen har: blok:<type>, slags:<liste>:<variant>, liste:<id>, indstillinger eller side.`,
31
+ noScreenshot: (file) => `${file} findes ikke. Tag billederne med npx morpheme app-screenshots.`,
32
+ unlistedScreenshot: 'Billedet står ikke under screenshots i appens index.ts.',
33
+ install: 'Installer',
34
+ uninstall: 'Afinstaller',
35
+ installing: 'Installerer…',
36
+ uninstalling: 'Afinstallerer…',
37
+ updating: 'Opdaterer…',
38
+ isInstalled: (app) => `${app} er installeret.`,
39
+ isUninstalled: (app) => `${app} er afinstalleret.`,
40
+ isInstalledSoon: (app) => `${app} er installeret og kan bruges, når hjemmesiden er bygget.`,
41
+ isUpdatedSoon: (app, version) => `${app} er opdateret til ${version} og virker sådan, når hjemmesiden er bygget.`,
42
+ askUninstall: (app) => `Afinstaller ${app}? Det, appen tilføjer, forsvinder fra editoren.`,
43
+ activeOf: (block) => `Aktiveret: ${block}`,
44
+ uninstallHint: 'Kan afinstalleres, fordi intet på hjemmesiden bruger appen.',
45
+ used: 'Bruges på',
46
+ notUsed: 'Bruges ingen steder.',
47
+ stuck: 'Appen bruges og kan ikke afinstalleres. Fjern den fra stederne ovenfor først.',
48
+ blocks: 'Blokke',
49
+ lists: 'Lister',
50
+ settings: 'Indstillinger',
51
+ find: 'Appstore',
52
+ searchStore: 'Søg efter apps',
53
+ loadingStore: 'Henter apps',
54
+ storeFailed: 'Kunne ikke hente Appstore.',
55
+ noStore: 'Sitet har ingen Appstore.',
56
+ storeBroken: (app) => `${app} kunne ikke hentes rigtigt fra Appstore.`,
57
+ notInStore: 'Appen findes ikke i Appstore.',
58
+ categoryFilter: 'Kategori',
59
+ allCategories: 'Alle kategorier',
60
+ stateFilter: 'Status',
61
+ allStates: 'Alle',
62
+ categories: {
63
+ booking: 'Booking',
64
+ newsletter: 'Nyhedsbrev',
65
+ payment: 'Betaling',
66
+ analytics: 'Måling',
67
+ content: 'Indhold',
68
+ design: 'Udseende',
69
+ },
70
+ version: (version) => `Version ${version}`,
71
+ pending: 'Installeres …',
72
+ pendingHint: 'Appen kan bruges, når hjemmesiden er bygget.',
73
+ updateFound: 'Opdatering findes',
74
+ update: (version) => `Opdater til ${version}`,
75
+ askUpdate: (app, version) => `Opdater ${app} til ${version}?`,
76
+ overwrites: 'Det, der er rettet i filerne her, bliver overskrevet.',
77
+ updateNow: 'Opdater',
78
+ autoUpdated: (app, version) => `${app} er opdateret til ${version}.`,
79
+ whatsNew: 'Se, hvad der er nyt',
80
+ breakingFound: (app, version) => `${app} ${version} findes. Den kan ødelægge noget, så den opdateres ikke af sig selv.`,
81
+ breaking: 'Versionen har ændringer, der kan ødelægge noget.',
82
+ noneHere: 'Ingen installerede apps har indstillinger her.',
83
+ settingsOf: (app) => `indstillinger for ${app}`,
84
+ missing: (id, folder) => `Appen "${id}" er installeret, men ${folder}/ findes ikke.`,
85
+ commit: {
86
+ install: (app) => `Editor: installer appen ${app}`,
87
+ uninstall: (app) => `Editor: afinstaller appen ${app}`,
88
+ update: (app, version) => `Editor: opdater appen ${app} til ${version}`,
89
+ },
90
+ };
@@ -0,0 +1,38 @@
1
+ import type { Messages } from '../en-US';
2
+
3
+ export const blockSettings: Messages['blockSettings'] = {
4
+ stillOn: (n) => `Blokken bruges på ${n} ${n === 1 ? 'side' : 'sider'}. Fjern den derfra først.`,
5
+ on: 'Til',
6
+ off: 'Fra',
7
+ inactive: 'Deaktiveret',
8
+ standard: 'Standardblokke',
9
+ noBlocks: 'Appen har ingen blokke.',
10
+ isStandard: 'En standardblok.',
11
+ isApp: (app) => `En appblok fra ${app}.`,
12
+ isKind: (one, app) => `En ${one}sblok fra ${app}.`,
13
+ stuck: 'Blokken bruges på sider og kan ikke slås fra.',
14
+ onHint: 'Vises under Indsæt.',
15
+ offHint: 'Vises ikke under Indsæt.',
16
+ active: 'Aktiveret',
17
+ kindStuck: (more) => `Blokken bruges i ${more} og kan ikke slås fra.`,
18
+ kindStillOn: (n, what) => `Blokken bruges i ${n} ${what}. Slet ${n === 1 ? 'den' : 'dem'} først.`,
19
+ kindOnHint: (create) => `Vises under ${create}.`,
20
+ kindOffHint: (create) => `Vises ikke under ${create}.`,
21
+ looks: 'Eksempel',
22
+ asOn: (page) => `Som den vises på ${page}.`,
23
+ empty: 'Et eksempel. Blokken bruges endnu ikke på nogen side.',
24
+ nothing: 'Blokken bruges endnu ikke på nogen side, så der er intet at vise.',
25
+ asIn: (entry) => `Som den vises i ${entry}.`,
26
+ kindEmpty: 'Et eksempel. Blokken bruges endnu ikke.',
27
+ kindNothing: 'Blokken bruges endnu ikke, så der er intet at vise.',
28
+ pages: 'Bruges på',
29
+ noPages: 'Ingen sider.',
30
+ usedIn: 'Bruges i',
31
+ noEntries: (more) => `Ingen ${more}.`,
32
+ commit: {
33
+ on: (block) => `Editor: slå blokken til: ${block}`,
34
+ off: (block) => `Editor: slå blokken fra: ${block}`,
35
+ kindOn: (kind) => `Editor: slå til: ${kind}`,
36
+ kindOff: (kind) => `Editor: slå fra: ${kind}`,
37
+ },
38
+ };