@capillarytech/creatives-library 8.0.250-alpha.2 → 8.0.251

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