From eae888aa6b056ecea5ed69178a997b1c752b7581 Mon Sep 17 00:00:00 2001 From: bulandent <1326895569@qq.com> Date: Fri, 31 Mar 2023 10:30:35 +0200 Subject: [PATCH] fix: properly parse closing where the last attribute has no value (#485) Closes #486 --- CHANGELOG.md | 18 +++ lib/sax.js | 4 +- test/dom/document.test.js | 38 +++--- .../__snapshots__/parse-element.test.js.snap | 18 +++ test/parse/parse-element.test.js | 111 ++++++++++++++++++ 5 files changed, 169 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 989c7b8f3..d4be84997 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,24 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.8.7](https://github.com/xmldom/xmldom/compare/0.8.6...0.8.7) + +### Fixed + +- properly parse closing where the last attribute has no value [`#485`](https://github.com/xmldom/xmldom/pull/485) / [`#486`](https://github.com/xmldom/xmldom/issues/486) + +Thank you, [@bulandent](https://github.com/bulandent), for your contributions + + +## [0.7.10](https://github.com/xmldom/xmldom/compare/0.7.9...0.7.10) + +### Fixed + +- properly parse closing where the last attribute has no value [`#485`](https://github.com/xmldom/xmldom/pull/485) / [`#486`](https://github.com/xmldom/xmldom/issues/486) + +Thank you, [@bulandent](https://github.com/bulandent), for your contributions + + ## [0.8.6](https://github.com/xmldom/xmldom/compare/0.8.5...0.8.6) ### Fixed diff --git a/lib/sax.js b/lib/sax.js index 0764523fb..2ec3ea1ef 100644 --- a/lib/sax.js +++ b/lib/sax.js @@ -303,7 +303,9 @@ function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,error el.closed = true; case S_ATTR_NOQUOT_VALUE: case S_ATTR: - case S_ATTR_SPACE: + break; + case S_ATTR_SPACE: + el.closed = true; break; //case S_EQ: default: diff --git a/test/dom/document.test.js b/test/dom/document.test.js index c07f4ca49..666e55c9e 100644 --- a/test/dom/document.test.js +++ b/test/dom/document.test.js @@ -165,31 +165,31 @@ describe('Document.prototype', () => { }) describe('replaceChild', () => { it('should remove the only element and add the new one', () => { - const doc = new DOMImplementation().createDocument('', 'xml'); - const initialFirstChild = doc.firstChild; - const replacement = doc.createElement('replaced'); + const doc = new DOMImplementation().createDocument('', 'xml') + const initialFirstChild = doc.firstChild + const replacement = doc.createElement('replaced') - doc.replaceChild(replacement, doc.firstChild); + doc.replaceChild(replacement, doc.firstChild) - expect(doc.childNodes).toHaveLength(1); - expect(initialFirstChild.parentNode).toBeNull(); - expect(doc.documentElement.name).toBe(replacement.name); - }); - }); + expect(doc.childNodes).toHaveLength(1) + expect(initialFirstChild.parentNode).toBeNull() + expect(doc.documentElement.name).toBe(replacement.name) + }) + }) describe('removeChild', () => { it('should remove all connections to node', () => { - const doc = new DOMImplementation().createDocument('', 'xml'); - doc.insertBefore(doc.createComment('just a comment'), doc.firstChild); - expect(doc.childNodes).toHaveLength(2); - const initialElement = doc.firstChild; + const doc = new DOMImplementation().createDocument('', 'xml') + doc.insertBefore(doc.createComment('just a comment'), doc.firstChild) + expect(doc.childNodes).toHaveLength(2) + const initialElement = doc.firstChild - doc.removeChild(initialElement); + doc.removeChild(initialElement) // expect(doc.documentElement).toBeNull(); - expect(initialElement.parentNode).toBeNull(); - expect(initialElement.nextSibling).toBeNull(); + expect(initialElement.parentNode).toBeNull() + expect(initialElement.nextSibling).toBeNull() // expect(initialElement.previousSibling).toBeNull(); - expect(doc.childNodes).toHaveLength(1); - }); - }); + expect(doc.childNodes).toHaveLength(1) + }) + }) }) diff --git a/test/parse/__snapshots__/parse-element.test.js.snap b/test/parse/__snapshots__/parse-element.test.js.snap index 50e2ddfd4..468f4e137 100644 --- a/test/parse/__snapshots__/parse-element.test.js.snap +++ b/test/parse/__snapshots__/parse-element.test.js.snap @@ -1,5 +1,23 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`XML Node Parse closing tag with unquoted value ending with // 1`] = ` +Object { + "warning": Array [ + "[xmldom warning] attribute \\"lazy/\\" missed quot(\\")! +@#[line:3,col:3]", + ], +} +`; + +exports[`XML Node Parse closing tag with unquoted value including / followed by space / 1`] = ` +Object { + "warning": Array [ + "[xmldom warning] attribute \\"lazy/\\" missed quot(\\")!! +@#[line:3,col:3]", + ], +} +`; + exports[`XML Node Parse namespaced attributes unclosed root tag will be closed 1`] = ` Object { "actual": "", diff --git a/test/parse/parse-element.test.js b/test/parse/parse-element.test.js index 5f6d2cf7b..2e4c3f7a5 100644 --- a/test/parse/parse-element.test.js +++ b/test/parse/parse-element.test.js @@ -49,6 +49,117 @@ describe('XML Node Parse', () => { expect(actual).toBe(`Harry Potter`) }) + it('closing tag without attribute value', () => { + const actual = new DOMParser() + .parseFromString( + ``, + 'text/xml' + ) + .toString() + expect(actual).toBe( + `` + ) + }) + it('closing tag with unquoted value following /', () => { + const actual = new DOMParser() + .parseFromString( + ``, + 'text/xml' + ) + .toString() + expect(actual).toBe( + `` + ) + }) + it('closing tag with unquoted value following space and /', () => { + const actual = new DOMParser() + .parseFromString( + ``, + 'text/xml' + ) + .toString() + expect(actual).toBe( + `` + ) + }) + it('closing tag with unquoted value including / followed by space /', () => { + const { errors, parser } = getTestParser() + const actual = parser + .parseFromString( + ``, + 'text/xml' + ) + .toString() + expect(errors).toMatchSnapshot() + expect(actual).toBe( + `` + ) + }) + it('closing tag with unquoted value ending with //', () => { + const { errors, parser } = getTestParser() + + const actual = parser + .parseFromString( + ``, + 'text/xml' + ) + .toString() + expect(errors).toMatchSnapshot() + expect(actual).toBe( + `` + ) + }) + describe('simple attributes', () => { describe('nothing special', () => { it.each([