@jhits/plugin-blog 0.0.9 → 0.0.11

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 (276) hide show
  1. package/package.json +58 -59
  2. package/src/api/categories.ts +0 -43
  3. package/src/api/check-title.ts +0 -60
  4. package/src/api/config-handler.ts +0 -76
  5. package/src/api/handler.ts +0 -418
  6. package/src/api/index.ts +0 -33
  7. package/src/api/route.ts +0 -116
  8. package/src/api/router.ts +0 -128
  9. package/src/api-server.ts +0 -11
  10. package/src/config.ts +0 -161
  11. package/src/hooks/index.d.ts +0 -8
  12. package/src/hooks/index.d.ts.map +0 -1
  13. package/src/hooks/index.js +0 -7
  14. package/src/hooks/index.ts +0 -9
  15. package/src/hooks/useBlog.d.ts +0 -31
  16. package/src/hooks/useBlog.d.ts.map +0 -1
  17. package/src/hooks/useBlog.js +0 -57
  18. package/src/hooks/useBlog.ts +0 -85
  19. package/src/hooks/useBlogs.d.ts +0 -39
  20. package/src/hooks/useBlogs.d.ts.map +0 -1
  21. package/src/hooks/useBlogs.js +0 -82
  22. package/src/hooks/useBlogs.ts +0 -123
  23. package/src/hooks/useCategories.d.ts +0 -9
  24. package/src/hooks/useCategories.d.ts.map +0 -1
  25. package/src/hooks/useCategories.js +0 -70
  26. package/src/hooks/useCategories.ts +0 -76
  27. package/src/index.d.ts +0 -55
  28. package/src/index.d.ts.map +0 -1
  29. package/src/index.js +0 -228
  30. package/src/index.server.ts +0 -14
  31. package/src/index.tsx +0 -335
  32. package/src/init.d.ts +0 -40
  33. package/src/init.d.ts.map +0 -1
  34. package/src/init.js +0 -41
  35. package/src/init.tsx +0 -63
  36. package/src/lib/blocks/BlockRenderer.d.ts +0 -54
  37. package/src/lib/blocks/BlockRenderer.d.ts.map +0 -1
  38. package/src/lib/blocks/BlockRenderer.js +0 -54
  39. package/src/lib/blocks/BlockRenderer.tsx +0 -141
  40. package/src/lib/blocks/index.ts +0 -6
  41. package/src/lib/config-storage.d.ts +0 -30
  42. package/src/lib/config-storage.d.ts.map +0 -1
  43. package/src/lib/config-storage.js +0 -31
  44. package/src/lib/config-storage.ts +0 -65
  45. package/src/lib/index.ts +0 -9
  46. package/src/lib/layouts/blocks/ColumnsBlock.d.ts +0 -25
  47. package/src/lib/layouts/blocks/ColumnsBlock.d.ts.map +0 -1
  48. package/src/lib/layouts/blocks/ColumnsBlock.js +0 -182
  49. package/src/lib/layouts/blocks/ColumnsBlock.tsx +0 -298
  50. package/src/lib/layouts/blocks/ColumnsBlock.tsx.tmp +0 -81
  51. package/src/lib/layouts/blocks/SectionBlock.d.ts +0 -25
  52. package/src/lib/layouts/blocks/SectionBlock.d.ts.map +0 -1
  53. package/src/lib/layouts/blocks/SectionBlock.js +0 -44
  54. package/src/lib/layouts/blocks/SectionBlock.tsx +0 -104
  55. package/src/lib/layouts/blocks/index.ts +0 -8
  56. package/src/lib/layouts/index.d.ts +0 -23
  57. package/src/lib/layouts/index.d.ts.map +0 -1
  58. package/src/lib/layouts/index.js +0 -45
  59. package/src/lib/layouts/index.ts +0 -52
  60. package/src/lib/layouts/registerLayoutBlocks.d.ts +0 -9
  61. package/src/lib/layouts/registerLayoutBlocks.d.ts.map +0 -1
  62. package/src/lib/layouts/registerLayoutBlocks.js +0 -60
  63. package/src/lib/layouts/registerLayoutBlocks.ts +0 -64
  64. package/src/lib/mappers/apiMapper.d.ts +0 -66
  65. package/src/lib/mappers/apiMapper.d.ts.map +0 -1
  66. package/src/lib/mappers/apiMapper.js +0 -191
  67. package/src/lib/mappers/apiMapper.ts +0 -254
  68. package/src/lib/migration/index.ts +0 -6
  69. package/src/lib/migration/mapper.ts +0 -140
  70. package/src/lib/rich-text/RichTextEditor.d.ts +0 -45
  71. package/src/lib/rich-text/RichTextEditor.d.ts.map +0 -1
  72. package/src/lib/rich-text/RichTextEditor.js +0 -564
  73. package/src/lib/rich-text/RichTextEditor.tsx +0 -826
  74. package/src/lib/rich-text/RichTextPreview.d.ts +0 -16
  75. package/src/lib/rich-text/RichTextPreview.d.ts.map +0 -1
  76. package/src/lib/rich-text/RichTextPreview.js +0 -144
  77. package/src/lib/rich-text/RichTextPreview.tsx +0 -210
  78. package/src/lib/rich-text/index.d.ts +0 -9
  79. package/src/lib/rich-text/index.d.ts.map +0 -1
  80. package/src/lib/rich-text/index.js +0 -6
  81. package/src/lib/rich-text/index.ts +0 -10
  82. package/src/lib/utils/blockHelpers.d.ts +0 -23
  83. package/src/lib/utils/blockHelpers.d.ts.map +0 -1
  84. package/src/lib/utils/blockHelpers.js +0 -65
  85. package/src/lib/utils/blockHelpers.ts +0 -72
  86. package/src/lib/utils/configValidation.d.ts +0 -23
  87. package/src/lib/utils/configValidation.d.ts.map +0 -1
  88. package/src/lib/utils/configValidation.js +0 -113
  89. package/src/lib/utils/configValidation.ts +0 -137
  90. package/src/lib/utils/index.ts +0 -8
  91. package/src/lib/utils/slugify.ts +0 -79
  92. package/src/registry/BlockRegistry.d.ts +0 -62
  93. package/src/registry/BlockRegistry.d.ts.map +0 -1
  94. package/src/registry/BlockRegistry.js +0 -112
  95. package/src/registry/BlockRegistry.ts +0 -139
  96. package/src/registry/index.d.ts +0 -6
  97. package/src/registry/index.d.ts.map +0 -1
  98. package/src/registry/index.js +0 -4
  99. package/src/registry/index.ts +0 -11
  100. package/src/state/EditorContext.d.ts +0 -45
  101. package/src/state/EditorContext.d.ts.map +0 -1
  102. package/src/state/EditorContext.js +0 -215
  103. package/src/state/EditorContext.tsx +0 -283
  104. package/src/state/index.d.ts +0 -7
  105. package/src/state/index.d.ts.map +0 -1
  106. package/src/state/index.js +0 -6
  107. package/src/state/index.ts +0 -8
  108. package/src/state/reducer.d.ts +0 -11
  109. package/src/state/reducer.d.ts.map +0 -1
  110. package/src/state/reducer.js +0 -443
  111. package/src/state/reducer.ts +0 -694
  112. package/src/state/types.d.ts +0 -162
  113. package/src/state/types.d.ts.map +0 -1
  114. package/src/state/types.js +0 -27
  115. package/src/state/types.ts +0 -160
  116. package/src/types/block.d.ts +0 -221
  117. package/src/types/block.d.ts.map +0 -1
  118. package/src/types/block.js +0 -6
  119. package/src/types/block.ts +0 -269
  120. package/src/types/index.d.ts +0 -8
  121. package/src/types/index.d.ts.map +0 -1
  122. package/src/types/index.js +0 -5
  123. package/src/types/index.ts +0 -17
  124. package/src/types/post.d.ts +0 -136
  125. package/src/types/post.d.ts.map +0 -1
  126. package/src/types/post.js +0 -5
  127. package/src/types/post.ts +0 -169
  128. package/src/utils/client.d.ts +0 -48
  129. package/src/utils/client.d.ts.map +0 -1
  130. package/src/utils/client.js +0 -77
  131. package/src/utils/client.ts +0 -122
  132. package/src/utils/index.ts +0 -7
  133. package/src/views/CanvasEditor/BlockWrapper.d.ts +0 -16
  134. package/src/views/CanvasEditor/BlockWrapper.d.ts.map +0 -1
  135. package/src/views/CanvasEditor/BlockWrapper.js +0 -276
  136. package/src/views/CanvasEditor/BlockWrapper.tsx +0 -522
  137. package/src/views/CanvasEditor/CanvasEditorView.d.ts +0 -14
  138. package/src/views/CanvasEditor/CanvasEditorView.d.ts.map +0 -1
  139. package/src/views/CanvasEditor/CanvasEditorView.js +0 -209
  140. package/src/views/CanvasEditor/CanvasEditorView.tsx +0 -337
  141. package/src/views/CanvasEditor/EditorBody.d.ts +0 -22
  142. package/src/views/CanvasEditor/EditorBody.d.ts.map +0 -1
  143. package/src/views/CanvasEditor/EditorBody.js +0 -505
  144. package/src/views/CanvasEditor/EditorBody.tsx +0 -665
  145. package/src/views/CanvasEditor/EditorHeader.d.ts +0 -18
  146. package/src/views/CanvasEditor/EditorHeader.d.ts.map +0 -1
  147. package/src/views/CanvasEditor/EditorHeader.js +0 -101
  148. package/src/views/CanvasEditor/EditorHeader.tsx +0 -268
  149. package/src/views/CanvasEditor/LayoutContainer.d.ts +0 -17
  150. package/src/views/CanvasEditor/LayoutContainer.d.ts.map +0 -1
  151. package/src/views/CanvasEditor/LayoutContainer.js +0 -222
  152. package/src/views/CanvasEditor/LayoutContainer.tsx +0 -322
  153. package/src/views/CanvasEditor/SaveConfirmationModal.d.ts +0 -13
  154. package/src/views/CanvasEditor/SaveConfirmationModal.d.ts.map +0 -1
  155. package/src/views/CanvasEditor/SaveConfirmationModal.js +0 -78
  156. package/src/views/CanvasEditor/SaveConfirmationModal.tsx +0 -233
  157. package/src/views/CanvasEditor/components/CustomBlockItem.d.ts +0 -14
  158. package/src/views/CanvasEditor/components/CustomBlockItem.d.ts.map +0 -1
  159. package/src/views/CanvasEditor/components/CustomBlockItem.js +0 -44
  160. package/src/views/CanvasEditor/components/CustomBlockItem.tsx +0 -92
  161. package/src/views/CanvasEditor/components/EditorCanvas.d.ts +0 -29
  162. package/src/views/CanvasEditor/components/EditorCanvas.d.ts.map +0 -1
  163. package/src/views/CanvasEditor/components/EditorCanvas.js +0 -32
  164. package/src/views/CanvasEditor/components/EditorCanvas.tsx +0 -160
  165. package/src/views/CanvasEditor/components/EditorLibrary.d.ts +0 -7
  166. package/src/views/CanvasEditor/components/EditorLibrary.d.ts.map +0 -1
  167. package/src/views/CanvasEditor/components/EditorLibrary.js +0 -25
  168. package/src/views/CanvasEditor/components/EditorLibrary.tsx +0 -122
  169. package/src/views/CanvasEditor/components/EditorSidebar.d.ts +0 -13
  170. package/src/views/CanvasEditor/components/EditorSidebar.d.ts.map +0 -1
  171. package/src/views/CanvasEditor/components/EditorSidebar.js +0 -20
  172. package/src/views/CanvasEditor/components/EditorSidebar.tsx +0 -181
  173. package/src/views/CanvasEditor/components/ErrorBanner.d.ts +0 -6
  174. package/src/views/CanvasEditor/components/ErrorBanner.d.ts.map +0 -1
  175. package/src/views/CanvasEditor/components/ErrorBanner.js +0 -8
  176. package/src/views/CanvasEditor/components/ErrorBanner.tsx +0 -31
  177. package/src/views/CanvasEditor/components/FeaturedMediaSection.d.ts +0 -25
  178. package/src/views/CanvasEditor/components/FeaturedMediaSection.d.ts.map +0 -1
  179. package/src/views/CanvasEditor/components/FeaturedMediaSection.js +0 -182
  180. package/src/views/CanvasEditor/components/FeaturedMediaSection.tsx +0 -341
  181. package/src/views/CanvasEditor/components/LibraryItem.d.ts +0 -14
  182. package/src/views/CanvasEditor/components/LibraryItem.d.ts.map +0 -1
  183. package/src/views/CanvasEditor/components/LibraryItem.js +0 -43
  184. package/src/views/CanvasEditor/components/LibraryItem.tsx +0 -80
  185. package/src/views/CanvasEditor/components/PrivacySettingsSection.d.ts +0 -15
  186. package/src/views/CanvasEditor/components/PrivacySettingsSection.d.ts.map +0 -1
  187. package/src/views/CanvasEditor/components/PrivacySettingsSection.js +0 -63
  188. package/src/views/CanvasEditor/components/PrivacySettingsSection.tsx +0 -212
  189. package/src/views/CanvasEditor/components/index.d.ts +0 -21
  190. package/src/views/CanvasEditor/components/index.d.ts.map +0 -1
  191. package/src/views/CanvasEditor/components/index.js +0 -12
  192. package/src/views/CanvasEditor/components/index.ts +0 -28
  193. package/src/views/CanvasEditor/hooks/index.d.ts +0 -10
  194. package/src/views/CanvasEditor/hooks/index.d.ts.map +0 -1
  195. package/src/views/CanvasEditor/hooks/index.js +0 -9
  196. package/src/views/CanvasEditor/hooks/index.ts +0 -10
  197. package/src/views/CanvasEditor/hooks/useHeroBlock.d.ts +0 -8
  198. package/src/views/CanvasEditor/hooks/useHeroBlock.d.ts.map +0 -1
  199. package/src/views/CanvasEditor/hooks/useHeroBlock.js +0 -79
  200. package/src/views/CanvasEditor/hooks/useHeroBlock.ts +0 -103
  201. package/src/views/CanvasEditor/hooks/useKeyboardShortcuts.d.ts +0 -3
  202. package/src/views/CanvasEditor/hooks/useKeyboardShortcuts.d.ts.map +0 -1
  203. package/src/views/CanvasEditor/hooks/useKeyboardShortcuts.js +0 -114
  204. package/src/views/CanvasEditor/hooks/useKeyboardShortcuts.ts +0 -142
  205. package/src/views/CanvasEditor/hooks/usePostLoader.d.ts +0 -5
  206. package/src/views/CanvasEditor/hooks/usePostLoader.d.ts.map +0 -1
  207. package/src/views/CanvasEditor/hooks/usePostLoader.js +0 -32
  208. package/src/views/CanvasEditor/hooks/usePostLoader.ts +0 -39
  209. package/src/views/CanvasEditor/hooks/useRegisteredBlocks.d.ts +0 -2
  210. package/src/views/CanvasEditor/hooks/useRegisteredBlocks.d.ts.map +0 -1
  211. package/src/views/CanvasEditor/hooks/useRegisteredBlocks.js +0 -47
  212. package/src/views/CanvasEditor/hooks/useRegisteredBlocks.ts +0 -55
  213. package/src/views/CanvasEditor/hooks/useUnsavedChanges.d.ts +0 -25
  214. package/src/views/CanvasEditor/hooks/useUnsavedChanges.d.ts.map +0 -1
  215. package/src/views/CanvasEditor/hooks/useUnsavedChanges.js +0 -285
  216. package/src/views/CanvasEditor/hooks/useUnsavedChanges.ts +0 -339
  217. package/src/views/CanvasEditor/index.d.ts +0 -16
  218. package/src/views/CanvasEditor/index.d.ts.map +0 -1
  219. package/src/views/CanvasEditor/index.js +0 -9
  220. package/src/views/CanvasEditor/index.ts +0 -16
  221. package/src/views/PostManager/EmptyState.d.ts +0 -10
  222. package/src/views/PostManager/EmptyState.d.ts.map +0 -1
  223. package/src/views/PostManager/EmptyState.js +0 -12
  224. package/src/views/PostManager/EmptyState.tsx +0 -42
  225. package/src/views/PostManager/PostActionsMenu.d.ts +0 -12
  226. package/src/views/PostManager/PostActionsMenu.d.ts.map +0 -1
  227. package/src/views/PostManager/PostActionsMenu.js +0 -58
  228. package/src/views/PostManager/PostActionsMenu.tsx +0 -112
  229. package/src/views/PostManager/PostCards.d.ts +0 -15
  230. package/src/views/PostManager/PostCards.d.ts.map +0 -1
  231. package/src/views/PostManager/PostCards.js +0 -79
  232. package/src/views/PostManager/PostCards.tsx +0 -197
  233. package/src/views/PostManager/PostFilters.d.ts +0 -16
  234. package/src/views/PostManager/PostFilters.d.ts.map +0 -1
  235. package/src/views/PostManager/PostFilters.js +0 -10
  236. package/src/views/PostManager/PostFilters.tsx +0 -95
  237. package/src/views/PostManager/PostManagerView.d.ts +0 -11
  238. package/src/views/PostManager/PostManagerView.d.ts.map +0 -1
  239. package/src/views/PostManager/PostManagerView.js +0 -174
  240. package/src/views/PostManager/PostManagerView.tsx +0 -289
  241. package/src/views/PostManager/PostStats.d.ts +0 -11
  242. package/src/views/PostManager/PostStats.d.ts.map +0 -1
  243. package/src/views/PostManager/PostStats.js +0 -46
  244. package/src/views/PostManager/PostStats.tsx +0 -81
  245. package/src/views/PostManager/PostTable.d.ts +0 -15
  246. package/src/views/PostManager/PostTable.d.ts.map +0 -1
  247. package/src/views/PostManager/PostTable.js +0 -79
  248. package/src/views/PostManager/PostTable.tsx +0 -230
  249. package/src/views/PostManager/index.d.ts +0 -12
  250. package/src/views/PostManager/index.d.ts.map +0 -1
  251. package/src/views/PostManager/index.js +0 -11
  252. package/src/views/PostManager/index.ts +0 -15
  253. package/src/views/Preview/PreviewBridgeView.d.ts +0 -12
  254. package/src/views/Preview/PreviewBridgeView.d.ts.map +0 -1
  255. package/src/views/Preview/PreviewBridgeView.js +0 -11
  256. package/src/views/Preview/PreviewBridgeView.tsx +0 -64
  257. package/src/views/Preview/index.d.ts +0 -6
  258. package/src/views/Preview/index.d.ts.map +0 -1
  259. package/src/views/Preview/index.js +0 -4
  260. package/src/views/Preview/index.ts +0 -7
  261. package/src/views/Settings/SettingsView.d.ts +0 -10
  262. package/src/views/Settings/SettingsView.d.ts.map +0 -1
  263. package/src/views/Settings/SettingsView.js +0 -111
  264. package/src/views/Settings/SettingsView.tsx +0 -298
  265. package/src/views/Settings/index.d.ts +0 -6
  266. package/src/views/Settings/index.d.ts.map +0 -1
  267. package/src/views/Settings/index.js +0 -4
  268. package/src/views/Settings/index.ts +0 -7
  269. package/src/views/SlugSEO/SlugSEOManagerView.d.ts +0 -12
  270. package/src/views/SlugSEO/SlugSEOManagerView.d.ts.map +0 -1
  271. package/src/views/SlugSEO/SlugSEOManagerView.js +0 -11
  272. package/src/views/SlugSEO/SlugSEOManagerView.tsx +0 -94
  273. package/src/views/SlugSEO/index.d.ts +0 -6
  274. package/src/views/SlugSEO/index.d.ts.map +0 -1
  275. package/src/views/SlugSEO/index.js +0 -4
  276. package/src/views/SlugSEO/index.ts +0 -7
@@ -1,113 +0,0 @@
1
- /**
2
- * Plugin Configuration Validation Utilities
3
- * Validates plugin configuration and custom blocks
4
- */
5
- import { useEffect, useState, useMemo } from 'react';
6
- /**
7
- * Routes that require the hero block to be defined
8
- */
9
- const ROUTES_REQUIRING_HERO_BLOCK = ['editor', 'new', 'preview'];
10
- /**
11
- * Check if a route requires the hero block
12
- */
13
- export function routeRequiresHeroBlock(route) {
14
- return ROUTES_REQUIRING_HERO_BLOCK.includes(route);
15
- }
16
- /**
17
- * Find hero block definition in custom blocks
18
- */
19
- export function findHeroBlock(customBlocks) {
20
- return customBlocks.find(block => block.type === 'hero');
21
- }
22
- /**
23
- * Hook to validate hero block configuration
24
- * Only validates for routes that require it, and waits for customBlocks to load
25
- *
26
- * @param route - Current route (e.g., 'posts', 'editor', 'new')
27
- * @param customBlocks - Array of custom block definitions
28
- * @param propsCustomBlocks - Custom blocks from props (for immediate validation)
29
- */
30
- export function useHeroBlockValidation(route, customBlocks, propsCustomBlocks) {
31
- const needsHeroBlock = useMemo(() => routeRequiresHeroBlock(route), [route]);
32
- const heroBlockDefinition = useMemo(() => {
33
- // Only search for hero block if route needs it
34
- return needsHeroBlock ? findHeroBlock(customBlocks) : undefined;
35
- }, [customBlocks, needsHeroBlock]);
36
- // Track if we've given customBlocks time to load from window global
37
- // This prevents false errors when customBlocks are loaded asynchronously
38
- // Only track this if we actually need the hero block
39
- const [hasCheckedForBlocks, setHasCheckedForBlocks] = useState(false);
40
- // Give window global a chance to load before validating
41
- // Only do this if the route needs the hero block
42
- useEffect(() => {
43
- var _a, _b;
44
- // Early return: Skip all validation logic if route doesn't need hero block
45
- if (!needsHeroBlock) {
46
- return;
47
- }
48
- if (typeof window === 'undefined') {
49
- setHasCheckedForBlocks(true); // Server-side, no need to wait
50
- return;
51
- }
52
- // If props are provided, we can validate immediately
53
- if (propsCustomBlocks && propsCustomBlocks.length > 0) {
54
- setHasCheckedForBlocks(true);
55
- return;
56
- }
57
- // Check if window global is already available
58
- if ((_b = (_a = window.__JHITS_PLUGIN_PROPS__) === null || _a === void 0 ? void 0 : _a['plugin-blog']) === null || _b === void 0 ? void 0 : _b.customBlocks) {
59
- setHasCheckedForBlocks(true);
60
- return;
61
- }
62
- // Retry mechanism: check multiple times with increasing delays
63
- // This handles the case where BlogPluginInit's useEffect runs after BlogPlugin mounts
64
- // BlogPluginInit runs initBlogPlugin in useEffect, which may execute after BlogPlugin's first render
65
- let attempt = 0;
66
- const maxAttempts = 6;
67
- const delays = [50, 100, 200, 300, 500, 1000]; // Progressive delays: total ~2.15s
68
- const timers = [];
69
- const checkWithRetry = () => {
70
- var _a, _b;
71
- const windowGlobal = (_b = (_a = window.__JHITS_PLUGIN_PROPS__) === null || _a === void 0 ? void 0 : _a['plugin-blog']) === null || _b === void 0 ? void 0 : _b.customBlocks;
72
- if (windowGlobal && windowGlobal.length > 0) {
73
- // Found it! Mark as checked
74
- setHasCheckedForBlocks(true);
75
- return;
76
- }
77
- if (attempt < maxAttempts) {
78
- const timer = setTimeout(() => {
79
- attempt++;
80
- checkWithRetry();
81
- }, delays[attempt]);
82
- timers.push(timer);
83
- }
84
- else {
85
- // After all retries, mark as checked (even if not found)
86
- // This prevents infinite waiting and allows validation to proceed
87
- setHasCheckedForBlocks(true);
88
- }
89
- };
90
- // Start checking
91
- checkWithRetry();
92
- // Cleanup all timers
93
- return () => {
94
- timers.forEach(timer => clearTimeout(timer));
95
- };
96
- }, [propsCustomBlocks, needsHeroBlock]);
97
- // Validate that Hero block is required (only for editor routes, and only after we've checked for blocks)
98
- useEffect(() => {
99
- // Early return if route doesn't need hero block - no validation needed
100
- if (!needsHeroBlock) {
101
- return;
102
- }
103
- // Only validate if:
104
- // 1. We're in a route that needs the hero block (already checked above)
105
- // 2. We've given customBlocks time to load (hasCheckedForBlocks is true)
106
- // 3. The hero block is still not found
107
- if (hasCheckedForBlocks && !heroBlockDefinition) {
108
- console.error('[BlogPlugin] Hero block is REQUIRED but not found in customBlocks. ' +
109
- 'Please define a block with type: "hero" in your blog config. ' +
110
- `Current route: "${route}"`);
111
- }
112
- }, [heroBlockDefinition, needsHeroBlock, hasCheckedForBlocks, route]);
113
- }
@@ -1,137 +0,0 @@
1
- /**
2
- * Plugin Configuration Validation Utilities
3
- * Validates plugin configuration and custom blocks
4
- */
5
-
6
- import { useEffect, useState, useMemo } from 'react';
7
- import { ClientBlockDefinition } from '../../types/block';
8
-
9
- /**
10
- * Routes that require the hero block to be defined
11
- */
12
- const ROUTES_REQUIRING_HERO_BLOCK = ['editor', 'new', 'preview'] as const;
13
-
14
- /**
15
- * Check if a route requires the hero block
16
- */
17
- export function routeRequiresHeroBlock(route: string): boolean {
18
- return ROUTES_REQUIRING_HERO_BLOCK.includes(route as any);
19
- }
20
-
21
- /**
22
- * Find hero block definition in custom blocks
23
- */
24
- export function findHeroBlock(customBlocks: ClientBlockDefinition[]): ClientBlockDefinition | undefined {
25
- return customBlocks.find(block => block.type === 'hero');
26
- }
27
-
28
- /**
29
- * Hook to validate hero block configuration
30
- * Only validates for routes that require it, and waits for customBlocks to load
31
- *
32
- * @param route - Current route (e.g., 'posts', 'editor', 'new')
33
- * @param customBlocks - Array of custom block definitions
34
- * @param propsCustomBlocks - Custom blocks from props (for immediate validation)
35
- */
36
- export function useHeroBlockValidation(
37
- route: string,
38
- customBlocks: ClientBlockDefinition[],
39
- propsCustomBlocks?: ClientBlockDefinition[]
40
- ): void {
41
- const needsHeroBlock = useMemo(() => routeRequiresHeroBlock(route), [route]);
42
-
43
- const heroBlockDefinition = useMemo(() => {
44
- // Only search for hero block if route needs it
45
- return needsHeroBlock ? findHeroBlock(customBlocks) : undefined;
46
- }, [customBlocks, needsHeroBlock]);
47
-
48
- // Track if we've given customBlocks time to load from window global
49
- // This prevents false errors when customBlocks are loaded asynchronously
50
- // Only track this if we actually need the hero block
51
- const [hasCheckedForBlocks, setHasCheckedForBlocks] = useState(false);
52
-
53
- // Give window global a chance to load before validating
54
- // Only do this if the route needs the hero block
55
- useEffect(() => {
56
- // Early return: Skip all validation logic if route doesn't need hero block
57
- if (!needsHeroBlock) {
58
- return;
59
- }
60
-
61
- if (typeof window === 'undefined') {
62
- setHasCheckedForBlocks(true); // Server-side, no need to wait
63
- return;
64
- }
65
-
66
- // If props are provided, we can validate immediately
67
- if (propsCustomBlocks && propsCustomBlocks.length > 0) {
68
- setHasCheckedForBlocks(true);
69
- return;
70
- }
71
-
72
- // Check if window global is already available
73
- if ((window as any).__JHITS_PLUGIN_PROPS__?.['plugin-blog']?.customBlocks) {
74
- setHasCheckedForBlocks(true);
75
- return;
76
- }
77
-
78
- // Retry mechanism: check multiple times with increasing delays
79
- // This handles the case where BlogPluginInit's useEffect runs after BlogPlugin mounts
80
- // BlogPluginInit runs initBlogPlugin in useEffect, which may execute after BlogPlugin's first render
81
- let attempt = 0;
82
- const maxAttempts = 6;
83
- const delays = [50, 100, 200, 300, 500, 1000]; // Progressive delays: total ~2.15s
84
-
85
- const timers: NodeJS.Timeout[] = [];
86
-
87
- const checkWithRetry = () => {
88
- const windowGlobal = (window as any).__JHITS_PLUGIN_PROPS__?.['plugin-blog']?.customBlocks;
89
- if (windowGlobal && windowGlobal.length > 0) {
90
- // Found it! Mark as checked
91
- setHasCheckedForBlocks(true);
92
- return;
93
- }
94
-
95
- if (attempt < maxAttempts) {
96
- const timer = setTimeout(() => {
97
- attempt++;
98
- checkWithRetry();
99
- }, delays[attempt]);
100
- timers.push(timer);
101
- } else {
102
- // After all retries, mark as checked (even if not found)
103
- // This prevents infinite waiting and allows validation to proceed
104
- setHasCheckedForBlocks(true);
105
- }
106
- };
107
-
108
- // Start checking
109
- checkWithRetry();
110
-
111
- // Cleanup all timers
112
- return () => {
113
- timers.forEach(timer => clearTimeout(timer));
114
- };
115
- }, [propsCustomBlocks, needsHeroBlock]);
116
-
117
- // Validate that Hero block is required (only for editor routes, and only after we've checked for blocks)
118
- useEffect(() => {
119
- // Early return if route doesn't need hero block - no validation needed
120
- if (!needsHeroBlock) {
121
- return;
122
- }
123
-
124
- // Only validate if:
125
- // 1. We're in a route that needs the hero block (already checked above)
126
- // 2. We've given customBlocks time to load (hasCheckedForBlocks is true)
127
- // 3. The hero block is still not found
128
- if (hasCheckedForBlocks && !heroBlockDefinition) {
129
- console.error(
130
- '[BlogPlugin] Hero block is REQUIRED but not found in customBlocks. ' +
131
- 'Please define a block with type: "hero" in your blog config. ' +
132
- `Current route: "${route}"`
133
- );
134
- }
135
- }, [heroBlockDefinition, needsHeroBlock, hasCheckedForBlocks, route]);
136
- }
137
-
@@ -1,8 +0,0 @@
1
- /**
2
- * Utility exports
3
- */
4
-
5
- export * from './slugify';
6
- export * from './blockHelpers';
7
- export * from './configValidation';
8
-
@@ -1,79 +0,0 @@
1
- /**
2
- * Slug Utilities
3
- * Functions for generating and validating URL slugs
4
- */
5
-
6
- /**
7
- * Convert a string to a URL-friendly slug
8
- */
9
- export function slugify(text: string): string {
10
- return text
11
- .toString()
12
- .toLowerCase()
13
- .trim()
14
- .replace(/\s+/g, '-') // Replace spaces with hyphens
15
- .replace(/[^\w\-]+/g, '') // Remove all non-word chars
16
- .replace(/\-\-+/g, '-') // Replace multiple hyphens with single hyphen
17
- .replace(/^-+/, '') // Trim hyphens from start
18
- .replace(/-+$/, ''); // Trim hyphens from end
19
- }
20
-
21
- /**
22
- * Generate a slug from a title
23
- * Automatically handles edge cases and ensures uniqueness
24
- */
25
- export function generateSlugFromTitle(title: string, existingSlugs: string[] = []): string {
26
- let baseSlug = slugify(title);
27
-
28
- // If slug is empty after processing, use a fallback
29
- if (!baseSlug) {
30
- baseSlug = 'untitled-post';
31
- }
32
-
33
- // Check for collisions and append number if needed
34
- let finalSlug = baseSlug;
35
- let counter = 1;
36
-
37
- while (existingSlugs.includes(finalSlug)) {
38
- finalSlug = `${baseSlug}-${counter}`;
39
- counter++;
40
- }
41
-
42
- return finalSlug;
43
- }
44
-
45
- /**
46
- * Validate a slug format
47
- */
48
- export function isValidSlug(slug: string): boolean {
49
- // Slug should be lowercase, alphanumeric with hyphens
50
- const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
51
- return slugRegex.test(slug) && slug.length > 0 && slug.length <= 200;
52
- }
53
-
54
- /**
55
- * Check if a slug collides with existing slugs
56
- */
57
- export function checkSlugCollision(slug: string, existingSlugs: string[], excludeId?: string): {
58
- isCollision: boolean;
59
- conflictingId?: string;
60
- } {
61
- // Normalize the slug for comparison
62
- const normalizedSlug = slug.toLowerCase().trim();
63
-
64
- // Check against existing slugs (excluding current post if editing)
65
- for (const existing of existingSlugs) {
66
- if (existing.toLowerCase().trim() === normalizedSlug) {
67
- // If we have an excludeId, we need to check if this is the same post
68
- // This would require additional context (like a post ID map)
69
- // For now, we'll return collision if it matches
70
- return {
71
- isCollision: true,
72
- conflictingId: existing,
73
- };
74
- }
75
- }
76
-
77
- return { isCollision: false };
78
- }
79
-
@@ -1,62 +0,0 @@
1
- /**
2
- * Block Registry
3
- * Dynamic registry for all block types in the system
4
- * Multi-Tenant Architecture: Blocks are provided by client applications
5
- *
6
- * The registry is a singleton that starts empty and is populated by client apps
7
- */
8
- import { BlockTypeDefinition, BlockRegistry as IBlockRegistry, ClientBlockDefinition } from '../types/block';
9
- /**
10
- * Dynamic Block Registry Implementation
11
- * No default blocks - all blocks must be registered by client applications
12
- */
13
- declare class BlockRegistryImpl implements IBlockRegistry {
14
- private _types;
15
- get types(): Map<string, BlockTypeDefinition>;
16
- /**
17
- * Register a single block type
18
- */
19
- register(definition: BlockTypeDefinition): void;
20
- /**
21
- * Register multiple client blocks at once
22
- * This is the primary method for client applications to register their blocks
23
- */
24
- registerClientBlocks(definitions: ClientBlockDefinition[]): void;
25
- /**
26
- * Get block type definition by type string
27
- */
28
- get(type: string): BlockTypeDefinition | undefined;
29
- /**
30
- * Get all registered block types
31
- */
32
- getAll(): BlockTypeDefinition[];
33
- /**
34
- * Get block types filtered by category
35
- */
36
- getByCategory(category: BlockTypeDefinition['category']): BlockTypeDefinition[];
37
- /**
38
- * Check if a block type is registered
39
- */
40
- has(type: string): boolean;
41
- /**
42
- * Unregister a block type (useful for testing or dynamic loading)
43
- */
44
- unregister(type: string): boolean;
45
- /**
46
- * Clear all registered block types
47
- * Useful for testing or resetting the registry
48
- */
49
- clear(): void;
50
- /**
51
- * Get count of registered blocks
52
- */
53
- getCount(): number;
54
- }
55
- export declare const blockRegistry: BlockRegistryImpl;
56
- export {};
57
- /**
58
- * NOTE: No default blocks are registered automatically.
59
- * Client applications must call registerClientBlocks() to populate the registry.
60
- * This ensures the editor is a true "shell" without hardcoded blocks.
61
- */
62
- //# sourceMappingURL=BlockRegistry.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BlockRegistry.d.ts","sourceRoot":"","sources":["BlockRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACH,mBAAmB,EACnB,aAAa,IAAI,cAAc,EAC/B,qBAAqB,EACxB,MAAM,gBAAgB,CAAC;AAExB;;;GAGG;AACH,cAAM,iBAAkB,YAAW,cAAc;IAC7C,OAAO,CAAC,MAAM,CAA+C;IAE7D,IAAI,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAE5C;IAED;;OAEG;IACH,QAAQ,CAAC,UAAU,EAAE,mBAAmB,GAAG,IAAI;IAa/C;;;OAGG;IACH,oBAAoB,CAAC,WAAW,EAAE,qBAAqB,EAAE,GAAG,IAAI;IAmChE;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS;IAIlD;;OAEG;IACH,MAAM,IAAI,mBAAmB,EAAE;IAI/B;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,mBAAmB,CAAC,UAAU,CAAC,GAAG,mBAAmB,EAAE;IAI/E;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIjC;;;OAGG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,QAAQ,IAAI,MAAM;CAGrB;AAGD,eAAO,MAAM,aAAa,mBAA0B,CAAC;;AAErD;;;;GAIG"}
@@ -1,112 +0,0 @@
1
- /**
2
- * Block Registry
3
- * Dynamic registry for all block types in the system
4
- * Multi-Tenant Architecture: Blocks are provided by client applications
5
- *
6
- * The registry is a singleton that starts empty and is populated by client apps
7
- */
8
- /**
9
- * Dynamic Block Registry Implementation
10
- * No default blocks - all blocks must be registered by client applications
11
- */
12
- class BlockRegistryImpl {
13
- constructor() {
14
- this._types = new Map();
15
- }
16
- get types() {
17
- return this._types;
18
- }
19
- /**
20
- * Register a single block type
21
- */
22
- register(definition) {
23
- // Validate that components are provided
24
- if (!definition.components || !definition.components.Edit || !definition.components.Preview) {
25
- throw new Error(`Block type "${definition.type}" must provide both Edit and Preview components. ` +
26
- `Use registerClientBlocks() for client-provided blocks.`);
27
- }
28
- // Silently overwrite if already registered (expected in React 18 Strict Mode)
29
- this._types.set(definition.type, definition);
30
- }
31
- /**
32
- * Register multiple client blocks at once
33
- * This is the primary method for client applications to register their blocks
34
- */
35
- registerClientBlocks(definitions) {
36
- for (const def of definitions) {
37
- // Validate required fields
38
- if (!def.type || !def.name || !def.components) {
39
- console.error('Invalid block definition:', def);
40
- throw new Error('Block definition must have: type, name, and components (with Edit and Preview)');
41
- }
42
- // Validate components
43
- if (!def.components.Edit || !def.components.Preview) {
44
- throw new Error(`Block "${def.type}" must provide both Edit and Preview components in the components object`);
45
- }
46
- // Convert ClientBlockDefinition to BlockTypeDefinition
47
- const blockDefinition = {
48
- type: def.type,
49
- name: def.name,
50
- description: def.description,
51
- icon: def.icon || def.components.Icon,
52
- defaultData: def.defaultData,
53
- validate: def.validate,
54
- isContainer: def.isContainer,
55
- allowedChildren: def.allowedChildren,
56
- category: def.category || 'custom',
57
- components: def.components,
58
- };
59
- this.register(blockDefinition);
60
- }
61
- }
62
- /**
63
- * Get block type definition by type string
64
- */
65
- get(type) {
66
- return this._types.get(type);
67
- }
68
- /**
69
- * Get all registered block types
70
- */
71
- getAll() {
72
- return Array.from(this._types.values());
73
- }
74
- /**
75
- * Get block types filtered by category
76
- */
77
- getByCategory(category) {
78
- return this.getAll().filter(block => block.category === category);
79
- }
80
- /**
81
- * Check if a block type is registered
82
- */
83
- has(type) {
84
- return this._types.has(type);
85
- }
86
- /**
87
- * Unregister a block type (useful for testing or dynamic loading)
88
- */
89
- unregister(type) {
90
- return this._types.delete(type);
91
- }
92
- /**
93
- * Clear all registered block types
94
- * Useful for testing or resetting the registry
95
- */
96
- clear() {
97
- this._types.clear();
98
- }
99
- /**
100
- * Get count of registered blocks
101
- */
102
- getCount() {
103
- return this._types.size;
104
- }
105
- }
106
- // Singleton instance - starts empty, populated by client apps
107
- export const blockRegistry = new BlockRegistryImpl();
108
- /**
109
- * NOTE: No default blocks are registered automatically.
110
- * Client applications must call registerClientBlocks() to populate the registry.
111
- * This ensures the editor is a true "shell" without hardcoded blocks.
112
- */
@@ -1,139 +0,0 @@
1
- /**
2
- * Block Registry
3
- * Dynamic registry for all block types in the system
4
- * Multi-Tenant Architecture: Blocks are provided by client applications
5
- *
6
- * The registry is a singleton that starts empty and is populated by client apps
7
- */
8
-
9
- import {
10
- BlockTypeDefinition,
11
- BlockRegistry as IBlockRegistry,
12
- ClientBlockDefinition
13
- } from '../types/block';
14
-
15
- /**
16
- * Dynamic Block Registry Implementation
17
- * No default blocks - all blocks must be registered by client applications
18
- */
19
- class BlockRegistryImpl implements IBlockRegistry {
20
- private _types: Map<string, BlockTypeDefinition> = new Map();
21
-
22
- get types(): Map<string, BlockTypeDefinition> {
23
- return this._types;
24
- }
25
-
26
- /**
27
- * Register a single block type
28
- */
29
- register(definition: BlockTypeDefinition): void {
30
- // Validate that components are provided
31
- if (!definition.components || !definition.components.Edit || !definition.components.Preview) {
32
- throw new Error(
33
- `Block type "${definition.type}" must provide both Edit and Preview components. ` +
34
- `Use registerClientBlocks() for client-provided blocks.`
35
- );
36
- }
37
-
38
- // Silently overwrite if already registered (expected in React 18 Strict Mode)
39
- this._types.set(definition.type, definition);
40
- }
41
-
42
- /**
43
- * Register multiple client blocks at once
44
- * This is the primary method for client applications to register their blocks
45
- */
46
- registerClientBlocks(definitions: ClientBlockDefinition[]): void {
47
- for (const def of definitions) {
48
- // Validate required fields
49
- if (!def.type || !def.name || !def.components) {
50
- console.error('Invalid block definition:', def);
51
- throw new Error(
52
- 'Block definition must have: type, name, and components (with Edit and Preview)'
53
- );
54
- }
55
-
56
- // Validate components
57
- if (!def.components.Edit || !def.components.Preview) {
58
- throw new Error(
59
- `Block "${def.type}" must provide both Edit and Preview components in the components object`
60
- );
61
- }
62
-
63
- // Convert ClientBlockDefinition to BlockTypeDefinition
64
- const blockDefinition: BlockTypeDefinition = {
65
- type: def.type,
66
- name: def.name,
67
- description: def.description,
68
- icon: def.icon || def.components.Icon,
69
- defaultData: def.defaultData,
70
- validate: def.validate,
71
- isContainer: def.isContainer,
72
- allowedChildren: def.allowedChildren,
73
- category: def.category || 'custom',
74
- components: def.components,
75
- };
76
-
77
- this.register(blockDefinition);
78
- }
79
- }
80
-
81
- /**
82
- * Get block type definition by type string
83
- */
84
- get(type: string): BlockTypeDefinition | undefined {
85
- return this._types.get(type);
86
- }
87
-
88
- /**
89
- * Get all registered block types
90
- */
91
- getAll(): BlockTypeDefinition[] {
92
- return Array.from(this._types.values());
93
- }
94
-
95
- /**
96
- * Get block types filtered by category
97
- */
98
- getByCategory(category: BlockTypeDefinition['category']): BlockTypeDefinition[] {
99
- return this.getAll().filter(block => block.category === category);
100
- }
101
-
102
- /**
103
- * Check if a block type is registered
104
- */
105
- has(type: string): boolean {
106
- return this._types.has(type);
107
- }
108
-
109
- /**
110
- * Unregister a block type (useful for testing or dynamic loading)
111
- */
112
- unregister(type: string): boolean {
113
- return this._types.delete(type);
114
- }
115
-
116
- /**
117
- * Clear all registered block types
118
- * Useful for testing or resetting the registry
119
- */
120
- clear(): void {
121
- this._types.clear();
122
- }
123
-
124
- /**
125
- * Get count of registered blocks
126
- */
127
- getCount(): number {
128
- return this._types.size;
129
- }
130
- }
131
-
132
- // Singleton instance - starts empty, populated by client apps
133
- export const blockRegistry = new BlockRegistryImpl();
134
-
135
- /**
136
- * NOTE: No default blocks are registered automatically.
137
- * Client applications must call registerClientBlocks() to populate the registry.
138
- * This ensures the editor is a true "shell" without hardcoded blocks.
139
- */
@@ -1,6 +0,0 @@
1
- /**
2
- * Registry exports
3
- */
4
- export { blockRegistry } from './BlockRegistry';
5
- export type { ClientBlockDefinition, BlockTypeDefinition, BlockRegistry, } from '../types/block';
6
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EACR,qBAAqB,EACrB,mBAAmB,EACnB,aAAa,GAChB,MAAM,gBAAgB,CAAC"}
@@ -1,4 +0,0 @@
1
- /**
2
- * Registry exports
3
- */
4
- export { blockRegistry } from './BlockRegistry';
@@ -1,11 +0,0 @@
1
- /**
2
- * Registry exports
3
- */
4
-
5
- export { blockRegistry } from './BlockRegistry';
6
- export type {
7
- ClientBlockDefinition,
8
- BlockTypeDefinition,
9
- BlockRegistry,
10
- } from '../types/block';
11
-