@evfrenkel/decap-cms-core 3.13.0-image-conversions.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 (306) hide show
  1. package/README.md +9 -0
  2. package/dist/20.decap-cms-core.js +2 -0
  3. package/dist/20.decap-cms-core.js.map +1 -0
  4. package/dist/3802306e7b58a11862fb.wasm +0 -0
  5. package/dist/@evfrenkel/20.decap-cms-core.js +2 -0
  6. package/dist/@evfrenkel/20.decap-cms-core.js.map +1 -0
  7. package/dist/@evfrenkel/decap-cms-core.js +44 -0
  8. package/dist/@evfrenkel/decap-cms-core.js.LICENSE.txt +126 -0
  9. package/dist/@evfrenkel/decap-cms-core.js.map +1 -0
  10. package/dist/decap-cms-core.js +47 -0
  11. package/dist/decap-cms-core.js.LICENSE.txt +126 -0
  12. package/dist/decap-cms-core.js.map +1 -0
  13. package/dist/esm/actions/auth.js +97 -0
  14. package/dist/esm/actions/collections.js +15 -0
  15. package/dist/esm/actions/config.js +503 -0
  16. package/dist/esm/actions/deploys.js +80 -0
  17. package/dist/esm/actions/editorialWorkflow.js +480 -0
  18. package/dist/esm/actions/entries.js +876 -0
  19. package/dist/esm/actions/media.js +147 -0
  20. package/dist/esm/actions/mediaLibrary.js +599 -0
  21. package/dist/esm/actions/notifications.js +21 -0
  22. package/dist/esm/actions/search.js +149 -0
  23. package/dist/esm/actions/status.js +74 -0
  24. package/dist/esm/actions/waitUntil.js +32 -0
  25. package/dist/esm/backend.js +1090 -0
  26. package/dist/esm/bootstrap.js +101 -0
  27. package/dist/esm/components/App/App.js +296 -0
  28. package/dist/esm/components/App/Header.js +172 -0
  29. package/dist/esm/components/App/NotFoundPage.js +19 -0
  30. package/dist/esm/components/Collection/Collection.js +198 -0
  31. package/dist/esm/components/Collection/CollectionControls.js +47 -0
  32. package/dist/esm/components/Collection/CollectionSearch.js +222 -0
  33. package/dist/esm/components/Collection/CollectionTop.js +68 -0
  34. package/dist/esm/components/Collection/ControlButton.js +17 -0
  35. package/dist/esm/components/Collection/Entries/Entries.js +73 -0
  36. package/dist/esm/components/Collection/Entries/EntriesCollection.js +241 -0
  37. package/dist/esm/components/Collection/Entries/EntriesSearch.js +113 -0
  38. package/dist/esm/components/Collection/Entries/EntryCard.js +192 -0
  39. package/dist/esm/components/Collection/Entries/EntryListing.js +143 -0
  40. package/dist/esm/components/Collection/FilterControl.js +33 -0
  41. package/dist/esm/components/Collection/GroupControl.js +33 -0
  42. package/dist/esm/components/Collection/NestedCollection.js +308 -0
  43. package/dist/esm/components/Collection/Sidebar.js +91 -0
  44. package/dist/esm/components/Collection/SortControl.js +59 -0
  45. package/dist/esm/components/Collection/ViewStyleControl.js +41 -0
  46. package/dist/esm/components/Editor/Editor.js +466 -0
  47. package/dist/esm/components/Editor/EditorControlPane/EditorControl.js +398 -0
  48. package/dist/esm/components/Editor/EditorControlPane/EditorControlPane.js +254 -0
  49. package/dist/esm/components/Editor/EditorControlPane/Widget.js +374 -0
  50. package/dist/esm/components/Editor/EditorInterface.js +386 -0
  51. package/dist/esm/components/Editor/EditorPreviewPane/EditorPreview.js +47 -0
  52. package/dist/esm/components/Editor/EditorPreviewPane/EditorPreviewContent.js +67 -0
  53. package/dist/esm/components/Editor/EditorPreviewPane/EditorPreviewPane.js +306 -0
  54. package/dist/esm/components/Editor/EditorPreviewPane/PreviewHOC.js +27 -0
  55. package/dist/esm/components/Editor/EditorToolbar.js +554 -0
  56. package/dist/esm/components/Editor/withWorkflow.js +56 -0
  57. package/dist/esm/components/EditorWidgets/Unknown/UnknownControl.js +18 -0
  58. package/dist/esm/components/EditorWidgets/Unknown/UnknownPreview.js +20 -0
  59. package/dist/esm/components/EditorWidgets/index.js +4 -0
  60. package/dist/esm/components/MediaLibrary/EmptyMessage.js +22 -0
  61. package/dist/esm/components/MediaLibrary/MediaLibrary.js +446 -0
  62. package/dist/esm/components/MediaLibrary/MediaLibraryButtons.js +92 -0
  63. package/dist/esm/components/MediaLibrary/MediaLibraryCard.js +99 -0
  64. package/dist/esm/components/MediaLibrary/MediaLibraryCardGrid.js +198 -0
  65. package/dist/esm/components/MediaLibrary/MediaLibraryHeader.js +34 -0
  66. package/dist/esm/components/MediaLibrary/MediaLibraryModal.js +156 -0
  67. package/dist/esm/components/MediaLibrary/MediaLibrarySearch.js +51 -0
  68. package/dist/esm/components/MediaLibrary/MediaLibraryTop.js +124 -0
  69. package/dist/esm/components/UI/DragDrop.js +67 -0
  70. package/dist/esm/components/UI/ErrorBoundary.js +170 -0
  71. package/dist/esm/components/UI/FileUploadButton.js +27 -0
  72. package/dist/esm/components/UI/Modal.js +104 -0
  73. package/dist/esm/components/UI/Notifications.js +62 -0
  74. package/dist/esm/components/UI/SettingsDropdown.js +107 -0
  75. package/dist/esm/components/UI/index.js +6 -0
  76. package/dist/esm/components/Workflow/Workflow.js +133 -0
  77. package/dist/esm/components/Workflow/WorkflowCard.js +128 -0
  78. package/dist/esm/components/Workflow/WorkflowList.js +204 -0
  79. package/dist/esm/constants/collectionTypes.js +2 -0
  80. package/dist/esm/constants/collectionViews.js +2 -0
  81. package/dist/esm/constants/commitProps.js +2 -0
  82. package/dist/esm/constants/configSchema.js +695 -0
  83. package/dist/esm/constants/fieldInference.js +57 -0
  84. package/dist/esm/constants/publishModes.js +18 -0
  85. package/dist/esm/constants/validationErrorTypes.js +6 -0
  86. package/dist/esm/formats/formats.js +83 -0
  87. package/dist/esm/formats/frontmatter.js +146 -0
  88. package/dist/esm/formats/helpers.js +12 -0
  89. package/dist/esm/formats/json.js +8 -0
  90. package/dist/esm/formats/toml.js +32 -0
  91. package/dist/esm/formats/yaml.js +60 -0
  92. package/dist/esm/index.js +7 -0
  93. package/dist/esm/integrations/index.js +28 -0
  94. package/dist/esm/integrations/providers/algolia/implementation.js +174 -0
  95. package/dist/esm/integrations/providers/assetStore/implementation.js +165 -0
  96. package/dist/esm/lib/consoleError.js +3 -0
  97. package/dist/esm/lib/formatters.js +201 -0
  98. package/dist/esm/lib/i18n.js +372 -0
  99. package/dist/esm/lib/imageTransformations.js +143 -0
  100. package/dist/esm/lib/phrases.js +6 -0
  101. package/dist/esm/lib/polyfill.js +8 -0
  102. package/dist/esm/lib/registry.js +332 -0
  103. package/dist/esm/lib/serializeEntryValues.js +67 -0
  104. package/dist/esm/lib/stega.js +142 -0
  105. package/dist/esm/lib/textHelper.js +9 -0
  106. package/dist/esm/lib/urlHelper.js +129 -0
  107. package/dist/esm/mediaLibrary.js +37 -0
  108. package/dist/esm/reducers/auth.js +27 -0
  109. package/dist/esm/reducers/collections.js +428 -0
  110. package/dist/esm/reducers/combinedReducer.js +8 -0
  111. package/dist/esm/reducers/config.js +29 -0
  112. package/dist/esm/reducers/cursors.js +31 -0
  113. package/dist/esm/reducers/deploys.js +50 -0
  114. package/dist/esm/reducers/editorialWorkflow.js +83 -0
  115. package/dist/esm/reducers/entries.js +568 -0
  116. package/dist/esm/reducers/entryDraft.js +211 -0
  117. package/dist/esm/reducers/globalUI.js +25 -0
  118. package/dist/esm/reducers/index.js +66 -0
  119. package/dist/esm/reducers/integrations.js +53 -0
  120. package/dist/esm/reducers/mediaLibrary.js +252 -0
  121. package/dist/esm/reducers/medias.js +68 -0
  122. package/dist/esm/reducers/notifications.js +23 -0
  123. package/dist/esm/reducers/search.js +92 -0
  124. package/dist/esm/reducers/status.js +30 -0
  125. package/dist/esm/redux/index.js +7 -0
  126. package/dist/esm/redux/middleware/waitUntilAction.js +48 -0
  127. package/dist/esm/routing/history.js +12 -0
  128. package/dist/esm/types/diacritics.d.js +0 -0
  129. package/dist/esm/types/global.d.js +1 -0
  130. package/dist/esm/types/immutable.js +7 -0
  131. package/dist/esm/types/redux.js +14 -0
  132. package/dist/esm/types/tomlify-j0.4.d.js +0 -0
  133. package/dist/esm/valueObjects/AssetProxy.js +44 -0
  134. package/dist/esm/valueObjects/EditorComponent.js +34 -0
  135. package/dist/esm/valueObjects/Entry.js +20 -0
  136. package/index.d.ts +662 -0
  137. package/package.json +100 -0
  138. package/src/__tests__/backend.spec.js +1223 -0
  139. package/src/actions/__tests__/config.spec.js +1023 -0
  140. package/src/actions/__tests__/editorialWorkflow.spec.js +216 -0
  141. package/src/actions/__tests__/entries.spec.js +610 -0
  142. package/src/actions/__tests__/media.spec.ts +171 -0
  143. package/src/actions/__tests__/mediaLibrary.spec.js +462 -0
  144. package/src/actions/__tests__/search.spec.js +209 -0
  145. package/src/actions/auth.ts +127 -0
  146. package/src/actions/collections.ts +18 -0
  147. package/src/actions/config.ts +574 -0
  148. package/src/actions/deploys.ts +105 -0
  149. package/src/actions/editorialWorkflow.ts +567 -0
  150. package/src/actions/entries.ts +1070 -0
  151. package/src/actions/media.ts +139 -0
  152. package/src/actions/mediaLibrary.ts +639 -0
  153. package/src/actions/notifications.ts +36 -0
  154. package/src/actions/search.ts +221 -0
  155. package/src/actions/status.ts +99 -0
  156. package/src/actions/waitUntil.ts +49 -0
  157. package/src/backend.ts +1411 -0
  158. package/src/bootstrap.js +104 -0
  159. package/src/components/App/App.js +295 -0
  160. package/src/components/App/Header.js +291 -0
  161. package/src/components/App/NotFoundPage.js +23 -0
  162. package/src/components/Collection/Collection.js +210 -0
  163. package/src/components/Collection/CollectionControls.js +58 -0
  164. package/src/components/Collection/CollectionSearch.js +243 -0
  165. package/src/components/Collection/CollectionTop.js +81 -0
  166. package/src/components/Collection/ControlButton.js +27 -0
  167. package/src/components/Collection/Entries/Entries.js +82 -0
  168. package/src/components/Collection/Entries/EntriesCollection.js +277 -0
  169. package/src/components/Collection/Entries/EntriesSearch.js +102 -0
  170. package/src/components/Collection/Entries/EntryCard.js +256 -0
  171. package/src/components/Collection/Entries/EntryListing.js +151 -0
  172. package/src/components/Collection/Entries/__tests__/EntriesCollection.spec.js +163 -0
  173. package/src/components/Collection/Entries/__tests__/__snapshots__/EntriesCollection.spec.js.snap +46 -0
  174. package/src/components/Collection/FilterControl.js +39 -0
  175. package/src/components/Collection/GroupControl.js +39 -0
  176. package/src/components/Collection/NestedCollection.js +330 -0
  177. package/src/components/Collection/Sidebar.js +136 -0
  178. package/src/components/Collection/SortControl.js +68 -0
  179. package/src/components/Collection/ViewStyleControl.js +52 -0
  180. package/src/components/Collection/__tests__/Collection.spec.js +75 -0
  181. package/src/components/Collection/__tests__/NestedCollection.spec.js +445 -0
  182. package/src/components/Collection/__tests__/Sidebar.spec.js +87 -0
  183. package/src/components/Collection/__tests__/__snapshots__/Collection.spec.js.snap +144 -0
  184. package/src/components/Collection/__tests__/__snapshots__/NestedCollection.spec.js.snap +550 -0
  185. package/src/components/Collection/__tests__/__snapshots__/Sidebar.spec.js.snap +312 -0
  186. package/src/components/Editor/Editor.js +497 -0
  187. package/src/components/Editor/EditorControlPane/EditorControl.js +453 -0
  188. package/src/components/Editor/EditorControlPane/EditorControlPane.js +269 -0
  189. package/src/components/Editor/EditorControlPane/Widget.js +384 -0
  190. package/src/components/Editor/EditorInterface.js +444 -0
  191. package/src/components/Editor/EditorPreviewPane/EditorPreview.js +40 -0
  192. package/src/components/Editor/EditorPreviewPane/EditorPreviewContent.js +75 -0
  193. package/src/components/Editor/EditorPreviewPane/EditorPreviewPane.js +337 -0
  194. package/src/components/Editor/EditorPreviewPane/PreviewHOC.js +33 -0
  195. package/src/components/Editor/EditorToolbar.js +728 -0
  196. package/src/components/Editor/__tests__/Editor.spec.js +221 -0
  197. package/src/components/Editor/__tests__/EditorToolbar.spec.js +166 -0
  198. package/src/components/Editor/__tests__/__snapshots__/Editor.spec.js.snap +45 -0
  199. package/src/components/Editor/__tests__/__snapshots__/EditorToolbar.spec.js.snap +4265 -0
  200. package/src/components/Editor/withWorkflow.js +61 -0
  201. package/src/components/EditorWidgets/Unknown/UnknownControl.js +17 -0
  202. package/src/components/EditorWidgets/Unknown/UnknownPreview.js +19 -0
  203. package/src/components/EditorWidgets/index.js +5 -0
  204. package/src/components/MediaLibrary/EmptyMessage.js +28 -0
  205. package/src/components/MediaLibrary/MediaLibrary.js +411 -0
  206. package/src/components/MediaLibrary/MediaLibraryButtons.js +135 -0
  207. package/src/components/MediaLibrary/MediaLibraryCard.js +128 -0
  208. package/src/components/MediaLibrary/MediaLibraryCardGrid.js +199 -0
  209. package/src/components/MediaLibrary/MediaLibraryHeader.js +48 -0
  210. package/src/components/MediaLibrary/MediaLibraryModal.js +200 -0
  211. package/src/components/MediaLibrary/MediaLibrarySearch.js +61 -0
  212. package/src/components/MediaLibrary/MediaLibraryTop.js +144 -0
  213. package/src/components/MediaLibrary/__tests__/MediaLibraryButtons.spec.js +45 -0
  214. package/src/components/MediaLibrary/__tests__/MediaLibraryCard.spec.js +49 -0
  215. package/src/components/MediaLibrary/__tests__/__snapshots__/MediaLibraryCard.spec.js.snap +264 -0
  216. package/src/components/UI/DragDrop.js +66 -0
  217. package/src/components/UI/ErrorBoundary.js +213 -0
  218. package/src/components/UI/FileUploadButton.js +24 -0
  219. package/src/components/UI/Modal.js +112 -0
  220. package/src/components/UI/Notifications.tsx +83 -0
  221. package/src/components/UI/SettingsDropdown.js +130 -0
  222. package/src/components/UI/__tests__/ErrorBoundary.spec.js +57 -0
  223. package/src/components/UI/index.js +6 -0
  224. package/src/components/Workflow/Workflow.js +169 -0
  225. package/src/components/Workflow/WorkflowCard.js +177 -0
  226. package/src/components/Workflow/WorkflowList.js +272 -0
  227. package/src/constants/__tests__/configSchema.spec.js +644 -0
  228. package/src/constants/collectionTypes.ts +2 -0
  229. package/src/constants/collectionViews.js +2 -0
  230. package/src/constants/commitProps.ts +2 -0
  231. package/src/constants/configSchema.js +489 -0
  232. package/src/constants/fieldInference.tsx +78 -0
  233. package/src/constants/publishModes.ts +22 -0
  234. package/src/constants/validationErrorTypes.js +6 -0
  235. package/src/formats/__tests__/formats.spec.js +87 -0
  236. package/src/formats/__tests__/frontmatter.spec.js +450 -0
  237. package/src/formats/__tests__/toml.spec.js +9 -0
  238. package/src/formats/__tests__/yaml.spec.js +189 -0
  239. package/src/formats/formats.ts +97 -0
  240. package/src/formats/frontmatter.ts +150 -0
  241. package/src/formats/helpers.ts +14 -0
  242. package/src/formats/json.ts +9 -0
  243. package/src/formats/toml.ts +33 -0
  244. package/src/formats/yaml.ts +73 -0
  245. package/src/index.js +8 -0
  246. package/src/integrations/index.js +35 -0
  247. package/src/integrations/providers/algolia/implementation.js +176 -0
  248. package/src/integrations/providers/assetStore/implementation.js +148 -0
  249. package/src/lib/__tests__/formatters.spec.js +844 -0
  250. package/src/lib/__tests__/i18n.spec.js +792 -0
  251. package/src/lib/__tests__/imageTransformations.spec.ts +97 -0
  252. package/src/lib/__tests__/phrases.spec.js +119 -0
  253. package/src/lib/__tests__/registry.spec.js +261 -0
  254. package/src/lib/__tests__/serializeEntryValues.spec.js +22 -0
  255. package/src/lib/__tests__/urlHelper.spec.js +145 -0
  256. package/src/lib/consoleError.js +7 -0
  257. package/src/lib/formatters.ts +297 -0
  258. package/src/lib/i18n.ts +462 -0
  259. package/src/lib/imageTransformations.ts +212 -0
  260. package/src/lib/phrases.js +8 -0
  261. package/src/lib/polyfill.js +9 -0
  262. package/src/lib/registry.js +315 -0
  263. package/src/lib/serializeEntryValues.js +75 -0
  264. package/src/lib/stega.ts +145 -0
  265. package/src/lib/textHelper.js +11 -0
  266. package/src/lib/urlHelper.ts +152 -0
  267. package/src/mediaLibrary.ts +51 -0
  268. package/src/reducers/__tests__/auth.spec.ts +38 -0
  269. package/src/reducers/__tests__/collections.spec.js +610 -0
  270. package/src/reducers/__tests__/config.spec.js +38 -0
  271. package/src/reducers/__tests__/deploys.spec.ts +111 -0
  272. package/src/reducers/__tests__/entries.spec.js +694 -0
  273. package/src/reducers/__tests__/entryDraft.spec.js +315 -0
  274. package/src/reducers/__tests__/globalUI.js +43 -0
  275. package/src/reducers/__tests__/integrations.spec.ts +76 -0
  276. package/src/reducers/__tests__/mediaLibrary.spec.js +154 -0
  277. package/src/reducers/__tests__/medias.spec.ts +49 -0
  278. package/src/reducers/auth.ts +46 -0
  279. package/src/reducers/collections.ts +535 -0
  280. package/src/reducers/combinedReducer.ts +11 -0
  281. package/src/reducers/config.ts +38 -0
  282. package/src/reducers/cursors.js +36 -0
  283. package/src/reducers/deploys.ts +54 -0
  284. package/src/reducers/editorialWorkflow.ts +163 -0
  285. package/src/reducers/entries.ts +819 -0
  286. package/src/reducers/entryDraft.js +259 -0
  287. package/src/reducers/globalUI.ts +45 -0
  288. package/src/reducers/index.ts +82 -0
  289. package/src/reducers/integrations.ts +59 -0
  290. package/src/reducers/mediaLibrary.ts +296 -0
  291. package/src/reducers/medias.ts +66 -0
  292. package/src/reducers/notifications.ts +52 -0
  293. package/src/reducers/search.ts +111 -0
  294. package/src/reducers/status.ts +40 -0
  295. package/src/redux/index.ts +18 -0
  296. package/src/redux/middleware/waitUntilAction.ts +64 -0
  297. package/src/routing/__tests__/history.spec.ts +49 -0
  298. package/src/routing/history.ts +17 -0
  299. package/src/types/diacritics.d.ts +1 -0
  300. package/src/types/global.d.ts +8 -0
  301. package/src/types/immutable.ts +49 -0
  302. package/src/types/redux.ts +875 -0
  303. package/src/types/tomlify-j0.4.d.ts +13 -0
  304. package/src/valueObjects/AssetProxy.ts +48 -0
  305. package/src/valueObjects/EditorComponent.js +38 -0
  306. package/src/valueObjects/Entry.ts +63 -0
@@ -0,0 +1,332 @@
1
+ import { Map } from 'immutable';
2
+ import { produce } from 'immer';
3
+ import { oneLine } from 'common-tags';
4
+ import EditorComponent from '../valueObjects/EditorComponent';
5
+ const allowedEvents = ['prePublish', 'postPublish', 'preUnpublish', 'postUnpublish', 'preSave', 'postSave'];
6
+ const eventHandlers = {};
7
+ allowedEvents.forEach(e => {
8
+ eventHandlers[e] = [];
9
+ });
10
+
11
+ /**
12
+ * Global Registry Object
13
+ */
14
+ const registry = {
15
+ backends: {},
16
+ templates: {},
17
+ previewStyles: [],
18
+ widgets: {},
19
+ editorComponents: Map(),
20
+ remarkPlugins: [],
21
+ widgetValueSerializers: {},
22
+ mediaLibraries: [],
23
+ locales: {},
24
+ eventHandlers,
25
+ formats: {}
26
+ };
27
+ export default {
28
+ registerPreviewStyle,
29
+ getPreviewStyles,
30
+ registerPreviewTemplate,
31
+ getPreviewTemplate,
32
+ registerWidget,
33
+ getWidget,
34
+ getWidgets,
35
+ resolveWidget,
36
+ registerEditorComponent,
37
+ getEditorComponents,
38
+ registerRemarkPlugin,
39
+ getRemarkPlugins,
40
+ registerWidgetValueSerializer,
41
+ getWidgetValueSerializer,
42
+ registerBackend,
43
+ getBackend,
44
+ registerMediaLibrary,
45
+ getMediaLibrary,
46
+ registerLocale,
47
+ getLocale,
48
+ registerEventListener,
49
+ removeEventListener,
50
+ getEventListeners,
51
+ invokeEvent,
52
+ registerCustomFormat,
53
+ getCustomFormats,
54
+ getCustomFormatsExtensions,
55
+ getCustomFormatsFormatters
56
+ };
57
+
58
+ /**
59
+ * Preview Styles
60
+ *
61
+ * Valid options:
62
+ * - raw {boolean} if `true`, `style` value is expected to be a CSS string
63
+ */
64
+ export function registerPreviewStyle(style, opts) {
65
+ registry.previewStyles.push({
66
+ ...opts,
67
+ value: style
68
+ });
69
+ }
70
+ export function getPreviewStyles() {
71
+ return registry.previewStyles;
72
+ }
73
+
74
+ /**
75
+ * Preview Templates
76
+ */
77
+ export function registerPreviewTemplate(name, component) {
78
+ registry.templates[name] = component;
79
+ }
80
+ export function getPreviewTemplate(name) {
81
+ return registry.templates[name];
82
+ }
83
+
84
+ /**
85
+ * Editor Widgets
86
+ */
87
+ export function registerWidget(name, control, preview, schema = {}) {
88
+ if (Array.isArray(name)) {
89
+ name.forEach(widget => {
90
+ if (typeof widget !== 'object') {
91
+ console.error(`Cannot register widget: ${widget}`);
92
+ } else {
93
+ registerWidget(widget);
94
+ }
95
+ });
96
+ } else if (typeof name === 'string') {
97
+ // A registered widget control can be reused by a new widget, allowing
98
+ // multiple copies with different previews.
99
+ const newControl = typeof control === 'string' ? registry.widgets[control].control : control;
100
+ registry.widgets[name] = {
101
+ control: newControl,
102
+ preview,
103
+ schema
104
+ };
105
+ } else if (typeof name === 'object') {
106
+ const {
107
+ name: widgetName,
108
+ controlComponent: control,
109
+ previewComponent: preview,
110
+ schema = {},
111
+ allowMapValue,
112
+ globalStyles,
113
+ ...options
114
+ } = name;
115
+ if (registry.widgets[widgetName]) {
116
+ console.warn(oneLine`
117
+ Multiple widgets registered with name "${widgetName}". Only the last widget registered with
118
+ this name will be used.
119
+ `);
120
+ }
121
+ if (!control) {
122
+ throw Error(`Widget "${widgetName}" registered without \`controlComponent\`.`);
123
+ }
124
+ registry.widgets[widgetName] = {
125
+ control,
126
+ preview,
127
+ schema,
128
+ globalStyles,
129
+ allowMapValue,
130
+ ...options
131
+ };
132
+ } else {
133
+ console.error('`registerWidget` failed, called with incorrect arguments.');
134
+ }
135
+ }
136
+ export function getWidget(name) {
137
+ return registry.widgets[name];
138
+ }
139
+ export function getWidgets() {
140
+ return produce(Object.entries(registry.widgets), draft => {
141
+ return draft.map(([key, value]) => ({
142
+ name: key,
143
+ ...value
144
+ }));
145
+ });
146
+ }
147
+ export function resolveWidget(name) {
148
+ return getWidget(name || 'string') || getWidget('unknown');
149
+ }
150
+
151
+ /**
152
+ * Markdown Editor Custom Components
153
+ */
154
+ export function registerEditorComponent(component) {
155
+ const plugin = EditorComponent(component);
156
+ if (plugin.type === 'code-block') {
157
+ const codeBlock = registry.editorComponents.find(c => c.type === 'code-block');
158
+ if (codeBlock) {
159
+ console.warn(oneLine`
160
+ Only one editor component of type "code-block" may be registered. Previously registered code
161
+ block component(s) will be overwritten.
162
+ `);
163
+ registry.editorComponents = registry.editorComponents.delete(codeBlock.id);
164
+ }
165
+ }
166
+ registry.editorComponents = registry.editorComponents.set(plugin.id, plugin);
167
+ }
168
+ export function getEditorComponents() {
169
+ return registry.editorComponents;
170
+ }
171
+
172
+ /**
173
+ * Remark plugins
174
+ */
175
+ /** @typedef {import('unified').Pluggable} RemarkPlugin */
176
+ /** @type {(plugin: RemarkPlugin) => void} */
177
+ export function registerRemarkPlugin(plugin) {
178
+ registry.remarkPlugins.push(plugin);
179
+ }
180
+ /** @type {() => Array<RemarkPlugin>} */
181
+ export function getRemarkPlugins() {
182
+ return registry.remarkPlugins;
183
+ }
184
+
185
+ /**
186
+ * Widget Serializers
187
+ */
188
+ export function registerWidgetValueSerializer(widgetName, serializer) {
189
+ registry.widgetValueSerializers[widgetName] = serializer;
190
+ }
191
+ export function getWidgetValueSerializer(widgetName) {
192
+ return registry.widgetValueSerializers[widgetName];
193
+ }
194
+
195
+ /**
196
+ * Backend API
197
+ */
198
+ export function registerBackend(name, BackendClass) {
199
+ if (!name || !BackendClass) {
200
+ console.error("Backend parameters invalid. example: CMS.registerBackend('myBackend', BackendClass)");
201
+ } else if (registry.backends[name]) {
202
+ console.error(`Backend [${name}] already registered. Please choose a different name.`);
203
+ } else {
204
+ registry.backends[name] = {
205
+ init: (...args) => new BackendClass(...args)
206
+ };
207
+ }
208
+ }
209
+ export function getBackend(name) {
210
+ return registry.backends[name];
211
+ }
212
+
213
+ /**
214
+ * Media Libraries
215
+ */
216
+ export function registerMediaLibrary(mediaLibrary, options) {
217
+ if (registry.mediaLibraries.find(ml => mediaLibrary.name === ml.name)) {
218
+ throw new Error(`A media library named ${mediaLibrary.name} has already been registered.`);
219
+ }
220
+ registry.mediaLibraries.push({
221
+ ...mediaLibrary,
222
+ options
223
+ });
224
+ }
225
+ export function getMediaLibrary(name) {
226
+ return registry.mediaLibraries.find(ml => ml.name === name);
227
+ }
228
+ function validateEventName(name) {
229
+ if (!allowedEvents.includes(name)) {
230
+ throw new Error(`Invalid event name '${name}'`);
231
+ }
232
+ }
233
+ export function getEventListeners(name) {
234
+ validateEventName(name);
235
+ return [...registry.eventHandlers[name]];
236
+ }
237
+ export function registerEventListener({
238
+ name,
239
+ handler
240
+ }, options = {}) {
241
+ validateEventName(name);
242
+ registry.eventHandlers[name].push({
243
+ handler,
244
+ options
245
+ });
246
+ }
247
+ export async function invokeEvent({
248
+ name,
249
+ data
250
+ }) {
251
+ validateEventName(name);
252
+ const handlers = registry.eventHandlers[name];
253
+ let _data = {
254
+ ...data
255
+ };
256
+ for (const {
257
+ handler,
258
+ options
259
+ } of handlers) {
260
+ const result = await handler(_data, options);
261
+ if (result !== undefined) {
262
+ const entry = _data.entry.set('data', result);
263
+ _data = {
264
+ ...data,
265
+ entry
266
+ };
267
+ }
268
+ }
269
+ // Return the full entry object with all metadata (slug, path, meta, etc.)
270
+ // rather than just the data payload. Callers like invokePreSaveEvent expect
271
+ // the complete entry object to be preserved through the event handler chain.
272
+ return _data.entry;
273
+ }
274
+ export function removeEventListener({
275
+ name,
276
+ handler
277
+ }) {
278
+ validateEventName(name);
279
+ if (handler) {
280
+ registry.eventHandlers[name] = registry.eventHandlers[name].filter(item => item.handler !== handler);
281
+ } else {
282
+ registry.eventHandlers[name] = [];
283
+ }
284
+ }
285
+
286
+ /**
287
+ * Locales
288
+ */
289
+ export function registerLocale(locale, phrases) {
290
+ if (!locale || !phrases) {
291
+ console.error("Locale parameters invalid. example: CMS.registerLocale('locale', phrases)");
292
+ } else {
293
+ registry.locales[locale] = phrases;
294
+ }
295
+ }
296
+ export function getLocale(locale) {
297
+ return registry.locales[locale];
298
+ }
299
+ export function registerCustomFormat(name, extension, formatter) {
300
+ registry.formats[name] = {
301
+ extension,
302
+ formatter
303
+ };
304
+ }
305
+ export function getCustomFormats() {
306
+ return registry.formats;
307
+ }
308
+ export function getCustomFormatsExtensions() {
309
+ return Object.entries(registry.formats).reduce(function (acc, [name, {
310
+ extension
311
+ }]) {
312
+ return {
313
+ ...acc,
314
+ [name]: extension
315
+ };
316
+ }, {});
317
+ }
318
+
319
+ /** @type {() => Record<string, unknown>} */
320
+ export function getCustomFormatsFormatters() {
321
+ return Object.entries(registry.formats).reduce(function (acc, [name, {
322
+ formatter
323
+ }]) {
324
+ return {
325
+ ...acc,
326
+ [name]: formatter
327
+ };
328
+ }, {});
329
+ }
330
+ export function getFormatter(name) {
331
+ return registry.formats[name]?.formatter;
332
+ }
@@ -0,0 +1,67 @@
1
+ import isNil from 'lodash/isNil';
2
+ import { Map, List } from 'immutable';
3
+ import { getWidgetValueSerializer } from './registry';
4
+
5
+ /**
6
+ * Methods for serializing/deserializing entry field values. Most widgets don't
7
+ * require this for their values, and those that do can typically serialize/
8
+ * deserialize on every change from within the widget. The serialization
9
+ * handlers here are for widgets whose values require heavy serialization that
10
+ * would hurt performance if run for every change.
11
+
12
+ * An example of this is the markdown widget, whose value is stored as a
13
+ * markdown string. Instead of stringifying on every change of that field, a
14
+ * deserialization method is registered from the widget's control module that
15
+ * converts the stored markdown string to an AST, and that AST serves as the
16
+ * widget model during editing.
17
+ *
18
+ * Serialization handlers should be registered for each widget that requires
19
+ * them, and the registration method is exposed through the registry. Any
20
+ * registered deserialization handlers run on entry load, and serialization
21
+ * handlers run on persist.
22
+ */
23
+ function runSerializer(values, fields, method) {
24
+ /**
25
+ * Reduce the list of fields to a map where keys are field names and values
26
+ * are field values, serializing the values of fields whose widgets have
27
+ * registered serializers. If the field is a list or object, call recursively
28
+ * for nested fields.
29
+ */
30
+ let serializedData = fields.reduce((acc, field) => {
31
+ const fieldName = field.get('name');
32
+ const value = values.get(fieldName);
33
+ const serializer = getWidgetValueSerializer(field.get('widget'));
34
+ const nestedFields = field.get('fields');
35
+
36
+ // Call recursively for fields within lists
37
+ if (nestedFields && List.isList(value)) {
38
+ return acc.set(fieldName, value.map(val => runSerializer(val, nestedFields, method)));
39
+ }
40
+
41
+ // Call recursively for fields within objects
42
+ if (nestedFields && Map.isMap(value)) {
43
+ return acc.set(fieldName, runSerializer(value, nestedFields, method));
44
+ }
45
+
46
+ // Run serialization method on value if not null or undefined
47
+ if (serializer && !isNil(value)) {
48
+ return acc.set(fieldName, serializer[method](value));
49
+ }
50
+
51
+ // If no serializer is registered for the field's widget, use the field as is
52
+ if (!isNil(value)) {
53
+ return acc.set(fieldName, value);
54
+ }
55
+ return acc;
56
+ }, Map());
57
+
58
+ //preserve unknown fields value
59
+ serializedData = values.mergeDeep(serializedData);
60
+ return serializedData;
61
+ }
62
+ export function serializeValues(values, fields) {
63
+ return runSerializer(values, fields, 'serialize');
64
+ }
65
+ export function deserializeValues(values, fields) {
66
+ return runSerializer(values, fields, 'deserialize');
67
+ }
@@ -0,0 +1,142 @@
1
+ import { vercelStegaEncode } from '@vercel/stega';
2
+ import { isImmutableMap, isImmutableList } from '../types/immutable';
3
+
4
+ /**
5
+ * Context passed to encode functions, containing the current state of the encoding process
6
+ */
7
+
8
+ /**
9
+ * Get the fields that should be used for encoding nested values
10
+ */
11
+ function getNestedFields(f) {
12
+ if (f) {
13
+ if ('types' in f) {
14
+ return f.types ?? [];
15
+ }
16
+ if ('fields' in f) {
17
+ return f.fields ?? [];
18
+ }
19
+ if ('field' in f) {
20
+ return f.field ? [f.field] : [];
21
+ }
22
+ return [f];
23
+ }
24
+ return [];
25
+ }
26
+
27
+ /**
28
+ * Encode a string value by appending steganographic data
29
+ * For markdown fields, encode each paragraph separately
30
+ */
31
+ function encodeString(value, {
32
+ fields,
33
+ path
34
+ }) {
35
+ const [field] = fields;
36
+ if (!field) return value;
37
+ const {
38
+ widget
39
+ } = field;
40
+ if (widget === 'string' || widget === 'text') {
41
+ if ('visualEditing' in field && field.visualEditing === false) return value;
42
+ const stega = vercelStegaEncode({
43
+ decap: path
44
+ });
45
+ return value + stega;
46
+ }
47
+ if (widget === 'markdown') {
48
+ const stega = vercelStegaEncode({
49
+ decap: path
50
+ });
51
+ const blocks = value.split(/(\n\n+)/);
52
+ return blocks.map(block => block.trim() ? block + stega : block).join('');
53
+ }
54
+ return value;
55
+ }
56
+
57
+ /**
58
+ * Encode a list of values, handling both simple values and nested objects/lists
59
+ * For typed lists, use the type field to determine which fields to use
60
+ */
61
+ function encodeList(list, ctx) {
62
+ let newList = list;
63
+ for (let i = 0; i < newList.size; i++) {
64
+ const item = newList.get(i);
65
+ if (isImmutableMap(item)) {
66
+ const itemType = item.get('type');
67
+ if (typeof itemType === 'string') {
68
+ // For typed items, look up fields based on type
69
+ const field = ctx.fields.find(f => f.name === itemType);
70
+ const newItem = ctx.visit(item, getNestedFields(field), `${ctx.path}.${i}`);
71
+ newList = newList.set(i, newItem);
72
+ } else {
73
+ // For untyped items, use current fields
74
+ const newItem = ctx.visit(item, ctx.fields, `${ctx.path}.${i}`);
75
+ newList = newList.set(i, newItem);
76
+ }
77
+ } else {
78
+ // For simple values, use first field if available
79
+ const field = ctx.fields[0];
80
+ const newItem = ctx.visit(item, field ? [field] : [], `${ctx.path}.${i}`);
81
+ if (newItem !== item) {
82
+ newList = newList.set(i, newItem);
83
+ }
84
+ }
85
+ }
86
+ return newList;
87
+ }
88
+
89
+ /**
90
+ * Encode a map of values, looking up the appropriate field for each key
91
+ * and recursively encoding nested values
92
+ */
93
+ function encodeMap(map, ctx) {
94
+ let newMap = map;
95
+ for (const [key, val] of newMap.entrySeq().toArray()) {
96
+ const field = ctx.fields.find(f => f.name === key);
97
+ if (field) {
98
+ const fields = getNestedFields(field);
99
+ const newVal = ctx.visit(val, fields, ctx.path ? `${ctx.path}.${key}` : key);
100
+ if (newVal !== val) {
101
+ newMap = newMap.set(key, newVal);
102
+ }
103
+ }
104
+ }
105
+ return newMap;
106
+ }
107
+
108
+ /**
109
+ * Cache for encoded values to prevent re-encoding unchanged values
110
+ * across keystrokes. The cache is keyed by path.
111
+ */
112
+ const encodingCache = new Map();
113
+
114
+ /**
115
+ * Main entry point for encoding steganographic data into entry values
116
+ * Uses a visitor pattern with caching to handle recursive structures
117
+ */
118
+ export function encodeEntry(value, fields) {
119
+ const plainFields = fields.toJS();
120
+ function visit(value, fields, path = '') {
121
+ const cached = encodingCache.get(path);
122
+ if (cached === value) return value;
123
+ const ctx = {
124
+ fields,
125
+ path,
126
+ visit
127
+ };
128
+ let result;
129
+ if (isImmutableList(value)) {
130
+ result = encodeList(value, ctx);
131
+ } else if (isImmutableMap(value)) {
132
+ result = encodeMap(value, ctx);
133
+ } else if (typeof value === 'string') {
134
+ result = encodeString(value, ctx);
135
+ } else {
136
+ result = value;
137
+ }
138
+ encodingCache.set(path, result);
139
+ return result;
140
+ }
141
+ return visit(value, plainFields);
142
+ }
@@ -0,0 +1,9 @@
1
+ export function stringToRGB(str) {
2
+ if (!str) return '000000';
3
+ let hash = 0;
4
+ for (let i = 0; i < str.length; i++) {
5
+ hash = str.charCodeAt(i) + ((hash << 5) - hash);
6
+ }
7
+ const c = (hash & 0x00ffffff).toString(16).toUpperCase();
8
+ return `00000${c}`.slice(-6);
9
+ }
@@ -0,0 +1,129 @@
1
+ import url from 'url';
2
+ import urlJoin from 'url-join';
3
+ import diacritics from 'diacritics';
4
+ import sanitizeFilename from 'sanitize-filename';
5
+ import isString from 'lodash/isString';
6
+ import escapeRegExp from 'lodash/escapeRegExp';
7
+ import flow from 'lodash/flow';
8
+ import partialRight from 'lodash/partialRight';
9
+ function getUrl(urlString, direct) {
10
+ return `${direct ? '/#' : ''}${urlString}`;
11
+ }
12
+ export function getCollectionUrl(collectionName, direct) {
13
+ return getUrl(`/collections/${collectionName}`, direct);
14
+ }
15
+ export function getNewEntryUrl(collectionName, direct) {
16
+ return getUrl(`/collections/${collectionName}/new`, direct);
17
+ }
18
+ export function addParams(urlString, params) {
19
+ const parsedUrl = url.parse(urlString, true);
20
+ parsedUrl.query = {
21
+ ...parsedUrl.query,
22
+ ...params
23
+ };
24
+ return url.format(parsedUrl);
25
+ }
26
+ export function stripProtocol(urlString) {
27
+ const protocolEndIndex = urlString.indexOf('//');
28
+ return protocolEndIndex > -1 ? urlString.slice(protocolEndIndex + 2) : urlString;
29
+ }
30
+
31
+ /* See https://www.w3.org/International/articles/idn-and-iri/#path.
32
+ * According to the new IRI (Internationalized Resource Identifier) spec, RFC 3987,
33
+ * ASCII chars should be kept the same way as in standard URIs (letters digits _ - . ~).
34
+ * Non-ASCII chars (unless they are not in the allowed "ucschars" list) should be percent-encoded.
35
+ * If the string is not encoded in Unicode, it should be converted to UTF-8 and normalized first,
36
+ * but JS stores strings as UTF-16/UCS-2 internally, so we should not normalize or re-encode.
37
+ */
38
+ const uriChars = /[\w\-.~]/i;
39
+ const ucsChars = /[\xA0-\u{D7FF}\u{F900}-\u{FDCF}\u{FDF0}-\u{FFEF}\u{10000}-\u{1FFFD}\u{20000}-\u{2FFFD}\u{30000}-\u{3FFFD}\u{40000}-\u{4FFFD}\u{50000}-\u{5FFFD}\u{60000}-\u{6FFFD}\u{70000}-\u{7FFFD}\u{80000}-\u{8FFFD}\u{90000}-\u{9FFFD}\u{A0000}-\u{AFFFD}\u{B0000}-\u{BFFFD}\u{C0000}-\u{CFFFD}\u{D0000}-\u{DFFFD}\u{E1000}-\u{EFFFD}]/u;
40
+ function validURIChar(char) {
41
+ return uriChars.test(char);
42
+ }
43
+ function validIRIChar(char) {
44
+ return uriChars.test(char) || ucsChars.test(char);
45
+ }
46
+ export function getCharReplacer(encoding, options) {
47
+ const {
48
+ replacement,
49
+ preserveSlashes
50
+ } = options;
51
+ let validChar;
52
+ if (encoding === 'unicode') {
53
+ validChar = validIRIChar;
54
+ } else if (encoding === 'ascii') {
55
+ validChar = validURIChar;
56
+ } else {
57
+ throw new Error('`options.encoding` must be "unicode" or "ascii".');
58
+ }
59
+
60
+ // Check and make sure the replacement character is actually a safe char itself.
61
+ if (!Array.from(replacement).every(validChar)) {
62
+ throw new Error('The replacement character(s) (options.replacement) is itself unsafe.');
63
+ }
64
+ return (char, i = 0, arr = [char]) => {
65
+ if (preserveSlashes && char === '/' && i !== 0 && i !== arr.length - 1) {
66
+ return char;
67
+ }
68
+ return validChar(char) ? char : replacement;
69
+ };
70
+ }
71
+ // `sanitizeURI` does not actually URI-encode the chars (that is the browser's and server's job), just removes the ones that are not allowed.
72
+ export function sanitizeURI(str, options) {
73
+ const {
74
+ replacement = '',
75
+ encoding = 'unicode',
76
+ preserveSlashes
77
+ } = options || {};
78
+ if (!isString(str)) {
79
+ throw new Error('The input slug must be a string.');
80
+ }
81
+ if (!isString(replacement)) {
82
+ throw new Error('`options.replacement` must be a string.');
83
+ }
84
+
85
+ // `Array.from` must be used instead of `String.split` because
86
+ // `split` converts things like emojis into UTF-16 surrogate pairs.
87
+ return Array.from(str).map(getCharReplacer(encoding, {
88
+ replacement,
89
+ preserveSlashes
90
+ })).join('');
91
+ }
92
+ export function sanitizeChar(char, options) {
93
+ const {
94
+ encoding = 'unicode',
95
+ sanitize_replacement: replacement = ''
96
+ } = options || {};
97
+ return getCharReplacer(encoding, {
98
+ replacement
99
+ })(char);
100
+ }
101
+ export function sanitizeSlug(str, options, preserveSlashes) {
102
+ if (!isString(str)) {
103
+ throw new Error('The input slug must be a string.');
104
+ }
105
+ const {
106
+ encoding,
107
+ clean_accents: stripDiacritics,
108
+ sanitize_replacement: replacement
109
+ } = options || {};
110
+ const sanitizedSlug = flow([...(stripDiacritics ? [diacritics.remove] : []), partialRight(sanitizeURI, {
111
+ replacement,
112
+ encoding,
113
+ preserveSlashes
114
+ }), preserveSlashes ? slug => slug.split('/').filter(Boolean).map(part => sanitizeFilename(part, {
115
+ replacement
116
+ })).join('/') : partialRight(sanitizeFilename, {
117
+ replacement
118
+ })])(str);
119
+
120
+ // Remove any doubled or leading/trailing replacement characters (that were added in the sanitizers).
121
+ const doubleReplacement = new RegExp(`(?:${escapeRegExp(replacement)})+`, 'g');
122
+ const trailingReplacement = new RegExp(`${escapeRegExp(replacement)}$`);
123
+ const leadingReplacement = new RegExp(`^${escapeRegExp(replacement)}`);
124
+ const normalizedSlug = sanitizedSlug.replace(doubleReplacement, replacement).replace(leadingReplacement, '').replace(trailingReplacement, '');
125
+ return normalizedSlug;
126
+ }
127
+ export function joinUrlPath(base, ...path) {
128
+ return urlJoin(base, ...path);
129
+ }