@plone/volto 19.0.0-alpha.8 → 19.0.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 (540) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc +26 -15
  3. package/AGENTS.md +47 -0
  4. package/CHANGELOG.md +536 -9
  5. package/README.md +22 -19
  6. package/babel.js +1 -9
  7. package/cypress/docker/prefixed-rules.yml +26 -0
  8. package/cypress/docker/prefixed.yml +24 -0
  9. package/cypress/support/guillotina.js +1 -0
  10. package/cypress.config.js +1 -0
  11. package/global-test-setup.js +1 -2
  12. package/locales/af/LC_MESSAGES/volto.po +5516 -0
  13. package/locales/af.json +1 -1
  14. package/locales/ar/LC_MESSAGES/volto.po +5516 -0
  15. package/locales/ar.json +1 -1
  16. package/locales/bg/LC_MESSAGES/volto.po +5516 -0
  17. package/locales/bg.json +1 -1
  18. package/locales/bn/LC_MESSAGES/volto.po +5516 -0
  19. package/locales/bn.json +1 -1
  20. package/locales/ca/LC_MESSAGES/volto.po +547 -355
  21. package/locales/ca.json +1 -1
  22. package/locales/cs/LC_MESSAGES/volto.po +5516 -0
  23. package/locales/cs.json +1 -1
  24. package/locales/cy/LC_MESSAGES/volto.po +5516 -0
  25. package/locales/cy.json +1 -1
  26. package/locales/da/LC_MESSAGES/volto.po +5516 -0
  27. package/locales/da.json +1 -1
  28. package/locales/de/LC_MESSAGES/volto.po +218 -25
  29. package/locales/de.json +1 -1
  30. package/locales/el/LC_MESSAGES/volto.po +5516 -0
  31. package/locales/el.json +1 -1
  32. package/locales/en/LC_MESSAGES/volto.po +207 -11
  33. package/locales/en.json +1 -1
  34. package/locales/en_AU/LC_MESSAGES/volto.po +5516 -0
  35. package/locales/en_AU.json +1 -1
  36. package/locales/en_GB/LC_MESSAGES/volto.po +5516 -0
  37. package/locales/en_GB.json +1 -1
  38. package/locales/eo/LC_MESSAGES/volto.po +5516 -0
  39. package/locales/eo.json +1 -1
  40. package/locales/es/LC_MESSAGES/volto.po +332 -141
  41. package/locales/es.json +1 -1
  42. package/locales/et/LC_MESSAGES/volto.po +5516 -0
  43. package/locales/et.json +1 -1
  44. package/locales/eu/LC_MESSAGES/volto.po +409 -218
  45. package/locales/eu.json +1 -1
  46. package/locales/fa/LC_MESSAGES/volto.po +5516 -0
  47. package/locales/fa.json +1 -1
  48. package/locales/fi/LC_MESSAGES/volto.po +208 -16
  49. package/locales/fi.json +1 -1
  50. package/locales/fr/LC_MESSAGES/volto.po +365 -174
  51. package/locales/fr.json +1 -1
  52. package/locales/fu/LC_MESSAGES/volto.po +5516 -0
  53. package/locales/fu.json +1 -1
  54. package/locales/gl/LC_MESSAGES/volto.po +5516 -0
  55. package/locales/gl.json +1 -1
  56. package/locales/he/LC_MESSAGES/volto.po +5516 -0
  57. package/locales/he.json +1 -1
  58. package/locales/hi/LC_MESSAGES/volto.po +216 -19
  59. package/locales/hi.json +1 -1
  60. package/locales/hr/LC_MESSAGES/volto.po +5516 -0
  61. package/locales/hr.json +1 -1
  62. package/locales/hu/LC_MESSAGES/volto.po +5516 -0
  63. package/locales/hu.json +1 -1
  64. package/locales/hy/LC_MESSAGES/volto.po +5516 -0
  65. package/locales/hy.json +1 -1
  66. package/locales/id/LC_MESSAGES/volto.po +5516 -0
  67. package/locales/id.json +1 -1
  68. package/locales/it/LC_MESSAGES/volto.po +232 -35
  69. package/locales/it.json +1 -1
  70. package/locales/ja/LC_MESSAGES/volto.po +250 -57
  71. package/locales/ja.json +1 -1
  72. package/locales/ka/LC_MESSAGES/volto.po +5516 -0
  73. package/locales/ka.json +1 -1
  74. package/locales/kn/LC_MESSAGES/volto.po +5516 -0
  75. package/locales/kn.json +1 -1
  76. package/locales/ko/LC_MESSAGES/volto.po +5516 -0
  77. package/locales/ko.json +1 -1
  78. package/locales/lt/LC_MESSAGES/volto.po +5516 -0
  79. package/locales/lt.json +1 -1
  80. package/locales/lv/LC_MESSAGES/volto.po +5516 -0
  81. package/locales/lv.json +1 -1
  82. package/locales/mi/LC_MESSAGES/volto.po +5516 -0
  83. package/locales/mi.json +1 -1
  84. package/locales/mk/LC_MESSAGES/volto.po +5516 -0
  85. package/locales/mk.json +1 -1
  86. package/locales/my/LC_MESSAGES/volto.po +5516 -0
  87. package/locales/my.json +1 -1
  88. package/locales/nb_NO/LC_MESSAGES/volto.po +5516 -0
  89. package/locales/nb_NO.json +1 -1
  90. package/locales/nl/LC_MESSAGES/volto.po +260 -67
  91. package/locales/nl.json +1 -1
  92. package/locales/nn/LC_MESSAGES/volto.po +5516 -0
  93. package/locales/nn.json +1 -1
  94. package/locales/pl/LC_MESSAGES/volto.po +5516 -0
  95. package/locales/pl.json +1 -1
  96. package/locales/pt/LC_MESSAGES/volto.po +859 -667
  97. package/locales/pt.json +1 -1
  98. package/locales/pt_BR/LC_MESSAGES/volto.po +212 -21
  99. package/locales/pt_BR.json +1 -1
  100. package/locales/rm/LC_MESSAGES/volto.po +5516 -0
  101. package/locales/rm.json +1 -1
  102. package/locales/ro/LC_MESSAGES/volto.po +244 -53
  103. package/locales/ro.json +1 -1
  104. package/locales/ru/LC_MESSAGES/volto.po +207 -15
  105. package/locales/ru.json +1 -1
  106. package/locales/sk/LC_MESSAGES/volto.po +5516 -0
  107. package/locales/sk.json +1 -1
  108. package/locales/sl/LC_MESSAGES/volto.po +5516 -0
  109. package/locales/sl.json +1 -1
  110. package/locales/sm/LC_MESSAGES/volto.po +5516 -0
  111. package/locales/sm.json +1 -1
  112. package/locales/sq/LC_MESSAGES/volto.po +5516 -0
  113. package/locales/sq.json +1 -1
  114. package/locales/sr/LC_MESSAGES/volto.po +5516 -0
  115. package/locales/sr.json +1 -1
  116. package/locales/sr@cyrl/LC_MESSAGES/volto.po +5516 -0
  117. package/locales/sr@cyrl.json +1 -1
  118. package/locales/sr@latn/LC_MESSAGES/volto.po +5516 -0
  119. package/locales/sr@latn.json +1 -1
  120. package/locales/sv/LC_MESSAGES/volto.po +5516 -0
  121. package/locales/sv.json +1 -1
  122. package/locales/ta/LC_MESSAGES/volto.po +5516 -0
  123. package/locales/ta.json +1 -1
  124. package/locales/te/LC_MESSAGES/volto.po +5516 -0
  125. package/locales/te.json +1 -1
  126. package/locales/th/LC_MESSAGES/volto.po +5516 -0
  127. package/locales/th.json +1 -1
  128. package/locales/to/LC_MESSAGES/volto.po +5516 -0
  129. package/locales/to.json +1 -1
  130. package/locales/tr/LC_MESSAGES/volto.po +5516 -0
  131. package/locales/tr.json +1 -1
  132. package/locales/uk/LC_MESSAGES/volto.po +5516 -0
  133. package/locales/uk.json +1 -1
  134. package/locales/vi/LC_MESSAGES/volto.po +5516 -0
  135. package/locales/vi.json +1 -1
  136. package/locales/volto.pot +201 -10
  137. package/locales/zh_CN/LC_MESSAGES/volto.po +207 -15
  138. package/locales/zh_CN.json +1 -1
  139. package/locales/zh_Hant/LC_MESSAGES/volto.po +5516 -0
  140. package/locales/zh_Hant.json +1 -1
  141. package/locales/zh_Hant_HK/LC_MESSAGES/volto.po +5516 -0
  142. package/locales/zh_Hant_HK.json +1 -1
  143. package/package.json +71 -148
  144. package/razzle.config.js +32 -25
  145. package/src/actions/blockTypes/blockTypes.ts +24 -0
  146. package/src/actions/controlpanels/controlpanels.js +7 -12
  147. package/src/actions/controlpanels/controlpanels.test.js +2 -3
  148. package/src/components/manage/Actions/Actions.test.jsx +1 -5
  149. package/src/components/manage/Add/Add.jsx +15 -10
  150. package/src/components/manage/Add/Add.test.jsx +10 -3
  151. package/src/components/manage/Aliases/Aliases.test.jsx +5 -2
  152. package/src/components/manage/BlockChooser/BlockChooser.jsx +8 -10
  153. package/src/components/manage/Blocks/Block/BlocksForm.jsx +10 -7
  154. package/src/components/manage/Blocks/Block/BlocksForm.test.jsx +3 -14
  155. package/src/components/manage/Blocks/Block/Edit.jsx +19 -10
  156. package/src/components/manage/Blocks/Block/Order/Item.jsx +33 -14
  157. package/src/components/manage/Blocks/Block/Order/Item.test.jsx +90 -0
  158. package/src/components/manage/Blocks/Block/Order/Order.jsx +116 -67
  159. package/src/components/manage/Blocks/Block/Order/utilities.js +28 -11
  160. package/src/components/manage/Blocks/Block/Settings.test.jsx +1 -5
  161. package/src/components/manage/Blocks/Grid/View.jsx +14 -11
  162. package/src/components/manage/Blocks/Grid/context.js +3 -0
  163. package/src/components/manage/Blocks/HTML/Edit.test.jsx +1 -5
  164. package/src/components/manage/Blocks/Image/ImageSidebar.test.jsx +2 -5
  165. package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.test.jsx +2 -5
  166. package/src/components/manage/Blocks/Listing/Edit.jsx +1 -0
  167. package/src/components/manage/Blocks/Listing/ImageGallery.jsx +6 -4
  168. package/src/components/manage/Blocks/Listing/ListingBody.jsx +4 -0
  169. package/src/components/manage/Blocks/Maps/MapsSidebar.test.jsx +1 -5
  170. package/src/components/manage/Blocks/Search/components/DateRangeFacet.test.jsx +1 -6
  171. package/src/components/manage/Blocks/Search/components/SelectFacet.jsx +22 -1
  172. package/src/components/manage/Blocks/Search/components/SelectFacet.test.jsx +1 -6
  173. package/src/components/manage/Blocks/Search/components/SortOn.jsx +8 -2
  174. package/src/components/manage/Blocks/Search/components/ToggleFacet.jsx +14 -0
  175. package/src/components/manage/Blocks/Teaser/DefaultBody.jsx +10 -2
  176. package/src/components/manage/Blocks/Teaser/View.jsx +0 -1
  177. package/src/components/manage/Blocks/Teaser/utils.js +13 -0
  178. package/src/components/manage/Blocks/Teaser/utils.test.js +34 -0
  179. package/src/components/manage/Blocks/Title/Edit.jsx +5 -0
  180. package/src/components/manage/Blocks/Video/Body.jsx +69 -43
  181. package/src/components/manage/Blocks/Video/Body.test.jsx +122 -5
  182. package/src/components/manage/Blocks/Video/Edit.jsx +20 -2
  183. package/src/components/manage/Blocks/Video/Edit.test.jsx +6 -0
  184. package/src/components/manage/Blocks/Video/VideoSidebar.test.jsx +1 -5
  185. package/src/components/manage/Blocks/Video/View.jsx +1 -0
  186. package/src/components/manage/Blocks/Video/View.test.jsx +29 -15
  187. package/src/components/manage/Blocks/Video/schema.js +14 -1
  188. package/src/components/manage/Contents/Contents.jsx +854 -747
  189. package/src/components/manage/Contents/Contents.test.jsx +9 -10
  190. package/src/components/manage/Contents/ContentsBreadcrumbs.jsx +6 -5
  191. package/src/components/manage/Contents/ContentsIndexHeader.jsx +47 -81
  192. package/src/components/manage/Contents/ContentsIndexHeader.test.jsx +10 -3
  193. package/src/components/manage/Contents/ContentsItem.jsx +226 -278
  194. package/src/components/manage/Contents/ContentsItem.test.jsx +10 -6
  195. package/src/components/manage/Contents/ContentsPropertiesModal.test.jsx +1 -5
  196. package/src/components/manage/Contents/ContentsRenameModal.test.jsx +1 -5
  197. package/src/components/manage/Contents/ContentsTagsModal.test.jsx +1 -5
  198. package/src/components/manage/Contents/ContentsWorkflowModal.test.jsx +1 -5
  199. package/src/components/manage/Contents/DropZoneContent.jsx +339 -0
  200. package/src/components/manage/Contents/__mocks__/index.tsx +2 -18
  201. package/src/components/manage/Controlpanels/AddonsControlpanel.jsx +7 -0
  202. package/src/components/manage/Controlpanels/AddonsControlpanel.test.jsx +7 -4
  203. package/src/components/manage/Controlpanels/Aliases.test.jsx +8 -9
  204. package/src/components/manage/Controlpanels/BlockType.tsx +165 -0
  205. package/src/components/manage/Controlpanels/BlockTypes.tsx +145 -0
  206. package/src/components/manage/Controlpanels/ContentType.jsx +131 -222
  207. package/src/components/manage/Controlpanels/ContentType.test.jsx +13 -14
  208. package/src/components/manage/Controlpanels/ContentTypeLayout.test.jsx +12 -9
  209. package/src/components/manage/Controlpanels/ContentTypeSchema.jsx +1 -1
  210. package/src/components/manage/Controlpanels/ContentTypes.jsx +9 -2
  211. package/src/components/manage/Controlpanels/ContentTypes.test.jsx +7 -4
  212. package/src/components/manage/Controlpanels/Controlpanel.jsx +122 -218
  213. package/src/components/manage/Controlpanels/Controlpanel.test.jsx +8 -33
  214. package/src/components/manage/Controlpanels/Controlpanels.jsx +28 -5
  215. package/src/components/manage/Controlpanels/Controlpanels.test.jsx +23 -8
  216. package/src/components/manage/Controlpanels/DatabaseInformation.jsx +9 -0
  217. package/src/components/manage/Controlpanels/Groups/GroupsControlpanel.test.jsx +7 -4
  218. package/src/components/manage/Controlpanels/ModerateComments.jsx +8 -0
  219. package/src/components/manage/Controlpanels/ModerateComments.test.jsx +7 -4
  220. package/src/components/manage/Controlpanels/Relations/Relations.jsx +1 -1
  221. package/src/components/manage/Controlpanels/Rules/AddRule.test.jsx +8 -9
  222. package/src/components/manage/Controlpanels/Rules/ConfigureRule.test.jsx +9 -6
  223. package/src/components/manage/Controlpanels/Rules/EditRule.test.jsx +8 -9
  224. package/src/components/manage/Controlpanels/Rules/Rules.test.jsx +7 -4
  225. package/src/components/manage/Controlpanels/UndoControlpanel.test.jsx +8 -9
  226. package/src/components/manage/Controlpanels/Users/UserGroupMembershipControlPanel.test.jsx +10 -4
  227. package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +628 -631
  228. package/src/components/manage/Controlpanels/Users/UsersControlpanel.ssr.test.jsx +624 -0
  229. package/src/components/manage/Controlpanels/Users/UsersControlpanel.test.jsx +70 -10
  230. package/src/components/manage/Delete/Delete.test.jsx +13 -8
  231. package/src/components/manage/Diff/Diff.jsx +201 -298
  232. package/src/components/manage/Diff/Diff.test.jsx +8 -10
  233. package/src/components/manage/Diff/DiffField.test.jsx +1 -6
  234. package/src/components/manage/Display/Display.test.jsx +2 -11
  235. package/src/components/manage/Edit/Edit.test.jsx +12 -11
  236. package/src/components/manage/Form/BlockDataForm.test.jsx +1 -5
  237. package/src/components/manage/Form/Field.jsx +1 -69
  238. package/src/components/manage/Form/Form.jsx +17 -4
  239. package/src/components/manage/Form/Form.test.jsx +130 -5
  240. package/src/components/manage/Form/InlineForm.test.jsx +1 -5
  241. package/src/components/manage/Form/ModalForm.jsx +175 -97
  242. package/src/components/manage/Form/ModalForm.test.jsx +27 -5
  243. package/src/components/manage/Form/__mocks__/index.tsx +9 -27
  244. package/src/components/manage/History/History.test.jsx +15 -8
  245. package/src/components/manage/LinksToItem/LinksToItem.test.jsx +7 -4
  246. package/src/components/manage/Multilingual/CompareLanguages.jsx +6 -6
  247. package/src/components/manage/Multilingual/CreateTranslation.jsx +16 -13
  248. package/src/components/manage/Multilingual/ManageTranslations.jsx +5 -5
  249. package/src/components/manage/Multilingual/ManageTranslations.test.jsx +15 -12
  250. package/src/components/manage/Multilingual/TranslationObject.jsx +11 -8
  251. package/src/components/manage/Preferences/ChangePassword.test.jsx +8 -9
  252. package/src/components/manage/Preferences/PersonalPreferences.jsx +8 -5
  253. package/src/components/manage/Preferences/PersonalPreferences.test.jsx +10 -23
  254. package/src/components/manage/Rules/Rules.test.jsx +5 -2
  255. package/src/components/manage/Sharing/Sharing.jsx +21 -15
  256. package/src/components/manage/Sharing/Sharing.test.jsx +9 -6
  257. package/src/components/manage/Sidebar/ObjectBrowser.jsx +10 -0
  258. package/src/components/manage/Sidebar/ObjectBrowserBody.jsx +25 -5
  259. package/src/components/manage/Sidebar/ObjectBrowserBody.test.jsx +52 -0
  260. package/src/components/manage/Sidebar/Sidebar.jsx +2 -0
  261. package/src/components/manage/Sidebar/Sidebar.test.jsx +4 -1
  262. package/src/components/manage/Sidebar/SidebarPortal.test.tsx +42 -0
  263. package/src/components/manage/Sidebar/SidebarPortal.tsx +48 -0
  264. package/src/components/manage/TemplateChooser/TemplateChooser.test.jsx +1 -0
  265. package/src/components/manage/Toast/Toast.jsx +32 -0
  266. package/src/components/manage/Toast/Toast.test.jsx +9 -5
  267. package/src/components/manage/Toolbar/PersonalTools.test.jsx +15 -0
  268. package/src/components/manage/Toolbar/Toolbar.jsx +103 -11
  269. package/src/components/manage/Toolbar/Toolbar.test.jsx +15 -10
  270. package/src/components/manage/Toolbar/Types.crash.test.jsx +48 -0
  271. package/src/components/manage/Toolbar/Types.jsx +6 -4
  272. package/src/components/manage/UniversalLink/UniversalLink.test.jsx +16 -0
  273. package/src/components/manage/UniversalLink/UniversalLink.tsx +1 -0
  274. package/src/components/manage/Widgets/AlignWidget.stories.jsx +9 -0
  275. package/src/components/manage/Widgets/AlignWidget.test.tsx +95 -0
  276. package/src/components/manage/Widgets/{AlignWidget.jsx → AlignWidget.tsx} +23 -7
  277. package/src/components/manage/Widgets/ArrayWidget.jsx +111 -88
  278. package/src/components/manage/Widgets/ArrayWidget.test.jsx +1 -12
  279. package/src/components/manage/Widgets/BlockAlignment.stories.tsx +104 -0
  280. package/src/components/manage/Widgets/BlockAlignment.test.tsx +104 -0
  281. package/src/components/manage/Widgets/BlockAlignment.tsx +88 -0
  282. package/src/components/manage/Widgets/BlockWidth.stories.tsx +69 -0
  283. package/src/components/manage/Widgets/BlockWidth.test.tsx +62 -0
  284. package/src/components/manage/Widgets/BlockWidth.tsx +101 -0
  285. package/src/components/manage/Widgets/ButtonsWidget.stories.jsx +61 -0
  286. package/src/components/manage/Widgets/ButtonsWidget.test.tsx +138 -0
  287. package/src/components/manage/Widgets/ButtonsWidget.tsx +195 -0
  288. package/src/components/manage/Widgets/CheckboxGroupWidget.test.jsx +1 -6
  289. package/src/components/manage/Widgets/DatetimeWidget.jsx +98 -54
  290. package/src/components/manage/Widgets/DatetimeWidget.test.jsx +56 -6
  291. package/src/components/manage/Widgets/FileWidget.jsx +7 -0
  292. package/src/components/manage/Widgets/FormFieldWrapper.jsx +143 -163
  293. package/src/components/manage/Widgets/ImageWidget.jsx +18 -5
  294. package/src/components/manage/Widgets/ObjectBrowserWidget.jsx +6 -0
  295. package/src/components/manage/Widgets/ObjectListWidget.test.jsx +2 -11
  296. package/src/components/manage/Widgets/ObjectWidget.test.jsx +1 -5
  297. package/src/components/manage/Widgets/QueryWidget.jsx +137 -9
  298. package/src/components/manage/Widgets/QuerystringWidget.test.jsx +3 -1
  299. package/src/components/manage/Widgets/RadioGroupWidget.test.jsx +1 -6
  300. package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.test.jsx +1 -6
  301. package/src/components/manage/Widgets/RecurrenceWidget/WeekdayOfTheMonthIndexField.jsx +56 -50
  302. package/src/components/manage/Widgets/RegistryImageWidget.jsx +1 -1
  303. package/src/components/manage/Widgets/RegistryImageWidget.test.jsx +1 -0
  304. package/src/components/manage/Widgets/SchemaWidget.test.jsx +1 -6
  305. package/src/components/manage/Widgets/SchemaWidgetFieldset.test.jsx +1 -6
  306. package/src/components/manage/Widgets/SelectAutoComplete.test.jsx +1 -6
  307. package/src/components/manage/Widgets/SelectStyling.jsx +52 -20
  308. package/src/components/manage/Widgets/SelectWidget.test.jsx +1 -6
  309. package/src/components/manage/Widgets/Size.stories.tsx +69 -0
  310. package/src/components/manage/Widgets/Size.test.tsx +59 -0
  311. package/src/components/manage/Widgets/Size.tsx +78 -0
  312. package/src/components/manage/Widgets/TextWidget.jsx +4 -0
  313. package/src/components/manage/Widgets/TimeWidget.test.jsx +1 -6
  314. package/src/components/manage/Widgets/TokenWidget.jsx +142 -186
  315. package/src/components/manage/Widgets/TokenWidget.test.jsx +1 -6
  316. package/src/components/manage/Widgets/UrlWidget.jsx +47 -18
  317. package/src/components/manage/Widgets/VocabularyTermsWidget.test.jsx +2 -11
  318. package/src/components/manage/Widgets/__mocks__/index.tsx +33 -51
  319. package/src/components/manage/Widgets/index.tsx +21 -0
  320. package/src/components/manage/Workflow/Workflow.test.jsx +2 -11
  321. package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.jsx +1 -0
  322. package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.test.jsx +30 -0
  323. package/src/components/theme/App/App.jsx +5 -1
  324. package/src/components/theme/App/App.test.jsx +13 -10
  325. package/src/components/theme/Comments/CommentEditModal.test.jsx +1 -5
  326. package/src/components/theme/Comments/Comments.test.jsx +2 -11
  327. package/src/components/theme/ConnectionRefused/ConnectionRefused.jsx +3 -2
  328. package/src/components/theme/ContactForm/ContactForm.test.jsx +14 -13
  329. package/src/components/theme/Image/Image.jsx +25 -13
  330. package/src/components/theme/Image/Image.test.jsx +247 -146
  331. package/src/components/theme/InjectPloneComponentsCSS/InjectPloneComponentsCSS.tsx +7 -0
  332. package/src/components/theme/LanguageSelector/LanguageSelector.tsx +3 -3
  333. package/src/components/theme/MultilingualRedirector/MultilingualRedirector.jsx +42 -12
  334. package/src/components/theme/MultilingualRedirector/MultilingualRedirector.test.jsx +6 -3
  335. package/src/components/theme/PasswordReset/PasswordReset.jsx +108 -191
  336. package/src/components/theme/PasswordReset/RequestPasswordReset.test.jsx +1 -5
  337. package/src/components/theme/Register/Register.test.jsx +1 -5
  338. package/src/components/theme/RequestTimeout/RequestTimeout.jsx +1 -1
  339. package/src/components/theme/Search/Search.jsx +230 -327
  340. package/src/components/theme/Search/Search.test.jsx +14 -14
  341. package/src/components/theme/Sitemap/Sitemap.jsx +22 -30
  342. package/src/components/theme/Sitemap/Sitemap.stories.jsx +82 -0
  343. package/src/components/theme/Sitemap/Sitemap.test.jsx +18 -0
  344. package/src/components/theme/SlotRenderer/SlotRenderer.tsx +12 -6
  345. package/src/components/theme/Unauthorized/Unauthorized.jsx +27 -24
  346. package/src/components/theme/Unauthorized/Unauthorized.test.jsx +31 -2
  347. package/src/components/theme/VideoEmbed/VideoEmbed.jsx +100 -0
  348. package/src/components/theme/View/EventDatesInfo.test.jsx +1 -6
  349. package/src/components/theme/View/EventView.stories.jsx +89 -0
  350. package/src/components/theme/View/EventView.test.jsx +1 -6
  351. package/src/components/theme/View/FileView.stories.jsx +50 -0
  352. package/src/components/theme/View/ImageView.jsx +2 -1
  353. package/src/components/theme/View/ImageView.test.jsx +3 -0
  354. package/src/components/theme/View/LinkView.stories.jsx +57 -0
  355. package/src/components/theme/View/ListingView.stories.jsx +70 -0
  356. package/src/components/theme/View/NewsItemView.stories.jsx +58 -0
  357. package/src/components/theme/View/RenderBlocks.jsx +8 -10
  358. package/src/components/theme/View/RenderBlocks.stories.jsx +112 -0
  359. package/src/components/theme/View/RenderBlocks.test.jsx +14 -4
  360. package/src/components/theme/View/SummaryView.stories.jsx +71 -0
  361. package/src/components/theme/View/TabularView.stories.jsx +66 -0
  362. package/src/components/theme/View/View.jsx +8 -1
  363. package/src/components/theme/View/View.test.jsx +37 -24
  364. package/src/components/theme/Widgets/DateWidget.jsx +4 -5
  365. package/src/components/theme/Widgets/DatetimeWidget.jsx +4 -5
  366. package/src/components/theme/Widgets/ImageWidget.test.jsx +31 -11
  367. package/src/components/theme/Widgets/RichTextWidget.jsx +1 -1
  368. package/src/config/Blocks.jsx +3 -0
  369. package/src/config/ControlPanels.js +2 -0
  370. package/src/config/Loadables.jsx +1 -5
  371. package/src/config/Widgets.jsx +7 -0
  372. package/src/config/index.js +22 -11
  373. package/src/config/server.js +0 -2
  374. package/src/config/slots.js +19 -0
  375. package/src/config/validation.ts +8 -0
  376. package/src/constants/ActionTypes.js +1 -0
  377. package/src/express-middleware/devproxy.js +16 -4
  378. package/src/express-middleware/files.js +1 -0
  379. package/src/express-middleware/files.test.js +59 -0
  380. package/src/express-middleware/images.js +1 -0
  381. package/src/express-middleware/images.test.js +50 -0
  382. package/src/helpers/Api/APIResourceWithAuth.js +8 -3
  383. package/src/helpers/Api/Api.js +9 -6
  384. package/src/helpers/AsyncConnect/ssr.js +4 -1
  385. package/src/helpers/AuthToken/AuthToken.js +1 -6
  386. package/src/helpers/Blocks/Blocks.js +113 -28
  387. package/src/helpers/Blocks/Blocks.test.js +100 -0
  388. package/src/helpers/Content/Content.js +23 -0
  389. package/src/helpers/Content/Content.test.js +39 -0
  390. package/src/helpers/Extensions/withBlockSchemaEnhancer.jsx +4 -1
  391. package/src/helpers/FormValidation/FormValidation.test.js +31 -0
  392. package/src/helpers/FormValidation/validators.ts +52 -6
  393. package/src/helpers/Html/Html.jsx +13 -4
  394. package/src/helpers/I18n/I18n.test.ts +44 -0
  395. package/src/helpers/I18n/I18n.ts +31 -0
  396. package/src/helpers/Loadable/__mocks__/Loadable.jsx +7 -22
  397. package/src/helpers/MessageLabels/MessageLabels.js +5 -0
  398. package/src/helpers/Robots/Robots.js +1 -1
  399. package/src/helpers/Robots/Robots.test.js +34 -0
  400. package/src/helpers/Sitemap/Sitemap.js +4 -4
  401. package/src/helpers/Url/Url.js +33 -2
  402. package/src/helpers/Url/Url.test.js +62 -0
  403. package/src/helpers/Utils/Date.js +26 -1
  404. package/src/helpers/Utils/Date.test.js +237 -0
  405. package/src/helpers/Utils/Utils.jsx +17 -0
  406. package/src/helpers/Utils/Utils.test.jsx +39 -0
  407. package/src/helpers/Utils/withSaveAsDraft.jsx +33 -9
  408. package/src/helpers/index.js +1 -0
  409. package/src/hooks/user/useUser.js +1 -1
  410. package/src/internalChecks.test.ts +11 -0
  411. package/src/middleware/api.js +14 -5
  412. package/src/reducers/blockTypes/blockTypes.js +38 -0
  413. package/src/reducers/content/content.js +3 -18
  414. package/src/reducers/diff/diff.js +5 -1
  415. package/src/reducers/diff/diff.test.js +60 -4
  416. package/src/reducers/index.js +2 -0
  417. package/src/reducers/querystring/querystring.js +8 -1
  418. package/src/reducers/users/users.js +1 -1
  419. package/src/routes.js +10 -0
  420. package/src/server.jsx +54 -14
  421. package/src/start-client.jsx +30 -5
  422. package/src/start-server.js +9 -3
  423. package/test-addons-loader.js +3 -0
  424. package/test-setup-globals.js +56 -2
  425. package/theme/themes/default/elements/segment.variables +9 -16
  426. package/theme/themes/default/globals/site.variables +3 -3
  427. package/theme/themes/pastanaga/collections/form.overrides +22 -1
  428. package/theme/themes/pastanaga/elements/button.overrides +30 -3
  429. package/theme/themes/pastanaga/elements/segment.variables +1 -4
  430. package/theme/themes/pastanaga/extras/block-types.less +17 -0
  431. package/theme/themes/pastanaga/extras/contents.less +63 -4
  432. package/theme/themes/pastanaga/extras/main.less +16 -4
  433. package/theme/themes/pastanaga/extras/toolbar.less +10 -5
  434. package/theme/themes/pastanaga/extras/videoembed.less +22 -0
  435. package/theme/themes/pastanaga/extras/widgets.less +79 -0
  436. package/theme/themes/pastanaga/globals/site.variables +0 -3
  437. package/tsconfig.declarations.json +1 -1
  438. package/tsconfig.json +1 -1
  439. package/types/actions/blockTypes/blockTypes.d.ts +7 -0
  440. package/types/components/index.d.ts +1 -1
  441. package/types/components/manage/Blocks/Block/Order/Item.test.d.ts +1 -0
  442. package/types/components/manage/Blocks/Block/Order/utilities.d.ts +2 -1
  443. package/types/components/manage/Blocks/Grid/context.d.ts +1 -0
  444. package/types/components/manage/Blocks/Teaser/utils.d.ts +5 -0
  445. package/types/components/manage/Blocks/Video/Body.d.ts +4 -2
  446. package/types/components/manage/Blocks/Video/schema.d.ts +4 -0
  447. package/types/components/manage/Contents/Contents.d.ts +1 -1
  448. package/types/components/manage/Contents/ContentsIndexHeader.d.ts +6 -11
  449. package/types/components/manage/Contents/ContentsItem.d.ts +3 -10
  450. package/types/components/manage/Contents/DropZoneContent.d.ts +2 -0
  451. package/types/components/manage/Contents/__mocks__/index.d.ts +2 -2
  452. package/types/components/manage/Controlpanels/BlockType.d.ts +7 -0
  453. package/types/components/manage/Controlpanels/BlockTypes.d.ts +7 -0
  454. package/types/components/manage/Controlpanels/ContentType.d.ts +2 -2
  455. package/types/components/manage/Controlpanels/Controlpanel.d.ts +2 -5
  456. package/types/components/manage/Controlpanels/Relations/RelationsMatrix.d.ts +1 -1
  457. package/types/components/manage/Controlpanels/Users/UsersControlpanel.ssr.test.d.ts +1 -0
  458. package/types/components/manage/Controlpanels/index.d.ts +2 -2
  459. package/types/components/manage/Diff/Diff.d.ts +7 -2
  460. package/types/components/manage/Form/__mocks__/index.d.ts +8 -8
  461. package/types/components/manage/Multilingual/ManageTranslations.d.ts +1 -1
  462. package/types/components/manage/Sidebar/ObjectBrowser.d.ts +1 -1
  463. package/types/components/manage/Sidebar/ObjectBrowserBody.test.d.ts +1 -0
  464. package/types/components/manage/Sidebar/SidebarPortal.d.ts +7 -15
  465. package/types/components/manage/Toolbar/Types.crash.test.d.ts +1 -0
  466. package/types/components/manage/Widgets/AlignWidget.d.ts +8 -10
  467. package/types/components/manage/Widgets/AlignWidget.stories.d.ts +1 -0
  468. package/types/components/manage/Widgets/BlockAlignment.d.ts +7 -0
  469. package/types/components/manage/Widgets/BlockAlignment.stories.d.ts +8 -0
  470. package/types/components/manage/Widgets/BlockWidth.d.ts +7 -0
  471. package/types/components/manage/Widgets/BlockWidth.stories.d.ts +6 -0
  472. package/types/components/manage/Widgets/ButtonsWidget.d.ts +48 -1
  473. package/types/components/manage/Widgets/ButtonsWidget.stories.d.ts +3 -0
  474. package/types/components/manage/Widgets/FormFieldWrapper.d.ts +28 -5
  475. package/types/components/manage/Widgets/ImageWidget.d.ts +1 -1
  476. package/types/components/manage/Widgets/InternalUrlWidget.d.ts +1 -1
  477. package/types/components/manage/Widgets/ObjectBrowserWidget.d.ts +2 -0
  478. package/types/components/manage/Widgets/QueryWidget.d.ts +5 -2
  479. package/types/components/manage/Widgets/RecurrenceWidget/WeekdayOfTheMonthIndexField.d.ts +22 -5
  480. package/types/components/manage/Widgets/SelectStyling.d.ts +1 -0
  481. package/types/components/manage/Widgets/Size.d.ts +7 -0
  482. package/types/components/manage/Widgets/Size.stories.d.ts +6 -0
  483. package/types/components/manage/Widgets/UrlWidget.d.ts +1 -1
  484. package/types/components/manage/Widgets/__mocks__/index.d.ts +33 -33
  485. package/types/components/manage/Widgets/index.d.ts +11 -6
  486. package/types/components/theme/ConnectionRefused/ConnectionRefused.d.ts +2 -2
  487. package/types/components/theme/InjectPloneComponentsCSS/InjectPloneComponentsCSS.d.ts +3 -0
  488. package/types/components/theme/PasswordReset/PasswordReset.d.ts +6 -2
  489. package/types/components/theme/Search/Search.d.ts +1 -1
  490. package/types/components/theme/Sitemap/Sitemap.stories.d.ts +13 -0
  491. package/types/components/theme/SlotRenderer/SlotRenderer.d.ts +4 -5
  492. package/types/components/theme/Unauthorized/Unauthorized.d.ts +2 -2
  493. package/types/components/theme/VideoEmbed/VideoEmbed.d.ts +2 -0
  494. package/types/components/theme/View/EventView.stories.d.ts +19 -0
  495. package/types/components/theme/View/FileView.stories.d.ts +18 -0
  496. package/types/components/theme/View/LinkView.stories.d.ts +18 -0
  497. package/types/components/theme/View/ListingView.stories.d.ts +24 -0
  498. package/types/components/theme/View/NewsItemView.stories.d.ts +23 -0
  499. package/types/components/theme/View/RenderBlocks.stories.d.ts +23 -0
  500. package/types/components/theme/View/SummaryView.stories.d.ts +23 -0
  501. package/types/components/theme/View/TabularView.stories.d.ts +23 -0
  502. package/types/config/ControlPanels.d.ts +1 -0
  503. package/types/config/Views.d.ts +1 -1
  504. package/types/config/Widgets.d.ts +6 -0
  505. package/types/config/slots.d.ts +7 -0
  506. package/types/constants/ActionTypes.d.ts +1 -0
  507. package/types/helpers/Blocks/Blocks.d.ts +4 -0
  508. package/types/helpers/Content/Content.d.ts +7 -0
  509. package/types/helpers/Extensions/withBlockSchemaEnhancer.d.ts +4 -5
  510. package/types/helpers/FormValidation/validators.d.ts +18 -1
  511. package/types/helpers/I18n/I18n.d.ts +20 -0
  512. package/types/helpers/Loadable/__mocks__/Loadable.d.ts +2 -2
  513. package/types/helpers/MessageLabels/MessageLabels.d.ts +100 -94
  514. package/types/helpers/Url/Url.d.ts +14 -0
  515. package/types/helpers/Utils/Utils.d.ts +1 -0
  516. package/types/helpers/index.d.ts +1 -0
  517. package/types/reducers/blockTypes/blockTypes.d.ts +16 -0
  518. package/types/reducers/index.d.ts +2 -0
  519. package/types/routes.d.ts +7 -5
  520. package/types/start-client.d.ts +0 -1
  521. package/vitest.config.mjs +84 -42
  522. package/webpack-plugins/webpack-less-plugin.js +1 -1
  523. package/webpack-plugins/webpack-scss-plugin.js +172 -0
  524. package/jest-addons-loader.js +0 -3
  525. package/jest-extender-plugin.js +0 -39
  526. package/jest-setup-afterenv.js +0 -2
  527. package/jest-svgsystem-transform.js +0 -10
  528. package/patches/patchit.sh +0 -2
  529. package/patches/razzle-jest.patch +0 -10
  530. package/src/components/manage/Contents/__mocks__/index.vitest.tsx +0 -5
  531. package/src/components/manage/Form/__mocks__/index.vitest.tsx +0 -73
  532. package/src/components/manage/Sidebar/SidebarPortal.jsx +0 -47
  533. package/src/components/manage/Sidebar/SidebarPortal.test.jsx +0 -26
  534. package/src/components/manage/Widgets/AlignWidget.test.jsx +0 -59
  535. package/src/components/manage/Widgets/ButtonsWidget.jsx +0 -41
  536. package/src/components/manage/Widgets/ButtonsWidget.test.jsx +0 -70
  537. package/src/components/manage/Widgets/__mocks__/index.vitest.tsx +0 -41
  538. package/src/helpers/Loadable/__mocks__/Loadable.vitest.jsx +0 -39
  539. package/test-setup-globals-vitest.js +0 -46
  540. package/theme/themes/pastanaga/extras/utils.less +0 -63
@@ -1,5 +1,6 @@
1
1
  import { validationMessage } from '@plone/volto/helpers/FormValidation/FormValidation';
2
2
  import { messages } from '@plone/volto/helpers/MessageLabels/MessageLabels';
3
+ import config from '@plone/volto/registry';
3
4
 
4
5
  type MinMaxValidator = {
5
6
  value: string | number;
@@ -15,6 +16,24 @@ type Validator = {
15
16
  formatMessage: Function;
16
17
  };
17
18
 
19
+ type Choice = {
20
+ token: string;
21
+ label: string;
22
+ };
23
+ type ChoiceValidator = {
24
+ value: string | Choice;
25
+ field: Record<string, any>;
26
+ formData: any;
27
+ formatMessage: Function;
28
+ };
29
+
30
+ type FileValidator = {
31
+ value: Record<string, any>;
32
+ field: Record<string, any>;
33
+ formData: any;
34
+ formatMessage: Function;
35
+ };
36
+
18
37
  export const isMaxPropertyValid = ({
19
38
  value,
20
39
  fieldSpec,
@@ -134,6 +153,15 @@ export const hasUniqueItemsValidator = ({
134
153
  return !isValid ? formatMessage(messages.uniqueItems) : null;
135
154
  };
136
155
 
156
+ const formatDateValue = (isoString: string) => {
157
+ const date = new Date(isoString);
158
+ if (isNaN(date.getTime())) return isoString;
159
+ return new Intl.DateTimeFormat(undefined, {
160
+ dateStyle: 'medium',
161
+ timeStyle: 'short',
162
+ }).format(date);
163
+ };
164
+
137
165
  export const startEventDateRangeValidator = ({
138
166
  value,
139
167
  field,
@@ -144,7 +172,9 @@ export const startEventDateRangeValidator = ({
144
172
  value && formData.end && new Date(value) < new Date(formData.end);
145
173
  return !isValid
146
174
  ? formatMessage(messages.startEventRange, {
147
- endDateValueOrEndFieldName: formData.end || 'end',
175
+ endDateValueOrEndFieldName: formData.end
176
+ ? formatDateValue(formData.end)
177
+ : 'end',
148
178
  })
149
179
  : null;
150
180
  };
@@ -159,7 +189,9 @@ export const endEventDateRangeValidator = ({
159
189
  value && formData.start && new Date(value) > new Date(formData.start);
160
190
  return !isValid
161
191
  ? formatMessage(messages.endEventRange, {
162
- startDateValueOrStartFieldName: formData.start || 'start',
192
+ startDateValueOrStartFieldName: formData.start
193
+ ? formatDateValue(formData.start)
194
+ : 'start',
163
195
  })
164
196
  : null;
165
197
  };
@@ -211,12 +243,26 @@ export const defaultLanguageControlPanelValidator = ({
211
243
  value,
212
244
  formData,
213
245
  formatMessage,
214
- }: Validator) => {
246
+ }: ChoiceValidator) => {
247
+ const token = typeof value === 'object' ? value.token : value;
215
248
  const isValid =
216
- value &&
249
+ token &&
217
250
  (formData.available_languages.find(
218
- (lang: { token: string }) => lang.token === value,
251
+ (lang: { token: string }) => lang.token === token,
219
252
  ) ||
220
- formData.available_languages.includes(value));
253
+ formData.available_languages.includes(token));
221
254
  return !isValid ? formatMessage(messages.defaultLanguage) : null;
222
255
  };
256
+
257
+ export const sizeValidator = ({
258
+ value,
259
+ field,
260
+ formatMessage,
261
+ }: FileValidator) => {
262
+ const maxSize = field.size
263
+ ? parseInt(field.size, 10)
264
+ : config.settings.maxFileUploadSize;
265
+ return maxSize && value.size > maxSize
266
+ ? formatMessage(messages.maxSize, { maxSize, size: value.size })
267
+ : null;
268
+ };
@@ -9,6 +9,7 @@ import Helmet from '@plone/volto/helpers/Helmet/Helmet';
9
9
  import serialize from 'serialize-javascript';
10
10
  import join from 'lodash/join';
11
11
  import BodyClass from '@plone/volto/helpers/BodyClass/BodyClass';
12
+ import { addSubpathPrefix } from '@plone/volto/helpers/Url/Url';
12
13
  import { runtimeConfig } from '@plone/volto/runtime_config';
13
14
  import config from '@plone/volto/registry';
14
15
 
@@ -126,14 +127,22 @@ class Html extends Component {
126
127
  }}
127
128
  />
128
129
 
129
- <link rel="icon" href="/favicon.ico" sizes="any" />
130
- <link rel="icon" href="/icon.svg" type="image/svg+xml" />
130
+ <link
131
+ rel="icon"
132
+ href={addSubpathPrefix('/favicon.ico')}
133
+ sizes="any"
134
+ />
135
+ <link
136
+ rel="icon"
137
+ href={addSubpathPrefix('/icon.svg')}
138
+ type="image/svg+xml"
139
+ />
131
140
  <link
132
141
  rel="apple-touch-icon"
133
142
  sizes="180x180"
134
- href="/apple-touch-icon.png"
143
+ href={addSubpathPrefix('/apple-touch-icon.png')}
135
144
  />
136
- <link rel="manifest" href="/site.webmanifest" />
145
+ <link rel="manifest" href={addSubpathPrefix('/site.webmanifest')} />
137
146
  <meta name="generator" content="Plone 6 - https://plone.org" />
138
147
  <meta name="viewport" content="width=device-width, initial-scale=1" />
139
148
  <meta name="mobile-web-app-capable" content="yes" />
@@ -0,0 +1,44 @@
1
+ import { createIntl, createIntlCache } from 'react-intl';
2
+ import type { IntlShape } from 'react-intl';
3
+ import { formatMessageWithFallback } from './I18n';
4
+
5
+ const buildIntl = (
6
+ locale: string,
7
+ messages: Record<string, string>,
8
+ ): IntlShape => createIntl({ locale, messages }, createIntlCache());
9
+
10
+ describe('formatMessageWithFallback', () => {
11
+ it('returns the translated string when the locale catalog has an entry', () => {
12
+ const intl = buildIntl('pt-BR', { Image: 'Imagem' });
13
+ expect(formatMessageWithFallback(intl, 'Image')).toBe('Imagem');
14
+ });
15
+
16
+ it('falls back to the input message when no translation is registered', () => {
17
+ const intl = buildIntl('pt-BR', {});
18
+ expect(formatMessageWithFallback(intl, 'Image')).toBe('Image');
19
+ });
20
+
21
+ it('returns undefined unchanged', () => {
22
+ const intl = buildIntl('en', {});
23
+ expect(formatMessageWithFallback(intl, undefined)).toBeUndefined();
24
+ });
25
+
26
+ it('returns null unchanged', () => {
27
+ const intl = buildIntl('en', {});
28
+ expect(formatMessageWithFallback(intl, null)).toBeNull();
29
+ });
30
+
31
+ it('returns an empty string unchanged', () => {
32
+ const intl = buildIntl('en', {});
33
+ expect(formatMessageWithFallback(intl, '')).toBe('');
34
+ });
35
+
36
+ it('does not call intl.formatMessage when the message is falsy', () => {
37
+ const intl = buildIntl('en', {});
38
+ const spy = vi.spyOn(intl, 'formatMessage');
39
+ formatMessageWithFallback(intl, undefined);
40
+ formatMessageWithFallback(intl, null);
41
+ formatMessageWithFallback(intl, '');
42
+ expect(spy).not.toHaveBeenCalled();
43
+ });
44
+ });
@@ -0,0 +1,31 @@
1
+ /**
2
+ * I18n helpers.
3
+ * @module helpers/I18n/I18n
4
+ */
5
+
6
+ import type { IntlShape } from 'react-intl';
7
+
8
+ /**
9
+ * Format a `react-intl` message using a plain string as both the id and the
10
+ * default fallback. Useful when a UI value (e.g. a block title configured as
11
+ * a plain string) should be looked up in the locale catalog when available,
12
+ * and rendered as-is otherwise.
13
+ *
14
+ * Returns the input untouched when it is falsy, so the result can be used
15
+ * directly in `||` fallback chains.
16
+ *
17
+ * @param intl react-intl `intl` instance, typically from `useIntl()`.
18
+ * @param message The string to translate; used as both `id` and
19
+ * `defaultMessage`.
20
+ * @returns Translated text, or `message` unchanged if falsy / no translation.
21
+ */
22
+ export function formatMessageWithFallback<T extends string | undefined | null>(
23
+ intl: IntlShape,
24
+ message: T,
25
+ ): T extends string ? string : T {
26
+ if (!message) return message as T extends string ? string : T;
27
+ return intl.formatMessage({
28
+ id: message,
29
+ defaultMessage: message,
30
+ }) as T extends string ? string : T;
31
+ }
@@ -1,19 +1,4 @@
1
- /* TODO: When the Volto Team removes Jest configuration support from Volto core, update this file with the Vitest version of the mock.
2
- Then, in the tests, we need to replace:
3
-
4
- vi.mock('@plone/volto/helpers/Loadable/Loadable', async () => {
5
- return await import(
6
- '@plone/volto/helpers/Loadable/__mocks__/Loadable.vitest.jsx'
7
- );
8
- });
9
-
10
- with the following:
11
-
12
- vi.mock('@plone/volto/helpers/Loadable/Loadable');
13
-
14
- Finally, remove this comment.
15
- */
16
-
1
+ import React from 'react';
17
2
  import config from '@plone/volto/registry';
18
3
  const loadables = config.settings.loadables;
19
4
 
@@ -33,21 +18,21 @@ export const __setLoadables = async () => {
33
18
  };
34
19
 
35
20
  // TODO: filter mockAllLoadables
36
- export const injectLazyLibs = jest.fn().mockImplementation(function ([
21
+ export const injectLazyLibs = vi.fn().mockImplementation(function ([
37
22
  libraries,
38
23
  ]) {
39
- return jest.fn((WrappedComponent) =>
40
- jest.fn((props) => {
24
+ return vi.fn((WrappedComponent) =>
25
+ vi.fn((props) => {
41
26
  return <WrappedComponent {...props} {...mockAllLoadables} />;
42
27
  }),
43
28
  );
44
29
  });
45
30
 
46
- export const preloadLazyLibs = jest.fn().mockImplementation(function ([
31
+ export const preloadLazyLibs = vi.fn().mockImplementation(function ([
47
32
  libraries,
48
33
  ]) {
49
- return jest.fn((WrappedComponent) =>
50
- jest.fn((props) => {
34
+ return vi.fn((WrappedComponent) =>
35
+ vi.fn((props) => {
51
36
  return <WrappedComponent {...props} />;
52
37
  }),
53
38
  );
@@ -25,6 +25,11 @@ export const messages = defineMessages({
25
25
  id: 'Maximum value is {len}.',
26
26
  defaultMessage: 'Maximum value is {len}.',
27
27
  },
28
+ maxSize: {
29
+ id: 'Maximum file size is {maxSize} bytes, but the uploaded file is {size} bytes.',
30
+ defaultMessage:
31
+ 'Maximum file size is {maxSize} bytes, but the uploaded file is {size} bytes.',
32
+ },
28
33
  uniqueItems: {
29
34
  id: 'Items must be unique.',
30
35
  defaultMessage: 'Items must be unique.',
@@ -24,7 +24,7 @@ export const generateRobots = (req) =>
24
24
  request.set('Authorization', `Bearer ${authToken}`);
25
25
  }
26
26
  request.use(addHeadersFactory(req));
27
- request.end((error, { text, body }) => {
27
+ request.end((error, { text, body } = {}) => {
28
28
  if (error) {
29
29
  resolve(text || error);
30
30
  } else {
@@ -0,0 +1,34 @@
1
+ import { generateRobots } from './Robots';
2
+
3
+ const request = {
4
+ set: vi.fn(() => request),
5
+ use: vi.fn(() => request),
6
+ end: vi.fn(),
7
+ };
8
+
9
+ vi.mock('superagent', () => ({
10
+ default: {
11
+ get: vi.fn(() => request),
12
+ },
13
+ }));
14
+
15
+ vi.mock('@plone/volto/helpers/Proxy/Proxy', () => ({
16
+ addHeadersFactory: vi.fn(() => vi.fn()),
17
+ }));
18
+
19
+ describe('generateRobots', () => {
20
+ beforeEach(() => {
21
+ vi.clearAllMocks();
22
+ });
23
+
24
+ it('resolves the original error when superagent does not provide a response', async () => {
25
+ const error = new Error('network error');
26
+ request.end.mockImplementationOnce((callback) => callback(error));
27
+
28
+ await expect(
29
+ generateRobots({
30
+ universalCookies: { get: vi.fn(() => null) },
31
+ }),
32
+ ).resolves.toBe(error);
33
+ });
34
+ });
@@ -22,10 +22,10 @@ export const SITEMAP_BATCH_SIZE = 5000;
22
22
  export const generateSitemap = (_req, start = 0, size = undefined) =>
23
23
  new Promise((resolve) => {
24
24
  const { settings } = config;
25
- const APISUFIX = settings.legacyTraverse ? '' : '/++api++';
25
+ const apiSuffix = settings.legacyTraverse ? '' : '/++api++';
26
26
  const apiPath = settings.internalApiPath ?? settings.apiPath;
27
27
  const request = superagent.get(
28
- `${apiPath}${APISUFIX}/@search?metadata_fields=modified&b_start=${start}&b_size=${
28
+ `${apiPath}${apiSuffix}/@search?metadata_fields=modified&b_start=${start}&b_size=${
29
29
  size !== undefined ? size : 100000000
30
30
  }&use_site_search_settings=1`,
31
31
  );
@@ -64,10 +64,10 @@ export const generateSitemap = (_req, start = 0, size = undefined) =>
64
64
  export const generateSitemapIndex = (_req, gzip = false) =>
65
65
  new Promise((resolve) => {
66
66
  const { settings } = config;
67
- const APISUFIX = settings.legacyTraverse ? '' : '/++api++';
67
+ const apiSuffix = settings.legacyTraverse ? '' : '/++api++';
68
68
  const apiPath = settings.internalApiPath ?? settings.apiPath;
69
69
  const request = superagent.get(
70
- `${apiPath}${APISUFIX}/@search?metadata_fields=modified&b_size=0&use_site_search_settings=1`,
70
+ `${apiPath}${apiSuffix}/@search?metadata_fields=modified&b_size=0&use_site_search_settings=1`,
71
71
  );
72
72
  request.set('Accept', 'application/json');
73
73
  const authToken = _req.universalCookies.get('auth_token');
@@ -193,7 +193,7 @@ export function addAppURL(url) {
193
193
  */
194
194
  export function expandToBackendURL(path) {
195
195
  const { settings } = config;
196
- const APISUFIX = settings.legacyTraverse ? '' : '/++api++';
196
+ const apiSuffix = settings.legacyTraverse ? '' : '/++api++';
197
197
  let adjustedPath;
198
198
  if (path.startsWith('http://') || path.startsWith('https://')) {
199
199
  // flattenToAppURL first if we get a full URL
@@ -210,7 +210,7 @@ export function expandToBackendURL(path) {
210
210
  apiPath = settings.apiPath;
211
211
  }
212
212
 
213
- return `${apiPath}${APISUFIX}${adjustedPath}`;
213
+ return `${apiPath}${apiSuffix}${adjustedPath}`;
214
214
  }
215
215
 
216
216
  /**
@@ -258,6 +258,36 @@ export function isUrl(url) {
258
258
  return urlRegex().test(url);
259
259
  }
260
260
 
261
+ /**
262
+ * Add subpath path if set in settings
263
+ * @method addSubpathPrefix
264
+ * @param {string} src pathname
265
+ * @returns {string} prefixed subpath pathname
266
+ */
267
+ export function addSubpathPrefix(src) {
268
+ let url = src;
269
+ const { subpathPrefix } = config.settings;
270
+ if (isInternalURL(src) && subpathPrefix && !src.startsWith(subpathPrefix)) {
271
+ url = subpathPrefix + src; //add subpathPrefix to src if it's an internal url and not a static resource.
272
+ }
273
+ return url;
274
+ }
275
+
276
+ /**
277
+ * strip subpath path particulary from api calls
278
+ * @method stripSubpathPrefix
279
+ * @param {string} src pathname
280
+ * @returns {string} pathname
281
+ */
282
+ export function stripSubpathPrefix(src) {
283
+ let url = src;
284
+ const { subpathPrefix } = config.settings;
285
+ if (subpathPrefix && src.match(new RegExp(`^${subpathPrefix}(/|$)`))) {
286
+ url = src.slice(subpathPrefix.length);
287
+ }
288
+ return url;
289
+ }
290
+
261
291
  /**
262
292
  * Get field url
263
293
  * @method getFieldURL
@@ -381,6 +411,7 @@ export function flattenScales(path, image) {
381
411
  const basePath = image.base_path || path;
382
412
  const imageInfo = {
383
413
  ...image,
414
+ scales: image.scales || {},
384
415
  download: flattenToAppURL(removeObjectIdFromURL(basePath, image.download)),
385
416
  };
386
417
 
@@ -19,6 +19,8 @@ import {
19
19
  normaliseMail,
20
20
  normalizeTelephone,
21
21
  flattenScales,
22
+ addSubpathPrefix,
23
+ stripSubpathPrefix,
22
24
  } from './Url';
23
25
 
24
26
  beforeEach(() => {
@@ -533,4 +535,64 @@ describe('Url', () => {
533
535
  });
534
536
  });
535
537
  });
538
+
539
+ describe('Subpath tests', () => {
540
+ beforeEach(() => {
541
+ settings.subpathPrefix = '/site';
542
+ });
543
+ describe('addSubpathPrefix', () => {
544
+ it('adds subpath prefix to internal URLs', () => {
545
+ expect(addSubpathPrefix('/some-page')).toBe('/site/some-page');
546
+ expect(addSubpathPrefix('/news/article')).toBe('/site/news/article');
547
+ });
548
+
549
+ it('does not add subpath prefix to URLs that already have it', () => {
550
+ expect(addSubpathPrefix('/site/some-page')).toBe('/site/some-page');
551
+ });
552
+
553
+ it('does not add subpath prefix to external URLs', () => {
554
+ expect(addSubpathPrefix('https://example.com/page')).toBe(
555
+ 'https://example.com/page',
556
+ );
557
+ });
558
+
559
+ it('handles empty subpath prefix', () => {
560
+ settings.subpathPrefix = '';
561
+ expect(addSubpathPrefix('/some-page')).toBe('/some-page');
562
+ });
563
+
564
+ it('handles undefined subpath prefix', () => {
565
+ settings.subpathPrefix = undefined;
566
+ expect(addSubpathPrefix('/some-page')).toBe('/some-page');
567
+ });
568
+ });
569
+
570
+ describe('stripSubpathPrefix', () => {
571
+ beforeEach(() => {
572
+ settings.subpathPrefix = '/site';
573
+ });
574
+ it('removes subpath prefix from URLs that have it', () => {
575
+ expect(stripSubpathPrefix('/site/some-page')).toBe('/some-page');
576
+ expect(stripSubpathPrefix('/site/news/article')).toBe('/news/article');
577
+ });
578
+
579
+ it('leaves URLs unchanged if they do not have the prefix', () => {
580
+ expect(stripSubpathPrefix('/other/some-page')).toBe('/other/some-page');
581
+ });
582
+
583
+ it('handles the case where URL is exactly the subpath prefix', () => {
584
+ expect(stripSubpathPrefix('/site')).toBe('');
585
+ });
586
+
587
+ it('handles empty subpath prefix', () => {
588
+ settings.subpathPrefix = '';
589
+ expect(stripSubpathPrefix('/some-page')).toBe('/some-page');
590
+ });
591
+
592
+ it('handles undefined subpath prefix', () => {
593
+ settings.subpathPrefix = undefined;
594
+ expect(stripSubpathPrefix('/some-page')).toBe('/some-page');
595
+ });
596
+ });
597
+ });
536
598
  });
@@ -5,6 +5,21 @@ const DAY = HOUR * 24;
5
5
  const MONTH = DAY * 30;
6
6
  const YEAR = DAY * 365; // ? is this safe or should it be more accurate
7
7
 
8
+ // moment-style format tokens → Intl.DateTimeFormat options (for backward compat)
9
+ const MOMENT_FORMAT_MAP = {
10
+ ll: { year: 'numeric', month: 'short', day: 'numeric' },
11
+ lll: {
12
+ year: 'numeric',
13
+ month: 'short',
14
+ day: 'numeric',
15
+ hour: 'numeric',
16
+ minute: 'numeric',
17
+ },
18
+ LLLL: { dateStyle: 'full', timeStyle: 'short' },
19
+ L: { year: 'numeric', month: '2-digit', day: '2-digit' },
20
+ LT: { timeStyle: 'short' },
21
+ };
22
+
8
23
  export const short_date_format = {
9
24
  // 12/9/2021
10
25
  year: 'numeric',
@@ -32,13 +47,23 @@ export const toDate = (d) =>
32
47
  */
33
48
  export function formatDate({
34
49
  date, // Date() or '2022-01-03T19:26:08.999Z'
35
- format, // format object, see https://tc39.es/ecma402/#datetimeformat-objects
50
+ format, // format object (Intl.DateTimeFormat options) or moment-style token string (e.g. 'll', 'lll', 'LLLL', 'L', 'LT')
36
51
  locale = 'en',
37
52
  long, // true if format should be in long readable form.
38
53
  includeTime, // true if short date format should include time
39
54
  formatToParts = false,
40
55
  }) {
41
56
  date = toDate(date);
57
+ // Resolve moment-style token strings to Intl format options
58
+ if (typeof format === 'string') {
59
+ if (process.env.NODE_ENV !== 'production' && !MOMENT_FORMAT_MAP[format]) {
60
+ // eslint-disable-next-line no-console
61
+ console.warn(
62
+ `[formatDate] Unknown format token "${format}". Supported tokens: ${Object.keys(MOMENT_FORMAT_MAP).join(', ')}. Falling back to short_date_format.`,
63
+ );
64
+ }
65
+ format = MOMENT_FORMAT_MAP[format] || short_date_format;
66
+ }
42
67
  format = format
43
68
  ? format
44
69
  : long && !includeTime