@xleddyl/nuxt-cms 0.9.3 → 0.10.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 (433) hide show
  1. package/README.md +1 -1
  2. package/dist/module.d.mts +20 -1
  3. package/dist/module.json +1 -1
  4. package/dist/module.mjs +1037 -148
  5. package/dist/runtime/app/blocks/CmsBlocks.d.vue.ts +1 -1
  6. package/dist/runtime/app/blocks/CmsBlocks.vue +57 -9
  7. package/dist/runtime/app/blocks/CmsBlocks.vue.d.ts +1 -1
  8. package/dist/runtime/app/blocks/CmsField.d.ts +24 -0
  9. package/dist/runtime/app/blocks/CmsField.js +16 -0
  10. package/dist/runtime/app/blocks/node.d.ts +37 -0
  11. package/dist/runtime/app/blocks/node.js +17 -0
  12. package/dist/runtime/app/blocks/resolve.d.ts +18 -0
  13. package/dist/runtime/app/blocks/resolve.js +34 -0
  14. package/dist/runtime/app/components/cms/BlockPicker.d.vue.ts +22 -0
  15. package/dist/runtime/app/components/cms/BlockPicker.vue +87 -0
  16. package/dist/runtime/app/components/cms/BlockPicker.vue.d.ts +22 -0
  17. package/dist/runtime/app/components/cms/BlockPickerPopover.d.vue.ts +38 -0
  18. package/dist/runtime/app/components/cms/BlockPickerPopover.vue +44 -0
  19. package/dist/runtime/app/components/cms/BlockPickerPopover.vue.d.ts +38 -0
  20. package/dist/runtime/app/components/cms/BlockTree.d.vue.ts +29 -0
  21. package/dist/runtime/app/components/cms/BlockTree.vue +322 -0
  22. package/dist/runtime/app/components/cms/BlockTree.vue.d.ts +29 -0
  23. package/dist/runtime/app/components/cms/BlocksField.vue +569 -218
  24. package/dist/runtime/app/components/cms/BrandMark.vue +7 -13
  25. package/dist/runtime/app/components/cms/ConfirmGroups.vue +15 -13
  26. package/dist/runtime/app/components/cms/{BlockPalette.vue.d.ts → EditorHistory.d.vue.ts} +6 -5
  27. package/dist/runtime/app/components/cms/EditorHistory.vue +34 -0
  28. package/dist/runtime/app/components/cms/{BlockPalette.d.vue.ts → EditorHistory.vue.d.ts} +6 -5
  29. package/dist/runtime/app/components/cms/EntryDrawer.d.vue.ts +11 -5
  30. package/dist/runtime/app/components/cms/EntryDrawer.vue +183 -152
  31. package/dist/runtime/app/components/cms/EntryDrawer.vue.d.ts +11 -5
  32. package/dist/runtime/app/components/cms/EntryForm.d.vue.ts +16 -4
  33. package/dist/runtime/app/components/cms/EntryForm.vue +106 -146
  34. package/dist/runtime/app/components/cms/EntryForm.vue.d.ts +16 -4
  35. package/dist/runtime/app/components/cms/FieldInput.vue +10 -2
  36. package/dist/runtime/app/components/cms/FormSections.d.vue.ts +22 -0
  37. package/dist/runtime/app/components/cms/FormSections.vue +71 -0
  38. package/dist/runtime/app/components/cms/FormSections.vue.d.ts +22 -0
  39. package/dist/runtime/app/components/cms/ImportModal.vue +46 -58
  40. package/dist/runtime/app/components/cms/LinkField.d.vue.ts +16 -0
  41. package/dist/runtime/app/components/cms/LinkField.vue +250 -0
  42. package/dist/runtime/app/components/cms/LinkField.vue.d.ts +16 -0
  43. package/dist/runtime/app/components/cms/ListFilters.vue +10 -12
  44. package/dist/runtime/app/components/cms/LocaleSwitch.d.vue.ts +2 -1
  45. package/dist/runtime/app/components/cms/LocaleSwitch.vue +29 -5
  46. package/dist/runtime/app/components/cms/LocaleSwitch.vue.d.ts +2 -1
  47. package/dist/runtime/app/components/cms/MediaDetail.d.vue.ts +2 -0
  48. package/dist/runtime/app/components/cms/MediaDetail.vue +112 -83
  49. package/dist/runtime/app/components/cms/MediaDetail.vue.d.ts +2 -0
  50. package/dist/runtime/app/components/cms/MediaField.vue +35 -25
  51. package/dist/runtime/app/components/cms/MediaFolderPicker.vue +26 -71
  52. package/dist/runtime/app/components/cms/MediaGallery.d.vue.ts +1 -0
  53. package/dist/runtime/app/components/cms/MediaGallery.vue +442 -419
  54. package/dist/runtime/app/components/cms/MediaGallery.vue.d.ts +1 -0
  55. package/dist/runtime/app/components/cms/MediaThumb.vue +9 -25
  56. package/dist/runtime/app/components/cms/MediaUpload.vue +1 -1
  57. package/dist/runtime/app/components/cms/{BlockOutline.d.vue.ts → NestedBlockList.d.vue.ts} +5 -5
  58. package/dist/runtime/app/components/cms/NestedBlockList.vue +87 -0
  59. package/dist/runtime/app/components/cms/{BlockOutline.vue.d.ts → NestedBlockList.vue.d.ts} +5 -5
  60. package/dist/runtime/app/components/cms/PoweredBy.vue +12 -5
  61. package/dist/runtime/app/components/cms/PresetModal.d.vue.ts +18 -0
  62. package/dist/runtime/app/components/cms/PresetModal.vue +70 -0
  63. package/dist/runtime/app/components/cms/PresetModal.vue.d.ts +18 -0
  64. package/dist/runtime/app/components/cms/RelationField.vue +2 -8
  65. package/dist/runtime/app/components/cms/SettingsAccount.vue +60 -71
  66. package/dist/runtime/app/components/cms/SettingsColumns.vue +47 -69
  67. package/dist/runtime/app/components/cms/SettingsEmptyAdd.d.vue.ts +13 -0
  68. package/dist/runtime/app/components/cms/SettingsEmptyAdd.vue +21 -0
  69. package/dist/runtime/app/components/cms/SettingsEmptyAdd.vue.d.ts +13 -0
  70. package/dist/runtime/app/components/cms/SettingsEntries.d.vue.ts +13 -0
  71. package/dist/runtime/app/components/cms/SettingsEntries.vue +50 -0
  72. package/dist/runtime/app/components/cms/SettingsEntries.vue.d.ts +13 -0
  73. package/dist/runtime/app/components/cms/SettingsEntry.d.vue.ts +1 -10
  74. package/dist/runtime/app/components/cms/SettingsEntry.vue +11 -95
  75. package/dist/runtime/app/components/cms/SettingsEntry.vue.d.ts +1 -10
  76. package/dist/runtime/app/components/cms/SettingsEntryActions.d.vue.ts +7 -0
  77. package/dist/runtime/app/components/cms/SettingsEntryActions.vue +42 -0
  78. package/dist/runtime/app/components/cms/SettingsEntryActions.vue.d.ts +7 -0
  79. package/dist/runtime/app/components/cms/SettingsEntryTabs.d.vue.ts +7 -0
  80. package/dist/runtime/app/components/cms/SettingsEntryTabs.vue +21 -0
  81. package/dist/runtime/app/components/cms/SettingsEntryTabs.vue.d.ts +7 -0
  82. package/dist/runtime/app/components/cms/SettingsFormAction.d.vue.ts +3 -0
  83. package/dist/runtime/app/components/cms/SettingsFormAction.vue +17 -0
  84. package/dist/runtime/app/components/cms/SettingsFormAction.vue.d.ts +3 -0
  85. package/dist/runtime/app/components/cms/SettingsLayout.vue +18 -14
  86. package/dist/runtime/app/components/cms/SettingsPresetForm.d.vue.ts +11 -0
  87. package/dist/runtime/app/components/cms/SettingsPresetForm.vue +60 -0
  88. package/dist/runtime/app/components/cms/SettingsPresetForm.vue.d.ts +11 -0
  89. package/dist/runtime/app/components/cms/SettingsPresets.d.vue.ts +13 -0
  90. package/dist/runtime/app/components/cms/SettingsPresets.vue +65 -0
  91. package/dist/runtime/app/components/cms/SettingsPresets.vue.d.ts +13 -0
  92. package/dist/runtime/app/components/cms/SettingsRecordActions.d.vue.ts +32 -0
  93. package/dist/runtime/app/components/cms/SettingsRecordActions.vue +45 -0
  94. package/dist/runtime/app/components/cms/SettingsRecordActions.vue.d.ts +32 -0
  95. package/dist/runtime/app/components/cms/SettingsRedirectActions.d.vue.ts +3 -0
  96. package/dist/runtime/app/components/cms/SettingsRedirectActions.vue +59 -0
  97. package/dist/runtime/app/components/cms/SettingsRedirectActions.vue.d.ts +3 -0
  98. package/dist/runtime/app/components/cms/SettingsRedirectForm.d.vue.ts +11 -0
  99. package/dist/runtime/app/components/cms/SettingsRedirectForm.vue +77 -0
  100. package/dist/runtime/app/components/cms/SettingsRedirectForm.vue.d.ts +11 -0
  101. package/dist/runtime/app/components/cms/SettingsRedirects.d.vue.ts +13 -0
  102. package/dist/runtime/app/components/cms/SettingsRedirects.vue +117 -0
  103. package/dist/runtime/app/components/cms/SettingsRedirects.vue.d.ts +13 -0
  104. package/dist/runtime/app/components/cms/SettingsSecretCard.d.vue.ts +17 -0
  105. package/dist/runtime/app/components/cms/SettingsSecretCard.vue +43 -0
  106. package/dist/runtime/app/components/cms/SettingsSecretCard.vue.d.ts +17 -0
  107. package/dist/runtime/app/components/cms/SettingsSite.d.vue.ts +3 -0
  108. package/dist/runtime/app/components/cms/SettingsSite.vue +140 -0
  109. package/dist/runtime/app/components/cms/SettingsSite.vue.d.ts +3 -0
  110. package/dist/runtime/app/components/cms/SettingsUserCreate.d.vue.ts +8 -0
  111. package/dist/runtime/app/components/cms/SettingsUserCreate.vue +82 -0
  112. package/dist/runtime/app/components/cms/SettingsUserCreate.vue.d.ts +8 -0
  113. package/dist/runtime/app/components/cms/SettingsUserDetail.d.vue.ts +11 -0
  114. package/dist/runtime/app/components/cms/SettingsUserDetail.vue +179 -0
  115. package/dist/runtime/app/components/cms/SettingsUserDetail.vue.d.ts +11 -0
  116. package/dist/runtime/app/components/cms/SettingsUsers.d.vue.ts +9 -6
  117. package/dist/runtime/app/components/cms/SettingsUsers.vue +88 -234
  118. package/dist/runtime/app/components/cms/SettingsUsers.vue.d.ts +9 -6
  119. package/dist/runtime/app/components/cms/SharePreview.d.vue.ts +18 -0
  120. package/dist/runtime/app/components/cms/SharePreview.vue +219 -0
  121. package/dist/runtime/app/components/cms/SharePreview.vue.d.ts +18 -0
  122. package/dist/runtime/app/components/cms/SlugField.vue +5 -3
  123. package/dist/runtime/app/components/cms/StatusBadge.vue +9 -8
  124. package/dist/runtime/app/components/cms/TranslationBadges.d.vue.ts +7 -0
  125. package/dist/runtime/app/components/cms/TranslationBadges.vue +45 -0
  126. package/dist/runtime/app/components/cms/TranslationBadges.vue.d.ts +7 -0
  127. package/dist/runtime/app/components/cms/TranslationMenu.d.vue.ts +17 -0
  128. package/dist/runtime/app/components/cms/TranslationMenu.vue +28 -0
  129. package/dist/runtime/app/components/cms/TranslationMenu.vue.d.ts +17 -0
  130. package/dist/runtime/app/components/cms/VisualEditor.d.vue.ts +22 -4
  131. package/dist/runtime/app/components/cms/VisualEditor.vue +1152 -335
  132. package/dist/runtime/app/components/cms/VisualEditor.vue.d.ts +22 -4
  133. package/dist/runtime/app/components/cms/WelcomeModal.vue +32 -50
  134. package/dist/runtime/app/composables/cms-clipboard.d.ts +8 -0
  135. package/dist/runtime/app/composables/cms-clipboard.js +38 -0
  136. package/dist/runtime/app/composables/cms-confirm.d.ts +6 -8
  137. package/dist/runtime/app/composables/cms-confirm.js +5 -7
  138. package/dist/runtime/app/composables/cms-entry-disabled.d.ts +5 -1
  139. package/dist/runtime/app/composables/cms-entry-disabled.js +7 -0
  140. package/dist/runtime/app/composables/cms-entry-form.d.ts +15 -0
  141. package/dist/runtime/app/composables/cms-entry-form.js +40 -0
  142. package/dist/runtime/app/composables/cms-entry-settings.d.ts +30 -0
  143. package/dist/runtime/app/composables/cms-entry-settings.js +122 -0
  144. package/dist/runtime/app/composables/cms-entry.d.ts +5 -1
  145. package/dist/runtime/app/composables/cms-entry.js +36 -11
  146. package/dist/runtime/app/composables/cms-history.d.ts +10 -0
  147. package/dist/runtime/app/composables/cms-history.js +24 -0
  148. package/dist/runtime/app/composables/cms-link-targets.d.ts +10 -0
  149. package/dist/runtime/app/composables/cms-link-targets.js +40 -0
  150. package/dist/runtime/app/composables/cms-link-usage.d.ts +1 -0
  151. package/dist/runtime/app/composables/cms-link-usage.js +45 -0
  152. package/dist/runtime/app/composables/cms-media-library.d.ts +19 -9
  153. package/dist/runtime/app/composables/cms-media-library.js +31 -13
  154. package/dist/runtime/app/composables/cms-media-uploader.js +6 -20
  155. package/dist/runtime/app/composables/cms-permissions.d.ts +18 -0
  156. package/dist/runtime/app/composables/cms-permissions.js +54 -0
  157. package/dist/runtime/app/composables/cms-presets.d.ts +11 -0
  158. package/dist/runtime/app/composables/cms-presets.js +40 -0
  159. package/dist/runtime/app/composables/cms-preview-mode.d.ts +4 -0
  160. package/dist/runtime/app/composables/cms-preview-mode.js +8 -0
  161. package/dist/runtime/app/composables/cms-query.d.ts +3 -0
  162. package/dist/runtime/app/composables/cms-query.js +45 -20
  163. package/dist/runtime/app/composables/cms-record-list.d.ts +31 -0
  164. package/dist/runtime/app/composables/cms-record-list.js +75 -0
  165. package/dist/runtime/app/composables/cms-route.d.ts +6 -0
  166. package/dist/runtime/app/composables/cms-route.js +36 -0
  167. package/dist/runtime/app/composables/cms-runtime.d.ts +1 -0
  168. package/dist/runtime/app/composables/cms-save-handoff.d.ts +4 -0
  169. package/dist/runtime/app/composables/cms-save-handoff.js +19 -0
  170. package/dist/runtime/app/composables/cms-seo.d.ts +12 -0
  171. package/dist/runtime/app/composables/cms-seo.js +69 -0
  172. package/dist/runtime/app/composables/cms-settings-form.d.ts +13 -0
  173. package/dist/runtime/app/composables/cms-settings-form.js +29 -0
  174. package/dist/runtime/app/composables/cms-settings-sections.d.ts +26 -0
  175. package/dist/runtime/app/composables/cms-settings-sections.js +181 -0
  176. package/dist/runtime/app/composables/cms-settings-stores.d.ts +52 -0
  177. package/dist/runtime/app/composables/cms-settings-stores.js +156 -0
  178. package/dist/runtime/app/composables/cms-settings.d.ts +3 -3
  179. package/dist/runtime/app/composables/cms-settings.js +14 -8
  180. package/dist/runtime/app/composables/cms-site-disabled.d.ts +7 -0
  181. package/dist/runtime/app/composables/cms-site-disabled.js +8 -0
  182. package/dist/runtime/app/composables/cms-site.d.ts +7 -0
  183. package/dist/runtime/app/composables/cms-site.js +22 -0
  184. package/dist/runtime/app/composables/cms-toast.d.ts +2 -8
  185. package/dist/runtime/app/composables/cms-toast.js +3 -9
  186. package/dist/runtime/app/composables/cms-translation-actions.d.ts +15 -0
  187. package/dist/runtime/app/composables/cms-translation-actions.js +108 -0
  188. package/dist/runtime/app/css-url.d.ts +4 -0
  189. package/dist/runtime/app/image/CmsImage.d.vue.ts +89 -0
  190. package/dist/runtime/app/image/CmsImage.vue +91 -0
  191. package/dist/runtime/app/image/CmsImage.vue.d.ts +89 -0
  192. package/dist/runtime/app/layouts/cms-admin.d.vue.ts +2 -2
  193. package/dist/runtime/app/layouts/cms-admin.vue +98 -76
  194. package/dist/runtime/app/layouts/cms-admin.vue.d.ts +2 -2
  195. package/dist/runtime/app/layouts/cms-editor.vue +7 -2
  196. package/dist/runtime/app/links/CmsLink.d.vue.ts +18 -0
  197. package/dist/runtime/app/links/CmsLink.vue +18 -0
  198. package/dist/runtime/app/links/CmsLink.vue.d.ts +18 -0
  199. package/dist/runtime/app/middleware/cms-auth.js +13 -1
  200. package/dist/runtime/app/pages/admin-collection.vue +473 -297
  201. package/dist/runtime/app/pages/admin-content.vue +190 -53
  202. package/dist/runtime/app/pages/admin-entry.vue +79 -75
  203. package/dist/runtime/app/pages/admin-index.vue +18 -5
  204. package/dist/runtime/app/pages/admin-login.vue +1 -1
  205. package/dist/runtime/app/pages/admin-logout.vue +1 -1
  206. package/dist/runtime/app/pages/admin-media.vue +3 -3
  207. package/dist/runtime/app/pages/admin-preview.vue +112 -24
  208. package/dist/runtime/app/plugins/cms-field.d.ts +2 -0
  209. package/dist/runtime/app/plugins/cms-field.js +8 -0
  210. package/dist/runtime/app/plugins/cms-preview-banner.client.d.ts +2 -0
  211. package/dist/runtime/app/plugins/cms-preview-banner.client.js +19 -0
  212. package/dist/runtime/app/plugins/cms-preview.d.ts +2 -0
  213. package/dist/runtime/app/plugins/cms-preview.js +27 -0
  214. package/dist/runtime/app/preview/CmsPreviewBanner.d.vue.ts +7 -0
  215. package/dist/runtime/app/preview/CmsPreviewBanner.vue +63 -0
  216. package/dist/runtime/app/preview/CmsPreviewBanner.vue.d.ts +7 -0
  217. package/dist/runtime/app/preview/PreviewOverlay.d.vue.ts +17 -3
  218. package/dist/runtime/app/preview/PreviewOverlay.vue +629 -166
  219. package/dist/runtime/app/preview/PreviewOverlay.vue.d.ts +17 -3
  220. package/dist/runtime/app/preview/field-marker.d.ts +12 -0
  221. package/dist/runtime/app/preview/field-marker.js +20 -0
  222. package/dist/runtime/app/preview/inline-text.d.ts +15 -0
  223. package/dist/runtime/app/preview/inline-text.js +158 -0
  224. package/dist/runtime/app/utils/block-editor.d.ts +22 -0
  225. package/dist/runtime/app/utils/block-editor.js +12 -0
  226. package/dist/runtime/app/utils/keyboard.d.ts +6 -0
  227. package/dist/runtime/app/utils/keyboard.js +52 -0
  228. package/dist/runtime/app/utils/redirects.d.ts +6 -0
  229. package/dist/runtime/app/utils/redirects.js +7 -0
  230. package/dist/runtime/app/utils/ui.d.ts +8 -0
  231. package/dist/runtime/app/utils/ui.js +15 -1
  232. package/dist/runtime/app/utils/users.d.ts +15 -0
  233. package/dist/runtime/app/utils/users.js +14 -0
  234. package/dist/runtime/assets/cms.css +1 -1
  235. package/dist/runtime/generate.js +16 -2
  236. package/dist/runtime/server/api/collection-export.get.js +3 -2
  237. package/dist/runtime/server/api/collection-import.post.js +39 -11
  238. package/dist/runtime/server/api/collection.get.js +29 -10
  239. package/dist/runtime/server/api/collection.post.js +28 -11
  240. package/dist/runtime/server/api/collection.put.js +35 -13
  241. package/dist/runtime/server/api/item.delete.js +19 -7
  242. package/dist/runtime/server/api/item.get.js +3 -2
  243. package/dist/runtime/server/api/item.put.js +52 -18
  244. package/dist/runtime/server/api/link-usage.post.d.ts +5 -0
  245. package/dist/runtime/server/api/link-usage.post.js +21 -0
  246. package/dist/runtime/server/api/media-delete.post.js +4 -2
  247. package/dist/runtime/server/api/media-download.get.js +2 -2
  248. package/dist/runtime/server/api/media-folder.delete.js +8 -2
  249. package/dist/runtime/server/api/media-folder.patch.js +10 -2
  250. package/dist/runtime/server/api/media-folder.post.js +4 -2
  251. package/dist/runtime/server/api/media-move.post.js +7 -4
  252. package/dist/runtime/server/api/media-presign.post.js +2 -2
  253. package/dist/runtime/server/api/media-upload.put.js +2 -2
  254. package/dist/runtime/server/api/media-usage.post.d.ts +2 -4
  255. package/dist/runtime/server/api/media-usage.post.js +13 -9
  256. package/dist/runtime/server/api/media.delete.js +4 -2
  257. package/dist/runtime/server/api/media.get.js +22 -7
  258. package/dist/runtime/server/api/media.post.js +4 -2
  259. package/dist/runtime/server/api/media.put.js +33 -16
  260. package/dist/runtime/server/api/preset.delete.d.ts +4 -0
  261. package/dist/runtime/server/api/preset.delete.js +9 -0
  262. package/dist/runtime/server/api/preset.put.d.ts +3 -0
  263. package/dist/runtime/server/api/preset.put.js +23 -0
  264. package/dist/runtime/server/api/presets-field.get.d.ts +3 -0
  265. package/dist/runtime/server/api/presets-field.get.js +13 -0
  266. package/dist/runtime/server/api/presets-field.post.d.ts +3 -0
  267. package/dist/runtime/server/api/presets-field.post.js +36 -0
  268. package/dist/runtime/server/api/presets.get.d.ts +3 -0
  269. package/dist/runtime/server/api/presets.get.js +7 -0
  270. package/dist/runtime/server/api/preview-link.delete.d.ts +4 -0
  271. package/dist/runtime/server/api/preview-link.delete.js +15 -0
  272. package/dist/runtime/server/api/preview-links.get.d.ts +3 -0
  273. package/dist/runtime/server/api/preview-links.get.js +10 -0
  274. package/dist/runtime/server/api/preview-links.post.d.ts +3 -0
  275. package/dist/runtime/server/api/preview-links.post.js +17 -0
  276. package/dist/runtime/server/api/preview.get.d.ts +3 -0
  277. package/dist/runtime/server/api/preview.get.js +7 -0
  278. package/dist/runtime/server/api/redirect.delete.d.ts +4 -0
  279. package/dist/runtime/server/api/redirect.delete.js +10 -0
  280. package/dist/runtime/server/api/redirect.put.d.ts +3 -0
  281. package/dist/runtime/server/api/redirect.put.js +8 -0
  282. package/dist/runtime/server/api/redirects-import.post.d.ts +3 -0
  283. package/dist/runtime/server/api/redirects-import.post.js +13 -0
  284. package/dist/runtime/server/api/redirects.get.d.ts +3 -0
  285. package/dist/runtime/server/api/redirects.get.js +7 -0
  286. package/dist/runtime/server/api/redirects.post.d.ts +3 -0
  287. package/dist/runtime/server/api/redirects.post.js +7 -0
  288. package/dist/runtime/server/api/search.get.js +8 -3
  289. package/dist/runtime/server/api/settings.delete.js +2 -2
  290. package/dist/runtime/server/api/settings.get.js +4 -2
  291. package/dist/runtime/server/api/settings.put.js +2 -2
  292. package/dist/runtime/server/api/site.get.d.ts +3 -0
  293. package/dist/runtime/server/api/site.get.js +7 -0
  294. package/dist/runtime/server/api/site.put.d.ts +3 -0
  295. package/dist/runtime/server/api/site.put.js +16 -0
  296. package/dist/runtime/server/api/tags.get.js +3 -2
  297. package/dist/runtime/server/api/user.delete.js +8 -2
  298. package/dist/runtime/server/api/user.put.js +14 -4
  299. package/dist/runtime/server/api/users.get.js +2 -2
  300. package/dist/runtime/server/api/users.post.js +8 -4
  301. package/dist/runtime/server/middleware/hidden-site.d.ts +2 -0
  302. package/dist/runtime/server/middleware/hidden-site.js +8 -0
  303. package/dist/runtime/server/middleware/preview-links.d.ts +2 -0
  304. package/dist/runtime/server/middleware/preview-links.js +6 -0
  305. package/dist/runtime/server/middleware/redirects.d.ts +2 -0
  306. package/dist/runtime/server/middleware/redirects.js +18 -0
  307. package/dist/runtime/server/plugins/session-validate.js +4 -1
  308. package/dist/runtime/server/plugins/webhooks.d.ts +3 -0
  309. package/dist/runtime/server/plugins/webhooks.js +27 -0
  310. package/dist/runtime/server/routes/graphql.js +5 -3
  311. package/dist/runtime/server/routes/robots.d.ts +2 -0
  312. package/dist/runtime/server/routes/robots.js +16 -0
  313. package/dist/runtime/server/routes/sitemap.d.ts +2 -0
  314. package/dist/runtime/server/routes/sitemap.js +67 -0
  315. package/dist/runtime/server/utils/cached-value.d.ts +5 -0
  316. package/dist/runtime/server/utils/cached-value.js +24 -0
  317. package/dist/runtime/server/utils/content-routes.d.ts +5 -0
  318. package/dist/runtime/server/utils/content-routes.js +29 -0
  319. package/dist/runtime/server/utils/field-rules.d.ts +19 -0
  320. package/dist/runtime/server/utils/field-rules.js +72 -0
  321. package/dist/runtime/server/utils/graphql.d.ts +3 -1
  322. package/dist/runtime/server/utils/graphql.js +145 -29
  323. package/dist/runtime/server/utils/hooks.d.ts +14 -0
  324. package/dist/runtime/server/utils/hooks.js +71 -0
  325. package/dist/runtime/server/utils/import.d.ts +7 -2
  326. package/dist/runtime/server/utils/import.js +108 -14
  327. package/dist/runtime/server/utils/link-usage.d.ts +4 -0
  328. package/dist/runtime/server/utils/link-usage.js +28 -0
  329. package/dist/runtime/server/utils/media-references.d.ts +6 -1
  330. package/dist/runtime/server/utils/media-references.js +49 -20
  331. package/dist/runtime/server/utils/media-usage.d.ts +2 -0
  332. package/dist/runtime/server/utils/media-usage.js +5 -3
  333. package/dist/runtime/server/utils/page-rows.d.ts +2 -0
  334. package/dist/runtime/server/utils/page-rows.js +42 -29
  335. package/dist/runtime/server/utils/permissions.d.ts +14 -0
  336. package/dist/runtime/server/utils/permissions.js +43 -0
  337. package/dist/runtime/server/utils/presets.d.ts +18 -0
  338. package/dist/runtime/server/utils/presets.js +68 -0
  339. package/dist/runtime/server/utils/preview-links.d.ts +207 -0
  340. package/dist/runtime/server/utils/preview-links.js +161 -0
  341. package/dist/runtime/server/utils/redirects.d.ts +31 -0
  342. package/dist/runtime/server/utils/redirects.js +240 -0
  343. package/dist/runtime/server/utils/registry.js +4 -1
  344. package/dist/runtime/server/utils/relations.d.ts +8 -0
  345. package/dist/runtime/server/utils/relations.js +25 -6
  346. package/dist/runtime/server/utils/require-admin.d.ts +0 -1
  347. package/dist/runtime/server/utils/require-admin.js +4 -8
  348. package/dist/runtime/server/utils/search.d.ts +1 -0
  349. package/dist/runtime/server/utils/search.js +44 -19
  350. package/dist/runtime/server/utils/single-row.d.ts +3 -0
  351. package/dist/runtime/server/utils/single-row.js +4 -0
  352. package/dist/runtime/server/utils/site.d.ts +23 -0
  353. package/dist/runtime/server/utils/site.js +79 -0
  354. package/dist/runtime/server/utils/sitemap.d.ts +12 -0
  355. package/dist/runtime/server/utils/sitemap.js +109 -0
  356. package/dist/runtime/server/utils/user-management.d.ts +4 -0
  357. package/dist/runtime/server/utils/user-management.js +20 -0
  358. package/dist/runtime/server/utils/users.d.ts +1 -1
  359. package/dist/runtime/server/utils/users.js +1 -1
  360. package/dist/runtime/server/utils/visibility.d.ts +1 -0
  361. package/dist/runtime/server/utils/visibility.js +6 -1
  362. package/dist/runtime/server/utils/webhooks.d.ts +24 -0
  363. package/dist/runtime/server/utils/webhooks.js +90 -0
  364. package/dist/runtime/shared/block-paths.d.ts +66 -0
  365. package/dist/runtime/shared/block-paths.js +310 -0
  366. package/dist/runtime/shared/block-picker.d.ts +18 -0
  367. package/dist/runtime/shared/block-picker.js +31 -0
  368. package/dist/runtime/shared/block-signature.d.ts +4 -0
  369. package/dist/runtime/shared/block-signature.js +46 -0
  370. package/dist/runtime/shared/clipboard.d.ts +31 -0
  371. package/dist/runtime/shared/clipboard.js +206 -0
  372. package/dist/runtime/shared/conditions.d.ts +36 -0
  373. package/dist/runtime/shared/conditions.js +100 -0
  374. package/dist/runtime/shared/content-routes.d.ts +42 -0
  375. package/dist/runtime/shared/content-routes.js +237 -0
  376. package/dist/runtime/shared/duplicate.js +2 -1
  377. package/dist/runtime/shared/editor-layout.d.ts +18 -0
  378. package/dist/runtime/shared/editor-layout.js +9 -0
  379. package/dist/runtime/shared/field-options.d.ts +21 -0
  380. package/dist/runtime/shared/field-options.js +90 -0
  381. package/dist/runtime/shared/graphql-sdl.d.ts +1 -0
  382. package/dist/runtime/shared/graphql-sdl.js +50 -26
  383. package/dist/runtime/shared/history.d.ts +27 -0
  384. package/dist/runtime/shared/history.js +123 -0
  385. package/dist/runtime/shared/hooks.d.ts +45 -0
  386. package/dist/runtime/shared/hooks.js +28 -0
  387. package/dist/runtime/shared/index.d.ts +90 -21
  388. package/dist/runtime/shared/index.js +121 -37
  389. package/dist/runtime/shared/inline-text.d.ts +38 -0
  390. package/dist/runtime/shared/inline-text.js +85 -0
  391. package/dist/runtime/shared/layout.d.ts +2 -1
  392. package/dist/runtime/shared/layout.js +3 -0
  393. package/dist/runtime/shared/links.d.ts +48 -0
  394. package/dist/runtime/shared/links.js +155 -0
  395. package/dist/runtime/shared/list-filters.d.ts +2 -0
  396. package/dist/runtime/shared/list-filters.js +2 -0
  397. package/dist/runtime/shared/media-focal.d.ts +30 -0
  398. package/dist/runtime/shared/media-focal.js +52 -0
  399. package/dist/runtime/shared/migrations-dir.d.ts +14 -0
  400. package/dist/runtime/shared/migrations-dir.js +48 -2
  401. package/dist/runtime/shared/presets.d.ts +67 -0
  402. package/dist/runtime/shared/presets.js +127 -0
  403. package/dist/runtime/shared/preview-links.d.ts +64 -0
  404. package/dist/runtime/shared/preview-links.js +54 -0
  405. package/dist/runtime/shared/preview.d.ts +124 -21
  406. package/dist/runtime/shared/preview.js +419 -81
  407. package/dist/runtime/shared/redirects.d.ts +75 -0
  408. package/dist/runtime/shared/redirects.js +230 -0
  409. package/dist/runtime/shared/roles.d.ts +57 -0
  410. package/dist/runtime/shared/roles.js +293 -0
  411. package/dist/runtime/shared/save-state.d.ts +8 -0
  412. package/dist/runtime/shared/save-state.js +15 -0
  413. package/dist/runtime/shared/search.d.ts +16 -1
  414. package/dist/runtime/shared/search.js +41 -7
  415. package/dist/runtime/shared/seo.d.ts +167 -0
  416. package/dist/runtime/shared/seo.js +335 -0
  417. package/dist/runtime/shared/transfer.js +2 -1
  418. package/dist/runtime/shared/translations.d.ts +29 -0
  419. package/dist/runtime/shared/translations.js +123 -0
  420. package/dist/runtime/shared/users.d.ts +1 -1
  421. package/dist/runtime/shared/validation.d.ts +23 -1
  422. package/dist/runtime/shared/validation.js +214 -64
  423. package/dist/runtime/webhooks.d.ts +33 -0
  424. package/dist/runtime/webhooks.js +57 -0
  425. package/dist/types.d.mts +5 -1
  426. package/package.json +6 -2
  427. package/dist/runtime/app/components/cms/BlockOutline.vue +0 -88
  428. package/dist/runtime/app/components/cms/BlockPalette.vue +0 -31
  429. package/dist/runtime/app/components/cms/SettingsModal.d.vue.ts +0 -12
  430. package/dist/runtime/app/components/cms/SettingsModal.vue +0 -126
  431. package/dist/runtime/app/components/cms/SettingsModal.vue.d.ts +0 -12
  432. package/dist/runtime/app/composables/cms-field-focus.d.ts +0 -4
  433. package/dist/runtime/app/composables/cms-field-focus.js +0 -20
@@ -0,0 +1,206 @@
1
+ import {
2
+ BLOCK_HIDDEN_KEY,
3
+ allowsExternalLinks,
4
+ declaredLinkTargets,
5
+ declaresHiddenField,
6
+ isTranslatableField,
7
+ linkUrlError,
8
+ selectOptionValues
9
+ } from "./index.js";
10
+ import { CMS_CLIPBOARD_MAX_LENGTH } from "./preview.js";
11
+ import { objectKeySchema } from "./validation.js";
12
+ export const CMS_CLIPBOARD_KIND = "blocks";
13
+ export const CMS_CLIPBOARD_VERSION = 1;
14
+ export const CMS_CLIPBOARD_MAX_ITEMS = 200;
15
+ function isRecord(value) {
16
+ return !!value && typeof value === "object" && !Array.isArray(value);
17
+ }
18
+ function isBlockItem(value) {
19
+ return isRecord(value) && typeof value.type === "string" && value.type !== "";
20
+ }
21
+ export function clipboardText(items) {
22
+ const payload = {
23
+ nuxtCms: CMS_CLIPBOARD_KIND,
24
+ version: CMS_CLIPBOARD_VERSION,
25
+ items: items.map((item) => ({ ...item }))
26
+ };
27
+ return JSON.stringify(payload);
28
+ }
29
+ export function parseClipboardText(text) {
30
+ if (typeof text !== "string" || text.length > CMS_CLIPBOARD_MAX_LENGTH) return null;
31
+ if (!text.trimStart().startsWith("{")) return null;
32
+ let data;
33
+ try {
34
+ data = JSON.parse(text);
35
+ } catch {
36
+ return null;
37
+ }
38
+ if (!isRecord(data) || data.nuxtCms !== CMS_CLIPBOARD_KIND) return null;
39
+ if (data.version !== CMS_CLIPBOARD_VERSION || !Array.isArray(data.items)) return null;
40
+ const items = data.items.filter(isBlockItem).slice(0, CMS_CLIPBOARD_MAX_ITEMS);
41
+ return items.length ? items : null;
42
+ }
43
+ function isMediaKey(value) {
44
+ return objectKeySchema.safeParse(value).success;
45
+ }
46
+ function localizedShape(raw, i18n, accepts) {
47
+ if (typeof raw === "string") return raw && accepts(raw) ? { [i18n.defaultLocale]: raw } : null;
48
+ if (!isRecord(raw)) return null;
49
+ const entries = Object.entries(raw).filter(
50
+ (pair) => i18n.locales.includes(pair[0]) && accepts(pair[1])
51
+ );
52
+ return entries.length ? Object.fromEntries(entries) : null;
53
+ }
54
+ function isString(value) {
55
+ return typeof value === "string";
56
+ }
57
+ function plainShape(field, raw, i18n) {
58
+ if (field.type === "json" || field.type === "link" || !isRecord(raw)) return raw;
59
+ const value = raw[i18n.defaultLocale];
60
+ if (typeof value === "string") return value;
61
+ return Object.values(raw).find((entry) => typeof entry === "string") ?? null;
62
+ }
63
+ function trimmedText(value) {
64
+ return typeof value === "string" ? value.trim() : "";
65
+ }
66
+ function linkLabelShape(field, raw, i18n) {
67
+ if (!field.withLabel || raw == null) return void 0;
68
+ if (field.translatable && i18n.locales.length) {
69
+ const label = localizedShape(raw, i18n, isString);
70
+ if (!label) return void 0;
71
+ const kept = Object.entries(label).map(([locale, text2]) => [locale, text2.trim()]).filter(([, text2]) => !!text2);
72
+ return kept.length ? Object.fromEntries(kept) : void 0;
73
+ }
74
+ const text = trimmedText(plainShape({ ...field, type: "text" }, raw, i18n));
75
+ return text || void 0;
76
+ }
77
+ function linkShape(field, raw, i18n) {
78
+ if (!isRecord(raw)) return null;
79
+ const url = trimmedText(raw.url);
80
+ const entry = trimmedText(raw.entry);
81
+ const id = trimmedText(raw.id);
82
+ const label = linkLabelShape(field, raw.label, i18n);
83
+ const extra = {
84
+ ...label !== void 0 ? { label } : {},
85
+ ...raw.newTab === true ? { newTab: true } : {}
86
+ };
87
+ if (url && !entry && !id) {
88
+ if (!allowsExternalLinks(field) || linkUrlError(url)) return null;
89
+ return { url, ...extra };
90
+ }
91
+ if (url || !entry || !id) return null;
92
+ const targets = declaredLinkTargets(field);
93
+ if (targets && !targets.includes(entry)) return null;
94
+ return { entry, id, ...extra };
95
+ }
96
+ function scalarShape(field, raw) {
97
+ if (raw === void 0 || raw === null) return null;
98
+ switch (field.type) {
99
+ case "json":
100
+ return raw;
101
+ case "number":
102
+ return typeof raw === "number" && Number.isFinite(raw) ? raw : null;
103
+ case "boolean":
104
+ return typeof raw === "boolean" ? raw : null;
105
+ case "media":
106
+ return isMediaKey(raw) ? raw : null;
107
+ case "select": {
108
+ const options = selectOptionValues(field);
109
+ if (field.multiple) {
110
+ if (!Array.isArray(raw)) return null;
111
+ const values = [...new Set(raw.filter((value) => options.includes(value)))];
112
+ return values.length ? values : null;
113
+ }
114
+ return typeof raw === "string" && options.includes(raw) ? raw : null;
115
+ }
116
+ case "tags": {
117
+ if (!Array.isArray(raw)) return null;
118
+ const values = raw.filter(isString);
119
+ return values.length ? values : null;
120
+ }
121
+ default:
122
+ return typeof raw === "string" ? raw : null;
123
+ }
124
+ }
125
+ export function pastedFieldValue(field, raw, i18n) {
126
+ if (field.type === "blocks") {
127
+ if (!Array.isArray(raw)) return null;
128
+ const { list } = pasteBlocks([], 0, raw.filter(isBlockItem), field, i18n);
129
+ return list.length ? list : null;
130
+ }
131
+ if (field.type === "link") return linkShape(field, raw, i18n);
132
+ if (isTranslatableField(field) && i18n.locales.length > 0)
133
+ return localizedShape(raw, i18n, field.type === "media" ? isMediaKey : isString);
134
+ return scalarShape(field, plainShape(field, raw, i18n));
135
+ }
136
+ export function pastedBlock(type, block, item, i18n) {
137
+ const value = { type };
138
+ for (const [key, field] of Object.entries(block.fields))
139
+ value[key] = pastedFieldValue(field, item[key], i18n);
140
+ if (!declaresHiddenField(block) && item[BLOCK_HIDDEN_KEY] === true)
141
+ value[BLOCK_HIDDEN_KEY] = true;
142
+ return value;
143
+ }
144
+ export function pasteBlocks(list, at, items, field, i18n) {
145
+ const blocks = field.blocks ?? {};
146
+ const unknown = [];
147
+ const allowed = [];
148
+ for (const item of items) {
149
+ const type = String(item.type);
150
+ if (Object.hasOwn(blocks, type)) allowed.push(item);
151
+ else unknown.push(type);
152
+ }
153
+ const room = field.max === void 0 ? allowed.length : Math.max(field.max - list.length, 0);
154
+ const kept = allowed.slice(0, room);
155
+ const index = Math.min(Math.max(at, 0), list.length);
156
+ const next = [...list];
157
+ next.splice(
158
+ index,
159
+ 0,
160
+ ...kept.map((item) => pastedBlock(String(item.type), blocks[String(item.type)], item, i18n))
161
+ );
162
+ return {
163
+ list: next,
164
+ at: index,
165
+ pasted: kept.length,
166
+ unknown,
167
+ overflow: allowed.length - kept.length
168
+ };
169
+ }
170
+ export function pasteableCount(items, field) {
171
+ const blocks = field.blocks ?? {};
172
+ return (items ?? []).filter((item) => Object.hasOwn(blocks, String(item.type))).length;
173
+ }
174
+ function blockCount(count) {
175
+ return `${count} ${count === 1 ? "block" : "blocks"}`;
176
+ }
177
+ export function skippedText(result, field) {
178
+ const parts = [];
179
+ if (result.unknown.length) {
180
+ const types = [...new Set(result.unknown)].join(", ");
181
+ parts.push(
182
+ `${blockCount(result.unknown.length)} skipped, not available in this field: ${types}.`
183
+ );
184
+ }
185
+ if (result.overflow) {
186
+ const max = field.max ?? 0;
187
+ parts.push(
188
+ `${blockCount(result.overflow)} skipped, this field holds at most ${blockCount(max)}.`
189
+ );
190
+ }
191
+ return parts.length ? parts.join(" ") : void 0;
192
+ }
193
+ export function copyNotice(count, cut = false) {
194
+ const what = count === 1 ? "Block" : blockCount(count);
195
+ return { title: `${what} ${cut ? "cut" : "copied"}` };
196
+ }
197
+ export function pasteNotice(result, field) {
198
+ if (!result) return { title: "Nothing to paste", description: "Copy or cut a block first." };
199
+ const description = skippedText(result, field);
200
+ if (!result.pasted) return { title: "Nothing pasted", description, color: "error" };
201
+ return {
202
+ title: `${result.pasted === 1 ? "Block" : blockCount(result.pasted)} pasted`,
203
+ description,
204
+ color: description ? void 0 : "success"
205
+ };
206
+ }
@@ -0,0 +1,36 @@
1
+ import type { FieldConfig, FieldType } from './index.js';
2
+ export type ConditionValue = string | number | boolean;
3
+ export interface FieldCondition {
4
+ field: string;
5
+ eq?: ConditionValue;
6
+ neq?: ConditionValue;
7
+ in?: readonly ConditionValue[];
8
+ notIn?: readonly ConditionValue[];
9
+ gt?: number | string;
10
+ gte?: number | string;
11
+ lt?: number | string;
12
+ lte?: number | string;
13
+ empty?: boolean;
14
+ has?: string;
15
+ }
16
+ export interface AllCondition {
17
+ all: readonly ShowIfCondition[];
18
+ }
19
+ export interface AnyCondition {
20
+ any: readonly ShowIfCondition[];
21
+ }
22
+ export interface NotCondition {
23
+ not: ShowIfCondition;
24
+ }
25
+ export type ShowIfCondition = FieldCondition | AllCondition | AnyCondition | NotCondition;
26
+ export type CmsShowIf = ShowIfCondition | readonly ShowIfCondition[];
27
+ export declare const CONDITION_OPERATORS: readonly ["eq", "neq", "in", "notIn", "gt", "gte", "lt", "lte", "empty", "has"];
28
+ export type ConditionOperator = (typeof CONDITION_OPERATORS)[number];
29
+ export declare const CONDITION_GROUPS: readonly ["all", "any", "not"];
30
+ export type ConditionScope = Record<string, Pick<FieldConfig, 'type'>> | null | undefined;
31
+ type Values = Record<string, unknown> | null | undefined;
32
+ export declare function fieldConditions(field: FieldConfig): ShowIfCondition[];
33
+ export declare function isEmptyConditionValue(value: unknown, type?: FieldType): boolean;
34
+ export declare function matchesShowIf(condition: ShowIfCondition, values: Values, scope?: ConditionScope): boolean;
35
+ export declare function isFieldVisible(field: FieldConfig, values: Values, scope?: ConditionScope): boolean;
36
+ export {};
@@ -0,0 +1,100 @@
1
+ export const CONDITION_OPERATORS = [
2
+ "eq",
3
+ "neq",
4
+ "in",
5
+ "notIn",
6
+ "gt",
7
+ "gte",
8
+ "lt",
9
+ "lte",
10
+ "empty",
11
+ "has"
12
+ ];
13
+ export const CONDITION_GROUPS = ["all", "any", "not"];
14
+ function isConditionList(value) {
15
+ return Array.isArray(value);
16
+ }
17
+ export function fieldConditions(field) {
18
+ const showIf = field.showIf;
19
+ if (!showIf) return [];
20
+ return isConditionList(showIf) ? [...showIf] : [showIf];
21
+ }
22
+ function isEmptyLinkTarget(link) {
23
+ return isEmptyConditionValue(link.url) && (isEmptyConditionValue(link.entry) || isEmptyConditionValue(link.id));
24
+ }
25
+ export function isEmptyConditionValue(value, type) {
26
+ if (value == null) return true;
27
+ if (typeof value === "string") return !value.trim();
28
+ if (Array.isArray(value)) return !value.length;
29
+ if (typeof value === "object") {
30
+ if (type === "json") return !Object.keys(value).length;
31
+ if (type === "link") return isEmptyLinkTarget(value);
32
+ return Object.values(value).every((entry) => isEmptyConditionValue(entry));
33
+ }
34
+ return false;
35
+ }
36
+ function timeOf(value) {
37
+ const time = new Date(value).getTime();
38
+ return Number.isNaN(time) ? null : time;
39
+ }
40
+ function compareValues(value, expected, type) {
41
+ if (typeof value === "number" && typeof expected === "number") return value - expected;
42
+ if (typeof value !== "string" || typeof expected !== "string" || !value) return null;
43
+ if (type === "datetime") {
44
+ const a = timeOf(value);
45
+ const b = timeOf(expected);
46
+ return a === null || b === null ? null : a - b;
47
+ }
48
+ return value < expected ? -1 : value > expected ? 1 : 0;
49
+ }
50
+ function sameValue(value, expected, type) {
51
+ if (type === "datetime") return compareValues(value, expected, type) === 0;
52
+ return value === expected;
53
+ }
54
+ function sameItem(item, expected, type) {
55
+ if (type === "tags" && typeof item === "string" && typeof expected === "string")
56
+ return item.trim().toLowerCase() === expected.trim().toLowerCase();
57
+ return item === expected;
58
+ }
59
+ function ordered(test) {
60
+ return (value, expected, type) => {
61
+ const diff = compareValues(value, expected, type);
62
+ return diff !== null && test(diff);
63
+ };
64
+ }
65
+ const OPERATORS = {
66
+ eq: sameValue,
67
+ neq: (value, expected, type) => !sameValue(value, expected, type),
68
+ in: (value, expected, type) => Array.isArray(expected) && expected.some((option) => sameValue(value, option, type)),
69
+ notIn: (value, expected, type) => Array.isArray(expected) && !expected.some((option) => sameValue(value, option, type)),
70
+ gt: ordered((diff) => diff > 0),
71
+ gte: ordered((diff) => diff >= 0),
72
+ lt: ordered((diff) => diff < 0),
73
+ lte: ordered((diff) => diff <= 0),
74
+ empty: (value, expected, type) => isEmptyConditionValue(value, type) === expected,
75
+ has: (value, expected, type) => Array.isArray(value) && value.some((item) => sameItem(item, expected, type))
76
+ };
77
+ function matchesFieldCondition(condition, values, scope) {
78
+ const value = values?.[condition.field];
79
+ const type = scope?.[condition.field]?.type;
80
+ let matched = false;
81
+ for (const operator of CONDITION_OPERATORS) {
82
+ const expected = condition[operator];
83
+ if (expected === void 0) continue;
84
+ if (!OPERATORS[operator](value, expected, type)) return false;
85
+ matched = true;
86
+ }
87
+ return matched;
88
+ }
89
+ export function matchesShowIf(condition, values, scope) {
90
+ if (!condition || typeof condition !== "object") return false;
91
+ if ("all" in condition)
92
+ return isConditionList(condition.all) && condition.all.every((c) => matchesShowIf(c, values, scope));
93
+ if ("any" in condition)
94
+ return isConditionList(condition.any) && condition.any.some((c) => matchesShowIf(c, values, scope));
95
+ if ("not" in condition) return !matchesShowIf(condition.not, values, scope);
96
+ return matchesFieldCondition(condition, values, scope);
97
+ }
98
+ export function isFieldVisible(field, values, scope) {
99
+ return fieldConditions(field).every((condition) => matchesShowIf(condition, values, scope));
100
+ }
@@ -0,0 +1,42 @@
1
+ import type { CmsConfig, CmsEntry, CmsI18n } from './index.js';
2
+ export declare const CONTENT_ROUTE_FIELDS: readonly string[];
3
+ export declare const CONTENT_ROUTE_PARAMS: readonly ["slug", "id", "year", "month", "day"];
4
+ export type CmsContentRouteParam = (typeof CONTENT_ROUTE_PARAMS)[number];
5
+ export type CmsContentRoute = string | Readonly<Record<string, string>>;
6
+ export type CmsContentRouteParams = Partial<Record<CmsContentRouteParam, string>>;
7
+ export type CmsContentRouteItem = Readonly<Record<string, unknown>>;
8
+ export interface CmsLocalePath {
9
+ locale: string;
10
+ path: string;
11
+ }
12
+ export interface CmsContentPathMatch {
13
+ entry: string;
14
+ pattern: string;
15
+ params: CmsContentRouteParams;
16
+ }
17
+ type RouteSegment = {
18
+ param: CmsContentRouteParam;
19
+ } | {
20
+ text: string;
21
+ };
22
+ type RoutedEntry = Pick<CmsEntry, 'kind' | 'route'>;
23
+ export declare function contentRouteSegments(pattern: string): RouteSegment[];
24
+ export declare function contentRouteErrors(pattern: unknown): string[];
25
+ export declare function contentRouteShape(pattern: string): string;
26
+ export declare function compareContentRoutes(a: string, b: string): number;
27
+ export declare function contentRouteLocales(i18n: Pick<CmsI18n, 'locales' | 'defaultLocale'>): string[];
28
+ export declare function contentRoutePattern(route: CmsContentRoute | null | undefined, locale: string): string | null;
29
+ export declare function contentRoutePatterns(route: CmsContentRoute | null | undefined): string[];
30
+ export declare function isRoutedContent(entry: RoutedEntry | null | undefined): boolean;
31
+ export declare function contentRouteValues(item: CmsContentRouteItem): CmsContentRouteParams;
32
+ export declare function buildContentPath(pattern: string, item: CmsContentRouteItem): string | null;
33
+ export declare function contentItemPath(entry: RoutedEntry, item: CmsContentRouteItem, locale: string): string | null;
34
+ export declare function contentItemPaths(entry: RoutedEntry, item: CmsContentRouteItem, locales: readonly string[]): CmsLocalePath[];
35
+ export declare function normalizeContentPath(path: string): string;
36
+ export declare function matchContentPattern(pattern: string, path: string): CmsContentRouteParams | null;
37
+ export declare function contentPathParamsMatch(params: CmsContentRouteParams, item: CmsContentRouteItem): boolean;
38
+ export declare function matchContentPath(config: CmsConfig, path: string, locale: string): CmsContentPathMatch[];
39
+ export declare function routedContentNames(config: CmsConfig): string[];
40
+ export declare function contentRouteConfigErrors(at: string, route: unknown, i18n: Pick<CmsI18n, 'locales'>): string[];
41
+ export declare function contentRouteClashErrors(config: CmsConfig): string[];
42
+ export {};
@@ -0,0 +1,237 @@
1
+ export const CONTENT_ROUTE_FIELDS = ["path", "paths"];
2
+ export const CONTENT_ROUTE_PARAMS = ["slug", "id", "year", "month", "day"];
3
+ const PARAM_SEGMENT = /^\[([^\]]*)\]$/;
4
+ const FORBIDDEN_CHARACTERS = /[?#\s\\]/;
5
+ const RESERVED_PREFIX = "cms";
6
+ const PARAM_VALUES = {
7
+ slug: /^.+$/,
8
+ id: /^.+$/,
9
+ year: /^\d{4}$/,
10
+ month: /^\d{2}$/,
11
+ day: /^\d{2}$/
12
+ };
13
+ const DATE_PARAMS = ["year", "month", "day"];
14
+ function isRouteParam(name) {
15
+ return CONTENT_ROUTE_PARAMS.includes(name);
16
+ }
17
+ export function contentRouteSegments(pattern) {
18
+ return pattern.split("/").filter(Boolean).map((segment) => {
19
+ const name = PARAM_SEGMENT.exec(segment)?.[1];
20
+ return name && isRouteParam(name) ? { param: name } : { text: segment };
21
+ });
22
+ }
23
+ export function contentRouteErrors(pattern) {
24
+ if (typeof pattern !== "string" || !pattern) return ["must be a non-empty string"];
25
+ if (!pattern.startsWith("/")) return [`'${pattern}' must start with /`];
26
+ if (FORBIDDEN_CHARACTERS.test(pattern))
27
+ return [`'${pattern}' cannot hold spaces, backslashes, ? or #`];
28
+ const segments = pattern.slice(1).split("/");
29
+ if (segments.some((segment) => !segment))
30
+ return [`'${pattern}' has an empty segment or a trailing slash`];
31
+ const errors = [];
32
+ if (segments[0] === RESERVED_PREFIX)
33
+ errors.push(`'${pattern}' is under /${RESERVED_PREFIX}, which belongs to the admin`);
34
+ const seen = /* @__PURE__ */ new Set();
35
+ for (const segment of segments) {
36
+ const name = PARAM_SEGMENT.exec(segment)?.[1];
37
+ if (name === void 0) {
38
+ if (/[[\]]/.test(segment))
39
+ errors.push(`'${pattern}': a placeholder must fill a whole segment ('${segment}')`);
40
+ continue;
41
+ }
42
+ if (!isRouteParam(name)) {
43
+ errors.push(
44
+ `'${pattern}': unknown placeholder [${name}] (use ${CONTENT_ROUTE_PARAMS.map(
45
+ (param) => `[${param}]`
46
+ ).join(", ")})`
47
+ );
48
+ } else if (seen.has(name)) {
49
+ errors.push(`'${pattern}': placeholder [${name}] is used twice`);
50
+ }
51
+ seen.add(name);
52
+ }
53
+ if (!seen.has("slug") && !seen.has("id"))
54
+ errors.push(`'${pattern}' needs a [slug] or [id] placeholder`);
55
+ return errors;
56
+ }
57
+ export function contentRouteShape(pattern) {
58
+ const shape = contentRouteSegments(pattern).map((segment) => {
59
+ if ("text" in segment) return segment.text;
60
+ if (segment.param === "year") return "[yyyy]";
61
+ if (DATE_PARAMS.includes(segment.param)) return "[nn]";
62
+ return "[*]";
63
+ });
64
+ return `/${shape.join("/")}`;
65
+ }
66
+ function routeRank(pattern) {
67
+ const segments = contentRouteSegments(pattern);
68
+ const statics = segments.filter((segment) => "text" in segment).length;
69
+ const dates = segments.filter(
70
+ (segment) => "param" in segment && DATE_PARAMS.includes(segment.param)
71
+ ).length;
72
+ return [statics, dates, segments.length];
73
+ }
74
+ export function compareContentRoutes(a, b) {
75
+ const left = routeRank(a);
76
+ const right = routeRank(b);
77
+ return right[0] - left[0] || right[1] - left[1] || right[2] - left[2] || a.localeCompare(b);
78
+ }
79
+ export function contentRouteLocales(i18n) {
80
+ return i18n.locales.length ? [...i18n.locales] : [i18n.defaultLocale];
81
+ }
82
+ export function contentRoutePattern(route, locale) {
83
+ if (!route) return null;
84
+ if (typeof route === "string") return route;
85
+ return route[locale] ?? null;
86
+ }
87
+ export function contentRoutePatterns(route) {
88
+ if (!route) return [];
89
+ return typeof route === "string" ? [route] : [...new Set(Object.values(route))];
90
+ }
91
+ export function isRoutedContent(entry) {
92
+ return entry?.kind === "content" && !!entry.route;
93
+ }
94
+ function datePart(value, part) {
95
+ if (typeof value !== "string" || !value) return void 0;
96
+ const date = new Date(value);
97
+ if (Number.isNaN(date.getTime())) return void 0;
98
+ if (part === "year") return String(date.getUTCFullYear()).padStart(4, "0");
99
+ const number = part === "month" ? date.getUTCMonth() + 1 : date.getUTCDate();
100
+ return String(number).padStart(2, "0");
101
+ }
102
+ function textValue(value) {
103
+ if (typeof value === "number") return String(value);
104
+ return typeof value === "string" && value ? value : void 0;
105
+ }
106
+ export function contentRouteValues(item) {
107
+ const values = {};
108
+ const slug = textValue(item.slug);
109
+ const id = textValue(item.id);
110
+ if (slug) values.slug = slug;
111
+ if (id) values.id = id;
112
+ for (const part of ["year", "month", "day"]) {
113
+ const value = datePart(item.publishedAt, part);
114
+ if (value) values[part] = value;
115
+ }
116
+ return values;
117
+ }
118
+ export function buildContentPath(pattern, item) {
119
+ const values = contentRouteValues(item);
120
+ const parts = [];
121
+ for (const segment of contentRouteSegments(pattern)) {
122
+ if ("text" in segment) {
123
+ parts.push(segment.text);
124
+ continue;
125
+ }
126
+ const value = values[segment.param];
127
+ if (!value) return null;
128
+ parts.push(encodeURIComponent(value));
129
+ }
130
+ return `/${parts.join("/")}`;
131
+ }
132
+ export function contentItemPath(entry, item, locale) {
133
+ if (!isRoutedContent(entry)) return null;
134
+ const pattern = contentRoutePattern(entry.route, locale);
135
+ return pattern ? buildContentPath(pattern, item) : null;
136
+ }
137
+ export function contentItemPaths(entry, item, locales) {
138
+ const paths = [];
139
+ for (const locale of locales) {
140
+ const path = contentItemPath(entry, item, locale);
141
+ if (path) paths.push({ locale, path });
142
+ }
143
+ return paths;
144
+ }
145
+ export function normalizeContentPath(path) {
146
+ const bare = path.replace(/[?#].*$/, "");
147
+ const segments = bare.split("/").filter(Boolean);
148
+ return `/${segments.join("/")}`;
149
+ }
150
+ function decodeSegment(segment) {
151
+ try {
152
+ return decodeURIComponent(segment);
153
+ } catch {
154
+ return null;
155
+ }
156
+ }
157
+ export function matchContentPattern(pattern, path) {
158
+ const segments = contentRouteSegments(pattern);
159
+ const parts = normalizeContentPath(path).split("/").filter(Boolean);
160
+ if (parts.length !== segments.length) return null;
161
+ const params = {};
162
+ for (const [index, segment] of segments.entries()) {
163
+ const part = decodeSegment(parts[index]);
164
+ if (part === null) return null;
165
+ if ("text" in segment) {
166
+ if (part !== segment.text) return null;
167
+ continue;
168
+ }
169
+ if (!PARAM_VALUES[segment.param].test(part)) return null;
170
+ params[segment.param] = part;
171
+ }
172
+ return params;
173
+ }
174
+ export function contentPathParamsMatch(params, item) {
175
+ const values = contentRouteValues(item);
176
+ return Object.entries(params).every(
177
+ ([param, value]) => values[param] === value
178
+ );
179
+ }
180
+ export function matchContentPath(config, path, locale) {
181
+ const matches = [];
182
+ for (const [name, entry] of Object.entries(config)) {
183
+ if (!isRoutedContent(entry)) continue;
184
+ const pattern = contentRoutePattern(entry.route, locale);
185
+ if (!pattern) continue;
186
+ const params = matchContentPattern(pattern, path);
187
+ if (params) matches.push({ entry: name, pattern, params });
188
+ }
189
+ return matches.sort((a, b) => compareContentRoutes(a.pattern, b.pattern));
190
+ }
191
+ function mostSpecificRoute(entry) {
192
+ return contentRoutePatterns(entry.route).sort(compareContentRoutes)[0] ?? "";
193
+ }
194
+ export function routedContentNames(config) {
195
+ return Object.entries(config).filter(([, entry]) => isRoutedContent(entry)).sort(([, a], [, b]) => compareContentRoutes(mostSpecificRoute(a), mostSpecificRoute(b))).map(([name]) => name);
196
+ }
197
+ export function contentRouteConfigErrors(at, route, i18n) {
198
+ if (typeof route === "string") return contentRouteErrors(route).map((e) => `${at}: route ${e}`);
199
+ if (!route || typeof route !== "object" || Array.isArray(route))
200
+ return [`${at}: route must be a path pattern or a map of locale to path pattern`];
201
+ const { locales } = i18n;
202
+ if (!locales.length)
203
+ return [`${at}: a per-locale route needs cms.i18n locales, use a single pattern instead`];
204
+ const errors = [];
205
+ const map = route;
206
+ for (const [locale, pattern] of Object.entries(map)) {
207
+ if (!locales.includes(locale))
208
+ errors.push(`${at}: route names the unknown locale '${locale}'`);
209
+ errors.push(...contentRouteErrors(pattern).map((e) => `${at}: route.${locale} ${e}`));
210
+ }
211
+ const missing = locales.filter((locale) => !Object.hasOwn(map, locale));
212
+ if (missing.length)
213
+ errors.push(`${at}: route has no pattern for the locale(s) ${missing.join(", ")}`);
214
+ return errors;
215
+ }
216
+ export function contentRouteClashErrors(config) {
217
+ const errors = [];
218
+ const owners = /* @__PURE__ */ new Map();
219
+ for (const [name, entry] of Object.entries(config)) {
220
+ if (!isRoutedContent(entry)) continue;
221
+ const patterns = contentRoutePatterns(entry.route).filter(
222
+ (pattern) => !contentRouteErrors(pattern).length
223
+ );
224
+ for (const shape of new Set(patterns.map(contentRouteShape))) {
225
+ const pattern = patterns.find((candidate) => contentRouteShape(candidate) === shape);
226
+ const owner = owners.get(shape);
227
+ if (owner) {
228
+ errors.push(
229
+ `cms.config entry '${name}': route '${pattern}' matches the same paths as '${owner.pattern}' of entry '${owner.entry}'`
230
+ );
231
+ } else {
232
+ owners.set(shape, { entry: name, pattern });
233
+ }
234
+ }
235
+ }
236
+ return errors;
237
+ }
@@ -1,10 +1,11 @@
1
+ import { isUniqueValueField } from "./field-options.js";
1
2
  import { CONTENT_PUBLISHED_AT_FIELD, isCollectionKind, isTranslatableField } from "./index.js";
2
3
  export const DUPLICATE_TITLE_SUFFIX = " (copy)";
3
4
  const DUPLICATE_TOKEN_LENGTH = 4;
4
5
  const DUPLICATE_TOKEN_ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789";
5
6
  const COPIED_SLUG = new RegExp(`-copy-[a-z0-9]{${DUPLICATE_TOKEN_LENGTH}}$`);
6
7
  export function isUniqueField(field) {
7
- return field.type === "slug" || field.type === "relation" && field.cardinality === "one-to-one";
8
+ return field.type === "slug" || field.type === "relation" && field.cardinality === "one-to-one" || isUniqueValueField(field);
8
9
  }
9
10
  export function uniqueFieldKeys(entry) {
10
11
  return Object.keys(entry.fields).filter((key) => isUniqueField(entry.fields[key]));
@@ -0,0 +1,18 @@
1
+ export declare const CMS_EDITOR_PANES: {
2
+ readonly left: {
3
+ readonly min: 260;
4
+ readonly max: 440;
5
+ readonly initial: 288;
6
+ };
7
+ readonly right: {
8
+ readonly min: 300;
9
+ readonly max: 560;
10
+ readonly initial: 360;
11
+ };
12
+ };
13
+ export declare const CMS_PREVIEW_DEVICE_WIDTHS: {
14
+ readonly desktop: null;
15
+ readonly tablet: 768;
16
+ readonly mobile: 390;
17
+ };
18
+ export type CmsPreviewDevice = keyof typeof CMS_PREVIEW_DEVICE_WIDTHS;
@@ -0,0 +1,9 @@
1
+ export const CMS_EDITOR_PANES = {
2
+ left: { min: 260, max: 440, initial: 288 },
3
+ right: { min: 300, max: 560, initial: 360 }
4
+ };
5
+ export const CMS_PREVIEW_DEVICE_WIDTHS = {
6
+ desktop: null,
7
+ tablet: 768,
8
+ mobile: 390
9
+ };