@capillarytech/creatives-library 8.0.263 → 8.0.265

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 (280) hide show
  1. package/assets/Android.png +0 -0
  2. package/assets/iOS.png +0 -0
  3. package/constants/unified.js +1 -3
  4. package/initialReducer.js +0 -2
  5. package/package.json +1 -1
  6. package/services/api.js +0 -15
  7. package/services/tests/api.test.js +0 -34
  8. package/tests/integration/TemplateCreation/TemplateCreation.integration.test.js +35 -17
  9. package/tests/integration/TemplateCreation/api-response.js +1 -31
  10. package/tests/integration/TemplateCreation/msw-handler.js +0 -2
  11. package/utils/common.js +0 -11
  12. package/utils/commonUtils.js +5 -28
  13. package/utils/tests/commonUtil.test.js +0 -224
  14. package/utils/tests/transformerUtils.test.js +0 -297
  15. package/utils/transformTemplateConfig.js +10 -0
  16. package/utils/transformerUtils.js +0 -40
  17. package/v2Components/CapDeviceContent/index.js +56 -61
  18. package/v2Components/CapImageUpload/constants.js +0 -2
  19. package/v2Components/CapImageUpload/index.js +16 -65
  20. package/v2Components/CapImageUpload/index.scss +1 -4
  21. package/v2Components/CapImageUpload/messages.js +1 -5
  22. package/v2Components/CapTagList/index.js +1 -6
  23. package/v2Components/CapTagListWithInput/index.js +1 -5
  24. package/v2Components/CapTagListWithInput/messages.js +1 -1
  25. package/v2Components/CapWhatsappCTA/tests/index.test.js +0 -5
  26. package/v2Components/ErrorInfoNote/index.js +72 -402
  27. package/v2Components/ErrorInfoNote/messages.js +6 -32
  28. package/v2Components/ErrorInfoNote/style.scss +6 -278
  29. package/v2Components/FormBuilder/tests/index.test.js +4 -13
  30. package/v2Components/HtmlEditor/HTMLEditor.js +99 -418
  31. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +133 -1882
  32. package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +16 -27
  33. package/v2Components/HtmlEditor/_htmlEditor.scss +45 -108
  34. package/v2Components/HtmlEditor/_index.lazy.scss +1 -0
  35. package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +102 -23
  36. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +140 -148
  37. package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +1 -2
  38. package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
  39. package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +1 -9
  40. package/v2Components/HtmlEditor/components/EditorToolbar/index.js +6 -31
  41. package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +0 -22
  42. package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +7 -4
  43. package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +45 -35
  44. package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +3 -1
  45. package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
  46. package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +6 -7
  47. package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +10 -7
  48. package/v2Components/HtmlEditor/components/PreviewPane/index.js +43 -22
  49. package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
  50. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +152 -0
  51. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/_validationErrorDisplay.scss +0 -18
  52. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +31 -36
  53. package/v2Components/HtmlEditor/components/ValidationPanel/_validationPanel.scss +34 -46
  54. package/v2Components/HtmlEditor/components/ValidationPanel/index.js +46 -52
  55. package/v2Components/HtmlEditor/constants.js +20 -45
  56. package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +16 -373
  57. package/v2Components/HtmlEditor/hooks/__tests__/useValidation.test.js +16 -351
  58. package/v2Components/HtmlEditor/hooks/useEditorContent.js +2 -5
  59. package/v2Components/HtmlEditor/hooks/useInAppContent.js +146 -88
  60. package/v2Components/HtmlEditor/hooks/useValidation.js +56 -213
  61. package/v2Components/HtmlEditor/index.js +1 -1
  62. package/v2Components/HtmlEditor/messages.js +94 -102
  63. package/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +45 -214
  64. package/v2Components/HtmlEditor/utils/__tests__/validationAdapter.test.js +0 -134
  65. package/v2Components/HtmlEditor/utils/contentSanitizer.js +41 -40
  66. package/v2Components/HtmlEditor/utils/htmlValidator.js +72 -71
  67. package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +124 -158
  68. package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +25 -23
  69. package/v2Components/HtmlEditor/utils/validationAdapter.js +41 -66
  70. package/v2Components/MobilePushPreviewV2/index.js +7 -33
  71. package/v2Components/TemplatePreview/_templatePreview.scss +24 -55
  72. package/v2Components/TemplatePreview/index.js +32 -47
  73. package/v2Components/TemplatePreview/messages.js +0 -4
  74. package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +0 -1
  75. package/v2Containers/App/constants.js +0 -5
  76. package/v2Containers/BeeEditor/index.js +90 -172
  77. package/v2Containers/CreativesContainer/SlideBoxContent.js +53 -184
  78. package/v2Containers/CreativesContainer/SlideBoxFooter.js +13 -163
  79. package/v2Containers/CreativesContainer/SlideBoxHeader.js +1 -3
  80. package/v2Containers/CreativesContainer/constants.js +0 -4
  81. package/v2Containers/CreativesContainer/index.js +46 -408
  82. package/v2Containers/CreativesContainer/messages.js +0 -12
  83. package/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +0 -210
  84. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +2 -11
  85. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +50 -342
  86. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +0 -103
  87. package/v2Containers/Email/actions.js +0 -7
  88. package/v2Containers/Email/constants.js +1 -5
  89. package/v2Containers/Email/index.js +36 -237
  90. package/v2Containers/Email/messages.js +0 -32
  91. package/v2Containers/Email/reducer.js +1 -12
  92. package/v2Containers/Email/sagas.js +7 -61
  93. package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +0 -2
  94. package/v2Containers/Email/tests/reducer.test.js +0 -46
  95. package/v2Containers/Email/tests/sagas.test.js +29 -320
  96. package/v2Containers/EmailWrapper/components/EmailWrapperView.js +21 -211
  97. package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +74 -40
  98. package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +67 -2
  99. package/v2Containers/EmailWrapper/constants.js +0 -2
  100. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +77 -629
  101. package/v2Containers/EmailWrapper/index.js +23 -103
  102. package/v2Containers/EmailWrapper/messages.js +1 -65
  103. package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +214 -0
  104. package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +77 -594
  105. package/v2Containers/InApp/actions.js +0 -7
  106. package/v2Containers/InApp/constants.js +4 -20
  107. package/v2Containers/InApp/index.js +359 -802
  108. package/v2Containers/InApp/index.scss +3 -4
  109. package/v2Containers/InApp/messages.js +3 -7
  110. package/v2Containers/InApp/reducer.js +3 -21
  111. package/v2Containers/InApp/sagas.js +9 -29
  112. package/v2Containers/InApp/selectors.js +5 -25
  113. package/v2Containers/InApp/tests/index.test.js +50 -154
  114. package/v2Containers/InApp/tests/reducer.test.js +0 -34
  115. package/v2Containers/InApp/tests/sagas.test.js +9 -61
  116. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +0 -3
  117. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +0 -2
  118. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +0 -2
  119. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +0 -9
  120. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +0 -12
  121. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +0 -4
  122. package/v2Containers/TagList/index.js +19 -62
  123. package/v2Containers/Templates/ChannelTypeIllustration.js +1 -13
  124. package/v2Containers/Templates/_templates.scss +1 -265
  125. package/v2Containers/Templates/actions.js +1 -2
  126. package/v2Containers/Templates/constants.js +0 -1
  127. package/v2Containers/Templates/index.js +38 -363
  128. package/v2Containers/Templates/messages.js +0 -28
  129. package/v2Containers/Templates/reducer.js +0 -2
  130. package/v2Containers/Templates/tests/index.test.js +0 -10
  131. package/v2Containers/TemplatesV2/TemplatesV2.style.js +2 -4
  132. package/v2Containers/TemplatesV2/index.js +7 -15
  133. package/v2Containers/TemplatesV2/messages.js +0 -4
  134. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +0 -34
  135. package/utils/imageUrlUpload.js +0 -141
  136. package/v2Components/CapImageUrlUpload/constants.js +0 -26
  137. package/v2Components/CapImageUrlUpload/index.js +0 -365
  138. package/v2Components/CapImageUrlUpload/index.scss +0 -35
  139. package/v2Components/CapImageUrlUpload/messages.js +0 -47
  140. package/v2Components/ErrorInfoNote/constants.js +0 -1
  141. package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +0 -870
  142. package/v2Components/HtmlEditor/components/ValidationPanel/constants.js +0 -6
  143. package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +0 -281
  144. package/v2Components/HtmlEditor/components/ValidationTabs/index.js +0 -295
  145. package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +0 -51
  146. package/v2Components/HtmlEditor/utils/validationConstants.js +0 -38
  147. package/v2Components/MobilePushPreviewV2/constants.js +0 -6
  148. package/v2Containers/BeePopupEditor/_beePopupEditor.scss +0 -14
  149. package/v2Containers/BeePopupEditor/constants.js +0 -10
  150. package/v2Containers/BeePopupEditor/index.js +0 -194
  151. package/v2Containers/BeePopupEditor/tests/index.test.js +0 -627
  152. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +0 -1246
  153. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +0 -2472
  154. package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +0 -520
  155. package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +0 -956
  156. package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +0 -376
  157. package/v2Containers/InApp/__tests__/sagas.test.js +0 -363
  158. package/v2Containers/InApp/tests/selectors.test.js +0 -612
  159. package/v2Containers/InAppWrapper/components/InAppWrapperView.js +0 -151
  160. package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +0 -267
  161. package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +0 -23
  162. package/v2Containers/InAppWrapper/constants.js +0 -16
  163. package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +0 -473
  164. package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +0 -198
  165. package/v2Containers/InAppWrapper/index.js +0 -148
  166. package/v2Containers/InAppWrapper/messages.js +0 -49
  167. package/v2Containers/InappAdvance/index.js +0 -1099
  168. package/v2Containers/InappAdvance/index.scss +0 -10
  169. package/v2Containers/InappAdvance/tests/index.test.js +0 -448
  170. package/v2Containers/WebPush/Create/components/BrandIconSection.js +0 -108
  171. package/v2Containers/WebPush/Create/components/ButtonForm.js +0 -172
  172. package/v2Containers/WebPush/Create/components/ButtonItem.js +0 -101
  173. package/v2Containers/WebPush/Create/components/ButtonList.js +0 -145
  174. package/v2Containers/WebPush/Create/components/ButtonsLinksSection.js +0 -164
  175. package/v2Containers/WebPush/Create/components/ButtonsLinksSection.test.js +0 -463
  176. package/v2Containers/WebPush/Create/components/FormActions.js +0 -54
  177. package/v2Containers/WebPush/Create/components/FormActions.test.js +0 -163
  178. package/v2Containers/WebPush/Create/components/MediaSection.js +0 -142
  179. package/v2Containers/WebPush/Create/components/MediaSection.test.js +0 -341
  180. package/v2Containers/WebPush/Create/components/MessageSection.js +0 -103
  181. package/v2Containers/WebPush/Create/components/MessageSection.test.js +0 -268
  182. package/v2Containers/WebPush/Create/components/NotificationTitleSection.js +0 -87
  183. package/v2Containers/WebPush/Create/components/NotificationTitleSection.test.js +0 -210
  184. package/v2Containers/WebPush/Create/components/TemplateNameSection.js +0 -54
  185. package/v2Containers/WebPush/Create/components/TemplateNameSection.test.js +0 -143
  186. package/v2Containers/WebPush/Create/components/__snapshots__/ButtonsLinksSection.test.js.snap +0 -86
  187. package/v2Containers/WebPush/Create/components/__snapshots__/FormActions.test.js.snap +0 -16
  188. package/v2Containers/WebPush/Create/components/__snapshots__/MediaSection.test.js.snap +0 -41
  189. package/v2Containers/WebPush/Create/components/__snapshots__/MessageSection.test.js.snap +0 -54
  190. package/v2Containers/WebPush/Create/components/__snapshots__/NotificationTitleSection.test.js.snap +0 -37
  191. package/v2Containers/WebPush/Create/components/__snapshots__/TemplateNameSection.test.js.snap +0 -21
  192. package/v2Containers/WebPush/Create/components/_buttons.scss +0 -246
  193. package/v2Containers/WebPush/Create/components/tests/ButtonForm.test.js +0 -554
  194. package/v2Containers/WebPush/Create/components/tests/ButtonItem.test.js +0 -607
  195. package/v2Containers/WebPush/Create/components/tests/ButtonList.test.js +0 -633
  196. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonForm.test.js.snap +0 -666
  197. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonItem.test.js.snap +0 -74
  198. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonList.test.js.snap +0 -78
  199. package/v2Containers/WebPush/Create/hooks/useButtonManagement.js +0 -138
  200. package/v2Containers/WebPush/Create/hooks/useButtonManagement.test.js +0 -406
  201. package/v2Containers/WebPush/Create/hooks/useCharacterCount.js +0 -30
  202. package/v2Containers/WebPush/Create/hooks/useCharacterCount.test.js +0 -151
  203. package/v2Containers/WebPush/Create/hooks/useImageUpload.js +0 -104
  204. package/v2Containers/WebPush/Create/hooks/useImageUpload.test.js +0 -538
  205. package/v2Containers/WebPush/Create/hooks/useTagManagement.js +0 -122
  206. package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +0 -633
  207. package/v2Containers/WebPush/Create/index.js +0 -1148
  208. package/v2Containers/WebPush/Create/index.scss +0 -134
  209. package/v2Containers/WebPush/Create/messages.js +0 -211
  210. package/v2Containers/WebPush/Create/preview/DevicePreviewContent.js +0 -228
  211. package/v2Containers/WebPush/Create/preview/NotificationContainer.js +0 -294
  212. package/v2Containers/WebPush/Create/preview/PreviewContent.js +0 -90
  213. package/v2Containers/WebPush/Create/preview/PreviewControls.js +0 -305
  214. package/v2Containers/WebPush/Create/preview/PreviewDisclaimer.js +0 -25
  215. package/v2Containers/WebPush/Create/preview/WebPushPreview.js +0 -155
  216. package/v2Containers/WebPush/Create/preview/assets/Light.svg +0 -53
  217. package/v2Containers/WebPush/Create/preview/assets/Top.svg +0 -5
  218. package/v2Containers/WebPush/Create/preview/assets/android-arrow-down.svg +0 -9
  219. package/v2Containers/WebPush/Create/preview/assets/android-arrow-up.svg +0 -9
  220. package/v2Containers/WebPush/Create/preview/assets/chrome-icon.png +0 -0
  221. package/v2Containers/WebPush/Create/preview/assets/edge-icon.png +0 -0
  222. package/v2Containers/WebPush/Create/preview/assets/firefox-icon.svg +0 -106
  223. package/v2Containers/WebPush/Create/preview/assets/iOS.svg +0 -26
  224. package/v2Containers/WebPush/Create/preview/assets/macos-arrow-down-icon.svg +0 -9
  225. package/v2Containers/WebPush/Create/preview/assets/macos-triple-dot-icon.svg +0 -9
  226. package/v2Containers/WebPush/Create/preview/assets/opera-icon.svg +0 -18
  227. package/v2Containers/WebPush/Create/preview/assets/safari-icon.svg +0 -29
  228. package/v2Containers/WebPush/Create/preview/assets/windows-close-icon.svg +0 -9
  229. package/v2Containers/WebPush/Create/preview/assets/windows-triple-dot-icon.svg +0 -9
  230. package/v2Containers/WebPush/Create/preview/components/AndroidMobileChromeHeader.js +0 -51
  231. package/v2Containers/WebPush/Create/preview/components/AndroidMobileExpanded.js +0 -145
  232. package/v2Containers/WebPush/Create/preview/components/IOSHeader.js +0 -45
  233. package/v2Containers/WebPush/Create/preview/components/NotificationExpandedContent.js +0 -68
  234. package/v2Containers/WebPush/Create/preview/components/NotificationHeader.js +0 -61
  235. package/v2Containers/WebPush/Create/preview/components/WindowsChromeExpanded.js +0 -99
  236. package/v2Containers/WebPush/Create/preview/components/tests/AndroidMobileExpanded.test.js +0 -733
  237. package/v2Containers/WebPush/Create/preview/components/tests/WindowsChromeExpanded.test.js +0 -571
  238. package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/AndroidMobileExpanded.test.js.snap +0 -85
  239. package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/WindowsChromeExpanded.test.js.snap +0 -81
  240. package/v2Containers/WebPush/Create/preview/config/notificationMappings.js +0 -50
  241. package/v2Containers/WebPush/Create/preview/constants.js +0 -637
  242. package/v2Containers/WebPush/Create/preview/notification-container.scss +0 -79
  243. package/v2Containers/WebPush/Create/preview/preview.scss +0 -358
  244. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-chrome.scss +0 -370
  245. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-edge.scss +0 -12
  246. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-firefox.scss +0 -12
  247. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-opera.scss +0 -12
  248. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-chrome.scss +0 -47
  249. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-edge.scss +0 -11
  250. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-firefox.scss +0 -11
  251. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-opera.scss +0 -11
  252. package/v2Containers/WebPush/Create/preview/styles/_base.scss +0 -207
  253. package/v2Containers/WebPush/Create/preview/styles/_ios.scss +0 -153
  254. package/v2Containers/WebPush/Create/preview/styles/_ipados.scss +0 -107
  255. package/v2Containers/WebPush/Create/preview/styles/_macos-chrome.scss +0 -101
  256. package/v2Containers/WebPush/Create/preview/styles/_windows-chrome.scss +0 -229
  257. package/v2Containers/WebPush/Create/preview/tests/DevicePreviewContent.test.js +0 -909
  258. package/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +0 -1081
  259. package/v2Containers/WebPush/Create/preview/tests/PreviewControls.test.js +0 -723
  260. package/v2Containers/WebPush/Create/preview/tests/WebPushPreview.test.js +0 -1327
  261. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/DevicePreviewContent.test.js.snap +0 -131
  262. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/NotificationContainer.test.js.snap +0 -112
  263. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/PreviewControls.test.js.snap +0 -144
  264. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/WebPushPreview.test.js.snap +0 -129
  265. package/v2Containers/WebPush/Create/utils/payloadBuilder.js +0 -96
  266. package/v2Containers/WebPush/Create/utils/payloadBuilder.test.js +0 -396
  267. package/v2Containers/WebPush/Create/utils/previewUtils.js +0 -89
  268. package/v2Containers/WebPush/Create/utils/urlValidation.js +0 -115
  269. package/v2Containers/WebPush/Create/utils/urlValidation.test.js +0 -449
  270. package/v2Containers/WebPush/Create/utils/validation.js +0 -75
  271. package/v2Containers/WebPush/Create/utils/validation.test.js +0 -283
  272. package/v2Containers/WebPush/actions.js +0 -60
  273. package/v2Containers/WebPush/constants.js +0 -132
  274. package/v2Containers/WebPush/index.js +0 -2
  275. package/v2Containers/WebPush/reducer.js +0 -104
  276. package/v2Containers/WebPush/sagas.js +0 -119
  277. package/v2Containers/WebPush/selectors.js +0 -65
  278. package/v2Containers/WebPush/tests/reducer.test.js +0 -863
  279. package/v2Containers/WebPush/tests/sagas.test.js +0 -566
  280. package/v2Containers/WebPush/tests/selectors.test.js +0 -960
@@ -1,17 +1,11 @@
1
1
  /**
2
2
  * Validation Hook for HTML Editor
3
- * Manages real-time validation and error display.
4
- * UI gating: only Rule Group #1 (Input & Sanitization) blocks Save/Update/Preview/Test.
5
- * All other rules are warnings for backward compatibility with CKEditor legacy templates.
3
+ * Manages real-time validation and error display
6
4
  */
7
5
 
8
- import {
9
- useState, useEffect, useCallback, useRef,
10
- } from 'react';
6
+ import { useState, useEffect, useCallback, useRef } from 'react';
11
7
  import { validateHTML, extractAndValidateCSS } from '../utils/htmlValidator';
12
8
  import { sanitizeHTML, isContentSafe, findUnsafeContent } from '../utils/contentSanitizer';
13
- import { BLOCKING_ERROR_RULE_IDS, VALIDATION_SEVERITY } from '../constants';
14
- import { ISSUE_SOURCES } from '../utils/validationConstants';
15
9
 
16
10
  /**
17
11
  * Custom hook for managing HTML/CSS validation
@@ -22,61 +16,12 @@ import { ISSUE_SOURCES } from '../utils/validationConstants';
22
16
  * @param {Function} formatValidatorMessage - Message formatter function for validator internationalization
23
17
  * @returns {Object} Validation state and methods
24
18
  */
25
- /**
26
- * Get line number for a character position in text
27
- */
28
- const getLineNumberFromPosition = (text, position) => {
29
- if (position === undefined || position < 0) return 1;
30
- return text.substring(0, position).split('\n').length;
31
- };
32
-
33
- /**
34
- * Get 1-based line and column from a character position in text
35
- */
36
- const getLineAndColumnFromPosition = (text, position) => {
37
- if (!text || position === undefined || position < 0) {
38
- return { line: 1, column: 1 };
39
- }
40
- const before = text.substring(0, position);
41
- const lines = before.split('\n');
42
- const line = lines.length;
43
- const lastLine = lines[lines.length - 1] || '';
44
- const column = lastLine.length + 1;
45
- return { line, column };
46
- };
47
-
48
- /**
49
- * Find line number for a tag or pattern in content
50
- * Used for API errors to locate where the error occurs
51
- */
52
- const findLineNumberForTag = (content, tagName) => {
53
- if (!content || !tagName) return null;
54
-
55
- // Try to find the tag in the content
56
- // Look for patterns like {{ tagName }}, {{tagName}}, etc.
57
- const escapedTagName = tagName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
58
- const patterns = [
59
- new RegExp(`\\{\\{\\s*${escapedTagName}\\s*\\}\\}`, 'g'),
60
- new RegExp(`\\{%[^%]*${escapedTagName}[^%]*%\\}`, 'g'),
61
- ];
62
-
63
- for (const pattern of patterns) {
64
- const match = pattern.exec(content);
65
- if (match) {
66
- return getLineNumberFromPosition(content, match.index);
67
- }
68
- }
69
-
70
- return null;
71
- };
72
-
73
19
  export const useValidation = (content, variant = 'email', options = {}, formatSanitizerMessage = null, formatValidatorMessage = null) => {
74
20
  const {
75
21
  enableRealTime = true,
76
22
  debounceMs = 500,
77
23
  enableSanitization = true,
78
- securityLevel = 'standard',
79
- apiValidationErrors = null, // API validation errors from validateLiquidTemplateContent
24
+ securityLevel = 'standard'
80
25
  } = options;
81
26
 
82
27
  // Validation state
@@ -97,8 +42,8 @@ export const useValidation = (content, variant = 'email', options = {}, formatSa
97
42
  totalErrors: 0,
98
43
  totalWarnings: 0,
99
44
  totalInfo: 0,
100
- hasSecurityIssues: false,
101
- },
45
+ hasSecurityIssues: false
46
+ }
102
47
  });
103
48
 
104
49
  // Refs for debouncing
@@ -110,7 +55,7 @@ export const useValidation = (content, variant = 'email', options = {}, formatSa
110
55
  */
111
56
  const performValidation = useCallback(async (htmlContent) => {
112
57
  if (!htmlContent) {
113
- setValidationState((prev) => ({
58
+ setValidationState(prev => ({
114
59
  ...prev,
115
60
  isValidating: false,
116
61
  htmlErrors: [],
@@ -127,13 +72,13 @@ export const useValidation = (content, variant = 'email', options = {}, formatSa
127
72
  totalErrors: 0,
128
73
  totalWarnings: 0,
129
74
  totalInfo: 0,
130
- hasSecurityIssues: false,
131
- },
75
+ hasSecurityIssues: false
76
+ }
132
77
  }));
133
78
  return;
134
79
  }
135
80
 
136
- setValidationState((prev) => ({ ...prev, isValidating: true }));
81
+ setValidationState(prev => ({ ...prev, isValidating: true }));
137
82
 
138
83
  try {
139
84
  // 1. HTML Validation
@@ -146,21 +91,15 @@ export const useValidation = (content, variant = 'email', options = {}, formatSa
146
91
  const isSecure = isContentSafe(htmlContent);
147
92
  const securityIssues = isSecure ? [] : findUnsafeContent(htmlContent);
148
93
 
149
- // 4. Sanitization (if enabled) – Rule Group #1 issues come from here
94
+ // 4. Sanitization (if enabled)
150
95
  let sanitizationResult = null;
151
96
  if (enableSanitization) {
152
97
  sanitizationResult = sanitizeHTML(htmlContent, variant, securityLevel, formatSanitizerMessage);
153
98
  }
154
99
 
155
- const sanitizationWarnings = sanitizationResult?.warnings || [];
156
- const blockingSanitizerCount = sanitizationWarnings.filter((w) => BLOCKING_ERROR_RULE_IDS.includes(w.rule)).length;
157
- const protocolSecurityCount = (securityIssues || []).filter((s) => ['JavaScript Protocol', 'Data URL', 'VBScript Protocol'].includes(s?.type)).length;
158
-
159
- // Summary: totalErrors/totalWarnings are for display; blocking count is for gating
160
- const totalErrors = htmlValidation.errors.length + cssValidation.errors.length + blockingSanitizerCount + protocolSecurityCount;
161
- const totalWarnings = htmlValidation.warnings.length + cssValidation.warnings.length
162
- + (sanitizationWarnings.length - blockingSanitizerCount)
163
- + (securityIssues.length - protocolSecurityCount);
100
+ // Calculate summary
101
+ const totalErrors = htmlValidation.errors.length + cssValidation.errors.length;
102
+ const totalWarnings = htmlValidation.warnings.length + cssValidation.warnings.length;
164
103
  const totalInfo = htmlValidation.info.length + cssValidation.info.length;
165
104
  const hasSecurityIssues = securityIssues.length > 0;
166
105
 
@@ -175,19 +114,20 @@ export const useValidation = (content, variant = 'email', options = {}, formatSa
175
114
  cssWarnings: cssValidation.warnings,
176
115
  cssInfo: cssValidation.info,
177
116
  securityIssues,
178
- sanitizationWarnings,
117
+ sanitizationWarnings: sanitizationResult?.warnings || [],
179
118
  isValid: htmlValidation.isValid && cssValidation.isValid,
180
119
  isSecure,
181
120
  summary: {
182
121
  totalErrors,
183
122
  totalWarnings,
184
123
  totalInfo,
185
- hasSecurityIssues,
186
- },
124
+ hasSecurityIssues
125
+ }
187
126
  });
127
+
188
128
  } catch (error) {
189
129
  console.error('Validation error:', error);
190
- setValidationState((prev) => ({
130
+ setValidationState(prev => ({
191
131
  ...prev,
192
132
  isValidating: false,
193
133
  htmlErrors: [{
@@ -197,13 +137,13 @@ export const useValidation = (content, variant = 'email', options = {}, formatSa
197
137
  column: 1,
198
138
  rule: 'validation-error',
199
139
  severity: 'error',
200
- source: 'validator',
140
+ source: 'validator'
201
141
  }],
202
142
  isValid: false,
203
143
  summary: {
204
144
  ...prev.summary,
205
- totalErrors: 1,
206
- },
145
+ totalErrors: 1
146
+ }
207
147
  }));
208
148
  }
209
149
  }, [variant, enableSanitization, securityLevel, formatSanitizerMessage, formatValidatorMessage]);
@@ -268,8 +208,8 @@ export const useValidation = (content, variant = 'email', options = {}, formatSa
268
208
  totalErrors: 0,
269
209
  totalWarnings: 0,
270
210
  totalInfo: 0,
271
- hasSecurityIssues: false,
272
- },
211
+ hasSecurityIssues: false
212
+ }
273
213
  });
274
214
  }, []);
275
215
 
@@ -283,10 +223,10 @@ export const useValidation = (content, variant = 'email', options = {}, formatSa
283
223
  ...validationState.htmlInfo,
284
224
  ...validationState.cssErrors,
285
225
  ...validationState.cssWarnings,
286
- ...validationState.cssInfo,
226
+ ...validationState.cssInfo
287
227
  ];
288
228
 
289
- return allErrors.filter((error) => error.severity === severity);
229
+ return allErrors.filter(error => error.severity === severity);
290
230
  }, [validationState]);
291
231
 
292
232
  /**
@@ -299,116 +239,32 @@ export const useValidation = (content, variant = 'email', options = {}, formatSa
299
239
  ...validationState.htmlInfo,
300
240
  ...validationState.cssErrors,
301
241
  ...validationState.cssWarnings,
302
- ...validationState.cssInfo,
242
+ ...validationState.cssInfo
303
243
  ];
304
244
 
305
- return allErrors.filter((error) => error.source === source);
245
+ return allErrors.filter(error => error.source === source);
306
246
  }, [validationState]);
307
247
 
308
- /**
309
- * Extract line number from error message if present
310
- * API errors might contain line numbers in messages like "Error at line 5" or "Line 10: error"
311
- * Also tries to find line number by searching for the problematic tag in content
312
- */
313
- const extractLineNumberFromMessage = useCallback((message) => {
314
- if (!message || typeof message !== 'string') {
315
- return null;
316
- }
317
- // Try to match patterns like "line 5", "Line 10", "at line 15", "line: 20", etc.
318
- const lineMatch = message.match(/\b(?:line|Line|LINE)\s*:?\s*(\d+)\b/i);
319
- if (lineMatch && lineMatch[1]) {
320
- return parseInt(lineMatch[1], 10);
321
- }
322
-
323
- // Try to extract tag name from error message (e.g., "Unsupported tags: test" -> "test")
324
- const tagMatch = message.match(/(?:tag|tags|Tag|Tags)[\s:]+([a-zA-Z_][a-zA-Z0-9_.]*)/i);
325
- if (tagMatch && tagMatch[1] && content) {
326
- const tagName = tagMatch[1];
327
- const lineNumber = findLineNumberForTag(content, tagName);
328
- if (lineNumber) {
329
- return lineNumber;
330
- }
331
- }
332
-
333
- return null;
334
- }, [content]);
335
-
336
248
  /**
337
249
  * Get all errors and warnings combined
338
- * Includes both client-side validation errors and API validation errors
339
250
  */
340
251
  const getAllIssues = useCallback(() => {
341
- // API errors (liquid + standard) are blocking – they block Save/Update/Preview/Test
342
- const apiLiquidErrors = (apiValidationErrors?.liquidErrors || []).map((errorMessage) => {
343
- const extractedLine = extractLineNumberFromMessage(errorMessage);
344
- return {
345
- type: VALIDATION_SEVERITY.ERROR,
346
- message: errorMessage,
347
- line: extractedLine,
348
- column: null,
349
- rule: 'liquid-api-validation',
350
- severity: VALIDATION_SEVERITY.ERROR,
351
- source: ISSUE_SOURCES.LIQUID,
352
- };
353
- });
354
-
355
- const apiStandardErrors = (apiValidationErrors?.standardErrors || []).map((errorMessage) => {
356
- const extractedLine = extractLineNumberFromMessage(errorMessage);
357
- return {
358
- type: VALIDATION_SEVERITY.ERROR,
359
- message: errorMessage,
360
- line: extractedLine,
361
- column: null,
362
- rule: 'standard-api-validation',
363
- severity: VALIDATION_SEVERITY.ERROR,
364
- source: 'api-validator',
365
- };
366
- });
367
-
368
- // Security: protocol types are Rule Group #1 (blocking); others are warnings
369
- // Use issue.position (from findUnsafeContent) to show real line/column when available
370
- const PROTOCOL_TYPES = ['JavaScript Protocol', 'Data URL', 'VBScript Protocol'];
371
- const contentStr = typeof content === 'string' ? content : '';
372
- const securityAsIssues = (validationState.securityIssues || []).map((issue) => {
373
- const isBlocking = PROTOCOL_TYPES.includes(issue?.type);
374
- const { line, column } = (issue?.position !== undefined && contentStr)
375
- ? getLineAndColumnFromPosition(contentStr, issue.position)
376
- : { line: 1, column: 1 };
377
- return {
378
- type: isBlocking ? VALIDATION_SEVERITY.ERROR : VALIDATION_SEVERITY.WARNING,
252
+ return [
253
+ ...validationState.htmlErrors,
254
+ ...validationState.htmlWarnings,
255
+ ...validationState.htmlInfo,
256
+ ...validationState.cssErrors,
257
+ ...validationState.cssWarnings,
258
+ ...validationState.cssInfo,
259
+ ...validationState.securityIssues.map(issue => ({
260
+ type: 'error',
379
261
  message: `Security issue: ${issue.type}`,
380
- line,
381
- column,
382
- rule: isBlocking ? 'sanitizer.dangerousProtocolDetected' : 'security-violation',
383
- severity: isBlocking ? VALIDATION_SEVERITY.ERROR : VALIDATION_SEVERITY.WARNING,
384
- source: 'security',
385
- };
386
- });
387
-
388
- // Sanitization warnings (Rule Group #1 entries have rule set by contentSanitizer)
389
- const sanitizationAsIssues = (validationState.sanitizationWarnings || []).map((w) => {
390
- const sev = BLOCKING_ERROR_RULE_IDS.includes(w.rule) ? VALIDATION_SEVERITY.ERROR : VALIDATION_SEVERITY.WARNING;
391
- return {
392
- ...w,
393
- severity: sev,
394
- rule: w.rule || 'sanitizer.unknown',
395
- line: w.line ?? 1,
396
- column: w.column ?? 1,
397
- source: w.source || 'sanitizer',
398
- };
399
- });
400
-
401
- const allIssues = [
402
- ...(validationState.htmlErrors || []),
403
- ...(validationState.htmlWarnings || []),
404
- ...(validationState.htmlInfo || []),
405
- ...(validationState.cssErrors || []),
406
- ...(validationState.cssWarnings || []),
407
- ...(validationState.cssInfo || []),
408
- ...securityAsIssues,
409
- ...sanitizationAsIssues,
410
- ...apiLiquidErrors,
411
- ...apiStandardErrors,
262
+ line: 1,
263
+ column: 1,
264
+ rule: 'security-violation',
265
+ severity: 'error',
266
+ source: 'security'
267
+ }))
412
268
  ].sort((a, b) => {
413
269
  // Sort by severity (error > warning > info) then by line number
414
270
  const severityOrder = { error: 0, warning: 1, info: 2 };
@@ -417,22 +273,16 @@ export const useValidation = (content, variant = 'email', options = {}, formatSa
417
273
  }
418
274
  return (a.line || 0) - (b.line || 0);
419
275
  });
420
-
421
- // Ensure we always return an array
422
- return Array.isArray(allIssues) ? allIssues : [];
423
- }, [validationState, apiValidationErrors, extractLineNumberFromMessage, content]);
276
+ }, [validationState]);
424
277
 
425
278
  /**
426
279
  * Check if validation is clean (no errors or warnings)
427
- * Includes API validation errors in the check
428
280
  */
429
281
  const isClean = useCallback(() => {
430
- const hasApiErrors = (apiValidationErrors?.liquidErrors?.length || 0) + (apiValidationErrors?.standardErrors?.length || 0) > 0;
431
- return validationState.summary.totalErrors === 0
432
- && validationState.summary.totalWarnings === 0
433
- && !validationState.summary.hasSecurityIssues
434
- && !hasApiErrors;
435
- }, [validationState.summary, apiValidationErrors]);
282
+ return validationState.summary.totalErrors === 0 &&
283
+ validationState.summary.totalWarnings === 0 &&
284
+ !validationState.summary.hasSecurityIssues;
285
+ }, [validationState.summary]);
436
286
 
437
287
  // Effect to validate content when it changes
438
288
  useEffect(() => {
@@ -442,19 +292,14 @@ export const useValidation = (content, variant = 'email', options = {}, formatSa
442
292
  }, [content, validateContent, enableRealTime]);
443
293
 
444
294
  // Cleanup on unmount
445
- useEffect(() => () => {
446
- if (debounceRef.current) {
447
- clearTimeout(debounceRef.current);
448
- }
295
+ useEffect(() => {
296
+ return () => {
297
+ if (debounceRef.current) {
298
+ clearTimeout(debounceRef.current);
299
+ }
300
+ };
449
301
  }, []);
450
302
 
451
- const hasApiErrors = (apiValidationErrors?.liquidErrors?.length || 0) + (apiValidationErrors?.standardErrors?.length || 0) > 0;
452
-
453
- const protocolTypes = ['JavaScript Protocol', 'Data URL', 'VBScript Protocol'];
454
- // Client-side Liquid validation errors are blocking (genuine syntax errors)
455
- const hasClientSideLiquidErrors = (validationState.htmlErrors || []).some((e) => e.source === ISSUE_SOURCES.LIQUID && e.severity === VALIDATION_SEVERITY.ERROR);
456
- const hasBlockingErrors = (validationState.sanitizationWarnings || []).some((w) => BLOCKING_ERROR_RULE_IDS.includes(w.rule)) || (validationState.securityIssues || []).some((s) => protocolTypes.includes(s?.type)) || hasApiErrors || hasClientSideLiquidErrors;
457
-
458
303
  return {
459
304
  // Validation state
460
305
  ...validationState,
@@ -471,12 +316,10 @@ export const useValidation = (content, variant = 'email', options = {}, formatSa
471
316
  isClean,
472
317
 
473
318
  // Computed properties
474
- hasErrors: validationState.summary.totalErrors > 0 || hasApiErrors,
319
+ hasErrors: validationState.summary.totalErrors > 0,
475
320
  hasWarnings: validationState.summary.totalWarnings > 0,
476
- hasSecurityIssues: validationState.summary.hasSecurityIssues,
477
- /** True only when Rule Group #1 (Input & Sanitization) issues exist. Use for UI gating. */
478
- hasBlockingErrors,
321
+ hasSecurityIssues: validationState.summary.hasSecurityIssues
479
322
  };
480
323
  };
481
324
 
482
- export default useValidation;
325
+ export default useValidation;
@@ -26,4 +26,4 @@ export { HTML_EDITOR_VARIANTS, DEVICE_TYPES } from './constants';
26
26
  * - Default export (lazy): ~0KB initial bundle (loads ~400KB when needed)
27
27
  * - HTMLEditorSync: ~400KB added to initial bundle
28
28
  * - Constants: ~1KB added to initial bundle
29
- */
29
+ */