diff --git a/src/editors/sharedComponents/CodeEditor/hooks.js b/src/editors/sharedComponents/CodeEditor/hooks.js index cddf281dc..75e85f23e 100644 --- a/src/editors/sharedComponents/CodeEditor/hooks.js +++ b/src/editors/sharedComponents/CodeEditor/hooks.js @@ -24,9 +24,41 @@ export const prepareShowBtnEscapeHTML = () => { }; export const cleanHTML = ({ initialText }) => { + const altRegex = /(alt="(.*?)")/g; + const altTextMap = {}; + let altTextIndex = 0; + + // Replace alt attributes with ALT_TEXT_0/1/2... + const initialTextWithoutAltAttr = initialText.replace(altRegex, (match) => { + const altText = `ALT_TEXT_${altTextIndex++}`; + altTextMap[altText] = match; + return altText; + }); + + // Replace HTML entities in the rest of the text, excluding altTexts const translateRegex = new RegExp(`&(${Object.keys(alphanumericMap).join('|')});`, 'g'); const translator = ($0, $1) => alphanumericMap[$1]; - return initialText.replace(translateRegex, translator); + const cleanedTextWithoutAltAttr = initialTextWithoutAltAttr.replace(translateRegex, translator); + + // Clean altText matches in altTextMap, ignore " + const alphanumericMapForAltText = { ...alphanumericMap }; + delete alphanumericMapForAltText.quot; + Object.keys(altTextMap).forEach((key) => { + const altTextValue = altTextMap[key]; + const cleanedAltTextValue = altTextValue.replace( + /&(\w+);/g, + ($0, $1) => alphanumericMapForAltText[$1] || $0, + ); + altTextMap[key] = cleanedAltTextValue; + }); + + // Restore the original alt attributes from altTextMap + const finalCleanedText = Object.keys(altTextMap).reduce( + (text, altText) => text.replace(altText, altTextMap[altText]), + cleanedTextWithoutAltAttr, + ); + + return finalCleanedText; }; export const syntaxChecker = ({ textArr, lang }) => { diff --git a/src/editors/sharedComponents/CodeEditor/index.test.jsx b/src/editors/sharedComponents/CodeEditor/index.test.jsx index 0760f8e0d..560210966 100644 --- a/src/editors/sharedComponents/CodeEditor/index.test.jsx +++ b/src/editors/sharedComponents/CodeEditor/index.test.jsx @@ -64,10 +64,17 @@ describe('CodeEditor', () => { describe('cleanHTML', () => { const dirtyText = `&${Object.keys(alphanumericMap).join('; , &')};`; const cleanText = `${Object.values(alphanumericMap).join(' , ')}`; + const dirtyTextWithAlt = 'Description ≤ and ≥ "do not convert these to double quotes" 1 and ≤ and ≥'; + const cleanTextWithAlt = 'Description ≤ and ≥ "do not convert these to double quotes" 1 and ≤ and ≥'; it('escapes alphanumerics and sets them to be literals', () => { expect(hooks.cleanHTML({ initialText: dirtyText })).toEqual(cleanText); }); + + it('replaces alt attributes with placeholders and restores them', () => { + const result = hooks.cleanHTML({ initialText: dirtyTextWithAlt }); + expect(result).toEqual(cleanTextWithAlt); + }); }); describe('escapeHTMLSpecialChars', () => {