@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,254 +0,0 @@
1
- /**
2
- * API Mapper
3
- * Converts between API format (MongoDB) and BlogPost format
4
- */
5
-
6
- import { BlogPost, PostStatus, SEOMetadata, PostMetadata } from '../../types/post';
7
- import { Block } from '../../types/block';
8
-
9
- /**
10
- * API Blog Document Format (from MongoDB)
11
- */
12
- export interface APIBlogDocument {
13
- _id?: string;
14
- id?: string;
15
- title: string;
16
- slug: string;
17
- contentBlocks?: Block[]; // New block-based format
18
- content?: any[]; // Legacy format
19
- summary?: string;
20
- image?: {
21
- id?: string; // Semantic ID (preferred) - plugin-images handles everything else
22
- src?: string; // Legacy support - will be converted to id when loading
23
- alt?: string;
24
- isCustom?: boolean;
25
- // Transform fields (brightness, blur, scale, positionX, positionY) are NOT stored here
26
- // They are handled by plugin-images API only
27
- };
28
- categoryTags?: {
29
- category?: string;
30
- tags?: string[];
31
- };
32
- publicationData?: {
33
- status?: PostStatus | 'concept'; // API uses 'concept' instead of 'draft'
34
- date?: string | Date;
35
- };
36
- seo?: {
37
- title?: string;
38
- description?: string;
39
- keywords?: string[];
40
- ogImage?: string;
41
- canonicalUrl?: string;
42
- };
43
- authorId?: string;
44
- createdAt?: string | Date;
45
- updatedAt?: string | Date;
46
- }
47
-
48
- /**
49
- * Convert API document to BlogPost format
50
- */
51
- export function apiToBlogPost(doc: APIBlogDocument): BlogPost {
52
- const id = doc._id?.toString() || doc.id || '';
53
-
54
- // Use contentBlocks if available, otherwise fallback to content (legacy)
55
- // Hero block is included in contentBlocks
56
- const blocks = doc.contentBlocks || [];
57
-
58
- // Convert publication data
59
- const publicationDate = doc.publicationData?.date
60
- ? (typeof doc.publicationData.date === 'string'
61
- ? doc.publicationData.date
62
- : doc.publicationData.date.toISOString())
63
- : undefined;
64
-
65
- // Convert SEO data
66
- const seo: SEOMetadata = {
67
- title: doc.seo?.title,
68
- description: doc.seo?.description,
69
- keywords: doc.seo?.keywords,
70
- ogImage: doc.seo?.ogImage,
71
- canonicalUrl: doc.seo?.canonicalUrl,
72
- };
73
-
74
- // Convert metadata
75
- // Only store semantic ID (id) and alt - plugin-images handles everything else
76
- const metadata: PostMetadata = {
77
- featuredImage: doc.image ? {
78
- // Prefer id (semantic ID) over src (legacy)
79
- id: doc.image.id || doc.image.src,
80
- alt: doc.image.alt,
81
- isCustom: doc.image.isCustom,
82
- // Don't load transform fields - plugin-images handles those
83
- } : undefined,
84
- categories: doc.categoryTags?.category ? [doc.categoryTags.category] : [],
85
- tags: doc.categoryTags?.tags || [],
86
- excerpt: doc.summary,
87
- privacy: undefined, // Privacy settings not in API yet
88
- };
89
-
90
- // Convert publication data - API uses 'concept' but we use 'draft'
91
- const apiStatus = doc.publicationData?.status || 'concept';
92
- const normalizedStatus = apiStatus === 'concept' ? 'draft' : apiStatus;
93
-
94
- const publication = {
95
- status: normalizedStatus as PostStatus,
96
- date: publicationDate,
97
- authorId: doc.authorId,
98
- updatedAt: doc.updatedAt
99
- ? (typeof doc.updatedAt === 'string' ? doc.updatedAt : doc.updatedAt.toISOString())
100
- : undefined,
101
- };
102
-
103
- return {
104
- id,
105
- title: doc.title,
106
- slug: doc.slug,
107
- blocks,
108
- seo,
109
- publication,
110
- metadata,
111
- createdAt: doc.createdAt
112
- ? (typeof doc.createdAt === 'string' ? doc.createdAt : doc.createdAt.toISOString())
113
- : new Date().toISOString(),
114
- updatedAt: doc.updatedAt
115
- ? (typeof doc.updatedAt === 'string' ? doc.updatedAt : doc.updatedAt.toISOString())
116
- : new Date().toISOString(),
117
- };
118
- }
119
-
120
- /**
121
- * Convert BlogPost to API document format
122
- */
123
- export function blogPostToAPI(post: BlogPost, authorId?: string): Partial<APIBlogDocument> {
124
- return {
125
- title: post.title,
126
- slug: post.slug,
127
- contentBlocks: post.blocks, // Use new block format
128
- summary: post.metadata.excerpt,
129
- // Only save semantic ID (id) and alt - plugin-images handles transform data
130
- image: post.metadata.featuredImage ? {
131
- id: post.metadata.featuredImage.id,
132
- alt: post.metadata.featuredImage.alt,
133
- isCustom: post.metadata.featuredImage.isCustom,
134
- // Don't save transform fields - plugin-images API handles those
135
- } : undefined,
136
- categoryTags: {
137
- category: post.metadata.categories?.[0] || '',
138
- tags: post.metadata.tags || [],
139
- },
140
- publicationData: {
141
- // API uses 'concept' instead of 'draft'
142
- status: post.publication.status === 'draft' ? 'concept' : post.publication.status,
143
- date: post.publication.date ? new Date(post.publication.date) : new Date(),
144
- },
145
- seo: {
146
- title: post.seo.title,
147
- description: post.seo.description,
148
- keywords: post.seo.keywords,
149
- ogImage: post.seo.ogImage,
150
- canonicalUrl: post.seo.canonicalUrl,
151
- },
152
- authorId: authorId || post.publication.authorId,
153
- updatedAt: new Date(),
154
- };
155
- }
156
-
157
- /**
158
- * Convert EditorState to API format for saving
159
- * @param state - Editor state
160
- * @param authorId - Optional author ID
161
- * @param heroBlock - Optional hero block (stored separately from content blocks)
162
- */
163
- export function editorStateToAPI(state: {
164
- title: string;
165
- slug: string;
166
- blocks: Block[];
167
- seo: SEOMetadata;
168
- metadata: PostMetadata;
169
- status: PostStatus;
170
- postId?: string | null;
171
- }, authorId?: string, heroBlock?: Block | null): Partial<APIBlogDocument> {
172
- // Map status: draft -> concept, published -> published, everything else stays as-is
173
- const apiStatus = state.status === 'draft' ? 'concept' : state.status;
174
-
175
- console.log('[editorStateToAPI] Mapping status:', {
176
- editorStatus: state.status,
177
- apiStatus: apiStatus,
178
- willBePublished: apiStatus === 'published'
179
- });
180
-
181
- // Try to get category from metadata first, then check hero block
182
- let category: string | undefined = undefined;
183
- if (state.metadata.categories && state.metadata.categories.length > 0 && state.metadata.categories[0]?.trim()) {
184
- category = state.metadata.categories[0].trim();
185
- } else {
186
- // Check hero block for category - use the passed heroBlock parameter first, then check state.blocks
187
- const heroBlockToCheck = heroBlock || state.blocks.find(block => block.type === 'hero');
188
- if (heroBlockToCheck && heroBlockToCheck.data && typeof heroBlockToCheck.data === 'object') {
189
- const heroCategory = (heroBlockToCheck.data as any).category;
190
- if (heroCategory && typeof heroCategory === 'string' && heroCategory.trim()) {
191
- category = heroCategory.trim();
192
- }
193
- }
194
- }
195
-
196
- console.log('[editorStateToAPI] Category resolution:', {
197
- fromMetadata: state.metadata.categories?.[0],
198
- fromHeroBlock: (heroBlock || state.blocks.find(b => b.type === 'hero'))?.data ? ((heroBlock || state.blocks.find(b => b.type === 'hero'))!.data as any).category : undefined,
199
- finalCategory: category,
200
- hasHeroBlock: !!heroBlock,
201
- heroBlockImage: heroBlock?.data ? (heroBlock.data as any)?.image : undefined,
202
- });
203
-
204
- // Include hero block in contentBlocks if it exists
205
- // Filter out any existing hero blocks from state.blocks first, then add the current hero block
206
- const contentBlocksWithoutHero = state.blocks.filter(block => block.type !== 'hero');
207
- const allBlocks = heroBlock
208
- ? [heroBlock, ...contentBlocksWithoutHero]
209
- : contentBlocksWithoutHero;
210
-
211
- console.log('[editorStateToAPI] Hero block details:', {
212
- hasHeroBlock: !!heroBlock,
213
- heroBlockType: heroBlock?.type,
214
- heroBlockId: heroBlock?.id,
215
- heroBlockImage: heroBlock?.data ? (heroBlock.data as any)?.image : undefined,
216
- heroBlockImageSrc: heroBlock?.data ? (heroBlock.data as any)?.image?.src : undefined,
217
- contentBlocksCount: allBlocks.length,
218
- contentBlocksTypes: allBlocks.map(b => b.type),
219
- heroBlockInContentBlocks: allBlocks.find(b => b.type === 'hero')?.data ? (allBlocks.find(b => b.type === 'hero')!.data as any)?.image : undefined,
220
- });
221
-
222
- return {
223
- title: state.title,
224
- slug: state.slug,
225
- contentBlocks: allBlocks,
226
- summary: state.metadata.excerpt,
227
- // Only save semantic ID (id) and alt - plugin-images handles transform data
228
- // Only create image object if id exists and is not empty
229
- image: state.metadata.featuredImage?.id?.trim() ? {
230
- id: state.metadata.featuredImage.id.trim(),
231
- alt: state.metadata.featuredImage.alt || '',
232
- isCustom: state.metadata.featuredImage.isCustom,
233
- // Don't save transform fields - plugin-images API handles those
234
- } : undefined,
235
- categoryTags: {
236
- category: category,
237
- tags: state.metadata.tags || [],
238
- },
239
- publicationData: {
240
- status: apiStatus,
241
- date: new Date(),
242
- },
243
- seo: {
244
- title: state.seo.title,
245
- description: state.seo.description,
246
- keywords: state.seo.keywords,
247
- ogImage: state.seo.ogImage,
248
- canonicalUrl: state.seo.canonicalUrl,
249
- },
250
- authorId,
251
- updatedAt: new Date(),
252
- };
253
- }
254
-
@@ -1,6 +0,0 @@
1
- /**
2
- * Migration utilities exports
3
- */
4
-
5
- export * from './mapper';
6
-
@@ -1,140 +0,0 @@
1
- /**
2
- * Migration Mapper
3
- * Utility functions for converting legacy data to block-based format
4
- */
5
-
6
- import { Block } from '../../types/block';
7
- import { BlogPost } from '../../types/post';
8
-
9
- /**
10
- * Legacy Post Structure (example - adjust based on your actual legacy format)
11
- */
12
- export interface LegacyPost {
13
- id?: string;
14
- title: string;
15
- content: string; // HTML string
16
- slug?: string;
17
- excerpt?: string;
18
- [key: string]: unknown;
19
- }
20
-
21
- /**
22
- * Convert HTML string to blocks
23
- * This is a basic implementation - can be enhanced with more sophisticated parsing
24
- */
25
- export function htmlToBlocks(html: string): Block[] {
26
- // This is a simplified parser - you may want to use a proper HTML parser
27
- // like htmlparser2 or cheerio for production use
28
-
29
- const blocks: Block[] = [];
30
- let blockIdCounter = 0;
31
-
32
- function generateId(): string {
33
- return `block-${Date.now()}-${blockIdCounter++}`;
34
- }
35
-
36
- // Simple regex-based parsing (for demonstration)
37
- // In production, use a proper HTML parser
38
-
39
- // Extract headings
40
- const headingRegex = /<h([1-6])[^>]*>(.*?)<\/h[1-6]>/gi;
41
- let match;
42
- let lastIndex = 0;
43
-
44
- while ((match = headingRegex.exec(html)) !== null) {
45
- // Add text before heading as paragraph if exists
46
- const textBefore = html.substring(lastIndex, match.index).trim();
47
- if (textBefore) {
48
- blocks.push({
49
- id: generateId(),
50
- type: 'paragraph',
51
- data: { text: textBefore.replace(/<[^>]+>/g, '') },
52
- });
53
- }
54
-
55
- // Add heading
56
- blocks.push({
57
- id: generateId(),
58
- type: 'heading',
59
- data: {
60
- text: match[2].replace(/<[^>]+>/g, ''),
61
- level: parseInt(match[1], 10),
62
- },
63
- });
64
-
65
- lastIndex = match.index + match[0].length;
66
- }
67
-
68
- // Add remaining text as paragraph
69
- const remainingText = html.substring(lastIndex).trim();
70
- if (remainingText) {
71
- blocks.push({
72
- id: generateId(),
73
- type: 'paragraph',
74
- data: { text: remainingText.replace(/<[^>]+>/g, '') },
75
- });
76
- }
77
-
78
- // If no blocks were created, create a single paragraph with the HTML content
79
- if (blocks.length === 0) {
80
- blocks.push({
81
- id: generateId(),
82
- type: 'paragraph',
83
- data: { text: html.replace(/<[^>]+>/g, '') },
84
- });
85
- }
86
-
87
- return blocks;
88
- }
89
-
90
- /**
91
- * Map legacy post to new BlogPost format
92
- */
93
- export function mapLegacyPostToBlogPost(
94
- legacyPost: LegacyPost,
95
- options?: {
96
- defaultStatus?: 'draft' | 'published' | 'scheduled';
97
- authorId?: string;
98
- }
99
- ): BlogPost {
100
- const blocks = legacyPost.content
101
- ? htmlToBlocks(legacyPost.content)
102
- : [];
103
-
104
- return {
105
- id: legacyPost.id || `post-${Date.now()}`,
106
- title: legacyPost.title || 'Untitled Post',
107
- slug: legacyPost.slug || legacyPost.title?.toLowerCase().replace(/\s+/g, '-') || 'untitled',
108
- blocks,
109
- seo: {
110
- title: legacyPost.title,
111
- description: legacyPost.excerpt || '',
112
- },
113
- publication: {
114
- status: options?.defaultStatus || 'draft',
115
- date: new Date().toISOString(),
116
- authorId: options?.authorId,
117
- },
118
- metadata: {
119
- excerpt: legacyPost.excerpt || '',
120
- categories: [],
121
- tags: [],
122
- },
123
- createdAt: new Date().toISOString(),
124
- updatedAt: new Date().toISOString(),
125
- };
126
- }
127
-
128
- /**
129
- * Batch convert multiple legacy posts
130
- */
131
- export function mapLegacyPostsToBlogPosts(
132
- legacyPosts: LegacyPost[],
133
- options?: {
134
- defaultStatus?: 'draft' | 'published' | 'scheduled';
135
- authorId?: string;
136
- }
137
- ): BlogPost[] {
138
- return legacyPosts.map(post => mapLegacyPostToBlogPost(post, options));
139
- }
140
-
@@ -1,45 +0,0 @@
1
- /**
2
- * Rich Text Editor Component
3
- * Provides formatting toolbar (bold, italic, underline, links, colors)
4
- * Only shows options if client has provided styles for them
5
- */
6
- import React from 'react';
7
- export interface RichTextFormattingConfig {
8
- /** Whether bold formatting is available */
9
- bold?: boolean;
10
- /** Whether italic formatting is available */
11
- italic?: boolean;
12
- /** Whether underline formatting is available */
13
- underline?: boolean;
14
- /** Whether links are available */
15
- links?: boolean;
16
- /** Available colors (array of color values or Tailwind classes) */
17
- colors?: string[];
18
- /** Custom CSS classes for formatted text */
19
- styles?: {
20
- bold?: string;
21
- italic?: string;
22
- underline?: string;
23
- link?: string;
24
- /** Color classes mapped by color value */
25
- colorClasses?: Record<string, string>;
26
- };
27
- }
28
- export interface RichTextEditorProps {
29
- /** HTML content value */
30
- value: string;
31
- /** Change handler */
32
- onChange: (html: string) => void;
33
- /** Placeholder text */
34
- placeholder?: string;
35
- /** Formatting configuration */
36
- formatting?: RichTextFormattingConfig;
37
- /** Additional CSS classes */
38
- className?: string;
39
- /** Whether the editor is focused */
40
- isFocused?: boolean;
41
- /** Custom keydown handler (called before default handler) */
42
- onKeyDown?: (e: React.KeyboardEvent) => void;
43
- }
44
- export declare function RichTextEditor({ value, onChange, placeholder, formatting, className, isFocused, onKeyDown: customOnKeyDown, }: RichTextEditorProps): import("react/jsx-runtime").JSX.Element;
45
- //# sourceMappingURL=RichTextEditor.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"RichTextEditor.d.ts","sourceRoot":"","sources":["RichTextEditor.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAsC,MAAM,OAAO,CAAC;AAG3D,MAAM,WAAW,wBAAwB;IACrC,2CAA2C;IAC3C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,6CAA6C;IAC7C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gDAAgD;IAChD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kCAAkC;IAClC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,4CAA4C;IAC5C,MAAM,CAAC,EAAE;QACL,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,0CAA0C;QAC1C,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACzC,CAAC;CACL;AAED,MAAM,WAAW,mBAAmB;IAChC,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,UAAU,CAAC,EAAE,wBAAwB,CAAC;IACtC,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,aAAa,KAAK,IAAI,CAAC;CAChD;AAED,wBAAgB,cAAc,CAAC,EAC3B,KAAK,EACL,QAAQ,EACR,WAA6B,EAC7B,UAAU,EACV,SAAc,EACd,SAAiB,EACjB,SAAS,EAAE,eAAe,GAC7B,EAAE,mBAAmB,2CA8vBrB"}