@capillarytech/creatives-library 8.0.249 → 8.0.250-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/assets/Android.png +0 -0
  2. package/assets/iOS.png +0 -0
  3. package/constants/unified.js +2 -1
  4. package/initialReducer.js +2 -0
  5. package/package.json +1 -1
  6. package/services/api.js +10 -0
  7. package/services/tests/api.test.js +18 -0
  8. package/utils/common.js +5 -0
  9. package/utils/commonUtils.js +28 -5
  10. package/utils/tests/commonUtil.test.js +224 -0
  11. package/utils/transformTemplateConfig.js +0 -10
  12. package/v2Components/CapDeviceContent/index.js +61 -56
  13. package/v2Components/CapTagList/index.js +6 -1
  14. package/v2Components/CapTagListWithInput/index.js +5 -1
  15. package/v2Components/CapTagListWithInput/messages.js +1 -1
  16. package/v2Components/CapWhatsappCTA/tests/index.test.js +5 -0
  17. package/v2Components/ErrorInfoNote/index.js +452 -72
  18. package/v2Components/ErrorInfoNote/messages.js +22 -0
  19. package/v2Components/ErrorInfoNote/style.scss +280 -4
  20. package/v2Components/FormBuilder/tests/index.test.js +13 -4
  21. package/v2Components/HtmlEditor/HTMLEditor.js +640 -94
  22. package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +874 -0
  23. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +1167 -133
  24. package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +27 -16
  25. package/v2Components/HtmlEditor/_htmlEditor.scss +108 -45
  26. package/v2Components/HtmlEditor/_index.lazy.scss +1 -1
  27. package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +13 -101
  28. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +148 -139
  29. package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +2 -1
  30. package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
  31. package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +9 -0
  32. package/v2Components/HtmlEditor/components/EditorToolbar/index.js +1 -1
  33. package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +22 -0
  34. package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +4 -7
  35. package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +35 -45
  36. package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +1 -3
  37. package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
  38. package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +7 -6
  39. package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +3 -6
  40. package/v2Components/HtmlEditor/components/PreviewPane/index.js +11 -13
  41. package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
  42. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +49 -31
  43. package/v2Components/HtmlEditor/components/ValidationPanel/index.js +68 -39
  44. package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +254 -0
  45. package/v2Components/HtmlEditor/components/ValidationTabs/index.js +391 -0
  46. package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +51 -0
  47. package/v2Components/HtmlEditor/constants.js +42 -20
  48. package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +373 -16
  49. package/v2Components/HtmlEditor/hooks/__tests__/useValidation.apiErrors.test.js +795 -0
  50. package/v2Components/HtmlEditor/hooks/useEditorContent.js +5 -2
  51. package/v2Components/HtmlEditor/hooks/useInAppContent.js +88 -146
  52. package/v2Components/HtmlEditor/hooks/useValidation.js +189 -53
  53. package/v2Components/HtmlEditor/index.js +1 -1
  54. package/v2Components/HtmlEditor/messages.js +95 -85
  55. package/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +94 -45
  56. package/v2Components/HtmlEditor/utils/contentSanitizer.js +40 -41
  57. package/v2Components/HtmlEditor/utils/htmlValidator.js +71 -72
  58. package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +134 -102
  59. package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +23 -25
  60. package/v2Components/HtmlEditor/utils/validationAdapter.js +66 -41
  61. package/v2Components/MobilePushPreviewV2/index.js +32 -7
  62. package/v2Components/TemplatePreview/_templatePreview.scss +44 -24
  63. package/v2Components/TemplatePreview/index.js +47 -32
  64. package/v2Components/TemplatePreview/messages.js +4 -0
  65. package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +1 -0
  66. package/v2Containers/BeeEditor/index.js +172 -90
  67. package/v2Containers/BeePopupEditor/constants.js +10 -0
  68. package/v2Containers/BeePopupEditor/index.js +193 -0
  69. package/v2Containers/BeePopupEditor/tests/index.test.js +627 -0
  70. package/v2Containers/CreativesContainer/SlideBoxContent.js +127 -51
  71. package/v2Containers/CreativesContainer/SlideBoxFooter.js +163 -13
  72. package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -1
  73. package/v2Containers/CreativesContainer/constants.js +1 -0
  74. package/v2Containers/CreativesContainer/index.js +239 -46
  75. package/v2Containers/CreativesContainer/messages.js +8 -0
  76. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +11 -2
  77. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +38 -50
  78. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +106 -0
  79. package/v2Containers/Email/actions.js +7 -0
  80. package/v2Containers/Email/constants.js +5 -1
  81. package/v2Containers/Email/index.js +222 -27
  82. package/v2Containers/Email/messages.js +32 -0
  83. package/v2Containers/Email/reducer.js +12 -1
  84. package/v2Containers/Email/sagas.js +61 -7
  85. package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +2 -0
  86. package/v2Containers/Email/tests/sagas.test.js +320 -29
  87. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +1321 -0
  88. package/v2Containers/EmailWrapper/components/EmailWrapperView.js +210 -15
  89. package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +40 -74
  90. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +1749 -0
  91. package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +520 -0
  92. package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +2 -67
  93. package/v2Containers/EmailWrapper/constants.js +2 -0
  94. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +629 -77
  95. package/v2Containers/EmailWrapper/index.js +103 -23
  96. package/v2Containers/EmailWrapper/messages.js +61 -1
  97. package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +643 -0
  98. package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +594 -77
  99. package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +376 -0
  100. package/v2Containers/InApp/__tests__/sagas.test.js +363 -0
  101. package/v2Containers/InApp/actions.js +7 -0
  102. package/v2Containers/InApp/constants.js +20 -4
  103. package/v2Containers/InApp/index.js +802 -359
  104. package/v2Containers/InApp/index.scss +4 -3
  105. package/v2Containers/InApp/messages.js +7 -3
  106. package/v2Containers/InApp/reducer.js +21 -3
  107. package/v2Containers/InApp/sagas.js +29 -9
  108. package/v2Containers/InApp/selectors.js +25 -5
  109. package/v2Containers/InApp/tests/index.test.js +154 -50
  110. package/v2Containers/InApp/tests/reducer.test.js +34 -0
  111. package/v2Containers/InApp/tests/sagas.test.js +61 -9
  112. package/v2Containers/InApp/tests/selectors.test.js +612 -0
  113. package/v2Containers/InAppWrapper/components/InAppWrapperView.js +162 -0
  114. package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +267 -0
  115. package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +9 -0
  116. package/v2Containers/InAppWrapper/constants.js +16 -0
  117. package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +473 -0
  118. package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +198 -0
  119. package/v2Containers/InAppWrapper/index.js +148 -0
  120. package/v2Containers/InAppWrapper/messages.js +49 -0
  121. package/v2Containers/InappAdvance/index.js +1099 -0
  122. package/v2Containers/InappAdvance/index.scss +10 -0
  123. package/v2Containers/InappAdvance/tests/index.test.js +448 -0
  124. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +3 -0
  125. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -0
  126. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +2 -0
  127. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +9 -0
  128. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +12 -0
  129. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -0
  130. package/v2Containers/TagList/index.js +62 -19
  131. package/v2Containers/Templates/_templates.scss +60 -1
  132. package/v2Containers/Templates/index.js +89 -4
  133. package/v2Containers/Templates/messages.js +4 -0
  134. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -0
  135. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +0 -152
  136. package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +0 -214
@@ -34,7 +34,7 @@ export const LIQUID_PATTERNS = {
34
34
  OPERATORS: /\b(and|or|not|contains|in|==|!=|<|>|<=|>=)\b/g,
35
35
 
36
36
  // String literals in Liquid
37
- STRING_LITERALS: /(["'])((?:\\.|(?!\1)[^\\])*?)\1/g
37
+ STRING_LITERALS: /(["'])((?:\\.|(?!\1)[^\\])*?)\1/g,
38
38
  };
39
39
 
40
40
  /**
@@ -68,7 +68,7 @@ export const liquidVSCodeTheme = HighlightStyle.define([
68
68
  { tag: tags.atom, color: '#4ec9b0' }, // Liquid filters
69
69
  { tag: tags.punctuation, color: '#d4d4d4' },
70
70
  { tag: tags.bracket, color: '#ffd700' },
71
- { tag: tags.brace, color: '#ffd700' }
71
+ { tag: tags.brace, color: '#ffd700' },
72
72
  ]);
73
73
 
74
74
  /**
@@ -151,7 +151,7 @@ export class LiquidValidator {
151
151
  column: 1,
152
152
  rule: 'liquid-stray-closing-output',
153
153
  severity: 'error',
154
- source: 'liquid-validator'
154
+ source: 'liquid-validator',
155
155
  });
156
156
  }
157
157
  }
@@ -160,7 +160,7 @@ export class LiquidValidator {
160
160
  // After scan, any remaining entries on stack are unclosed opening braces
161
161
  if (stack.length > 0) {
162
162
  // Report each unclosed opening brace
163
- stack.forEach(position => {
163
+ stack.forEach((position) => {
164
164
  this.errors.push({
165
165
  type: 'error',
166
166
  message: 'unclosed Liquid output tag - missing }}',
@@ -168,7 +168,7 @@ export class LiquidValidator {
168
168
  column: 1,
169
169
  rule: 'liquid-unclosed-output',
170
170
  severity: 'error',
171
- source: 'liquid-validator'
171
+ source: 'liquid-validator',
172
172
  });
173
173
  });
174
174
  }
@@ -203,7 +203,7 @@ export class LiquidValidator {
203
203
  column: 1,
204
204
  rule: 'liquid-unclosed-logic',
205
205
  severity: 'error',
206
- source: 'liquid-validator'
206
+ source: 'liquid-validator',
207
207
  });
208
208
  }
209
209
  }
@@ -216,7 +216,7 @@ export class LiquidValidator {
216
216
  const nestedOutputPattern = /\{\{[^}]*\{\{[^}]*\}\}/g;
217
217
  const nestedOutput = html.match(nestedOutputPattern);
218
218
  if (nestedOutput) {
219
- nestedOutput.forEach(match => {
219
+ nestedOutput.forEach((match) => {
220
220
  this.errors.push({
221
221
  type: 'error',
222
222
  message: `Nested braces in Liquid output tag: ${match}`,
@@ -224,7 +224,7 @@ export class LiquidValidator {
224
224
  column: 1,
225
225
  rule: 'liquid-nested-braces',
226
226
  severity: 'error',
227
- source: 'liquid-validator'
227
+ source: 'liquid-validator',
228
228
  });
229
229
  });
230
230
  }
@@ -233,7 +233,7 @@ export class LiquidValidator {
233
233
  const nestedLogicPattern = /\{%[^%]*\{%[^%]*%\}/g;
234
234
  const nestedLogic = html.match(nestedLogicPattern);
235
235
  if (nestedLogic) {
236
- nestedLogic.forEach(match => {
236
+ nestedLogic.forEach((match) => {
237
237
  this.errors.push({
238
238
  type: 'error',
239
239
  message: `Nested braces in Liquid logic tag: ${match}`,
@@ -241,7 +241,7 @@ export class LiquidValidator {
241
241
  column: 1,
242
242
  rule: 'liquid-nested-braces',
243
243
  severity: 'error',
244
- source: 'liquid-validator'
244
+ source: 'liquid-validator',
245
245
  });
246
246
  });
247
247
  }
@@ -262,10 +262,10 @@ export class LiquidValidator {
262
262
 
263
263
  logicTags.push({
264
264
  full: match[0],
265
- content: content,
266
- keyword: keyword,
265
+ content,
266
+ keyword,
267
267
  position: match.index,
268
- line: this.getLineNumber(html, match.index)
268
+ line: this.getLineNumber(html, match.index),
269
269
  });
270
270
  }
271
271
 
@@ -279,25 +279,25 @@ export class LiquidValidator {
279
279
  validateBalancedTags(logicTags) {
280
280
  const stack = [];
281
281
  const pairs = {
282
- 'if': 'endif',
283
- 'unless': 'endunless',
284
- 'for': 'endfor',
285
- 'case': 'endcase',
286
- 'capture': 'endcapture',
287
- 'comment': 'endcomment',
288
- 'tablerow': 'endtablerow',
289
- 'raw': 'endraw'
282
+ if: 'endif',
283
+ unless: 'endunless',
284
+ for: 'endfor',
285
+ case: 'endcase',
286
+ capture: 'endcapture',
287
+ comment: 'endcomment',
288
+ tablerow: 'endtablerow',
289
+ raw: 'endraw',
290
290
  };
291
291
 
292
- logicTags.forEach(tag => {
293
- const keyword = tag.keyword;
292
+ logicTags.forEach((tag) => {
293
+ const {keyword} = tag;
294
294
 
295
295
  if (pairs[keyword]) {
296
296
  // Opening tag
297
297
  stack.push({ keyword, tag });
298
298
  } else if (Object.values(pairs).includes(keyword)) {
299
299
  // Closing tag
300
- const expectedOpening = Object.keys(pairs).find(key => pairs[key] === keyword);
300
+ const expectedOpening = Object.keys(pairs).find((key) => pairs[key] === keyword);
301
301
  const lastOpening = stack.pop();
302
302
 
303
303
  if (!lastOpening) {
@@ -308,7 +308,7 @@ export class LiquidValidator {
308
308
  column: 1,
309
309
  rule: 'liquid-unexpected-closing',
310
310
  severity: 'error',
311
- source: 'liquid-validator'
311
+ source: 'liquid-validator',
312
312
  });
313
313
  } else if (lastOpening.keyword !== expectedOpening) {
314
314
  this.errors.push({
@@ -318,14 +318,31 @@ export class LiquidValidator {
318
318
  column: 1,
319
319
  rule: 'liquid-mismatched-tags',
320
320
  severity: 'error',
321
- source: 'liquid-validator'
321
+ source: 'liquid-validator',
322
322
  });
323
323
  }
324
324
  }
325
325
  });
326
326
 
327
327
  // Check for unclosed opening tags
328
- stack.forEach(unclosed => {
328
+ if (stack.length > 0) {
329
+ stack.forEach(({ keyword, tag }) => {
330
+ const expectedClosing = pairs[keyword];
331
+ const error = {
332
+ type: 'error',
333
+ message: `Unclosed Liquid tag: {% ${keyword} %} - missing {% ${expectedClosing} %}`,
334
+ line: tag.line,
335
+ column: 1,
336
+ rule: 'liquid-unclosed-tag',
337
+ severity: 'error',
338
+ source: 'liquid-validator',
339
+ };
340
+ this.errors.push(error);
341
+ });
342
+ }
343
+
344
+ // Check for unclosed opening tags
345
+ stack.forEach((unclosed) => {
329
346
  this.errors.push({
330
347
  type: 'error',
331
348
  message: `Unclosed Liquid tag: {% ${unclosed.keyword} %}`,
@@ -333,7 +350,7 @@ export class LiquidValidator {
333
350
  column: 1,
334
351
  rule: 'liquid-unclosed-tag',
335
352
  severity: 'error',
336
- source: 'liquid-validator'
353
+ source: 'liquid-validator',
337
354
  });
338
355
  });
339
356
  }
@@ -345,7 +362,7 @@ export class LiquidValidator {
345
362
  // Check for malformed filters
346
363
  const malformedFilters = html.match(/\|\s*\||\|\s*$/gm);
347
364
  if (malformedFilters) {
348
- malformedFilters.forEach(match => {
365
+ malformedFilters.forEach((match) => {
349
366
  this.warnings.push({
350
367
  type: 'warning',
351
368
  message: `Malformed Liquid filter: ${match.trim()}`,
@@ -353,19 +370,36 @@ export class LiquidValidator {
353
370
  column: 1,
354
371
  rule: 'liquid-malformed-filter',
355
372
  severity: 'warning',
356
- source: 'liquid-validator'
373
+ source: 'liquid-validator',
357
374
  });
358
375
  });
359
376
  }
360
377
 
361
378
  // Check for common filter usage
362
- const commonFilters = ['date', 'capitalize', 'upcase', 'downcase', 'strip', 'truncate', 'default'];
379
+ // Standard Liquid filters that are commonly used and shouldn't trigger info messages
380
+ // This list includes standard Liquid filters to avoid false positives
381
+ const commonFilters = [
382
+ // String filters
383
+ 'capitalize', 'upcase', 'downcase', 'strip', 'lstrip', 'rstrip', 'strip_html', 'strip_newlines',
384
+ 'truncate', 'truncatewords', 'prepend', 'append', 'remove', 'remove_first', 'replace', 'replace_first',
385
+ 'split', 'join', 'concat', 'escape', 'escape_once', 'newline_to_br',
386
+ // Array filters
387
+ 'first', 'last', 'size', 'slice', 'sort', 'sort_natural', 'map', 'where', 'uniq', 'compact', 'reverse',
388
+ // Number filters
389
+ 'abs', 'ceil', 'floor', 'round', 'times', 'divided_by', 'modulo', 'minus', 'plus', 'at_least', 'at_most',
390
+ // Date filters
391
+ 'date',
392
+ // Other common filters
393
+ 'default', 'url_encode', 'url_decode',
394
+ ];
363
395
  const filterPattern = /\|\s*([a-zA-Z_][a-zA-Z0-9_]*)/g;
364
396
  let filterMatch;
365
397
 
366
398
  while ((filterMatch = filterPattern.exec(html)) !== null) {
367
399
  const filterName = filterMatch[1];
368
400
  if (!commonFilters.includes(filterName)) {
401
+ // Only show info for truly custom/unknown filters
402
+ // Standard Liquid filters are now included in commonFilters list
369
403
  this.info.push({
370
404
  type: 'info',
371
405
  message: `Using filter: ${filterName}`,
@@ -373,7 +407,7 @@ export class LiquidValidator {
373
407
  column: 1,
374
408
  rule: 'liquid-filter-usage',
375
409
  severity: 'info',
376
- source: 'liquid-validator'
410
+ source: 'liquid-validator',
377
411
  });
378
412
  }
379
413
  }
@@ -386,7 +420,7 @@ export class LiquidValidator {
386
420
  // Check for undefined variable patterns (basic check)
387
421
  const suspiciousVariables = html.match(/\{\{\s*[^}]*undefined[^}]*\s*\}\}/g);
388
422
  if (suspiciousVariables) {
389
- suspiciousVariables.forEach(match => {
423
+ suspiciousVariables.forEach((match) => {
390
424
  this.warnings.push({
391
425
  type: 'warning',
392
426
  message: `Potentially undefined variable: ${match}`,
@@ -394,7 +428,7 @@ export class LiquidValidator {
394
428
  column: 1,
395
429
  rule: 'liquid-undefined-variable',
396
430
  severity: 'warning',
397
- source: 'liquid-validator'
431
+ source: 'liquid-validator',
398
432
  });
399
433
  });
400
434
  }
@@ -417,7 +451,7 @@ export class LiquidValidator {
417
451
  isValid: this.errors.length === 0,
418
452
  errors: this.errors,
419
453
  warnings: this.warnings,
420
- info: this.info
454
+ info: this.info,
421
455
  };
422
456
  }
423
457
  }
@@ -425,60 +459,58 @@ export class LiquidValidator {
425
459
  /**
426
460
  * Enhanced CodeMirror extensions with Liquid support
427
461
  */
428
- export const createLiquidExtensions = () => {
429
- return [
430
- // HTML language support (base)
431
- html(),
432
-
433
- // Enhanced syntax highlighting with Liquid support
434
- syntaxHighlighting(liquidVSCodeTheme),
435
-
436
- // Editor theme
437
- EditorView.theme({
438
- "&": {
439
- height: "500px",
440
- backgroundColor: "#1e1e1e",
441
- fontSize: "14px",
442
- fontFamily: "'DM Mono', 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace"
443
- },
444
- ".cm-content": {
445
- padding: "12px",
446
- backgroundColor: "#1e1e1e",
447
- fontSize: "14px",
448
- lineHeight: "20px",
449
- fontFamily: "'DM Mono', 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace",
450
- color: "#d4d4d4"
451
- },
452
- ".cm-focused": {
453
- outline: "none"
454
- },
455
- ".cm-lineNumbers": {
456
- fontSize: "14px",
457
- lineHeight: "20px",
458
- color: "#858585",
459
- backgroundColor: "#1e1e1e",
460
- paddingRight: "8px",
461
- paddingLeft: "8px",
462
- borderRight: "1px solid #3e3e3e",
463
- minWidth: "45px",
464
- textAlign: "right"
465
- },
466
- ".cm-gutters": {
467
- backgroundColor: "#1e1e1e",
468
- borderRight: "1px solid #3e3e3e"
469
- },
470
- ".cm-activeLine": {
471
- backgroundColor: "#2a2d2e"
472
- },
473
- ".cm-selection": {
474
- backgroundColor: "#264f78"
475
- },
476
- ".cm-cursor": {
477
- borderLeft: "2px solid #ffffff"
478
- }
479
- })
480
- ];
481
- };
462
+ export const createLiquidExtensions = () => [
463
+ // HTML language support (base)
464
+ html(),
465
+
466
+ // Enhanced syntax highlighting with Liquid support
467
+ syntaxHighlighting(liquidVSCodeTheme),
468
+
469
+ // Editor theme
470
+ EditorView.theme({
471
+ "&": {
472
+ height: "500px",
473
+ backgroundColor: "#1e1e1e",
474
+ fontSize: "14px",
475
+ fontFamily: "'DM Mono', 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace",
476
+ },
477
+ ".cm-content": {
478
+ padding: "12px",
479
+ backgroundColor: "#1e1e1e",
480
+ fontSize: "14px",
481
+ lineHeight: "20px",
482
+ fontFamily: "'DM Mono', 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace",
483
+ color: "#d4d4d4",
484
+ },
485
+ ".cm-focused": {
486
+ outline: "none",
487
+ },
488
+ ".cm-lineNumbers": {
489
+ fontSize: "14px",
490
+ lineHeight: "20px",
491
+ color: "#858585",
492
+ backgroundColor: "#1e1e1e",
493
+ paddingRight: "8px",
494
+ paddingLeft: "8px",
495
+ borderRight: "1px solid #3e3e3e",
496
+ minWidth: "45px",
497
+ textAlign: "right",
498
+ },
499
+ ".cm-gutters": {
500
+ backgroundColor: "#1e1e1e",
501
+ borderRight: "1px solid #3e3e3e",
502
+ },
503
+ ".cm-activeLine": {
504
+ backgroundColor: "#2a2d2e",
505
+ },
506
+ ".cm-selection": {
507
+ backgroundColor: "#264f78",
508
+ },
509
+ ".cm-cursor": {
510
+ borderLeft: "2px solid #ffffff",
511
+ },
512
+ }),
513
+ ];
482
514
 
483
515
  /**
484
516
  * Validates HTML content with Liquid template support
@@ -496,22 +528,22 @@ export const validateLiquidHTML = (html, variant = 'email') => {
496
528
  */
497
529
  export const LIQUID_SNIPPETS = {
498
530
  // Output tags
499
- 'customer_name': '{{ customer.first_name }} {{ customer.last_name }}',
500
- 'customer_email': '{{ customer.email }}',
501
- 'current_date': '{{ "now" | date: "%B %d, %Y" }}',
502
- 'organization_name': '{{ organization.name }}',
531
+ customer_name: '{{ customer.first_name }} {{ customer.last_name }}',
532
+ customer_email: '{{ customer.email }}',
533
+ current_date: '{{ "now" | date: "%B %d, %Y" }}',
534
+ organization_name: '{{ organization.name }}',
503
535
 
504
536
  // Logic tags
505
- 'if_statement': '{% if condition %}\n <!-- content -->\n{% endif %}',
506
- 'for_loop': '{% for item in collection %}\n {{ item.name }}\n{% endfor %}',
507
- 'unless_statement': '{% unless condition %}\n <!-- content -->\n{% endunless %}',
508
- 'case_statement': '{% case variable %}\n {% when "value1" %}\n <!-- content -->\n {% when "value2" %}\n <!-- content -->\n {% else %}\n <!-- default content -->\n{% endcase %}',
537
+ if_statement: '{% if condition %}\n <!-- content -->\n{% endif %}',
538
+ for_loop: '{% for item in collection %}\n {{ item.name }}\n{% endfor %}',
539
+ unless_statement: '{% unless condition %}\n <!-- content -->\n{% endunless %}',
540
+ case_statement: '{% case variable %}\n {% when "value1" %}\n <!-- content -->\n {% when "value2" %}\n <!-- content -->\n {% else %}\n <!-- default content -->\n{% endcase %}',
509
541
 
510
542
  // Common filters
511
- 'date_filter': '{{ date_variable | date: "%B %d, %Y" }}',
512
- 'capitalize_filter': '{{ text | capitalize }}',
513
- 'truncate_filter': '{{ text | truncate: 50 }}',
514
- 'default_filter': '{{ variable | default: "Default Value" }}'
543
+ date_filter: '{{ date_variable | date: "%B %d, %Y" }}',
544
+ capitalize_filter: '{{ text | capitalize }}',
545
+ truncate_filter: '{{ text | truncate: 50 }}',
546
+ default_filter: '{{ variable | default: "Default Value" }}',
515
547
  };
516
548
 
517
549
  export default {
@@ -520,5 +552,5 @@ export default {
520
552
  LiquidValidator,
521
553
  createLiquidExtensions,
522
554
  validateLiquidHTML,
523
- LIQUID_SNIPPETS
555
+ LIQUID_SNIPPETS,
524
556
  };
@@ -76,7 +76,7 @@ export const comprehensiveVSCodeTheme = HighlightStyle.define([
76
76
  { tag: tags.link, color: '#4fc1ff', textDecoration: 'underline' },
77
77
  { tag: tags.heading, color: '#9cdcfe', fontWeight: 'bold' },
78
78
  { tag: tags.emphasis, fontStyle: 'italic' },
79
- { tag: tags.strong, fontWeight: 'bold' }
79
+ { tag: tags.strong, fontWeight: 'bold' },
80
80
  ]);
81
81
 
82
82
  /**
@@ -88,7 +88,7 @@ export const cleanEditorTheme = EditorView.theme({
88
88
  height: "500px",
89
89
  backgroundColor: "#1e1e1e",
90
90
  fontSize: "14px",
91
- fontFamily: "'DM Mono', 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace"
91
+ fontFamily: "'DM Mono', 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace",
92
92
  },
93
93
  ".cm-content": {
94
94
  padding: "12px",
@@ -96,17 +96,17 @@ export const cleanEditorTheme = EditorView.theme({
96
96
  fontSize: "14px",
97
97
  lineHeight: "20px",
98
98
  fontFamily: "'DM Mono', 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace",
99
- color: "#d4d4d4" // Base text color for all content
99
+ color: "#d4d4d4", // Base text color for all content
100
100
  },
101
101
  ".cm-focused": {
102
- outline: "none"
102
+ outline: "none",
103
103
  },
104
104
  ".cm-editor": {
105
105
  borderRadius: "0",
106
- border: "none"
106
+ border: "none",
107
107
  },
108
108
  ".cm-scroller": {
109
- fontFamily: "'DM Mono', 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace"
109
+ fontFamily: "'DM Mono', 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace",
110
110
  },
111
111
  ".cm-lineNumbers": {
112
112
  fontSize: "14px",
@@ -117,47 +117,45 @@ export const cleanEditorTheme = EditorView.theme({
117
117
  paddingLeft: "8px",
118
118
  borderRight: "1px solid #3e3e3e",
119
119
  minWidth: "45px",
120
- textAlign: "right"
120
+ textAlign: "right",
121
121
  },
122
122
  ".cm-gutters": {
123
123
  backgroundColor: "#1e1e1e",
124
- borderRight: "1px solid #3e3e3e"
124
+ borderRight: "1px solid #3e3e3e",
125
125
  },
126
126
  ".cm-activeLine": {
127
- backgroundColor: "#2a2d2e"
127
+ backgroundColor: "#2a2d2e",
128
128
  },
129
129
  ".cm-selection": {
130
- backgroundColor: "#264f78"
130
+ backgroundColor: "#264f78",
131
131
  },
132
132
  ".cm-cursor": {
133
- borderLeft: "2px solid #ffffff"
133
+ borderLeft: "2px solid #ffffff",
134
134
  },
135
135
  // Additional fallback for text nodes
136
136
  ".cm-line": {
137
- color: "#d4d4d4"
138
- }
137
+ color: "#d4d4d4",
138
+ },
139
139
  });
140
140
 
141
141
  /**
142
142
  * ROBUST Extension Creator - Single, clean implementation
143
143
  * Uses only verified tags to avoid undefined errors
144
144
  */
145
- export const createRobustExtensions = () => {
146
- return [
147
- // 1. HTML language support with proper parsing
148
- html(),
145
+ export const createRobustExtensions = () => [
146
+ // 1. HTML language support with proper parsing
147
+ html(),
149
148
 
150
- // 2. SAFE syntax highlighting (using only confirmed tags)
151
- syntaxHighlighting(comprehensiveVSCodeTheme),
149
+ // 2. SAFE syntax highlighting (using only confirmed tags)
150
+ syntaxHighlighting(comprehensiveVSCodeTheme),
152
151
 
153
- // 3. Clean theme (structure only, no color conflicts)
154
- cleanEditorTheme
155
- ];
156
- };
152
+ // 3. Clean theme (structure only, no color conflicts)
153
+ cleanEditorTheme,
154
+ ];
157
155
 
158
156
  // Export the main function
159
157
  export default {
160
158
  comprehensiveVSCodeTheme,
161
159
  cleanEditorTheme,
162
- createRobustExtensions
163
- };
160
+ createRobustExtensions,
161
+ };