@morphemecms/cms 0.5.0 → 0.7.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 (396) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/astro.mjs +3 -0
  3. package/bin/morpheme.mjs +3 -1
  4. package/defaults/blockTexts.ts +2 -2
  5. package/defaults/collections.ts +10 -0
  6. package/defaults/editor.ts +57 -53
  7. package/defaults/privacy.ts +4 -1
  8. package/defaults/rules.ts +36 -38
  9. package/defaults/standardPages.ts +0 -3
  10. package/defaults/texts.ts +11 -2
  11. package/demo/src/content/pages/about.md +2 -0
  12. package/icons/lucide/browser-fill.svg +1 -0
  13. package/icons/lucide/buildings-fill.svg +1 -0
  14. package/icons/lucide/certificate-fill.svg +1 -0
  15. package/icons/lucide/chart-line-up-fill.svg +1 -0
  16. package/icons/lucide/chats-fill.svg +1 -0
  17. package/icons/lucide/envelope-simple-fill.svg +1 -0
  18. package/icons/lucide/file-text-fill.svg +1 -0
  19. package/icons/lucide/folder-simple-fill.svg +1 -0
  20. package/icons/lucide/gauge.svg +1 -1
  21. package/icons/lucide/gear-six.svg +1 -0
  22. package/icons/lucide/globe-simple.svg +1 -0
  23. package/icons/lucide/heart-fill.svg +1 -0
  24. package/icons/lucide/layout.svg +1 -0
  25. package/icons/lucide/list-checks-fill.svg +1 -0
  26. package/icons/lucide/magnifying-glass-fill.svg +1 -0
  27. package/icons/lucide/megaphone-fill.svg +1 -0
  28. package/icons/lucide/newspaper-fill.svg +1 -0
  29. package/icons/lucide/paint-brush-broad-fill.svg +1 -0
  30. package/icons/lucide/puzzle-piece-fill.svg +1 -0
  31. package/icons/lucide/shield-check-fill.svg +1 -0
  32. package/icons/lucide/sidebar-simple.svg +1 -1
  33. package/icons/lucide/sidebar.svg +1 -0
  34. package/icons/lucide/square-half-bottom-fill.svg +1 -0
  35. package/icons/lucide/square-half.svg +1 -0
  36. package/icons/lucide/squares-four-fill.svg +1 -0
  37. package/icons/lucide/storefront-fill.svg +1 -0
  38. package/icons/lucide/tag-fill.svg +1 -0
  39. package/icons/lucide/toggle-right-fill.svg +1 -0
  40. package/icons/lucide/trash-fill.svg +1 -0
  41. package/icons/lucide/user-fill.svg +1 -0
  42. package/icons/lucide/wrench-fill.svg +1 -0
  43. package/icons/material-symbols/browser-fill.svg +1 -0
  44. package/icons/material-symbols/buildings-fill.svg +1 -0
  45. package/icons/material-symbols/certificate-fill.svg +1 -0
  46. package/icons/material-symbols/chart-line-up-fill.svg +1 -0
  47. package/icons/material-symbols/chats-fill.svg +1 -0
  48. package/icons/material-symbols/envelope-simple-fill.svg +1 -0
  49. package/icons/material-symbols/file-text-fill.svg +1 -0
  50. package/icons/material-symbols/folder-simple-fill.svg +1 -0
  51. package/icons/material-symbols/gauge.svg +1 -1
  52. package/icons/material-symbols/gear-six.svg +1 -0
  53. package/icons/material-symbols/globe-simple.svg +1 -0
  54. package/icons/material-symbols/heart-fill.svg +1 -0
  55. package/icons/material-symbols/layout.svg +1 -0
  56. package/icons/material-symbols/list-checks-fill.svg +1 -0
  57. package/icons/material-symbols/magnifying-glass-fill.svg +1 -0
  58. package/icons/material-symbols/megaphone-fill.svg +1 -0
  59. package/icons/material-symbols/newspaper-fill.svg +1 -0
  60. package/icons/material-symbols/paint-brush-broad-fill.svg +1 -0
  61. package/icons/material-symbols/puzzle-piece-fill.svg +1 -0
  62. package/icons/material-symbols/shield-check-fill.svg +1 -0
  63. package/icons/material-symbols/sidebar-simple.svg +1 -1
  64. package/icons/material-symbols/sidebar.svg +1 -0
  65. package/icons/material-symbols/square-half-bottom-fill.svg +1 -0
  66. package/icons/material-symbols/square-half.svg +1 -0
  67. package/icons/material-symbols/squares-four-fill.svg +1 -0
  68. package/icons/material-symbols/storefront-fill.svg +1 -0
  69. package/icons/material-symbols/tag-fill.svg +1 -0
  70. package/icons/material-symbols/toggle-right-fill.svg +1 -0
  71. package/icons/material-symbols/trash-fill.svg +1 -0
  72. package/icons/material-symbols/user-fill.svg +1 -0
  73. package/icons/material-symbols/wrench-fill.svg +1 -0
  74. package/icons/phosphor/browser-fill.svg +1 -0
  75. package/icons/phosphor/buildings-fill.svg +1 -0
  76. package/icons/phosphor/certificate-fill.svg +1 -0
  77. package/icons/phosphor/chart-line-up-fill.svg +1 -0
  78. package/icons/phosphor/chats-fill.svg +1 -0
  79. package/icons/phosphor/envelope-simple-fill.svg +1 -0
  80. package/icons/phosphor/file-text-fill.svg +1 -0
  81. package/icons/phosphor/folder-simple-fill.svg +1 -0
  82. package/icons/phosphor/gear-six.svg +1 -0
  83. package/icons/phosphor/globe-simple.svg +1 -0
  84. package/icons/phosphor/heart-fill.svg +1 -0
  85. package/icons/phosphor/layout.svg +1 -0
  86. package/icons/phosphor/list-checks-fill.svg +1 -0
  87. package/icons/phosphor/magnifying-glass-fill.svg +1 -0
  88. package/icons/phosphor/megaphone-fill.svg +1 -0
  89. package/icons/phosphor/newspaper-fill.svg +1 -0
  90. package/icons/phosphor/paint-brush-broad-fill.svg +1 -0
  91. package/icons/phosphor/puzzle-piece-fill.svg +1 -0
  92. package/icons/phosphor/shield-check-fill.svg +1 -0
  93. package/icons/phosphor/sidebar.svg +1 -0
  94. package/icons/phosphor/square-half-bottom-fill.svg +1 -0
  95. package/icons/phosphor/square-half.svg +1 -0
  96. package/icons/phosphor/squares-four-fill.svg +1 -0
  97. package/icons/phosphor/storefront-fill.svg +1 -0
  98. package/icons/phosphor/tag-fill.svg +1 -0
  99. package/icons/phosphor/toggle-right-fill.svg +1 -0
  100. package/icons/phosphor/trash-fill.svg +1 -0
  101. package/icons/phosphor/user-fill.svg +1 -0
  102. package/icons/phosphor/wrench-fill.svg +1 -0
  103. package/lib/breakpoints.d.mts +13 -0
  104. package/lib/breakpoints.mjs +20 -0
  105. package/lib/breakpoints.test.mjs +39 -0
  106. package/lib/build-lane.d.mts +15 -0
  107. package/lib/build-lane.mjs +23 -0
  108. package/lib/build-lane.test.mjs +74 -0
  109. package/lib/build-settings.d.mts +16 -0
  110. package/lib/build-settings.mjs +39 -0
  111. package/lib/build-settings.test.mjs +41 -0
  112. package/lib/contracts.d.mts +3 -2
  113. package/lib/contracts.mjs +3 -2
  114. package/lib/drawer-swipe.d.mts +10 -0
  115. package/lib/drawer-swipe.mjs +17 -0
  116. package/lib/drawer-swipe.test.mjs +33 -0
  117. package/lib/drawerKeys.d.mts +9 -0
  118. package/lib/drawerKeys.mjs +26 -0
  119. package/lib/drawerKeys.test.mjs +21 -0
  120. package/lib/eyebrow.d.mts +6 -0
  121. package/lib/eyebrow.mjs +24 -0
  122. package/lib/eyebrow.test.mjs +20 -0
  123. package/lib/front-sections.test.mjs +82 -0
  124. package/lib/heading-levels.d.mts +7 -0
  125. package/lib/heading-levels.mjs +16 -0
  126. package/lib/heading-levels.test.mjs +37 -0
  127. package/lib/inline.ts +3 -2
  128. package/lib/markdown.ts +2 -0
  129. package/lib/materialIcon.d.mts +21 -0
  130. package/lib/materialIcon.mjs +29 -0
  131. package/lib/materialIcon.test.mjs +45 -0
  132. package/lib/menu-layout.d.mts +11 -0
  133. package/lib/menu-layout.mjs +14 -0
  134. package/lib/menu-layout.test.mjs +23 -0
  135. package/lib/menu.d.mts +59 -0
  136. package/lib/menu.mjs +129 -0
  137. package/lib/menu.test.mjs +291 -0
  138. package/lib/rehype-emphasize.d.mts +4 -0
  139. package/lib/rehype-emphasize.mjs +20 -0
  140. package/lib/rehype-emphasize.test.mjs +39 -0
  141. package/lib/section-in-view.d.mts +8 -0
  142. package/lib/section-in-view.mjs +25 -0
  143. package/lib/section-in-view.test.mjs +35 -0
  144. package/lib/section-marker.d.mts +5 -0
  145. package/lib/section-marker.mjs +18 -0
  146. package/lib/section-marker.test.mjs +22 -0
  147. package/lib/section-ranges.d.mts +12 -0
  148. package/lib/section-ranges.mjs +43 -0
  149. package/lib/section-ranges.test.mjs +61 -0
  150. package/lib/sheet-stops.d.mts +68 -0
  151. package/lib/sheet-stops.mjs +198 -0
  152. package/lib/sheet-stops.test.mjs +155 -0
  153. package/lib/still-timer.d.mts +5 -0
  154. package/lib/still-timer.mjs +17 -0
  155. package/lib/still-timer.test.mjs +42 -0
  156. package/lib/text-sections.d.mts +10 -0
  157. package/lib/text-sections.mjs +45 -0
  158. package/lib/text-sections.test.mjs +78 -0
  159. package/lib/video.mjs +2 -1
  160. package/lib/without-h1.d.mts +1 -0
  161. package/lib/without-h1.mjs +7 -0
  162. package/lib/without-h1.test.mjs +26 -0
  163. package/lib/word-at.d.mts +6 -0
  164. package/lib/word-at.mjs +20 -0
  165. package/lib/word-at.test.mjs +19 -0
  166. package/package.json +3 -1
  167. package/pages/editor/version.json.js +22 -2
  168. package/scripts/already-checked.mjs +11 -0
  169. package/scripts/already-checked.test.mjs +18 -0
  170. package/scripts/build-settings-problems.mjs +27 -0
  171. package/scripts/build-settings-problems.test.mjs +35 -0
  172. package/scripts/check-content.mjs +42 -4
  173. package/scripts/check-worker.mjs +96 -4
  174. package/scripts/ci-build.mjs +85 -0
  175. package/scripts/ci-build.test.mjs +137 -0
  176. package/scripts/editor-roundtrip.mjs +62 -3
  177. package/scripts/editor-screens.mjs +21 -7
  178. package/scripts/git-env.mjs +6 -0
  179. package/scripts/step-command.mjs +34 -0
  180. package/scripts/step-command.test.mjs +50 -0
  181. package/scripts/text-problems.mjs +83 -0
  182. package/scripts/text-problems.test.mjs +74 -0
  183. package/scripts/worker-modules.mjs +11 -1
  184. package/site/breakpoints.d.mts +6 -0
  185. package/site/breakpoints.mjs +52 -0
  186. package/site/breakpoints.test.mjs +36 -0
  187. package/site/casing.d.mts +3 -0
  188. package/site/casing.mjs +26 -0
  189. package/site/content.config.ts +2 -0
  190. package/site/content.ts +2 -4
  191. package/site/defineSite.d.mts +1 -0
  192. package/site/defineSite.mjs +3 -0
  193. package/site/home.ts +3 -2
  194. package/site/icons.d.mts +116 -4
  195. package/site/icons.mjs +62 -6
  196. package/site/images.mjs +1 -1
  197. package/site/live-diff.d.mts +22 -0
  198. package/site/live-diff.mjs +98 -0
  199. package/site/live-diff.test.mjs +235 -0
  200. package/site/materialSymbols.d.mts +5 -0
  201. package/site/materialSymbols.mjs +19 -0
  202. package/site/sections.ts +1 -1
  203. package/site/theme.d.mts +1 -1
  204. package/site/theme.mjs +7 -1
  205. package/src/ActionParts.tsx +1 -1
  206. package/src/Advanced.tsx +101 -20
  207. package/src/App.tsx +47 -121
  208. package/src/AppList.tsx +1 -1
  209. package/src/BlockParts.tsx +3 -3
  210. package/src/Colors.tsx +1 -1
  211. package/src/CommunicationParts.tsx +1 -1
  212. package/src/ContainmentParts.tsx +80 -28
  213. package/src/Deleted.tsx +18 -4
  214. package/src/EditorFooter.tsx +14 -0
  215. package/src/EntryForm.tsx +75 -39
  216. package/src/FormFrame.tsx +3 -8
  217. package/src/Library.tsx +46 -51
  218. package/src/Licenses.tsx +27 -11
  219. package/src/MainDrawerParts.tsx +60 -0
  220. package/src/MainMenu.tsx +136 -0
  221. package/src/MarkdownEditor.tsx +175 -32
  222. package/src/Media.tsx +69 -16
  223. package/src/MediaTags.tsx +91 -0
  224. package/src/ModalSheetSample.tsx +47 -0
  225. package/src/NavigationParts.tsx +67 -21
  226. package/src/NavigationRestParts.tsx +1 -1
  227. package/src/Parts.tsx +71 -0
  228. package/src/PartsShown.tsx +1 -1
  229. package/src/PickerParts.tsx +2 -2
  230. package/src/Redirects.tsx +3 -2
  231. package/src/Screen.tsx +93 -90
  232. package/src/SelectionParts.tsx +22 -6
  233. package/src/SiteLogoLink.tsx +14 -0
  234. package/src/StartFab.tsx +22 -0
  235. package/src/StartStatus.tsx +1 -1
  236. package/src/autoTags.d.mts +28 -0
  237. package/src/autoTags.mjs +68 -0
  238. package/src/autoTags.test.mjs +109 -0
  239. package/src/buildSettings.test.mjs +20 -0
  240. package/src/buildSettings.ts +20 -0
  241. package/src/checkSite.ts +14 -1
  242. package/src/deploy.ts +7 -9
  243. package/src/editor.css +150 -17
  244. package/src/eyebrow.d.mts +5 -0
  245. package/src/eyebrow.mjs +53 -0
  246. package/src/eyebrowState.d.mts +21 -0
  247. package/src/eyebrowState.mjs +62 -0
  248. package/src/eyebrowState.test.mjs +78 -0
  249. package/src/fileRecords.d.mts +115 -0
  250. package/src/fileRecords.mjs +224 -0
  251. package/src/fileRecords.test.mjs +224 -0
  252. package/src/fileTagFilter.d.mts +30 -0
  253. package/src/fileTagFilter.mjs +44 -0
  254. package/src/fileTagFilter.test.mjs +57 -0
  255. package/src/fileTags.d.mts +56 -0
  256. package/src/fileTags.mjs +100 -0
  257. package/src/fileTags.test.mjs +127 -0
  258. package/src/firstHeading.d.mts +6 -0
  259. package/src/firstHeading.mjs +37 -0
  260. package/src/i18n/da-DK/advanced.ts +27 -12
  261. package/src/i18n/da-DK/app.ts +9 -7
  262. package/src/i18n/da-DK/apps.ts +16 -16
  263. package/src/i18n/da-DK/blockSettings.ts +9 -9
  264. package/src/i18n/da-DK/blocks.ts +2 -2
  265. package/src/i18n/da-DK/check.ts +5 -2
  266. package/src/i18n/da-DK/cms.ts +14 -12
  267. package/src/i18n/da-DK/colors.ts +5 -5
  268. package/src/i18n/da-DK/common.ts +2 -2
  269. package/src/i18n/da-DK/company.ts +3 -3
  270. package/src/i18n/da-DK/consents.ts +6 -6
  271. package/src/i18n/da-DK/forms.ts +6 -6
  272. package/src/i18n/da-DK/history.ts +6 -6
  273. package/src/i18n/da-DK/keywords.ts +2 -2
  274. package/src/i18n/da-DK/library.ts +17 -15
  275. package/src/i18n/da-DK/licenses.ts +4 -4
  276. package/src/i18n/da-DK/media.ts +10 -4
  277. package/src/i18n/da-DK/parts.ts +62 -25
  278. package/src/i18n/da-DK/preview.ts +5 -6
  279. package/src/i18n/da-DK/redirects.ts +7 -7
  280. package/src/i18n/da-DK/seo.ts +1 -1
  281. package/src/i18n/da-DK/text.ts +2 -0
  282. package/src/i18n/da-DK/theme.ts +5 -5
  283. package/src/i18n/en-US/advanced.ts +34 -18
  284. package/src/i18n/en-US/app.ts +7 -5
  285. package/src/i18n/en-US/apps.ts +9 -9
  286. package/src/i18n/en-US/blockSettings.ts +4 -4
  287. package/src/i18n/en-US/blocks.ts +6 -6
  288. package/src/i18n/en-US/check.ts +6 -3
  289. package/src/i18n/en-US/cms.ts +15 -14
  290. package/src/i18n/en-US/colors.ts +18 -18
  291. package/src/i18n/en-US/common.ts +3 -3
  292. package/src/i18n/en-US/consents.ts +4 -4
  293. package/src/i18n/en-US/forms.ts +5 -5
  294. package/src/i18n/en-US/history.ts +2 -2
  295. package/src/i18n/en-US/library.ts +21 -15
  296. package/src/i18n/en-US/licenses.ts +6 -6
  297. package/src/i18n/en-US/media.ts +7 -1
  298. package/src/i18n/en-US/parts.ts +60 -21
  299. package/src/i18n/en-US/preview.ts +5 -6
  300. package/src/i18n/en-US/redirects.ts +3 -3
  301. package/src/i18n/en-US/seo.ts +1 -1
  302. package/src/i18n/en-US/text.ts +3 -0
  303. package/src/i18n/en-US/theme.ts +6 -6
  304. package/src/icon.tsx +90 -27
  305. package/src/licenseData.test.mjs +28 -0
  306. package/src/licenseData.ts +12 -1
  307. package/src/markdown.d.mts +2 -0
  308. package/src/markdown.mjs +73 -5
  309. package/src/markdown.test.mjs +74 -0
  310. package/src/materialIcons.ts +8 -0
  311. package/src/menuChildren.ts +36 -0
  312. package/src/menuOpen.ts +34 -0
  313. package/src/pagePreview.tsx +23 -19
  314. package/src/r2Caching.ts +14 -0
  315. package/src/sectionFrame.ts +39 -0
  316. package/src/sectionState.d.mts +19 -0
  317. package/src/sectionState.mjs +31 -0
  318. package/src/sectionState.test.mjs +59 -0
  319. package/src/sections.d.mts +9 -7
  320. package/src/sections.mjs +74 -27
  321. package/src/sections.test.mjs +59 -0
  322. package/src/sidebar.ts +2 -2
  323. package/src/site.ts +27 -17
  324. package/src/stillCursor.d.mts +8 -0
  325. package/src/stillCursor.mjs +19 -0
  326. package/src/stillCursor.test.mjs +26 -0
  327. package/src/tagUses.d.mts +47 -0
  328. package/src/tagUses.mjs +121 -0
  329. package/src/tagUses.test.mjs +141 -0
  330. package/src/themeUi.ts +10 -0
  331. package/src/topBarSlot.tsx +37 -0
  332. package/src/ui.tsx +654 -150
  333. package/src/virtual.d.ts +5 -0
  334. package/starter/README.md +2 -1
  335. package/starter/package.json +2 -1
  336. package/starter/wrangler.jsonc +3 -2
  337. package/theme/blocks/cards/LinkCards.tsx +2 -1
  338. package/theme/blocks/hero/View.tsx +2 -1
  339. package/theme/blocks/video/View.tsx +2 -1
  340. package/theme/components/BlogIndex.astro +2 -2
  341. package/theme/components/BlogPosts.astro +1 -1
  342. package/theme/components/BlogPosts.tsx +9 -6
  343. package/theme/components/Container.astro +1 -1
  344. package/theme/components/CookieConsent.astro +1 -1
  345. package/theme/components/EndBlock.astro +1 -1
  346. package/theme/components/Footer.astro +5 -5
  347. package/theme/components/Header.astro +3 -3
  348. package/theme/components/Icon.astro +2 -2
  349. package/theme/components/MobileMenu.tsx +72 -61
  350. package/theme/components/MobileNav.astro +2 -2
  351. package/theme/components/PageHeader.astro +2 -2
  352. package/theme/components/PageSection.astro +1 -1
  353. package/theme/components/PopupButton.tsx +2 -2
  354. package/theme/components/PopupView.tsx +2 -2
  355. package/theme/components/PostList.tsx +7 -3
  356. package/theme/components/RichText.astro +22 -7
  357. package/theme/components/Section.astro +17 -10
  358. package/theme/components/SectionHeading.tsx +1 -1
  359. package/theme/components/home/PageBlock.astro +4 -4
  360. package/theme/components/home/Text.astro +3 -3
  361. package/theme/layouts/PageLayout.astro +3 -3
  362. package/theme/layouts/PostLayout.astro +9 -8
  363. package/theme/styles/base.css +13 -3
  364. package/theme/styles/blocks.css +97 -10
  365. package/theme/styles/components.css +9 -9
  366. package/theme/styles/elevation.test.mjs +168 -0
  367. package/theme/styles/global.css +65 -59
  368. package/theme/styles/ui.css +460 -131
  369. package/theme/templates/Home.astro +1 -1
  370. package/theme/templates/New.astro +5 -5
  371. package/theme/templates/NotFound.astro +2 -2
  372. package/theme/ui/BottomSheet.tsx +118 -21
  373. package/theme/ui/BottomSheetResizeIcon.tsx +13 -0
  374. package/theme/ui/Button.tsx +4 -3
  375. package/theme/ui/Dialog.tsx +1 -1
  376. package/theme/ui/FabMenu.tsx +13 -12
  377. package/theme/ui/LoadingIndicator.tsx +1 -1
  378. package/theme/ui/NavigationDrawer.tsx +116 -15
  379. package/theme/ui/NavigationRail.tsx +22 -13
  380. package/theme/ui/Search.tsx +1 -1
  381. package/theme/ui/SettingRow.tsx +31 -0
  382. package/theme/ui/Switch.tsx +11 -11
  383. package/theme/ui/TextField.tsx +17 -6
  384. package/theme/ui/bottomSheet.script.ts +3 -2
  385. package/theme/ui/bottomSheetControl.ts +131 -46
  386. package/theme/ui/fabMenu.script.ts +69 -53
  387. package/theme/ui/modalSheetSize.ts +214 -0
  388. package/theme/ui/navigationDrawerControl.ts +35 -0
  389. package/theme/ui/search.script.ts +4 -2
  390. package/worker/index.js +3 -0
  391. package/worker/plan-status.js +46 -0
  392. package/worker/push.js +7 -5
  393. package/worker/r2-status.js +2 -1
  394. package/icons/lucide/desktop.svg +0 -1
  395. package/icons/material-symbols/desktop.svg +0 -1
  396. package/icons/phosphor/desktop.svg +0 -1
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" /></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z" /></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M140-160q-24 0-42-18t-18-42v-520q0-24 18-42t42-18h680q24 0 42 18t18 42v520q0 24-18 42t-42 18H140Zm0-60h461v-163H140v163Zm521 0h159v-386H661v386ZM140-443h461v-163H140v163Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M80-120v-720h390v165h410v555H80Zm60-60h105v-105H140v105Zm0-165h105v-105H140v105Zm0-165h105v-105H140v105Zm0-165h105v-105H140v105Zm165 495h105v-105H305v105Zm0-165h105v-105H305v105Zm0-165h105v-105H305v105Zm0-165h105v-105H305v105Zm165 495h350v-435H470v105h80v60h-80v105h80v60h-80v105Zm185-270v-60h60v60h-60Zm0 165v-60h60v60h-60Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M402.5-482.5Q370-515 370-560t32.5-77.5Q435-670 480-670t77.5 32.5Q590-605 590-560t-32.5 77.5Q525-450 480-450t-77.5-32.5ZM244-40v-304q-45-47-64.5-103T160-560q0-136 92-228t228-92q136 0 228 92t92 228q0 57-19.5 113T716-344v304l-236-79-236 79Zm420.5-335.5Q740-451 740-560t-75.5-184.5Q589-820 480-820t-184.5 75.5Q220-669 220-560t75.5 184.5Q371-300 480-300t184.5-75.5Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M120-120v-76l60-60v136h-60Zm165 0v-236l60-60v296h-60Zm165 0v-296l60 61v235h-60Zm165 0v-235l60-60v295h-60Zm165 0v-396l60-60v456h-60ZM120-356v-85l280-278 160 160 280-281v85L560-474 400-634 120-356Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M281-240q-14 0-27.5-14T240-282v-98h500v-340h100q14 0 27 14t13 29v596L721-240H281ZM80-280v-558q0-14 13-28t27-14h519q15 0 28 13.5t13 28.5v356q0 14-13 28t-28 14H240L80-280Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M140-160q-24 0-42-18t-18-42v-520q0-24 18-42t42-18h680q24 0 42 18t18 42v520q0 24-18 42t-42 18H140Zm340-302 340-223v-55L480-522 140-740v55l340 223Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M319-250h322v-60H319v60Zm0-170h322v-60H319v60ZM220-80q-24 0-42-18t-18-42v-680q0-24 18-42t42-18h361l219 219v521q0 24-18 42t-42 18H220Zm331-554h189L551-820v186Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M140-160q-24 0-42-18.5T80-220v-520q0-23 18-41.5t42-18.5h281l60 60h339q23 0 41.5 18.5T880-680v460q0 23-18.5 41.5T820-160H140Z"/></svg>
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M473.5-303.5Q517-305 537-336l216-339-335 219q-30 20-32 64t21 67q23 23 66.5 21.5ZM478-799q57 0 119 18.5T716-717l-52 37q-45-30-96.5-44.5T477.98-739q-140.47 0-239.23 100.22Q140-538.57 140-396.02 140-351 152.5-305q12.5 46 35.5 85h579q22-36 35-84t13-94q0-42-12.5-90.5T758-578l39-52q38 56 57 112.5T875-404q2 60-12 113t-41 98q-12 23-25.5 28t-33.5 5H192q-17 0-33.5-8.5T134-193q-26-48-40-97.5T80-396q0-83 31.5-156.5t85.5-128Q251-735 323.68-767T478-799Zm-9 331Z"/></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M510-570v-270h330v270H510ZM120-450v-390h330v390H120Zm390 330v-390h330v390H510Zm-390 0v-270h330v270H120Zm60-390h210v-270H180v270Zm390 330h210v-270H570v270Zm0-450h210v-150H570v150ZM180-180h210v-150H180v150Zm210-330Zm180-120Zm0 180ZM390-330Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="m388-80-20-126q-19-7-40-19t-37-25l-118 54-93-164 108-79q-2-9-2.5-20.5T185-480q0-9 .5-20.5T188-521L80-600l93-164 118 54q16-13 37-25t40-18l20-127h184l20 126q19 7 40.5 18.5T669-710l118-54 93 164-108 77q2 10 2.5 21.5t.5 21.5q0 10-.5 21t-2.5 21l108 78-93 164-118-54q-16 13-36.5 25.5T592-206L572-80H388Zm48-60h88l14-112q33-8 62.5-25t53.5-41l106 46 40-72-94-69q4-17 6.5-33.5T715-480q0-17-2-33.5t-7-33.5l94-69-40-72-106 46q-23-26-52-43.5T538-708l-14-112h-88l-14 112q-34 7-63.5 24T306-642l-106-46-40 72 94 69q-4 17-6.5 33.5T245-480q0 17 2.5 33.5T254-413l-94 69 40 72 106-46q24 24 53.5 41t62.5 25l14 112Zm44-210q54 0 92-38t38-92q0-54-38-92t-92-38q-54 0-92 38t-38 92q0 54 38 92t92 38Zm0-130Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M323-111.5Q250-143 196-197t-85-127.5Q80-398 80-482t31-156.5Q142-711 196-765t127-84.5Q396-880 480-880t157 30.5Q710-819 764-765t85 126.5Q880-566 880-482t-31 157.5Q818-251 764-197t-127 85.5Q564-80 480-80t-157-31.5ZM480-138q35-36 58.5-82.5T577-331H384q14 60 37.5 108t58.5 85Zm-85-12q-25-38-43-82t-30-99H172q38 71 88 111.5T395-150Zm171-1q72-23 129.5-69T788-331H639q-13 54-30.5 98T566-151ZM152-391h159q-3-27-3.5-48.5T307-482q0-25 1-44.5t4-43.5H152q-7 24-9.5 43t-2.5 45q0 26 2.5 46.5T152-391Zm221 0h215q4-31 5-50.5t1-40.5q0-20-1-38.5t-5-49.5H373q-4 31-5 49.5t-1 38.5q0 21 1 40.5t5 50.5Zm275 0h160q7-24 9.5-44.5T820-482q0-26-2.5-45t-9.5-43H649q3 35 4 53.5t1 34.5q0 22-1.5 41.5T648-391Zm-10-239h150q-33-69-90.5-115T565-810q25 37 42.5 80T638-630Zm-254 0h194q-11-53-37-102.5T480-820q-32 27-54 71t-42 119Zm-212 0h151q11-54 28-96.5t43-82.5q-75 19-131 64t-91 115Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="m480-121-41-37q-106-97-175-167.5t-110-126Q113-507 96.5-552T80-643q0-90 60.5-150.5T290-854q57 0 105.5 27t84.5 78q42-54 89-79.5T670-854q89 0 149.5 60.5T880-643q0 46-16.5 91T806-451.5q-41 55.5-110 126T521-158l-41 37Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M433-344v-272L297-480l136 136ZM180-120q-24.75 0-42.37-17.63Q120-155.25 120-180v-600q0-24.75 17.63-42.38Q155.25-840 180-840h600q24.75 0 42.38 17.62Q840-804.75 840-780v600q0 24.75-17.62 42.37Q804.75-120 780-120H180Zm453-60h147v-600H633v600Zm-60 0v-600H180v600h393Zm60 0h147-147Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M222-214 80-356l42-42 100 99 179-179 42 43-221 221Zm0-320L80-676l42-42 100 99 179-179 42 43-221 221Zm298 244v-60h360v60H520Zm0-320v-60h360v60H520Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M796-121 533-384q-30 26-70 40.5T378-329q-108 0-183-75t-75-181q0-106 75-181t182-75q106 0 180.5 75T632-585q0 43-14 83t-42 75l264 262-44 44ZM377-389q81 0 138-57.5T572-585q0-81-57-138.5T377-781q-82 0-139.5 57.5T180-585q0 81 57.5 138.5T377-389Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M730-450v-60h150v60H730Zm50 290-121-90 36-48 121 90-36 48Zm-82-503-36-48 118-89 36 48-118 89ZM210-200v-160h-70q-25 0-42.5-17.5T80-420v-120q0-25 17.5-42.5T140-600h180l200-120v480L320-360h-50v160h-60Zm350-146v-268q27 24 43.5 58.5T620-480q0 41-16.5 75.5T560-346Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M140-120q-24.75 0-42.37-17.63Q80-155.25 80-180v-660l67 67 66-67 67 67 67-67 66 67 67-67 67 67 66-67 67 67 67-67 66 67 67-67v660q0 24.75-17.62 42.37Q844.75-120 820-120H140Zm0-60h310v-280H140v280Zm370 0h310v-110H510v110Zm0-170h310v-110H510v110ZM140-520h680v-120H140v120Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M215-117q-34 0-67-11.5T90-166q35-12 50-35t15-62q0-44 30.5-74.5T260-368q44 0 74.5 30.5T365-263q0 64-43.5 105T215-117Zm230-237-90-95 376-376q14-14 31-14.5t32 14.5l29 29q15 15 14.5 32.5T823-732L445-354Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M191-120q-29 0-50-21t-21-51v-139q52-3 88-39t36-88q0-52-36-88.5T121-585v-144q0-30 20.5-50.5T192-800h136q7-49 44-82t87-33q49 0 86 33t45 82h139q30 0 50.5 20.5T800-729v147q38 18 60.5 49.5T883-458q0 43-22.5 75T800-334v142q0 30-20.5 51T729-120H191Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="m436-356 228-228-42-41-183 183-101-101-44 44 142 143Zm44 275q-140-35-230-162.5T160-523v-238l320-120 320 120v238q0 152-90 279.5T480-81Z"/></svg>
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M180-120q-24 0-42-18t-18-42v-600q0-24 18-42t42-18h600q24 0 42 18t18 42v600q0 24-18 42t-42 18H180Zm300-60h300v-600H480v600Z"/></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M527-616v272l136-136-136-136ZM180-120q-24.75 0-42.37-17.63Q120-155.25 120-180v-600q0-24.75 17.63-42.38Q155.25-840 180-840h600q24.75 0 42.38 17.62Q840-804.75 840-780v600q0 24.75-17.62 42.37Q804.75-120 780-120H180Zm147-60v-600H180v600h147Zm60 0h393v-600H387v600Zm-60 0H180h147Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M663-344v-272L527-480l136 136ZM180-120q-24.75 0-42.37-17.63Q120-155.25 120-180v-600q0-24.75 17.63-42.38Q155.25-840 180-840h600q24.75 0 42.38 17.62Q840-804.75 840-780v600q0 24.75-17.62 42.37Q804.75-120 780-120H180Zm147-60v-600H180v600h147Zm60 0h393v-600H387v600Zm-60 0H180h147Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M236-274h488v-105H236v105Zm-96 114q-24 0-42-18t-18-42v-520q0-24 18-42t42-18h680q24 0 42 18t18 42v520q0 24-18 42t-42 18H140Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M297-616v272l136-136-136-136ZM180-120q-24.75 0-42.37-17.63Q120-155.25 120-180v-600q0-24.75 17.63-42.38Q155.25-840 180-840h600q24.75 0 42.38 17.62Q840-804.75 840-780v600q0 24.75-17.62 42.37Q804.75-120 780-120H180Zm453-60h147v-600H633v600Zm-60 0v-600H180v600h393Zm60 0h147-147Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M120-510v-330h330v330H120Zm0 390v-330h330v330H120Zm390-390v-330h330v330H510Zm0 390v-330h330v330H510Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M840-519v339q0 24-18 42t-42 18H179q-24 0-42-18t-18-42v-339q-28-24-37-59t2-70l43-135q8-27 28-42t46-15h553q28 0 49 15.5t29 41.5l44 135q11 35 1.5 70T840-519Zm-270-31q29 0 49-19t16-46l-25-165H510v165q0 26 17 45.5t43 19.5Zm-187 0q28 0 47.5-19t19.5-46v-165H350l-25 165q-4 26 14 45.5t44 19.5Zm-182 0q24 0 41.5-16.5T263-607l26-173H189l-46 146q-10 31 8 57.5t50 26.5Zm557 0q32 0 50.5-26t8.5-58l-46-146H671l26 173q3 24 20.5 40.5T758-550Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M863-404 557-97q-9 8.5-20.25 12.75T514.25-80Q503-80 492-84.5T472-97L98-472q-8-8-13-18.96-5-10.95-5-23.04v-306q0-24.75 17.63-42.38Q115.25-880 140-880h307q12.07 0 23.39 4.87Q481.7-870.25 490-862l373 373q9.39 9 13.7 20.25 4.3 11.25 4.3 22.5t-4.5 22.75Q872-412 863-404ZM245-664q21 0 36.5-15.5T297-716q0-21-15.5-36.5T245-768q-21 0-36.5 15.5T193-716q0 21 15.5 36.5T245-664Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M280-240q-100 0-170-70T40-480q0-100 70-170t170-70h400q100 0 170 70t70 170q0 100-70 170t-170 70H280Zm472.5-168.44q29.5-29.44 29.5-71.5t-29.44-71.56q-29.44-29.5-71.5-29.5t-71.56 29.44q-29.5 29.44-29.5 71.5t29.44 71.56q29.44 29.5 71.5 29.5t71.56-29.44Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M261-120q-24 0-42-18t-18-42v-570h-41v-60h188v-30h264v30h188v60h-41v570q0 24-18 42t-42 18H261Zm106-146h60v-399h-60v399Zm166 0h60v-399h-60v399Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M372-523q-42-42-42-108t42-108q42-42 108-42t108 42q42 42 42 108t-42 108q-42 42-108 42t-108-42ZM160-160v-94q0-38 19-65t49-41q67-30 128.5-45T480-420q62 0 123 15.5T731-360q31 14 50 41t19 65v94H160Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M705-128 447-388q-23 8-46 13t-47 5q-97 0-165-67.5T121-602q0-31 8-60.5t23-55.5l145 145 92-86-149-149q26-15 55-23.5t59-8.5q99 0 168.5 69.5T592-602q0 24-5 47t-13 46l259 258q11 11 11 26.5T833-198l-76 70q-11 11-26 11t-26-11Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40Zm0,16V88H40V56Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M239.73,208H224V96a16,16,0,0,0-16-16H164a4,4,0,0,0-4,4V208H144V32.41a16.43,16.43,0,0,0-6.16-13,16,16,0,0,0-18.72-.69L39.12,72A16,16,0,0,0,32,85.34V208H16.27A8.18,8.18,0,0,0,8,215.47,8,8,0,0,0,16,224H240a8,8,0,0,0,8-8.53A8.18,8.18,0,0,0,239.73,208ZM76,184a8,8,0,0,1-8.53,8A8.18,8.18,0,0,1,60,183.72V168.27A8.19,8.19,0,0,1,67.47,160,8,8,0,0,1,76,168Zm0-56a8,8,0,0,1-8.53,8A8.19,8.19,0,0,1,60,127.72V112.27A8.19,8.19,0,0,1,67.47,104,8,8,0,0,1,76,112Zm40,56a8,8,0,0,1-8.53,8,8.18,8.18,0,0,1-7.47-8.26V168.27a8.19,8.19,0,0,1,7.47-8.26,8,8,0,0,1,8.53,8Zm0-56a8,8,0,0,1-8.53,8,8.19,8.19,0,0,1-7.47-8.26V112.27a8.19,8.19,0,0,1,7.47-8.26,8,8,0,0,1,8.53,8Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,86.53V56a16,16,0,0,0-16-16H40A16,16,0,0,0,24,56V184a16,16,0,0,0,16,16H160v24A8,8,0,0,0,172,231l24-13.74L220,231A8,8,0,0,0,232,224V161.47a51.88,51.88,0,0,0,0-74.94ZM128,144H72a8,8,0,0,1,0-16h56a8,8,0,0,1,0,16Zm0-32H72a8,8,0,0,1,0-16h56a8,8,0,0,1,0,16Zm88,98.21-16-9.16a8,8,0,0,0-7.94,0l-16,9.16V172a51.88,51.88,0,0,0,40,0ZM196,160a36,36,0,1,1,36-36A36,36,0,0,1,196,160Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM200,192H56a8,8,0,0,1-8-8V72a8,8,0,0,1,16,0v76.69l34.34-34.35a8,8,0,0,1,11.32,0L128,132.69,172.69,88H144a8,8,0,0,1,0-16h48a8,8,0,0,1,8,8v48a8,8,0,0,1-16,0V99.31l-50.34,50.35a8,8,0,0,1-11.32,0L104,131.31l-40,40V176H200a8,8,0,0,1,0,16Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,96a16,16,0,0,0-16-16H184V48a16,16,0,0,0-16-16H40A16,16,0,0,0,24,48V176a8,8,0,0,0,13,6.22L72,154V184a16,16,0,0,0,16,16h93.59L219,230.22a8,8,0,0,0,5,1.78,8,8,0,0,0,8-8Zm-42.55,89.78a8,8,0,0,0-5-1.78H88V152h80a16,16,0,0,0,16-16V96h32V207.25Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M224,48H32a8,8,0,0,0-8,8V192a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A8,8,0,0,0,224,48Zm-8,144H40V74.19l82.59,75.71a8,8,0,0,0,10.82,0L216,74.19V192Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,176H96a8,8,0,0,1,0-16h64a8,8,0,0,1,0,16Zm0-32H96a8,8,0,0,1,0-16h64a8,8,0,0,1,0,16Zm-8-56V44l44,44Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,88V200.89A15.13,15.13,0,0,1,216.89,216H40a16,16,0,0,1-16-16V64A16,16,0,0,1,40,48H93.33a16.12,16.12,0,0,1,9.6,3.2L130.67,72H216A16,16,0,0,1,232,88Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M128,80a48,48,0,1,0,48,48A48.05,48.05,0,0,0,128,80Zm0,80a32,32,0,1,1,32-32A32,32,0,0,1,128,160Zm109.94-52.79a8,8,0,0,0-3.89-5.4l-29.83-17-.12-33.62a8,8,0,0,0-2.83-6.08,111.91,111.91,0,0,0-36.72-20.67,8,8,0,0,0-6.46.59L128,41.85,97.88,25a8,8,0,0,0-6.47-.6A112.1,112.1,0,0,0,54.73,45.15a8,8,0,0,0-2.83,6.07l-.15,33.65-29.83,17a8,8,0,0,0-3.89,5.4,106.47,106.47,0,0,0,0,41.56,8,8,0,0,0,3.89,5.4l29.83,17,.12,33.62a8,8,0,0,0,2.83,6.08,111.91,111.91,0,0,0,36.72,20.67,8,8,0,0,0,6.46-.59L128,214.15,158.12,231a7.91,7.91,0,0,0,3.9,1,8.09,8.09,0,0,0,2.57-.42,112.1,112.1,0,0,0,36.68-20.73,8,8,0,0,0,2.83-6.07l.15-33.65,29.83-17a8,8,0,0,0,3.89-5.4A106.47,106.47,0,0,0,237.94,107.21Zm-15,34.91-28.57,16.25a8,8,0,0,0-3,3c-.58,1-1.19,2.06-1.81,3.06a7.94,7.94,0,0,0-1.22,4.21l-.15,32.25a95.89,95.89,0,0,1-25.37,14.3L134,199.13a8,8,0,0,0-3.91-1h-.19c-1.21,0-2.43,0-3.64,0a8.08,8.08,0,0,0-4.1,1l-28.84,16.1A96,96,0,0,1,67.88,201l-.11-32.2a8,8,0,0,0-1.22-4.22c-.62-1-1.23-2-1.8-3.06a8.09,8.09,0,0,0-3-3.06l-28.6-16.29a90.49,90.49,0,0,1,0-28.26L61.67,97.63a8,8,0,0,0,3-3c.58-1,1.19-2.06,1.81-3.06a7.94,7.94,0,0,0,1.22-4.21l.15-32.25a95.89,95.89,0,0,1,25.37-14.3L122,56.87a8,8,0,0,0,4.1,1c1.21,0,2.43,0,3.64,0a8.08,8.08,0,0,0,4.1-1l28.84-16.1A96,96,0,0,1,188.12,55l.11,32.2a8,8,0,0,0,1.22,4.22c.62,1,1.23,2,1.8,3.06a8.09,8.09,0,0,0,3,3.06l28.6,16.29A90.49,90.49,0,0,1,222.9,142.12Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M128,24h0A104,104,0,1,0,232,128,104.12,104.12,0,0,0,128,24Zm87.62,96H175.79C174,83.49,159.94,57.67,148.41,42.4A88.19,88.19,0,0,1,215.63,120ZM96.23,136h63.54c-2.31,41.61-22.23,67.11-31.77,77C118.45,203.1,98.54,177.6,96.23,136Zm0-16C98.54,78.39,118.46,52.89,128,43c9.55,9.93,29.46,35.43,31.77,77Zm11.36-77.6C96.06,57.67,82,83.49,80.21,120H40.37A88.19,88.19,0,0,1,107.59,42.4ZM40.37,136H80.21c1.82,36.51,15.85,62.33,27.38,77.6A88.19,88.19,0,0,1,40.37,136Zm108,77.6c11.53-15.27,25.56-41.09,27.38-77.6h39.84A88.19,88.19,0,0,1,148.41,213.6Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M240,102c0,70-103.79,126.66-108.21,129a8,8,0,0,1-7.58,0C119.79,228.66,16,172,16,102A62.07,62.07,0,0,1,78,40c20.65,0,38.73,8.88,50,23.89C139.27,48.88,157.35,40,178,40A62.07,62.07,0,0,1,240,102Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40Zm0,16V96H40V56ZM40,112H96v88H40Zm176,88H112V112H216v88Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM117.66,149.66l-32,32a8,8,0,0,1-11.32,0l-16-16a8,8,0,0,1,11.32-11.32L80,164.69l26.34-26.35a8,8,0,0,1,11.32,11.32Zm0-64-32,32a8,8,0,0,1-11.32,0l-16-16A8,8,0,0,1,69.66,90.34L80,100.69l26.34-26.35a8,8,0,0,1,11.32,11.32ZM192,168H144a8,8,0,0,1,0-16h48a8,8,0,0,1,0,16Zm0-64H144a8,8,0,0,1,0-16h48a8,8,0,0,1,0,16Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M168,112a56,56,0,1,1-56-56A56,56,0,0,1,168,112Zm61.66,117.66a8,8,0,0,1-11.32,0l-50.06-50.07a88,88,0,1,1,11.32-11.31l50.06,50.06A8,8,0,0,1,229.66,229.66ZM112,184a72,72,0,1,0-72-72A72.08,72.08,0,0,0,112,184Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M200,72H160.2c-2.91-.17-53.62-3.74-101.91-44.24A16,16,0,0,0,32,40V200a16,16,0,0,0,26.29,12.25c37.77-31.68,77-40.76,93.71-43.3v31.72A16,16,0,0,0,159.12,214l11,7.33A16,16,0,0,0,194.5,212l11.77-44.36A48,48,0,0,0,200,72ZM179,207.89l0,.11-11-7.33V168h21.6ZM200,152H168V88h32a32,32,0,1,1,0,64Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,48H56A16,16,0,0,0,40,64V184a8,8,0,0,1-16,0V88A8,8,0,0,0,8,88v96.11A24,24,0,0,0,32,208H208a24,24,0,0,0,24-24V64A16,16,0,0,0,216,48ZM176,152H96a8,8,0,0,1,0-16h80a8,8,0,0,1,0,16Zm0-32H96a8,8,0,0,1,0-16h80a8,8,0,0,1,0,16Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,24H72A40,40,0,0,0,32,64v72a24,24,0,0,0,24,24h48l-7.89,46.67A8.42,8.42,0,0,0,96,208a32,32,0,0,0,64,0,8.42,8.42,0,0,0-.11-1.33L152,160h48a24,24,0,0,0,24-24V32A8,8,0,0,0,216,24ZM72,40H176V80a8,8,0,0,0,16,0V40h16v72H48V64A24,24,0,0,1,72,40Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M165.78,224H208a16,16,0,0,0,16-16V170.35A8,8,0,0,0,212.94,163a23.37,23.37,0,0,1-8.94,1.77c-13.23,0-24-11.1-24-24.73s10.77-24.73,24-24.73a23.37,23.37,0,0,1,8.94,1.77A8,8,0,0,0,224,109.65V72a16,16,0,0,0-16-16H171.78a35.36,35.36,0,0,0,.22-4,36,36,0,0,0-72,0,35.36,35.36,0,0,0,.22,4H64A16,16,0,0,0,48,72v32.22a35.36,35.36,0,0,0-4-.22,36,36,0,0,0,0,72,35.36,35.36,0,0,0,4-.22V208a16,16,0,0,0,16,16h42.22"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M208,40H48A16,16,0,0,0,32,56v56c0,52.72,25.52,84.67,46.93,102.19,23.06,18.86,46,25.26,47,25.53a8,8,0,0,0,4.2,0c1-.27,23.91-6.67,47-25.53C198.48,196.67,224,164.72,224,112V56A16,16,0,0,0,208,40Zm-34.32,69.66-56,56a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L112,148.69l50.34-50.35a8,8,0,0,1,11.32,11.32Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM40,152H56a8,8,0,0,0,0-16H40V120H56a8,8,0,0,0,0-16H40V88H56a8,8,0,0,0,0-16H40V56H80V200H40Zm176,48H96V56H216V200Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M200,40H56A16,16,0,0,0,40,56V200a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V56A16,16,0,0,0,200,40Zm0,16v72H56V56Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M200,40H56A16,16,0,0,0,40,56V200a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V56A16,16,0,0,0,200,40Zm-64,80h64v16H136Zm0-16V88h64v16Zm0,48h64v16H136Zm64-80H136V56h64ZM56,56h64V200H56ZM200,200H136V184h64v16Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M120,56v48a16,16,0,0,1-16,16H56a16,16,0,0,1-16-16V56A16,16,0,0,1,56,40h48A16,16,0,0,1,120,56Zm80-16H152a16,16,0,0,0-16,16v48a16,16,0,0,0,16,16h48a16,16,0,0,0,16-16V56A16,16,0,0,0,200,40Zm-96,96H56a16,16,0,0,0-16,16v48a16,16,0,0,0,16,16h48a16,16,0,0,0,16-16V152A16,16,0,0,0,104,136Zm96,0H152a16,16,0,0,0-16,16v48a16,16,0,0,0,16,16h48a16,16,0,0,0,16-16V152A16,16,0,0,0,200,136Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M231.69,93.81,217.35,43.6A16.07,16.07,0,0,0,202,32H54A16.07,16.07,0,0,0,38.65,43.6L24.31,93.81A7.94,7.94,0,0,0,24,96v16a40,40,0,0,0,16,32v72a8,8,0,0,0,8,8H208a8,8,0,0,0,8-8V144a40,40,0,0,0,16-32V96A7.94,7.94,0,0,0,231.69,93.81ZM88,112a24,24,0,0,1-35.12,21.26,7.88,7.88,0,0,0-1.82-1.06A24,24,0,0,1,40,112v-8H88Zm64,0a24,24,0,0,1-48,0v-8h48Zm64,0a24,24,0,0,1-11.07,20.2,8.08,8.08,0,0,0-1.8,1.05A24,24,0,0,1,168,112v-8h48Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M243.31,136,144,36.69A15.86,15.86,0,0,0,132.69,32H40a8,8,0,0,0-8,8v92.69A15.86,15.86,0,0,0,36.69,144L136,243.31a16,16,0,0,0,22.63,0l84.68-84.68a16,16,0,0,0,0-22.63ZM84,96A12,12,0,1,1,96,84,12,12,0,0,1,84,96Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M176,56H80a72,72,0,0,0,0,144h96a72,72,0,0,0,0-144Zm0,112a40,40,0,1,1,40-40A40,40,0,0,1,176,168Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,48H176V40a24,24,0,0,0-24-24H104A24,24,0,0,0,80,40v8H40a8,8,0,0,0,0,16h8V208a16,16,0,0,0,16,16H192a16,16,0,0,0,16-16V64h8a8,8,0,0,0,0-16ZM112,168a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm48,0a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm0-120H96V40a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M230.93,220a8,8,0,0,1-6.93,4H32a8,8,0,0,1-6.92-12c15.23-26.33,38.7-45.21,66.09-54.16a72,72,0,1,1,73.66,0c27.39,8.95,50.86,27.83,66.09,54.16A8,8,0,0,1,230.93,220Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,96a72,72,0,0,1-100.94,66L79,222.22c-.12.14-.26.29-.39.42a32,32,0,0,1-45.26-45.26c.14-.13.28-.27.43-.39L94,124.94a72.07,72.07,0,0,1,83.54-98.78,8,8,0,0,1,3.93,13.19L144,80l5.66,26.35L176,112l40.65-37.52a8,8,0,0,1,13.19,3.93A72.6,72.6,0,0,1,232,96Z"/></svg>
@@ -0,0 +1,13 @@
1
+ /** The breakpoint a window `width` px wide is in.
2
+ * @param {number} width
3
+ * @returns {Breakpoint} */
4
+ export function breakpointOf(width: number): Breakpoint;
5
+ export namespace BREAKPOINTS {
6
+ let compact: 0;
7
+ let medium: 600;
8
+ let expanded: 840;
9
+ let large: 1200;
10
+ let extraLarge: 1600;
11
+ }
12
+ export function atLeast(name: Exclude<Breakpoint, "compact">): string;
13
+ export type Breakpoint = "compact" | "medium" | "expanded" | "large" | "extraLarge";
@@ -0,0 +1,20 @@
1
+ // Material 3's breakpoints (m3.material.io/foundations/layout/breakpoints): the window widths where the site's and the
2
+ // editor's layouts change, for scripts (matchMedia, the preview's widths). The CSS has the same ones as Tailwind's
3
+ // --breakpoint-* (theme/styles/base.css); breakpoints.test.mjs checks that they agree.
4
+
5
+ /** @typedef {'compact' | 'medium' | 'expanded' | 'large' | 'extraLarge'} Breakpoint */
6
+
7
+ /** Where each breakpoint begins, in dp (CSS px); compact is everything below medium. */
8
+ export const BREAKPOINTS = /** @type {const} */ ({ compact: 0, medium: 600, expanded: 840, large: 1200, extraLarge: 1600 });
9
+
10
+ /** The media query for a window at least as wide as a breakpoint, in rem as the CSS writes it.
11
+ * @param {Exclude<Breakpoint, 'compact'>} name */
12
+ export const atLeast = (name) => `(width >= ${BREAKPOINTS[name] / 16}rem)`;
13
+
14
+ /** The breakpoint a window `width` px wide is in.
15
+ * @param {number} width
16
+ * @returns {Breakpoint} */
17
+ export function breakpointOf(width) {
18
+ const names = /** @type {Breakpoint[]} */ (Object.keys(BREAKPOINTS));
19
+ return names.findLast((name) => width >= BREAKPOINTS[name]) ?? 'compact';
20
+ }
@@ -0,0 +1,39 @@
1
+ // Tests lib/breakpoints.mjs (Material 3's breakpoints for scripts) and that the theme's CSS has the same ones
2
+ // (--breakpoint-* in theme/styles/base.css). Run with `node --test packages/editor/lib/*.test.mjs` (part of npm run check).
3
+ import { test } from 'node:test';
4
+ import assert from 'node:assert/strict';
5
+ import { readFileSync } from 'node:fs';
6
+ import { BREAKPOINTS, atLeast, breakpointOf } from './breakpoints.mjs';
7
+
8
+ test('the breakpoints are Material 3’s', () => {
9
+ assert.deepEqual(BREAKPOINTS, { compact: 0, medium: 600, expanded: 840, large: 1200, extraLarge: 1600 });
10
+ });
11
+
12
+ test('atLeast gives the media query in rem, as the CSS writes it', () => {
13
+ assert.equal(atLeast('medium'), '(width >= 37.5rem)');
14
+ assert.equal(atLeast('extraLarge'), '(width >= 100rem)');
15
+ });
16
+
17
+ test('breakpointOf gives the breakpoint a window is in', () => {
18
+ assert.equal(breakpointOf(0), 'compact');
19
+ assert.equal(breakpointOf(599), 'compact');
20
+ assert.equal(breakpointOf(600), 'medium');
21
+ assert.equal(breakpointOf(839), 'medium');
22
+ assert.equal(breakpointOf(840), 'expanded');
23
+ assert.equal(breakpointOf(1199), 'expanded');
24
+ assert.equal(breakpointOf(1200), 'large');
25
+ assert.equal(breakpointOf(1600), 'extraLarge');
26
+ assert.equal(breakpointOf(3840), 'extraLarge');
27
+ });
28
+
29
+ test('the theme’s CSS has the same breakpoints', () => {
30
+ const css = readFileSync(new URL('../theme/styles/base.css', import.meta.url), 'utf8');
31
+ const inCss = Object.fromEntries(
32
+ [...css.matchAll(/--breakpoint-([a-z-]+):\s*([\d.]+)rem/g)].map(([, name, rem]) => [
33
+ name.replace(/-([a-z])/g, (_, c) => c.toUpperCase()),
34
+ Number(rem) * 16,
35
+ ]),
36
+ );
37
+ const { compact, ...rest } = BREAKPOINTS;
38
+ assert.deepEqual(inCss, rest);
39
+ });
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @param {string[] | null} paths the files changed since the live commit, or `null` when they are not known
3
+ * @param {{ contentLane: boolean }} settings (from readBuildSettings)
4
+ * @param {string} [why] the caller's reason it has no list
5
+ * @returns {{ lane: 'content' | 'full', reason: string }}
6
+ * any doubt gives the full lane.
7
+ */
8
+ export function laneFor(paths: string[] | null, settings: {
9
+ contentLane: boolean;
10
+ }, why?: string): {
11
+ lane: "content" | "full";
12
+ reason: string;
13
+ };
14
+ /** the folders an editor save writes to; a change anywhere else is code. */
15
+ export const CONTENT_PATHS: string[];
@@ -0,0 +1,23 @@
1
+ // Which lane a Cloudflare build takes (morpheme ci-build): the content lane, with the editor's checks only, when every
2
+ // file changed since the live commit is content; else the full lane. Exposes CONTENT_PATHS, laneFor. No dependencies.
3
+
4
+ /** the folders an editor save writes to; a change anywhere else is code. */
5
+ export const CONTENT_PATHS = ['src/content/', 'src/data/', 'public/images/uploads/'];
6
+
7
+ /**
8
+ * @param {string[] | null} paths the files changed since the live commit, or `null` when they are not known
9
+ * @param {{ contentLane: boolean }} settings (from readBuildSettings)
10
+ * @param {string} [why] the caller's reason it has no list
11
+ * @returns {{ lane: 'content' | 'full', reason: string }}
12
+ * any doubt gives the full lane.
13
+ */
14
+ export function laneFor(paths, settings, why) {
15
+ if (settings.contentLane === false) return { lane: 'full', reason: 'turned off in the editor' };
16
+ if (paths === null) return { lane: 'full', reason: why ?? 'changed files unknown' };
17
+ if (paths.length === 0) return { lane: 'full', reason: 'nothing changed since the live commit' };
18
+ const normalised = paths.map((p) => p.replace(/\\/g, '/'));
19
+ for (const path of normalised) {
20
+ if (!CONTENT_PATHS.some((prefix) => path.startsWith(prefix))) return { lane: 'full', reason: 'code changed: ' + path };
21
+ }
22
+ return { lane: 'content', reason: 'only content changed (' + paths.length + ' files)' };
23
+ }
@@ -0,0 +1,74 @@
1
+ // Tests for lib/build-lane.mjs: the content or full lane from the changed files, including the paths that count as content
2
+ // and the reasons given. Run: node --test packages/editor/lib/*.test.mjs
3
+ import { test } from 'node:test';
4
+ import assert from 'node:assert/strict';
5
+ import { CONTENT_PATHS, laneFor } from './build-lane.mjs';
6
+
7
+ const on = { contentLane: true };
8
+
9
+ test('one content file takes the content lane', () => {
10
+ const res = laneFor(['src/content/blog/a.md'], on);
11
+ assert.equal(res.lane, 'content');
12
+ assert.match(res.reason, /1 files/);
13
+ });
14
+
15
+ test('content, data and uploads take the content lane', () => {
16
+ const res = laneFor(['src/content/pages/x.md', 'src/data/menu.json', 'public/images/uploads/a.jpg'], on);
17
+ assert.equal(res.lane, 'content');
18
+ });
19
+
20
+ test('the build settings file is content', () => {
21
+ const res = laneFor(['src/data/build.json'], on);
22
+ assert.equal(res.lane, 'content');
23
+ });
24
+
25
+ test('editor code takes the full lane and names the file', () => {
26
+ const res = laneFor(['packages/editor/src/ui.tsx'], on);
27
+ assert.equal(res.lane, 'full');
28
+ assert.equal(res.reason, 'code changed: packages/editor/src/ui.tsx');
29
+ });
30
+
31
+ test('content and a lockfile take the full lane', () => {
32
+ const res = laneFor(['src/content/blog/a.md', 'package-lock.json'], on);
33
+ assert.equal(res.lane, 'full');
34
+ assert.equal(res.reason, 'code changed: package-lock.json');
35
+ });
36
+
37
+ test('the site config is code', () => {
38
+ const res = laneFor(['src/site/config.ts'], on);
39
+ assert.equal(res.lane, 'full');
40
+ });
41
+
42
+ test('a theme is code', () => {
43
+ const res = laneFor(['src/themes/venus/styles/global.css'], on);
44
+ assert.equal(res.lane, 'full');
45
+ });
46
+
47
+ test('only uploads under public are content', () => {
48
+ const res = laneFor(['public/favicon.svg'], on);
49
+ assert.equal(res.lane, 'full');
50
+ });
51
+
52
+ test('backslashes are normalised', () => {
53
+ const res = laneFor(['src\\content\\blog\\a.md'], on);
54
+ assert.equal(res.lane, 'content');
55
+ });
56
+
57
+ test('nothing changed takes the full lane', () => {
58
+ const res = laneFor([], on);
59
+ assert.deepEqual(res, { lane: 'full', reason: 'nothing changed since the live commit' });
60
+ });
61
+
62
+ test("unknown changes take the full lane with the caller's reason", () => {
63
+ const res = laneFor(null, on, 'live commit unknown');
64
+ assert.deepEqual(res, { lane: 'full', reason: 'live commit unknown' });
65
+ });
66
+
67
+ test('turned off in the editor takes the full lane', () => {
68
+ const res = laneFor(['src/content/blog/a.md'], { contentLane: false });
69
+ assert.deepEqual(res, { lane: 'full', reason: 'turned off in the editor' });
70
+ });
71
+
72
+ test('the content paths', () => {
73
+ assert.deepEqual(CONTENT_PATHS, ['src/content/', 'src/data/', 'public/images/uploads/']);
74
+ });
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @param {unknown} json the parsed contents of the file, or undefined when it is missing
3
+ * @returns {{ contentLane: boolean, paidBuilds: boolean }} the settings with the defaults filled in; a key that is not a boolean counts as missing.
4
+ */
5
+ export function readBuildSettings(json: unknown): {
6
+ contentLane: boolean;
7
+ paidBuilds: boolean;
8
+ };
9
+ /**
10
+ * @param {boolean} paidBuilds
11
+ * @returns {number} milliseconds
12
+ * how long the editor waits for a save's build before it says the build failed: 20 minutes on the free plan, where a build can queue behind others, 10 minutes on Workers Paid.
13
+ */
14
+ export function giveUpAfter(paidBuilds: boolean): number;
15
+ /** The settings file, from the repo root. */
16
+ export const BUILD_SETTINGS_PATH: "src/data/build.json";
@@ -0,0 +1,39 @@
1
+ // The build settings in src/data/build.json (Indstillinger › Avanceret): readBuildSettings fills in the defaults, and
2
+ // giveUpAfter is how long the editor waits for a save's build. Exposes BUILD_SETTINGS_PATH, readBuildSettings,
3
+ // giveUpAfter. No dependencies.
4
+
5
+ /** The settings file, from the repo root. */
6
+ export const BUILD_SETTINGS_PATH = 'src/data/build.json';
7
+
8
+ /**
9
+ * @param {unknown} json the parsed contents of the file, or undefined when it is missing
10
+ * @returns {{ contentLane: boolean, paidBuilds: boolean }} the settings with the defaults filled in; a key that is not a boolean counts as missing.
11
+ */
12
+ export function readBuildSettings(json) {
13
+ const defaults = { contentLane: true, paidBuilds: false };
14
+
15
+ if (typeof json !== 'object' || json === null || Array.isArray(json)) {
16
+ return { ...defaults };
17
+ }
18
+
19
+ const result = { ...defaults };
20
+
21
+ for (const key of Object.keys(defaults)) {
22
+ const value = json[key];
23
+
24
+ if (typeof value === 'boolean') {
25
+ result[key] = value;
26
+ }
27
+ }
28
+
29
+ return result;
30
+ }
31
+
32
+ /**
33
+ * @param {boolean} paidBuilds
34
+ * @returns {number} milliseconds
35
+ * how long the editor waits for a save's build before it says the build failed: 20 minutes on the free plan, where a build can queue behind others, 10 minutes on Workers Paid.
36
+ */
37
+ export function giveUpAfter(paidBuilds) {
38
+ return (paidBuilds ? 10 : 20) * 60_000;
39
+ }
@@ -0,0 +1,41 @@
1
+ // Tests for lib/build-settings.mjs: the build settings' defaults, what a missing or odd file falls back to, and the wait
2
+ // limit with and without paid builds. Run: node --test packages/editor/lib/*.test.mjs
3
+ import { test } from 'node:test';
4
+ import assert from 'node:assert/strict';
5
+ import { BUILD_SETTINGS_PATH, readBuildSettings, giveUpAfter } from './build-settings.mjs';
6
+
7
+ const defaults = { contentLane: true, paidBuilds: false };
8
+
9
+ test('a missing file gives the defaults', () => {
10
+ assert.deepEqual(readBuildSettings(undefined), defaults);
11
+ });
12
+
13
+ test('an empty object gives the defaults', () => {
14
+ assert.deepEqual(readBuildSettings({}), defaults);
15
+ });
16
+
17
+ test('contentLane can be turned off', () => {
18
+ assert.deepEqual(readBuildSettings({ contentLane: false }), { contentLane: false, paidBuilds: false });
19
+ });
20
+
21
+ test('paidBuilds can be turned on', () => {
22
+ assert.deepEqual(readBuildSettings({ paidBuilds: true }), { contentLane: true, paidBuilds: true });
23
+ });
24
+
25
+ test('a key that is not a boolean counts as missing', () => {
26
+ assert.deepEqual(readBuildSettings({ contentLane: 'no', paidBuilds: 1 }), defaults);
27
+ });
28
+
29
+ test('null and an array give the defaults', () => {
30
+ assert.deepEqual(readBuildSettings(null), defaults);
31
+ assert.deepEqual(readBuildSettings([]), defaults);
32
+ });
33
+
34
+ test('the wait is 20 minutes on the free plan and 10 on the paid plan', () => {
35
+ assert.equal(giveUpAfter(false), 1_200_000);
36
+ assert.equal(giveUpAfter(true), 600_000);
37
+ });
38
+
39
+ test('the settings file is src/data/build.json', () => {
40
+ assert.equal(BUILD_SETTINGS_PATH, 'src/data/build.json');
41
+ });
@@ -11,5 +11,6 @@ export const APP_API: 2;
11
11
  * CLAUDE.md, themeProblems in packages/editor/site/theme.mjs, the standard theme's UI parts with Material 3's names and
12
12
  * variants, the motion scheme's --motion-* springs and motionSpring/motionTiming (@morphemecms/cms/lib/motion),
13
13
  * and the classes it styles): only themes written to it are offered. Raised when a theme written to the one before no
14
- * longer works. */
15
- export const THEME_API: 3;
14
+ * longer works. Material 3's breakpoints (--breakpoint-*: medium:, expanded:, large:, extra-large:) instead of Tailwind's.
15
+ * The FAB menu's script with its setUpFabMenu export, and FabMenu with an icon as an element (the editor's start screen). */
16
+ export const THEME_API: 4;
package/lib/contracts.mjs CHANGED
@@ -13,5 +13,6 @@ export const APP_API = 2;
13
13
  * CLAUDE.md, themeProblems in packages/editor/site/theme.mjs, the standard theme's UI parts with Material 3's names and
14
14
  * variants, the motion scheme's --motion-* springs and motionSpring/motionTiming (@morphemecms/cms/lib/motion),
15
15
  * and the classes it styles): only themes written to it are offered. Raised when a theme written to the one before no
16
- * longer works. */
17
- export const THEME_API = 3;
16
+ * longer works. Material 3's breakpoints (--breakpoint-*: medium:, expanded:, large:, extra-large:) instead of Tailwind's.
17
+ * The FAB menu's script with its setUpFabMenu export, and FabMenu with an icon as an element (the editor's start screen). */
18
+ export const THEME_API = 4;
@@ -0,0 +1,10 @@
1
+ /** Whether a drag of `dx` and `dy` px (pointer up minus pointer down) is a swipe toward the drawer's start edge: the left
2
+ * edge, or the right one when the text runs right to left (`rtl`). It must be far enough and mostly sideways, so scrolling
3
+ * the list never closes it.
4
+ * @param {number} dx
5
+ * @param {number} dy
6
+ * @param {boolean} [rtl]
7
+ * @returns {boolean} */
8
+ export function swipeCloses(dx: number, dy: number, rtl?: boolean): boolean;
9
+ /** How far, in px, a drag must go toward the edge to count as a swipe. */
10
+ export const SWIPE_DISTANCE: 48;
@@ -0,0 +1,17 @@
1
+ // When a drag across the modal drawer closes it (Material 3: a swipe toward the drawer's edge).
2
+ // Exposes swipeCloses and SWIPE_DISTANCE (pure); used by MainDrawer in src/ui.tsx. No dependencies.
3
+
4
+ /** How far, in px, a drag must go toward the edge to count as a swipe. */
5
+ export const SWIPE_DISTANCE = 48;
6
+
7
+ /** Whether a drag of `dx` and `dy` px (pointer up minus pointer down) is a swipe toward the drawer's start edge: the left
8
+ * edge, or the right one when the text runs right to left (`rtl`). It must be far enough and mostly sideways, so scrolling
9
+ * the list never closes it.
10
+ * @param {number} dx
11
+ * @param {number} dy
12
+ * @param {boolean} [rtl]
13
+ * @returns {boolean} */
14
+ export function swipeCloses(dx, dy, rtl = false) {
15
+ const toward = rtl ? dx : -dx;
16
+ return toward >= SWIPE_DISTANCE && toward >= Math.abs(dy) * 2;
17
+ }