@pranaysahith/decap-cms-core 3.9.1

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 (299) hide show
  1. package/README.md +9 -0
  2. package/dist/@pranaysahith/decap-cms-core.js +52 -0
  3. package/dist/@pranaysahith/decap-cms-core.js.LICENSE.txt +141 -0
  4. package/dist/@pranaysahith/decap-cms-core.js.map +1 -0
  5. package/dist/decap-cms-core.js +47 -0
  6. package/dist/decap-cms-core.js.LICENSE.txt +116 -0
  7. package/dist/decap-cms-core.js.map +1 -0
  8. package/dist/esm/actions/auth.js +97 -0
  9. package/dist/esm/actions/collections.js +15 -0
  10. package/dist/esm/actions/config.js +493 -0
  11. package/dist/esm/actions/deploys.js +79 -0
  12. package/dist/esm/actions/editorialWorkflow.js +480 -0
  13. package/dist/esm/actions/entries.js +865 -0
  14. package/dist/esm/actions/media.js +147 -0
  15. package/dist/esm/actions/mediaLibrary.js +552 -0
  16. package/dist/esm/actions/notifications.js +21 -0
  17. package/dist/esm/actions/search.js +149 -0
  18. package/dist/esm/actions/status.js +74 -0
  19. package/dist/esm/actions/waitUntil.js +32 -0
  20. package/dist/esm/backend.js +1082 -0
  21. package/dist/esm/bootstrap.js +101 -0
  22. package/dist/esm/components/App/App.js +289 -0
  23. package/dist/esm/components/App/Header.js +172 -0
  24. package/dist/esm/components/App/NotFoundPage.js +19 -0
  25. package/dist/esm/components/Collection/Collection.js +198 -0
  26. package/dist/esm/components/Collection/CollectionControls.js +46 -0
  27. package/dist/esm/components/Collection/CollectionSearch.js +222 -0
  28. package/dist/esm/components/Collection/CollectionTop.js +68 -0
  29. package/dist/esm/components/Collection/ControlButton.js +17 -0
  30. package/dist/esm/components/Collection/Entries/Entries.js +73 -0
  31. package/dist/esm/components/Collection/Entries/EntriesCollection.js +241 -0
  32. package/dist/esm/components/Collection/Entries/EntriesSearch.js +113 -0
  33. package/dist/esm/components/Collection/Entries/EntryCard.js +177 -0
  34. package/dist/esm/components/Collection/Entries/EntryListing.js +143 -0
  35. package/dist/esm/components/Collection/FilterControl.js +33 -0
  36. package/dist/esm/components/Collection/FolderRenameControl.js +403 -0
  37. package/dist/esm/components/Collection/GroupControl.js +33 -0
  38. package/dist/esm/components/Collection/NestedCollection.js +308 -0
  39. package/dist/esm/components/Collection/Sidebar.js +91 -0
  40. package/dist/esm/components/Collection/SortControl.js +59 -0
  41. package/dist/esm/components/Collection/ViewStyleControl.js +38 -0
  42. package/dist/esm/components/Editor/Editor.js +466 -0
  43. package/dist/esm/components/Editor/EditorControlPane/EditorControl.js +395 -0
  44. package/dist/esm/components/Editor/EditorControlPane/EditorControlPane.js +254 -0
  45. package/dist/esm/components/Editor/EditorControlPane/Widget.js +374 -0
  46. package/dist/esm/components/Editor/EditorInterface.js +386 -0
  47. package/dist/esm/components/Editor/EditorPreviewPane/EditorPreview.js +47 -0
  48. package/dist/esm/components/Editor/EditorPreviewPane/EditorPreviewContent.js +66 -0
  49. package/dist/esm/components/Editor/EditorPreviewPane/EditorPreviewPane.js +288 -0
  50. package/dist/esm/components/Editor/EditorPreviewPane/PreviewHOC.js +27 -0
  51. package/dist/esm/components/Editor/EditorToolbar.js +536 -0
  52. package/dist/esm/components/Editor/EntryPathEditor.js +272 -0
  53. package/dist/esm/components/Editor/withWorkflow.js +56 -0
  54. package/dist/esm/components/EditorWidgets/Unknown/UnknownControl.js +18 -0
  55. package/dist/esm/components/EditorWidgets/Unknown/UnknownPreview.js +20 -0
  56. package/dist/esm/components/EditorWidgets/index.js +4 -0
  57. package/dist/esm/components/MediaLibrary/EmptyMessage.js +22 -0
  58. package/dist/esm/components/MediaLibrary/MediaLibrary.js +446 -0
  59. package/dist/esm/components/MediaLibrary/MediaLibraryButtons.js +93 -0
  60. package/dist/esm/components/MediaLibrary/MediaLibraryCard.js +99 -0
  61. package/dist/esm/components/MediaLibrary/MediaLibraryCardGrid.js +198 -0
  62. package/dist/esm/components/MediaLibrary/MediaLibraryHeader.js +32 -0
  63. package/dist/esm/components/MediaLibrary/MediaLibraryModal.js +156 -0
  64. package/dist/esm/components/MediaLibrary/MediaLibrarySearch.js +51 -0
  65. package/dist/esm/components/MediaLibrary/MediaLibraryTop.js +123 -0
  66. package/dist/esm/components/UI/DragDrop.js +67 -0
  67. package/dist/esm/components/UI/ErrorBoundary.js +173 -0
  68. package/dist/esm/components/UI/FileUploadButton.js +27 -0
  69. package/dist/esm/components/UI/Modal.js +104 -0
  70. package/dist/esm/components/UI/Notifications.js +62 -0
  71. package/dist/esm/components/UI/SettingsDropdown.js +107 -0
  72. package/dist/esm/components/UI/index.js +6 -0
  73. package/dist/esm/components/Workflow/Workflow.js +133 -0
  74. package/dist/esm/components/Workflow/WorkflowCard.js +128 -0
  75. package/dist/esm/components/Workflow/WorkflowList.js +204 -0
  76. package/dist/esm/constants/collectionTypes.js +2 -0
  77. package/dist/esm/constants/collectionViews.js +2 -0
  78. package/dist/esm/constants/commitProps.js +2 -0
  79. package/dist/esm/constants/configSchema.js +644 -0
  80. package/dist/esm/constants/fieldInference.js +57 -0
  81. package/dist/esm/constants/publishModes.js +18 -0
  82. package/dist/esm/constants/validationErrorTypes.js +6 -0
  83. package/dist/esm/formats/formats.js +83 -0
  84. package/dist/esm/formats/frontmatter.js +146 -0
  85. package/dist/esm/formats/helpers.js +12 -0
  86. package/dist/esm/formats/json.js +8 -0
  87. package/dist/esm/formats/toml.js +32 -0
  88. package/dist/esm/formats/yaml.js +51 -0
  89. package/dist/esm/index.js +7 -0
  90. package/dist/esm/integrations/index.js +28 -0
  91. package/dist/esm/integrations/providers/algolia/implementation.js +174 -0
  92. package/dist/esm/integrations/providers/assetStore/implementation.js +165 -0
  93. package/dist/esm/lib/consoleError.js +3 -0
  94. package/dist/esm/lib/formatters.js +191 -0
  95. package/dist/esm/lib/i18n.js +367 -0
  96. package/dist/esm/lib/phrases.js +6 -0
  97. package/dist/esm/lib/polyfill.js +8 -0
  98. package/dist/esm/lib/registry.js +329 -0
  99. package/dist/esm/lib/serializeEntryValues.js +67 -0
  100. package/dist/esm/lib/stega.js +142 -0
  101. package/dist/esm/lib/textHelper.js +9 -0
  102. package/dist/esm/lib/urlHelper.js +111 -0
  103. package/dist/esm/mediaLibrary.js +37 -0
  104. package/dist/esm/reducers/auth.js +27 -0
  105. package/dist/esm/reducers/collections.js +428 -0
  106. package/dist/esm/reducers/combinedReducer.js +8 -0
  107. package/dist/esm/reducers/config.js +29 -0
  108. package/dist/esm/reducers/cursors.js +31 -0
  109. package/dist/esm/reducers/deploys.js +45 -0
  110. package/dist/esm/reducers/editorialWorkflow.js +83 -0
  111. package/dist/esm/reducers/entries.js +568 -0
  112. package/dist/esm/reducers/entryDraft.js +212 -0
  113. package/dist/esm/reducers/globalUI.js +25 -0
  114. package/dist/esm/reducers/index.js +66 -0
  115. package/dist/esm/reducers/integrations.js +53 -0
  116. package/dist/esm/reducers/mediaLibrary.js +252 -0
  117. package/dist/esm/reducers/medias.js +68 -0
  118. package/dist/esm/reducers/notifications.js +23 -0
  119. package/dist/esm/reducers/search.js +92 -0
  120. package/dist/esm/reducers/status.js +30 -0
  121. package/dist/esm/redux/index.js +7 -0
  122. package/dist/esm/redux/middleware/waitUntilAction.js +48 -0
  123. package/dist/esm/routing/history.js +12 -0
  124. package/dist/esm/types/diacritics.d.js +0 -0
  125. package/dist/esm/types/global.d.js +1 -0
  126. package/dist/esm/types/immutable.js +7 -0
  127. package/dist/esm/types/redux.js +14 -0
  128. package/dist/esm/types/tomlify-j0.4.d.js +0 -0
  129. package/dist/esm/valueObjects/AssetProxy.js +44 -0
  130. package/dist/esm/valueObjects/EditorComponent.js +34 -0
  131. package/dist/esm/valueObjects/Entry.js +20 -0
  132. package/index.d.ts +618 -0
  133. package/package.json +106 -0
  134. package/src/__tests__/backend.spec.js +1161 -0
  135. package/src/actions/__tests__/config.spec.js +1009 -0
  136. package/src/actions/__tests__/editorialWorkflow.spec.js +216 -0
  137. package/src/actions/__tests__/entries.spec.js +596 -0
  138. package/src/actions/__tests__/media.spec.ts +171 -0
  139. package/src/actions/__tests__/mediaLibrary.spec.js +327 -0
  140. package/src/actions/__tests__/search.spec.js +209 -0
  141. package/src/actions/auth.ts +127 -0
  142. package/src/actions/collections.ts +18 -0
  143. package/src/actions/config.ts +565 -0
  144. package/src/actions/deploys.ts +104 -0
  145. package/src/actions/editorialWorkflow.ts +567 -0
  146. package/src/actions/entries.ts +1055 -0
  147. package/src/actions/media.ts +139 -0
  148. package/src/actions/mediaLibrary.ts +574 -0
  149. package/src/actions/notifications.ts +36 -0
  150. package/src/actions/search.ts +221 -0
  151. package/src/actions/status.ts +99 -0
  152. package/src/actions/waitUntil.ts +49 -0
  153. package/src/backend.ts +1400 -0
  154. package/src/bootstrap.js +104 -0
  155. package/src/components/App/App.js +286 -0
  156. package/src/components/App/Header.js +266 -0
  157. package/src/components/App/NotFoundPage.js +23 -0
  158. package/src/components/Collection/Collection.js +210 -0
  159. package/src/components/Collection/CollectionControls.js +58 -0
  160. package/src/components/Collection/CollectionSearch.js +243 -0
  161. package/src/components/Collection/CollectionTop.js +81 -0
  162. package/src/components/Collection/ControlButton.js +27 -0
  163. package/src/components/Collection/Entries/Entries.js +82 -0
  164. package/src/components/Collection/Entries/EntriesCollection.js +277 -0
  165. package/src/components/Collection/Entries/EntriesSearch.js +102 -0
  166. package/src/components/Collection/Entries/EntryCard.js +246 -0
  167. package/src/components/Collection/Entries/EntryListing.js +151 -0
  168. package/src/components/Collection/Entries/__tests__/EntriesCollection.spec.js +163 -0
  169. package/src/components/Collection/Entries/__tests__/__snapshots__/EntriesCollection.spec.js.snap +46 -0
  170. package/src/components/Collection/FilterControl.js +39 -0
  171. package/src/components/Collection/GroupControl.js +39 -0
  172. package/src/components/Collection/NestedCollection.js +330 -0
  173. package/src/components/Collection/Sidebar.js +136 -0
  174. package/src/components/Collection/SortControl.js +68 -0
  175. package/src/components/Collection/ViewStyleControl.js +50 -0
  176. package/src/components/Collection/__tests__/Collection.spec.js +75 -0
  177. package/src/components/Collection/__tests__/NestedCollection.spec.js +445 -0
  178. package/src/components/Collection/__tests__/Sidebar.spec.js +87 -0
  179. package/src/components/Collection/__tests__/__snapshots__/Collection.spec.js.snap +144 -0
  180. package/src/components/Collection/__tests__/__snapshots__/NestedCollection.spec.js.snap +550 -0
  181. package/src/components/Collection/__tests__/__snapshots__/Sidebar.spec.js.snap +312 -0
  182. package/src/components/Editor/Editor.js +497 -0
  183. package/src/components/Editor/EditorControlPane/EditorControl.js +452 -0
  184. package/src/components/Editor/EditorControlPane/EditorControlPane.js +269 -0
  185. package/src/components/Editor/EditorControlPane/Widget.js +384 -0
  186. package/src/components/Editor/EditorInterface.js +444 -0
  187. package/src/components/Editor/EditorPreviewPane/EditorPreview.js +40 -0
  188. package/src/components/Editor/EditorPreviewPane/EditorPreviewContent.js +74 -0
  189. package/src/components/Editor/EditorPreviewPane/EditorPreviewPane.js +333 -0
  190. package/src/components/Editor/EditorPreviewPane/PreviewHOC.js +33 -0
  191. package/src/components/Editor/EditorToolbar.js +691 -0
  192. package/src/components/Editor/__tests__/Editor.spec.js +221 -0
  193. package/src/components/Editor/__tests__/EditorToolbar.spec.js +120 -0
  194. package/src/components/Editor/__tests__/__snapshots__/Editor.spec.js.snap +45 -0
  195. package/src/components/Editor/__tests__/__snapshots__/EditorToolbar.spec.js.snap +4233 -0
  196. package/src/components/Editor/withWorkflow.js +61 -0
  197. package/src/components/EditorWidgets/Unknown/UnknownControl.js +17 -0
  198. package/src/components/EditorWidgets/Unknown/UnknownPreview.js +19 -0
  199. package/src/components/EditorWidgets/index.js +5 -0
  200. package/src/components/MediaLibrary/EmptyMessage.js +28 -0
  201. package/src/components/MediaLibrary/MediaLibrary.js +411 -0
  202. package/src/components/MediaLibrary/MediaLibraryButtons.js +136 -0
  203. package/src/components/MediaLibrary/MediaLibraryCard.js +128 -0
  204. package/src/components/MediaLibrary/MediaLibraryCardGrid.js +199 -0
  205. package/src/components/MediaLibrary/MediaLibraryHeader.js +48 -0
  206. package/src/components/MediaLibrary/MediaLibraryModal.js +200 -0
  207. package/src/components/MediaLibrary/MediaLibrarySearch.js +61 -0
  208. package/src/components/MediaLibrary/MediaLibraryTop.js +143 -0
  209. package/src/components/MediaLibrary/__tests__/MediaLibraryButtons.spec.js +45 -0
  210. package/src/components/MediaLibrary/__tests__/MediaLibraryCard.spec.js +49 -0
  211. package/src/components/MediaLibrary/__tests__/__snapshots__/MediaLibraryCard.spec.js.snap +264 -0
  212. package/src/components/UI/DragDrop.js +66 -0
  213. package/src/components/UI/ErrorBoundary.js +214 -0
  214. package/src/components/UI/FileUploadButton.js +24 -0
  215. package/src/components/UI/Modal.js +112 -0
  216. package/src/components/UI/Notifications.tsx +83 -0
  217. package/src/components/UI/SettingsDropdown.js +103 -0
  218. package/src/components/UI/__tests__/ErrorBoundary.spec.js +57 -0
  219. package/src/components/UI/index.js +6 -0
  220. package/src/components/Workflow/Workflow.js +169 -0
  221. package/src/components/Workflow/WorkflowCard.js +177 -0
  222. package/src/components/Workflow/WorkflowList.js +272 -0
  223. package/src/constants/__tests__/configSchema.spec.js +611 -0
  224. package/src/constants/collectionTypes.ts +2 -0
  225. package/src/constants/collectionViews.js +2 -0
  226. package/src/constants/commitProps.ts +2 -0
  227. package/src/constants/configSchema.js +441 -0
  228. package/src/constants/fieldInference.tsx +78 -0
  229. package/src/constants/publishModes.ts +22 -0
  230. package/src/constants/validationErrorTypes.js +6 -0
  231. package/src/formats/__tests__/formats.spec.js +87 -0
  232. package/src/formats/__tests__/frontmatter.spec.js +429 -0
  233. package/src/formats/__tests__/toml.spec.js +9 -0
  234. package/src/formats/__tests__/yaml.spec.js +162 -0
  235. package/src/formats/formats.ts +97 -0
  236. package/src/formats/frontmatter.ts +150 -0
  237. package/src/formats/helpers.ts +14 -0
  238. package/src/formats/json.ts +9 -0
  239. package/src/formats/toml.ts +33 -0
  240. package/src/formats/yaml.ts +58 -0
  241. package/src/index.js +8 -0
  242. package/src/integrations/index.js +35 -0
  243. package/src/integrations/providers/algolia/implementation.js +176 -0
  244. package/src/integrations/providers/assetStore/implementation.js +148 -0
  245. package/src/lib/__tests__/formatters.spec.js +751 -0
  246. package/src/lib/__tests__/i18n.spec.js +792 -0
  247. package/src/lib/__tests__/phrases.spec.js +119 -0
  248. package/src/lib/__tests__/registry.spec.js +261 -0
  249. package/src/lib/__tests__/serializeEntryValues.spec.js +22 -0
  250. package/src/lib/__tests__/urlHelper.spec.js +138 -0
  251. package/src/lib/consoleError.js +7 -0
  252. package/src/lib/formatters.ts +286 -0
  253. package/src/lib/i18n.ts +454 -0
  254. package/src/lib/phrases.js +8 -0
  255. package/src/lib/polyfill.js +9 -0
  256. package/src/lib/registry.js +312 -0
  257. package/src/lib/serializeEntryValues.js +75 -0
  258. package/src/lib/stega.ts +145 -0
  259. package/src/lib/textHelper.js +11 -0
  260. package/src/lib/urlHelper.ts +128 -0
  261. package/src/mediaLibrary.ts +51 -0
  262. package/src/reducers/__tests__/auth.spec.ts +38 -0
  263. package/src/reducers/__tests__/collections.spec.js +610 -0
  264. package/src/reducers/__tests__/config.spec.js +38 -0
  265. package/src/reducers/__tests__/entries.spec.js +694 -0
  266. package/src/reducers/__tests__/entryDraft.spec.js +297 -0
  267. package/src/reducers/__tests__/globalUI.js +43 -0
  268. package/src/reducers/__tests__/integrations.spec.ts +76 -0
  269. package/src/reducers/__tests__/mediaLibrary.spec.js +154 -0
  270. package/src/reducers/__tests__/medias.spec.ts +49 -0
  271. package/src/reducers/auth.ts +46 -0
  272. package/src/reducers/collections.ts +535 -0
  273. package/src/reducers/combinedReducer.ts +11 -0
  274. package/src/reducers/config.ts +38 -0
  275. package/src/reducers/cursors.js +36 -0
  276. package/src/reducers/deploys.ts +52 -0
  277. package/src/reducers/editorialWorkflow.ts +163 -0
  278. package/src/reducers/entries.ts +819 -0
  279. package/src/reducers/entryDraft.js +260 -0
  280. package/src/reducers/globalUI.ts +45 -0
  281. package/src/reducers/index.ts +82 -0
  282. package/src/reducers/integrations.ts +59 -0
  283. package/src/reducers/mediaLibrary.ts +296 -0
  284. package/src/reducers/medias.ts +66 -0
  285. package/src/reducers/notifications.ts +52 -0
  286. package/src/reducers/search.ts +111 -0
  287. package/src/reducers/status.ts +40 -0
  288. package/src/redux/index.ts +18 -0
  289. package/src/redux/middleware/waitUntilAction.ts +64 -0
  290. package/src/routing/__tests__/history.spec.ts +49 -0
  291. package/src/routing/history.ts +17 -0
  292. package/src/types/diacritics.d.ts +1 -0
  293. package/src/types/global.d.ts +8 -0
  294. package/src/types/immutable.ts +49 -0
  295. package/src/types/redux.ts +827 -0
  296. package/src/types/tomlify-j0.4.d.ts +13 -0
  297. package/src/valueObjects/AssetProxy.ts +48 -0
  298. package/src/valueObjects/EditorComponent.js +38 -0
  299. package/src/valueObjects/Entry.ts +63 -0
@@ -0,0 +1,694 @@
1
+ import { OrderedMap, fromJS } from 'immutable';
2
+
3
+ import * as actions from '../../actions/entries';
4
+ import reducer, {
5
+ selectMediaFolder,
6
+ selectMediaFilePath,
7
+ selectMediaFilePublicPath,
8
+ selectEntries,
9
+ } from '../entries';
10
+
11
+ const initialState = OrderedMap({
12
+ posts: fromJS({ name: 'posts' }),
13
+ });
14
+
15
+ describe('entries', () => {
16
+ describe('reducer', () => {
17
+ it('should mark entries as fetching', () => {
18
+ expect(reducer(initialState, actions.entriesLoading(fromJS({ name: 'posts' })))).toEqual(
19
+ OrderedMap(
20
+ fromJS({
21
+ posts: { name: 'posts' },
22
+ pages: {
23
+ posts: { isFetching: true },
24
+ },
25
+ }),
26
+ ),
27
+ );
28
+ });
29
+
30
+ it('should handle loaded entries', () => {
31
+ const entries = [
32
+ { slug: 'a', path: '' },
33
+ { slug: 'b', title: 'B' },
34
+ ];
35
+ expect(
36
+ reducer(initialState, actions.entriesLoaded(fromJS({ name: 'posts' }), entries, 0)),
37
+ ).toEqual(
38
+ OrderedMap(
39
+ fromJS({
40
+ posts: { name: 'posts' },
41
+ entities: {
42
+ 'posts.a': { slug: 'a', path: '', isFetching: false },
43
+ 'posts.b': { slug: 'b', title: 'B', isFetching: false },
44
+ },
45
+ pages: {
46
+ posts: {
47
+ page: 0,
48
+ ids: ['a', 'b'],
49
+ },
50
+ },
51
+ }),
52
+ ),
53
+ );
54
+ });
55
+
56
+ it('should handle loaded entry', () => {
57
+ const entry = { slug: 'a', path: '' };
58
+ expect(reducer(initialState, actions.entryLoaded(fromJS({ name: 'posts' }), entry))).toEqual(
59
+ OrderedMap(
60
+ fromJS({
61
+ posts: { name: 'posts' },
62
+ entities: {
63
+ 'posts.a': { slug: 'a', path: '' },
64
+ },
65
+ pages: {
66
+ posts: {
67
+ ids: ['a'],
68
+ },
69
+ },
70
+ }),
71
+ ),
72
+ );
73
+ });
74
+ });
75
+
76
+ describe('selectMediaFolder', () => {
77
+ it("should return global media folder when collection doesn't specify media_folder", () => {
78
+ expect(
79
+ selectMediaFolder(
80
+ { media_folder: 'static/media' },
81
+ fromJS({ name: 'posts' }),
82
+ undefined,
83
+ undefined,
84
+ ),
85
+ ).toEqual('static/media');
86
+ });
87
+
88
+ it('should return collection folder when collection specifies media_folder and entry is undefined', () => {
89
+ expect(
90
+ selectMediaFolder(
91
+ { media_folder: 'static/media' },
92
+ fromJS({ name: 'posts', folder: 'posts', media_folder: '' }),
93
+ undefined,
94
+ undefined,
95
+ ),
96
+ ).toEqual('posts');
97
+ });
98
+
99
+ it('should return relative media folder when collection specifies media_folder and entry path is not null', () => {
100
+ expect(
101
+ selectMediaFolder(
102
+ { media_folder: 'static/media' },
103
+ fromJS({ name: 'posts', folder: 'posts', media_folder: '' }),
104
+ fromJS({ path: 'posts/title/index.md' }),
105
+ undefined,
106
+ ),
107
+ ).toEqual('posts/title');
108
+ });
109
+
110
+ it('should resolve collection relative media folder', () => {
111
+ expect(
112
+ selectMediaFolder(
113
+ fromJS({ media_folder: 'static/media' }),
114
+ fromJS({ name: 'posts', folder: 'posts', media_folder: '../' }),
115
+ fromJS({ path: 'posts/title/index.md' }),
116
+ undefined,
117
+ ),
118
+ ).toEqual('posts');
119
+ });
120
+
121
+ it('should resolve field relative media folder', () => {
122
+ const field = fromJS({ media_folder: '' });
123
+ expect(
124
+ selectMediaFolder(
125
+ { media_folder: '/static/img' },
126
+ fromJS({
127
+ name: 'other',
128
+ folder: 'other',
129
+ fields: [field],
130
+ media_folder: '../',
131
+ }),
132
+ fromJS({ path: 'src/other/other.md', data: {} }),
133
+ field,
134
+ ),
135
+ ).toEqual('src/other');
136
+ });
137
+
138
+ it('should return collection absolute media folder without leading slash', () => {
139
+ expect(
140
+ selectMediaFolder(
141
+ { media_folder: '/static/Images' },
142
+ fromJS({
143
+ name: 'getting-started',
144
+ folder: 'src/docs/getting-started',
145
+ media_folder: '/static/images/docs/getting-started',
146
+ }),
147
+ fromJS({}),
148
+ undefined,
149
+ ),
150
+ ).toEqual('static/images/docs/getting-started');
151
+ });
152
+
153
+ it('should compile relative media folder template', () => {
154
+ const slugConfig = {
155
+ encoding: 'unicode',
156
+ clean_accents: false,
157
+ sanitize_replacement: '-',
158
+ };
159
+
160
+ const entry = fromJS({
161
+ path: 'content/en/hosting-and-deployment/deployment-with-nanobox.md',
162
+ data: { title: 'Deployment With NanoBox', category: 'Hosting And Deployment' },
163
+ });
164
+ const collection = fromJS({
165
+ name: 'posts',
166
+ folder: 'content',
167
+ media_folder: '../../../{{media_folder}}/{{category}}/{{slug}}',
168
+ fields: [{ name: 'title', widget: 'string' }],
169
+ });
170
+
171
+ expect(
172
+ selectMediaFolder(
173
+ { media_folder: 'static/media', slug: slugConfig },
174
+ collection,
175
+ entry,
176
+ undefined,
177
+ ),
178
+ ).toEqual('static/media/hosting-and-deployment/deployment-with-nanobox');
179
+ });
180
+
181
+ it('should compile absolute media folder template', () => {
182
+ const slugConfig = {
183
+ encoding: 'unicode',
184
+ clean_accents: false,
185
+ sanitize_replacement: '-',
186
+ };
187
+
188
+ const entry = fromJS({
189
+ data: { title: 'Overview' },
190
+ });
191
+ const collection = fromJS({
192
+ name: 'extending',
193
+ folder: 'src/docs/extending',
194
+ media_folder: '{{media_folder}}/docs/extending',
195
+ fields: [{ name: 'title', widget: 'string' }],
196
+ });
197
+
198
+ expect(
199
+ selectMediaFolder(
200
+ { media_folder: '/static/images', slug: slugConfig },
201
+ collection,
202
+ entry,
203
+ undefined,
204
+ ),
205
+ ).toEqual('static/images/docs/extending');
206
+ });
207
+
208
+ it('should compile field media folder template', () => {
209
+ const slugConfig = {
210
+ encoding: 'unicode',
211
+ clean_accents: false,
212
+ sanitize_replacement: '-',
213
+ };
214
+
215
+ const entry = fromJS({
216
+ path: 'content/en/hosting-and-deployment/deployment-with-nanobox.md',
217
+ data: { title: 'Deployment With NanoBox', category: 'Hosting And Deployment' },
218
+ });
219
+ const collection = fromJS({
220
+ name: 'posts',
221
+ folder: 'content',
222
+ fields: [
223
+ {
224
+ name: 'title',
225
+ widget: 'string',
226
+ media_folder: '../../../{{media_folder}}/{{category}}/{{slug}}',
227
+ },
228
+ ],
229
+ });
230
+
231
+ expect(
232
+ selectMediaFolder(
233
+ { media_folder: 'static/media', slug: slugConfig },
234
+ collection,
235
+ entry,
236
+ collection.get('fields').get(0),
237
+ ),
238
+ ).toEqual('static/media/hosting-and-deployment/deployment-with-nanobox');
239
+ });
240
+
241
+ it('should handle double slashes', () => {
242
+ const slugConfig = {
243
+ encoding: 'unicode',
244
+ clean_accents: false,
245
+ sanitize_replacement: '-',
246
+ };
247
+
248
+ const entry = fromJS({
249
+ path: 'content/en/hosting-and-deployment/deployment-with-nanobox.md',
250
+ data: { title: 'Deployment With NanoBox', category: 'Hosting And Deployment' },
251
+ });
252
+
253
+ const collection = fromJS({
254
+ name: 'posts',
255
+ folder: 'content',
256
+ media_folder: '{{media_folder}}/blog',
257
+ fields: [{ name: 'title', widget: 'string' }],
258
+ });
259
+
260
+ expect(
261
+ selectMediaFolder(
262
+ { media_folder: '/static/img/', slug: slugConfig },
263
+ collection,
264
+ entry,
265
+ undefined,
266
+ ),
267
+ ).toEqual('static/img/blog');
268
+
269
+ expect(
270
+ selectMediaFolder(
271
+ { media_folder: 'static/img/', slug: slugConfig },
272
+ collection,
273
+ entry,
274
+ undefined,
275
+ ),
276
+ ).toEqual('content/en/hosting-and-deployment/static/img/blog');
277
+ });
278
+
279
+ it('should handle file media_folder', () => {
280
+ expect(
281
+ selectMediaFolder(
282
+ { media_folder: 'static/media' },
283
+ fromJS({ name: 'posts', files: [{ name: 'index', media_folder: '/static/images/' }] }),
284
+ fromJS({ path: 'posts/title/index.md', slug: 'index' }),
285
+ undefined,
286
+ ),
287
+ ).toBe('static/images');
288
+ });
289
+
290
+ it('should cascade media_folders', () => {
291
+ const mainImageField = fromJS({ name: 'main_image' });
292
+ const logoField = fromJS({ name: 'logo', media_folder: '{{media_folder}}/logos/' });
293
+ const nestedField3 = fromJS({ name: 'nested', media_folder: '{{media_folder}}/nested3/' });
294
+ const nestedField2 = fromJS({
295
+ name: 'nested',
296
+ media_folder: '{{media_folder}}/nested2/',
297
+ types: [nestedField3],
298
+ });
299
+ const nestedField1 = fromJS({
300
+ name: 'nested',
301
+ media_folder: '{{media_folder}}/nested1/',
302
+ fields: [nestedField2],
303
+ });
304
+
305
+ const args = [
306
+ { media_folder: '/static/img' },
307
+ fromJS({
308
+ name: 'general',
309
+ media_folder: '{{media_folder}}/general/',
310
+ files: [
311
+ {
312
+ name: 'customers',
313
+ media_folder: '{{media_folder}}/customers/',
314
+ fields: [
315
+ mainImageField,
316
+ logoField,
317
+ { media_folder: '{{media_folder}}/nested', field: nestedField1 },
318
+ ],
319
+ },
320
+ ],
321
+ }),
322
+ fromJS({ path: 'src/customers/customers.md', slug: 'customers', data: { title: 'title' } }),
323
+ ];
324
+
325
+ expect(selectMediaFolder(...args, mainImageField)).toBe('static/img/general/customers');
326
+ expect(selectMediaFolder(...args, logoField)).toBe('static/img/general/customers/logos');
327
+ expect(selectMediaFolder(...args, nestedField1)).toBe(
328
+ 'static/img/general/customers/nested/nested1',
329
+ );
330
+ expect(selectMediaFolder(...args, nestedField2)).toBe(
331
+ 'static/img/general/customers/nested/nested1/nested2',
332
+ );
333
+ expect(selectMediaFolder(...args, nestedField3)).toBe(
334
+ 'static/img/general/customers/nested/nested1/nested2/nested3',
335
+ );
336
+ });
337
+ });
338
+
339
+ describe('selectMediaFilePath', () => {
340
+ it('should return absolute URL as is', () => {
341
+ expect(selectMediaFilePath(null, null, null, 'https://www.netlify.com/image.png')).toBe(
342
+ 'https://www.netlify.com/image.png',
343
+ );
344
+ });
345
+
346
+ it('should resolve path from global media folder for collection with no media folder', () => {
347
+ expect(
348
+ selectMediaFilePath(
349
+ { media_folder: 'static/media' },
350
+ fromJS({ name: 'posts', folder: 'posts' }),
351
+ undefined,
352
+ 'image.png',
353
+ undefined,
354
+ ),
355
+ ).toBe('static/media/image.png');
356
+ });
357
+
358
+ it('should resolve path from collection media folder for collection with media folder', () => {
359
+ expect(
360
+ selectMediaFilePath(
361
+ { media_folder: 'static/media' },
362
+ fromJS({ name: 'posts', folder: 'posts', media_folder: '' }),
363
+ undefined,
364
+ 'image.png',
365
+ undefined,
366
+ ),
367
+ ).toBe('posts/image.png');
368
+ });
369
+
370
+ it('should handle relative media_folder', () => {
371
+ expect(
372
+ selectMediaFilePath(
373
+ { media_folder: 'static/media' },
374
+ fromJS({ name: 'posts', folder: 'posts', media_folder: '../../static/media/' }),
375
+ fromJS({ path: 'posts/title/index.md' }),
376
+ 'image.png',
377
+ undefined,
378
+ ),
379
+ ).toBe('static/media/image.png');
380
+ });
381
+
382
+ it('should handle field media_folder', () => {
383
+ const field = fromJS({ media_folder: '../../static/media/' });
384
+ expect(
385
+ selectMediaFilePath(
386
+ { media_folder: 'static/media' },
387
+ fromJS({ name: 'posts', folder: 'posts', fields: [field] }),
388
+ fromJS({ path: 'posts/title/index.md' }),
389
+ 'image.png',
390
+ field,
391
+ ),
392
+ ).toBe('static/media/image.png');
393
+ });
394
+ });
395
+
396
+ describe('selectMediaFilePublicPath', () => {
397
+ it('should return absolute URL as is', () => {
398
+ expect(selectMediaFilePublicPath(null, null, 'https://www.netlify.com/image.png')).toBe(
399
+ 'https://www.netlify.com/image.png',
400
+ );
401
+ });
402
+
403
+ it('should resolve path from public folder for collection with no media folder', () => {
404
+ expect(
405
+ selectMediaFilePublicPath(
406
+ { public_folder: '/media' },
407
+ null,
408
+ '/media/image.png',
409
+ undefined,
410
+ undefined,
411
+ ),
412
+ ).toBe('/media/image.png');
413
+ });
414
+
415
+ it('should resolve path from collection public folder for collection with public folder', () => {
416
+ expect(
417
+ selectMediaFilePublicPath(
418
+ { public_folder: '/media' },
419
+ fromJS({ name: 'posts', folder: 'posts', public_folder: '' }),
420
+ 'image.png',
421
+ undefined,
422
+ undefined,
423
+ ),
424
+ ).toBe('image.png');
425
+ });
426
+
427
+ it('should handle relative public_folder', () => {
428
+ expect(
429
+ selectMediaFilePublicPath(
430
+ { public_folder: '/media' },
431
+ fromJS({ name: 'posts', folder: 'posts', public_folder: '../../static/media/' }),
432
+ 'image.png',
433
+ undefined,
434
+ undefined,
435
+ ),
436
+ ).toBe('../../static/media/image.png');
437
+ });
438
+
439
+ it('should handle absolute public_folder', () => {
440
+ expect(
441
+ selectMediaFilePublicPath(
442
+ { public_folder: 'https://www.netlify.com/media' },
443
+ fromJS({
444
+ name: 'posts',
445
+ folder: 'posts',
446
+ public_folder: 'https://www.netlify.com/media',
447
+ }),
448
+ 'image.png',
449
+ undefined,
450
+ undefined,
451
+ ),
452
+ ).toBe('https://www.netlify.com/media/image.png');
453
+ });
454
+
455
+ it('should compile collection public folder template', () => {
456
+ const slugConfig = {
457
+ encoding: 'unicode',
458
+ clean_accents: false,
459
+ sanitize_replacement: '-',
460
+ };
461
+
462
+ const entry = fromJS({
463
+ path: 'content/en/hosting-and-deployment/deployment-with-nanobox.md',
464
+ data: { title: 'Deployment With NanoBox', category: 'Hosting And Deployment' },
465
+ });
466
+ const collection = fromJS({
467
+ name: 'posts',
468
+ folder: 'content',
469
+ public_folder: '/{{public_folder}}/{{category}}/{{slug}}',
470
+ fields: [{ name: 'title', widget: 'string' }],
471
+ });
472
+
473
+ expect(
474
+ selectMediaFilePublicPath(
475
+ { public_folder: 'static/media', slug: slugConfig },
476
+ collection,
477
+ 'image.png',
478
+ entry,
479
+ undefined,
480
+ ),
481
+ ).toEqual('/static/media/hosting-and-deployment/deployment-with-nanobox/image.png');
482
+ });
483
+
484
+ it('should compile field public folder template', () => {
485
+ const slugConfig = {
486
+ encoding: 'unicode',
487
+ clean_accents: false,
488
+ sanitize_replacement: '-',
489
+ };
490
+
491
+ const entry = fromJS({
492
+ path: 'content/en/hosting-and-deployment/deployment-with-nanobox.md',
493
+ data: { title: 'Deployment With NanoBox', category: 'Hosting And Deployment' },
494
+ });
495
+
496
+ const field = fromJS({
497
+ name: 'title',
498
+ widget: 'string',
499
+ public_folder: '/{{public_folder}}/{{category}}/{{slug}}',
500
+ });
501
+ const collection = fromJS({
502
+ name: 'posts',
503
+ folder: 'content',
504
+ fields: [field],
505
+ });
506
+
507
+ expect(
508
+ selectMediaFilePublicPath(
509
+ { public_folder: 'static/media', slug: slugConfig },
510
+ collection,
511
+ 'image.png',
512
+ entry,
513
+ field,
514
+ ),
515
+ ).toEqual('/static/media/hosting-and-deployment/deployment-with-nanobox/image.png');
516
+ });
517
+
518
+ it('should handle double slashes', () => {
519
+ const slugConfig = {
520
+ encoding: 'unicode',
521
+ clean_accents: false,
522
+ sanitize_replacement: '-',
523
+ };
524
+
525
+ const entry = fromJS({
526
+ path: 'content/en/hosting-and-deployment/deployment-with-nanobox.md',
527
+ data: { title: 'Deployment With NanoBox', category: 'Hosting And Deployment' },
528
+ });
529
+
530
+ const field = fromJS({
531
+ name: 'title',
532
+ widget: 'string',
533
+ public_folder: '/{{public_folder}}/{{category}}/{{slug}}',
534
+ });
535
+ const collection = fromJS({
536
+ name: 'posts',
537
+ folder: 'content',
538
+ fields: [field],
539
+ });
540
+
541
+ expect(
542
+ selectMediaFilePublicPath(
543
+ { public_folder: 'static/media/', slug: slugConfig },
544
+ collection,
545
+ 'image.png',
546
+ entry,
547
+ field,
548
+ ),
549
+ ).toEqual('/static/media/hosting-and-deployment/deployment-with-nanobox/image.png');
550
+ });
551
+
552
+ it('should handle file public_folder', () => {
553
+ const entry = fromJS({
554
+ path: 'src/posts/index.md',
555
+ slug: 'index',
556
+ });
557
+
558
+ const collection = fromJS({
559
+ name: 'posts',
560
+ files: [
561
+ {
562
+ name: 'index',
563
+ public_folder: '/images',
564
+ fields: [{ name: 'title', widget: 'string' }],
565
+ },
566
+ ],
567
+ });
568
+
569
+ expect(
570
+ selectMediaFilePublicPath(
571
+ { public_folder: 'static/media/' },
572
+ collection,
573
+ 'image.png',
574
+ entry,
575
+ undefined,
576
+ ),
577
+ ).toBe('/images/image.png');
578
+ });
579
+ });
580
+
581
+ describe('selectEntries', () => {
582
+ it('should return all entries', () => {
583
+ const state = fromJS({
584
+ entities: {
585
+ 'posts.1': { slug: '1' },
586
+ 'posts.2': { slug: '2' },
587
+ 'posts.3': { slug: '3' },
588
+ 'posts.4': { slug: '4' },
589
+ },
590
+ pages: { posts: { ids: ['1', '2', '3', '4'] } },
591
+ });
592
+ const collection = fromJS({
593
+ name: 'posts',
594
+ });
595
+
596
+ expect(selectEntries(state, collection)).toEqual(
597
+ fromJS([{ slug: '1' }, { slug: '2' }, { slug: '3' }, { slug: '4' }]),
598
+ );
599
+ });
600
+ });
601
+
602
+ it('should return sorted entries entries by field', () => {
603
+ const state = fromJS({
604
+ entities: {
605
+ 'posts.1': { slug: '1', data: { title: '1' } },
606
+ 'posts.2': { slug: '2', data: { title: '2' } },
607
+ 'posts.3': { slug: '3', data: { title: '3' } },
608
+ 'posts.4': { slug: '4', data: { title: '4' } },
609
+ },
610
+ pages: { posts: { ids: ['1', '2', '3', '4'] } },
611
+ sort: { posts: { title: { key: 'title', direction: 'Descending' } } },
612
+ });
613
+ const collection = fromJS({
614
+ name: 'posts',
615
+ });
616
+
617
+ expect(selectEntries(state, collection)).toEqual(
618
+ fromJS([
619
+ { slug: '4', data: { title: '4' } },
620
+ { slug: '3', data: { title: '3' } },
621
+ { slug: '2', data: { title: '2' } },
622
+ { slug: '1', data: { title: '1' } },
623
+ ]),
624
+ );
625
+ });
626
+
627
+ it('should return sorted entries entries by nested field', () => {
628
+ const state = fromJS({
629
+ entities: {
630
+ 'posts.1': { slug: '1', data: { title: '1', nested: { date: 4 } } },
631
+ 'posts.2': { slug: '2', data: { title: '2', nested: { date: 3 } } },
632
+ 'posts.3': { slug: '3', data: { title: '3', nested: { date: 2 } } },
633
+ 'posts.4': { slug: '4', data: { title: '4', nested: { date: 1 } } },
634
+ },
635
+ pages: { posts: { ids: ['1', '2', '3', '4'] } },
636
+ sort: { posts: { title: { key: 'nested.date', direction: 'Ascending' } } },
637
+ });
638
+ const collection = fromJS({
639
+ name: 'posts',
640
+ });
641
+
642
+ expect(selectEntries(state, collection)).toEqual(
643
+ fromJS([
644
+ { slug: '4', data: { title: '4', nested: { date: 1 } } },
645
+ { slug: '3', data: { title: '3', nested: { date: 2 } } },
646
+ { slug: '2', data: { title: '2', nested: { date: 3 } } },
647
+ { slug: '1', data: { title: '1', nested: { date: 4 } } },
648
+ ]),
649
+ );
650
+ });
651
+
652
+ it('should return filtered entries entries by field', () => {
653
+ const state = fromJS({
654
+ entities: {
655
+ 'posts.1': { slug: '1', data: { title: '1' } },
656
+ 'posts.2': { slug: '2', data: { title: '2' } },
657
+ 'posts.3': { slug: '3', data: { title: '3' } },
658
+ 'posts.4': { slug: '4', data: { title: '4' } },
659
+ },
660
+ pages: { posts: { ids: ['1', '2', '3', '4'] } },
661
+ filter: { posts: { title__1: { field: 'title', pattern: '4', active: true } } },
662
+ });
663
+ const collection = fromJS({
664
+ name: 'posts',
665
+ });
666
+
667
+ expect(selectEntries(state, collection)).toEqual(fromJS([{ slug: '4', data: { title: '4' } }]));
668
+ });
669
+
670
+ it('should return filtered entries entries by nested field', () => {
671
+ const state = fromJS({
672
+ entities: {
673
+ 'posts.1': { slug: '1', data: { title: '1', nested: { draft: true } } },
674
+ 'posts.2': { slug: '2', data: { title: '2', nested: { draft: true } } },
675
+ 'posts.3': { slug: '3', data: { title: '3', nested: { draft: false } } },
676
+ 'posts.4': { slug: '4', data: { title: '4', nested: { draft: false } } },
677
+ },
678
+ pages: { posts: { ids: ['1', '2', '3', '4'] } },
679
+ filter: {
680
+ posts: { 'nested.draft__false': { field: 'nested.draft', pattern: false, active: true } },
681
+ },
682
+ });
683
+ const collection = fromJS({
684
+ name: 'posts',
685
+ });
686
+
687
+ expect(selectEntries(state, collection)).toEqual(
688
+ fromJS([
689
+ { slug: '3', data: { title: '3', nested: { draft: false } } },
690
+ { slug: '4', data: { title: '4', nested: { draft: false } } },
691
+ ]),
692
+ );
693
+ });
694
+ });