From 64c73883abf12dc023262c2c078a68313a0f540c Mon Sep 17 00:00:00 2001 From: Christian Bewernitz Date: Thu, 21 Jan 2021 03:34:09 +0100 Subject: [PATCH] fix(dom): Escape `]]>` when serializing CharData (#181) --- lib/dom.js | 20 ++++++++++++++++++- test/dom/serializer.test.js | 2 +- .../xmltest/__snapshots__/not-wf.test.js.snap | 14 ++++++------- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/lib/dom.js b/lib/dom.js index b20c47aa1..afd7130ae 100644 --- a/lib/dom.js +++ b/lib/dom.js @@ -1066,7 +1066,25 @@ function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){ case ATTRIBUTE_NODE: return buf.push(' ',node.name,'="',node.value.replace(/[<&"]/g,_xmlEncoder),'"'); case TEXT_NODE: - return buf.push(node.data.replace(/[<&]/g,_xmlEncoder)); + /** + * The ampersand character (&) and the left angle bracket (<) must not appear in their literal form, + * except when used as markup delimiters, or within a comment, a processing instruction, or a CDATA section. + * If they are needed elsewhere, they must be escaped using either numeric character references or the strings + * `&` and `<` respectively. + * The right angle bracket (>) may be represented using the string " > ", and must, for compatibility, + * be escaped using either `>` or a character reference when it appears in the string `]]>` in content, + * when that string is not marking the end of a CDATA section. + * + * In the content of elements, character data is any string of characters + * which does not contain the start-delimiter of any markup + * and does not include the CDATA-section-close delimiter, `]]>`. + * + * @see https://www.w3.org/TR/xml/#NT-CharData + */ + return buf.push(node.data + .replace(/[<&]/g,_xmlEncoder) + .replace(/]]>/g, ']]>') + ); case CDATA_SECTION_NODE: return buf.push( ''); case COMMENT_NODE: diff --git a/test/dom/serializer.test.js b/test/dom/serializer.test.js index 215c218b1..7ae9f8785 100644 --- a/test/dom/serializer.test.js +++ b/test/dom/serializer.test.js @@ -6,7 +6,7 @@ describe('XML Serializer', () => { it('supports text node containing "]]>"', () => { const doc = new DOMParser().parseFromString('', 'text/xml') doc.documentElement.appendChild(doc.createTextNode('hello ]]> there')) - expect(doc.documentElement.firstChild.toString()).toBe('hello ]]> there') + expect(doc.documentElement.firstChild.toString()).toBe('hello ]]> there') }) it('supports