@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.
- package/assets/Android.png +0 -0
- package/assets/iOS.png +0 -0
- package/constants/unified.js +2 -1
- package/initialReducer.js +2 -0
- package/package.json +1 -1
- package/services/api.js +10 -0
- package/services/tests/api.test.js +18 -0
- package/utils/common.js +5 -0
- package/utils/commonUtils.js +28 -5
- package/utils/tests/commonUtil.test.js +224 -0
- package/utils/transformTemplateConfig.js +0 -10
- package/v2Components/CapDeviceContent/index.js +61 -56
- package/v2Components/CapTagList/index.js +6 -1
- package/v2Components/CapTagListWithInput/index.js +5 -1
- package/v2Components/CapTagListWithInput/messages.js +1 -1
- package/v2Components/CapWhatsappCTA/tests/index.test.js +5 -0
- package/v2Components/ErrorInfoNote/index.js +452 -72
- package/v2Components/ErrorInfoNote/messages.js +22 -0
- package/v2Components/ErrorInfoNote/style.scss +280 -4
- package/v2Components/FormBuilder/tests/index.test.js +13 -4
- package/v2Components/HtmlEditor/HTMLEditor.js +640 -94
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +874 -0
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +1167 -133
- package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +27 -16
- package/v2Components/HtmlEditor/_htmlEditor.scss +108 -45
- package/v2Components/HtmlEditor/_index.lazy.scss +1 -1
- package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +13 -101
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +148 -139
- package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +2 -1
- package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
- package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +9 -0
- package/v2Components/HtmlEditor/components/EditorToolbar/index.js +1 -1
- package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +22 -0
- package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +4 -7
- package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +35 -45
- package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +1 -3
- package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
- package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +7 -6
- package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +3 -6
- package/v2Components/HtmlEditor/components/PreviewPane/index.js +11 -13
- package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +49 -31
- package/v2Components/HtmlEditor/components/ValidationPanel/index.js +68 -39
- package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +254 -0
- package/v2Components/HtmlEditor/components/ValidationTabs/index.js +391 -0
- package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +51 -0
- package/v2Components/HtmlEditor/constants.js +42 -20
- package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +373 -16
- package/v2Components/HtmlEditor/hooks/__tests__/useValidation.apiErrors.test.js +795 -0
- package/v2Components/HtmlEditor/hooks/useEditorContent.js +5 -2
- package/v2Components/HtmlEditor/hooks/useInAppContent.js +88 -146
- package/v2Components/HtmlEditor/hooks/useValidation.js +189 -53
- package/v2Components/HtmlEditor/index.js +1 -1
- package/v2Components/HtmlEditor/messages.js +95 -85
- package/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +94 -45
- package/v2Components/HtmlEditor/utils/contentSanitizer.js +40 -41
- package/v2Components/HtmlEditor/utils/htmlValidator.js +71 -72
- package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +134 -102
- package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +23 -25
- package/v2Components/HtmlEditor/utils/validationAdapter.js +66 -41
- package/v2Components/MobilePushPreviewV2/index.js +32 -7
- package/v2Components/TemplatePreview/_templatePreview.scss +44 -24
- package/v2Components/TemplatePreview/index.js +47 -32
- package/v2Components/TemplatePreview/messages.js +4 -0
- package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +1 -0
- package/v2Containers/BeeEditor/index.js +172 -90
- package/v2Containers/BeePopupEditor/constants.js +10 -0
- package/v2Containers/BeePopupEditor/index.js +193 -0
- package/v2Containers/BeePopupEditor/tests/index.test.js +627 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +127 -51
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +163 -13
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -1
- package/v2Containers/CreativesContainer/constants.js +1 -0
- package/v2Containers/CreativesContainer/index.js +239 -46
- package/v2Containers/CreativesContainer/messages.js +8 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +11 -2
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +38 -50
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +106 -0
- package/v2Containers/Email/actions.js +7 -0
- package/v2Containers/Email/constants.js +5 -1
- package/v2Containers/Email/index.js +222 -27
- package/v2Containers/Email/messages.js +32 -0
- package/v2Containers/Email/reducer.js +12 -1
- package/v2Containers/Email/sagas.js +61 -7
- package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +2 -0
- package/v2Containers/Email/tests/sagas.test.js +320 -29
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +1321 -0
- package/v2Containers/EmailWrapper/components/EmailWrapperView.js +210 -15
- package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +40 -74
- package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +1749 -0
- package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +520 -0
- package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +2 -67
- package/v2Containers/EmailWrapper/constants.js +2 -0
- package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +629 -77
- package/v2Containers/EmailWrapper/index.js +103 -23
- package/v2Containers/EmailWrapper/messages.js +61 -1
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +643 -0
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +594 -77
- package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +376 -0
- package/v2Containers/InApp/__tests__/sagas.test.js +363 -0
- package/v2Containers/InApp/actions.js +7 -0
- package/v2Containers/InApp/constants.js +20 -4
- package/v2Containers/InApp/index.js +802 -359
- package/v2Containers/InApp/index.scss +4 -3
- package/v2Containers/InApp/messages.js +7 -3
- package/v2Containers/InApp/reducer.js +21 -3
- package/v2Containers/InApp/sagas.js +29 -9
- package/v2Containers/InApp/selectors.js +25 -5
- package/v2Containers/InApp/tests/index.test.js +154 -50
- package/v2Containers/InApp/tests/reducer.test.js +34 -0
- package/v2Containers/InApp/tests/sagas.test.js +61 -9
- package/v2Containers/InApp/tests/selectors.test.js +612 -0
- package/v2Containers/InAppWrapper/components/InAppWrapperView.js +162 -0
- package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +267 -0
- package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +9 -0
- package/v2Containers/InAppWrapper/constants.js +16 -0
- package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +473 -0
- package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +198 -0
- package/v2Containers/InAppWrapper/index.js +148 -0
- package/v2Containers/InAppWrapper/messages.js +49 -0
- package/v2Containers/InappAdvance/index.js +1099 -0
- package/v2Containers/InappAdvance/index.scss +10 -0
- package/v2Containers/InappAdvance/tests/index.test.js +448 -0
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +3 -0
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -0
- package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +2 -0
- package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +9 -0
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +12 -0
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -0
- package/v2Containers/TagList/index.js +62 -19
- package/v2Containers/Templates/_templates.scss +60 -1
- package/v2Containers/Templates/index.js +89 -4
- package/v2Containers/Templates/messages.js +4 -0
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -0
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +0 -152
- package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +0 -214
|
@@ -20,7 +20,7 @@ const defaultMessageFormatter = (messageKey, values = {}) => {
|
|
|
20
20
|
'validator.largeImageDetected': 'Large image dimensions detected - consider mobile optimization',
|
|
21
21
|
'validator.unclosedCssRule': 'Unclosed CSS rule detected',
|
|
22
22
|
'validator.emptyCssRule': 'Empty CSS rule detected',
|
|
23
|
-
'validator.cssValidationFailed': `CSS validation failed: ${values.error || 'Unknown error'}
|
|
23
|
+
'validator.cssValidationFailed': `CSS validation failed: ${values.error || 'Unknown error'}`,
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
return fallbackMessages[messageKey] || messageKey;
|
|
@@ -49,7 +49,7 @@ const HTML_RULES = {
|
|
|
49
49
|
'space-tab-mixed-disabled': 'space',
|
|
50
50
|
'id-class-ad-disabled': false,
|
|
51
51
|
'href-abs-or-rel': false,
|
|
52
|
-
'attr-unsafe-chars': true
|
|
52
|
+
'attr-unsafe-chars': true,
|
|
53
53
|
};
|
|
54
54
|
|
|
55
55
|
// Additional custom validation rules
|
|
@@ -66,7 +66,7 @@ const CUSTOM_VALIDATIONS = {
|
|
|
66
66
|
|
|
67
67
|
// InApp-specific validations
|
|
68
68
|
MOBILE_INCOMPATIBLE: /<(object|embed|applet)\b/gi,
|
|
69
|
-
LARGE_IMAGES: /width\s*:\s*[5-9]\d{2,}px|height\s*:\s*[5-9]\d{2,}px/gi
|
|
69
|
+
LARGE_IMAGES: /width\s*:\s*[5-9]\d{2,}px|height\s*:\s*[5-9]\d{2,}px/gi,
|
|
70
70
|
};
|
|
71
71
|
|
|
72
72
|
/**
|
|
@@ -82,7 +82,7 @@ export const validateHTML = (html, variant = 'email', formatMessage = defaultMes
|
|
|
82
82
|
isValid: true,
|
|
83
83
|
errors: [],
|
|
84
84
|
warnings: [],
|
|
85
|
-
info: []
|
|
85
|
+
info: [],
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
88
|
|
|
@@ -90,7 +90,7 @@ export const validateHTML = (html, variant = 'email', formatMessage = defaultMes
|
|
|
90
90
|
isValid: true,
|
|
91
91
|
errors: [],
|
|
92
92
|
warnings: [],
|
|
93
|
-
info: []
|
|
93
|
+
info: [],
|
|
94
94
|
};
|
|
95
95
|
|
|
96
96
|
try {
|
|
@@ -98,7 +98,7 @@ export const validateHTML = (html, variant = 'email', formatMessage = defaultMes
|
|
|
98
98
|
const htmlHintResults = HTMLHint.verify(html, HTML_RULES);
|
|
99
99
|
|
|
100
100
|
// Process HTMLHint results
|
|
101
|
-
htmlHintResults.forEach(issue => {
|
|
101
|
+
htmlHintResults.forEach((issue) => {
|
|
102
102
|
const error = {
|
|
103
103
|
type: issue.type,
|
|
104
104
|
message: issue.message,
|
|
@@ -106,66 +106,64 @@ export const validateHTML = (html, variant = 'email', formatMessage = defaultMes
|
|
|
106
106
|
column: issue.col,
|
|
107
107
|
rule: issue.rule.id,
|
|
108
108
|
severity: getSeverityLevel(issue.type, issue.rule.id),
|
|
109
|
-
source: 'htmlhint'
|
|
109
|
+
source: 'htmlhint',
|
|
110
110
|
};
|
|
111
111
|
|
|
112
|
-
if (error.severity === '
|
|
113
|
-
results.errors.push(error);
|
|
114
|
-
results.isValid = false;
|
|
115
|
-
} else if (error.severity === 'warning') {
|
|
112
|
+
if (error.severity === 'warning') {
|
|
116
113
|
results.warnings.push(error);
|
|
117
|
-
} else {
|
|
114
|
+
} else if (error.severity === 'info') {
|
|
118
115
|
results.info.push(error);
|
|
116
|
+
} else {
|
|
117
|
+
results.warnings.push(error);
|
|
119
118
|
}
|
|
120
119
|
});
|
|
121
|
-
|
|
122
|
-
// Run custom validations
|
|
123
|
-
runCustomValidations(html, variant, results, formatMessage);
|
|
124
|
-
|
|
125
|
-
// Run Liquid template validation
|
|
126
|
-
runLiquidValidation(html, variant, results, formatMessage);
|
|
127
|
-
|
|
128
120
|
} catch (error) {
|
|
129
|
-
|
|
130
|
-
|
|
121
|
+
// HTMLHint failed, but we still want to run custom validations and Liquid validation
|
|
122
|
+
results.warnings.push({
|
|
123
|
+
type: 'warning',
|
|
131
124
|
message: formatMessage('validator.validationFailed', { error: error.message }),
|
|
132
125
|
line: 1,
|
|
133
126
|
column: 1,
|
|
134
127
|
rule: 'validation-error',
|
|
135
|
-
severity: '
|
|
136
|
-
source: 'validator'
|
|
128
|
+
severity: 'warning',
|
|
129
|
+
source: 'validator',
|
|
137
130
|
});
|
|
138
|
-
results.isValid = false;
|
|
139
131
|
}
|
|
140
132
|
|
|
133
|
+
// Always run custom validations and Liquid validation, even if HTMLHint failed
|
|
134
|
+
// This ensures unsafe protocol detection and other critical validations still run
|
|
135
|
+
runCustomValidations(html, variant, results, formatMessage);
|
|
136
|
+
runLiquidValidation(html, variant, results, formatMessage);
|
|
137
|
+
|
|
141
138
|
return results;
|
|
142
139
|
};
|
|
143
140
|
|
|
144
141
|
/**
|
|
145
|
-
* Determines severity level based on error type and rule
|
|
142
|
+
* Determines severity level based on error type and rule.
|
|
143
|
+
* ONLY Rule Group #1 (Input & Sanitization) is blocking; that is handled in
|
|
144
|
+
* contentSanitizer/useValidation. All HTML/CSS/Liquid/security rules here are
|
|
145
|
+
* WARNING only for backward compatibility with CKEditor legacy templates.
|
|
146
146
|
*/
|
|
147
147
|
const getSeverityLevel = (type, ruleId) => {
|
|
148
|
-
const
|
|
148
|
+
const warningRules = [
|
|
149
149
|
'tag-pair',
|
|
150
150
|
'attr-no-duplication',
|
|
151
151
|
'id-unique',
|
|
152
|
-
'spec-char-escape'
|
|
153
|
-
];
|
|
154
|
-
|
|
155
|
-
const warningRules = [
|
|
152
|
+
'spec-char-escape',
|
|
156
153
|
'tagname-lowercase',
|
|
157
154
|
'attr-lowercase',
|
|
158
155
|
'attr-value-double-quotes',
|
|
159
|
-
'alt-require'
|
|
156
|
+
'alt-require',
|
|
160
157
|
];
|
|
161
158
|
|
|
162
|
-
if (
|
|
163
|
-
return '
|
|
164
|
-
}
|
|
159
|
+
if (warningRules.includes(ruleId)) {
|
|
160
|
+
return 'warning';
|
|
161
|
+
}
|
|
162
|
+
// Downgrade HTMLHint "error" type to warning (Rule Group #1 is sanitizer-only)
|
|
163
|
+
if (type === 'error') {
|
|
165
164
|
return 'warning';
|
|
166
|
-
} else {
|
|
167
|
-
return 'info';
|
|
168
165
|
}
|
|
166
|
+
return 'info';
|
|
169
167
|
};
|
|
170
168
|
|
|
171
169
|
/**
|
|
@@ -177,6 +175,7 @@ const getSeverityLevel = (type, ruleId) => {
|
|
|
177
175
|
*/
|
|
178
176
|
const runCustomValidations = (html, variant, results, formatMessage = defaultMessageFormatter) => {
|
|
179
177
|
// Check for unsafe protocols using RegExp.exec loop
|
|
178
|
+
// These are BLOCKING ERRORS (Rule Group #1: sanitizer.dangerousProtocolDetected)
|
|
180
179
|
const unsafeProtocolsRegex = new RegExp(CUSTOM_VALIDATIONS.UNSAFE_PROTOCOLS.source, CUSTOM_VALIDATIONS.UNSAFE_PROTOCOLS.flags);
|
|
181
180
|
unsafeProtocolsRegex.lastIndex = 0; // Reset lastIndex before running
|
|
182
181
|
let match;
|
|
@@ -186,9 +185,9 @@ const runCustomValidations = (html, variant, results, formatMessage = defaultMes
|
|
|
186
185
|
message: formatMessage('validator.unsafeProtocolDetected', { protocol: match[0] }),
|
|
187
186
|
line: getLineNumber(html, match.index),
|
|
188
187
|
column: 1,
|
|
189
|
-
rule: '
|
|
188
|
+
rule: 'sanitizer.dangerousProtocolDetected',
|
|
190
189
|
severity: 'error',
|
|
191
|
-
source: 'custom'
|
|
190
|
+
source: 'custom',
|
|
192
191
|
});
|
|
193
192
|
results.isValid = false;
|
|
194
193
|
|
|
@@ -209,7 +208,7 @@ const runCustomValidations = (html, variant, results, formatMessage = defaultMes
|
|
|
209
208
|
column: 1,
|
|
210
209
|
rule: 'script-tag-warning',
|
|
211
210
|
severity: 'warning',
|
|
212
|
-
source: 'custom'
|
|
211
|
+
source: 'custom',
|
|
213
212
|
});
|
|
214
213
|
|
|
215
214
|
// Guard against zero-length matches to avoid infinite loops
|
|
@@ -245,7 +244,7 @@ const validateEmailSpecific = (html, results, formatMessage = defaultMessageForm
|
|
|
245
244
|
column: 1,
|
|
246
245
|
rule: 'outlook-compatibility',
|
|
247
246
|
severity: 'warning',
|
|
248
|
-
source: 'email-specific'
|
|
247
|
+
source: 'email-specific',
|
|
249
248
|
});
|
|
250
249
|
|
|
251
250
|
// Guard against zero-length matches to avoid infinite loops
|
|
@@ -265,7 +264,7 @@ const validateEmailSpecific = (html, results, formatMessage = defaultMessageForm
|
|
|
265
264
|
column: 1,
|
|
266
265
|
rule: 'email-css-compatibility',
|
|
267
266
|
severity: 'warning',
|
|
268
|
-
source: 'email-specific'
|
|
267
|
+
source: 'email-specific',
|
|
269
268
|
});
|
|
270
269
|
|
|
271
270
|
// Guard against zero-length matches to avoid infinite loops
|
|
@@ -294,7 +293,7 @@ const validateInAppSpecific = (html, results, formatMessage = defaultMessageForm
|
|
|
294
293
|
column: 1,
|
|
295
294
|
rule: 'mobile-compatibility',
|
|
296
295
|
severity: 'warning',
|
|
297
|
-
source: 'inapp-specific'
|
|
296
|
+
source: 'inapp-specific',
|
|
298
297
|
});
|
|
299
298
|
|
|
300
299
|
// Guard against zero-length matches to avoid infinite loops
|
|
@@ -314,7 +313,7 @@ const validateInAppSpecific = (html, results, formatMessage = defaultMessageForm
|
|
|
314
313
|
column: 1,
|
|
315
314
|
rule: 'mobile-image-size',
|
|
316
315
|
severity: 'info',
|
|
317
|
-
source: 'inapp-specific'
|
|
316
|
+
source: 'inapp-specific',
|
|
318
317
|
});
|
|
319
318
|
|
|
320
319
|
// Guard against zero-length matches to avoid infinite loops
|
|
@@ -336,8 +335,9 @@ const runLiquidValidation = (html, variant, results, formatMessage = defaultMess
|
|
|
336
335
|
const liquidResults = validateLiquidHTML(html, variant);
|
|
337
336
|
|
|
338
337
|
// Merge Liquid validation results
|
|
338
|
+
// Client-side Liquid validation errors are blocking (genuine syntax errors)
|
|
339
339
|
if (liquidResults.errors) {
|
|
340
|
-
results.errors.push(...liquidResults.errors);
|
|
340
|
+
results.errors.push(...liquidResults.errors.map((e) => ({ ...e, severity: 'error' })));
|
|
341
341
|
if (liquidResults.errors.length > 0) {
|
|
342
342
|
results.isValid = false;
|
|
343
343
|
}
|
|
@@ -375,7 +375,7 @@ export const validateCSS = (css, formatMessage = defaultMessageFormatter) => {
|
|
|
375
375
|
isValid: true,
|
|
376
376
|
errors: [],
|
|
377
377
|
warnings: [],
|
|
378
|
-
info: []
|
|
378
|
+
info: [],
|
|
379
379
|
};
|
|
380
380
|
|
|
381
381
|
if (!css || typeof css !== 'string') {
|
|
@@ -388,7 +388,7 @@ export const validateCSS = (css, formatMessage = defaultMessageFormatter) => {
|
|
|
388
388
|
unclosedBraces: /\{[^{}]*$/gm,
|
|
389
389
|
invalidProperty: /[^;{}]+:\s*[^;{}]*[^;}]/g,
|
|
390
390
|
missingColon: /[^;{}]+\s+[^;{}:]+;/g,
|
|
391
|
-
emptyRule: /[^{}]+\{\s*\}/g
|
|
391
|
+
emptyRule: /[^{}]+\{\s*\}/g,
|
|
392
392
|
};
|
|
393
393
|
|
|
394
394
|
// Check for unclosed braces using RegExp.exec loop
|
|
@@ -396,16 +396,15 @@ export const validateCSS = (css, formatMessage = defaultMessageFormatter) => {
|
|
|
396
396
|
unclosedBracesRegex.lastIndex = 0; // Reset lastIndex before running
|
|
397
397
|
let match;
|
|
398
398
|
while ((match = unclosedBracesRegex.exec(css)) !== null) {
|
|
399
|
-
results.
|
|
400
|
-
type: '
|
|
399
|
+
results.warnings.push({
|
|
400
|
+
type: 'warning',
|
|
401
401
|
message: formatMessage('validator.unclosedCssRule'),
|
|
402
402
|
line: getLineNumber(css, match.index),
|
|
403
403
|
column: 1,
|
|
404
404
|
rule: 'unclosed-brace',
|
|
405
|
-
severity: '
|
|
406
|
-
source: 'css-validator'
|
|
405
|
+
severity: 'warning',
|
|
406
|
+
source: 'css-validator',
|
|
407
407
|
});
|
|
408
|
-
results.isValid = false;
|
|
409
408
|
|
|
410
409
|
// Guard against zero-length matches to avoid infinite loops
|
|
411
410
|
if (match[0].length === 0) {
|
|
@@ -417,34 +416,31 @@ export const validateCSS = (css, formatMessage = defaultMessageFormatter) => {
|
|
|
417
416
|
const emptyRulesRegex = new RegExp(validationPatterns.emptyRule.source, validationPatterns.emptyRule.flags);
|
|
418
417
|
emptyRulesRegex.lastIndex = 0; // Reset lastIndex before running
|
|
419
418
|
while ((match = emptyRulesRegex.exec(css)) !== null) {
|
|
420
|
-
results.
|
|
421
|
-
type: '
|
|
419
|
+
results.warnings.push({
|
|
420
|
+
type: 'warning',
|
|
422
421
|
message: formatMessage('validator.emptyCssRule'),
|
|
423
422
|
line: getLineNumber(css, match.index),
|
|
424
423
|
column: 1,
|
|
425
424
|
rule: 'empty-rule',
|
|
426
|
-
severity: '
|
|
427
|
-
source: 'css-validator'
|
|
425
|
+
severity: 'warning',
|
|
426
|
+
source: 'css-validator',
|
|
428
427
|
});
|
|
429
|
-
results.isValid = false;
|
|
430
428
|
|
|
431
429
|
// Guard against zero-length matches to avoid infinite loops
|
|
432
430
|
if (match[0].length === 0) {
|
|
433
431
|
emptyRulesRegex.lastIndex++;
|
|
434
432
|
}
|
|
435
433
|
}
|
|
436
|
-
|
|
437
434
|
} catch (error) {
|
|
438
|
-
results.
|
|
439
|
-
type: '
|
|
435
|
+
results.warnings.push({
|
|
436
|
+
type: 'warning',
|
|
440
437
|
message: formatMessage('validator.cssValidationFailed', { error: error.message }),
|
|
441
438
|
line: 1,
|
|
442
439
|
column: 1,
|
|
443
440
|
rule: 'css-validation-error',
|
|
444
|
-
severity: '
|
|
445
|
-
source: 'css-validator'
|
|
441
|
+
severity: 'warning',
|
|
442
|
+
source: 'css-validator',
|
|
446
443
|
});
|
|
447
|
-
results.isValid = false;
|
|
448
444
|
}
|
|
449
445
|
|
|
450
446
|
return results;
|
|
@@ -457,16 +453,20 @@ export const validateCSS = (css, formatMessage = defaultMessageFormatter) => {
|
|
|
457
453
|
* @returns {Object} Combined validation results from all CSS blocks
|
|
458
454
|
*/
|
|
459
455
|
export const extractAndValidateCSS = (html, formatMessage = defaultMessageFormatter) => {
|
|
460
|
-
if (!html)
|
|
456
|
+
if (!html) {
|
|
457
|
+
return {
|
|
458
|
+
isValid: true, errors: [], warnings: [], info: [],
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
461
|
|
|
462
462
|
// Extract CSS from style tags
|
|
463
463
|
const styleTagPattern = /<style[^>]*>([\s\S]*?)<\/style>/gi;
|
|
464
464
|
let match;
|
|
465
|
-
|
|
465
|
+
const allResults = {
|
|
466
466
|
isValid: true,
|
|
467
467
|
errors: [],
|
|
468
468
|
warnings: [],
|
|
469
|
-
info: []
|
|
469
|
+
info: [],
|
|
470
470
|
};
|
|
471
471
|
|
|
472
472
|
while ((match = styleTagPattern.exec(html)) !== null) {
|
|
@@ -483,19 +483,18 @@ export const extractAndValidateCSS = (html, formatMessage = defaultMessageFormat
|
|
|
483
483
|
}
|
|
484
484
|
}
|
|
485
485
|
|
|
486
|
-
// Check for unclosed style tags
|
|
486
|
+
// Check for unclosed style tags (warning only for CKEditor legacy compatibility)
|
|
487
487
|
const unclosedStylePattern = /<style[^>]*>(?![\s\S]*?<\/style>)/gi;
|
|
488
488
|
if (unclosedStylePattern.test(html)) {
|
|
489
|
-
allResults.
|
|
490
|
-
type: '
|
|
489
|
+
allResults.warnings.push({
|
|
490
|
+
type: 'warning',
|
|
491
491
|
message: formatMessage('validator.unclosedCssRule'),
|
|
492
492
|
line: 1,
|
|
493
493
|
column: 1,
|
|
494
494
|
rule: 'unclosed-style-tag',
|
|
495
|
-
severity: '
|
|
496
|
-
source: 'css-validator'
|
|
495
|
+
severity: 'warning',
|
|
496
|
+
source: 'css-validator',
|
|
497
497
|
});
|
|
498
|
-
allResults.isValid = false;
|
|
499
498
|
}
|
|
500
499
|
|
|
501
500
|
return allResults;
|
|
@@ -504,5 +503,5 @@ export const extractAndValidateCSS = (html, formatMessage = defaultMessageFormat
|
|
|
504
503
|
export default {
|
|
505
504
|
validateHTML,
|
|
506
505
|
validateCSS,
|
|
507
|
-
extractAndValidateCSS
|
|
506
|
+
extractAndValidateCSS,
|
|
508
507
|
};
|