diff --git a/package.json b/package.json index 009eb8c..b560753 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "xml", "displayName": "XML Tools", "description": "XML Formatting, XQuery, and XPath Tools for Visual Studio Code", - "version": "2.3.0", + "version": "2.3.1", "preview": false, "publisher": "DotJoshJohnson", "author": { diff --git a/src/common/xml-traverser.ts b/src/common/xml-traverser.ts index 9273b77..e4aa5c6 100644 --- a/src/common/xml-traverser.ts +++ b/src/common/xml-traverser.ts @@ -64,7 +64,19 @@ export class XmlTraverser { } getSiblings(node: Node): Node[] { - return [...this.getChildAttributeArray(node.parentNode), ...this.getChildElementArray(node.parentNode)]; + if (this.isElement(node)) { + return this.getSiblingElements(node); + } + + return this.getSiblingAttributes(node); + } + + getSiblingAttributes(node: Node): Node[] { + return this.getChildAttributeArray(node.parentNode); + } + + getSiblingElements(node: Node): Node[] { + return this.getChildElementArray(node.parentNode); } hasSimilarSiblings(node: Node): boolean { diff --git a/src/formatting/formatters/v2-xml-formatter.ts b/src/formatting/formatters/v2-xml-formatter.ts index 0d8af2a..ab60c13 100644 --- a/src/formatting/formatters/v2-xml-formatter.ts +++ b/src/formatting/formatters/v2-xml-formatter.ts @@ -33,6 +33,7 @@ export class V2XmlFormatter implements XmlFormatter { let location = Location.Text; let lastNonTextLocation = Location.Text; // hah let attributeQuote = ""; + let lineBreakSpree = false; // NOTE: all "exiting" checks should appear after their associated "entering" checks for (let i = 0; i < xml.length; i++) { @@ -44,7 +45,14 @@ export class V2XmlFormatter implements XmlFormatter { // entering CData if (location === Location.Text && cc === "<" && nc === "!" && nnc === "[") { - output += `${this._getIndent(options, indentLevel)}<`; + if (pc === ">" && ppc !== "/") { + output += "<"; + } + + else { + output += `${this._getIndent(options, indentLevel)}<`; + } + location = Location.CData; } @@ -94,6 +102,8 @@ export class V2XmlFormatter implements XmlFormatter { } else { + // removing trailing non-breaking whitespace here prevents endless indentations (issue #193) + output = this._removeTrailingNonBreakingWhitespace(output); output += `${this._getIndent(options, indentLevel)}<`; } @@ -176,8 +186,11 @@ export class V2XmlFormatter implements XmlFormatter { // if the end tag immediately follows a line break, just add an indentation // if the end tag immediately follows another end tag or a self-closing tag (issue #185), add a line break and indent // otherwise, this should be treated as a same-line end tag(ex. text) - if (pc === "\n") { + if (pc === "\n" || lineBreakSpree) { + // removing trailing non-breaking whitespace here prevents endless indentations (issue #193) + output = this._removeTrailingNonBreakingWhitespace(output); output += `${this._getIndent(options, indentLevel)}<`; + lineBreakSpree = false; } else if (lastNonTextLocation === Location.EndTag) { @@ -204,6 +217,14 @@ export class V2XmlFormatter implements XmlFormatter { // Text else { + if (cc === "\n") { + lineBreakSpree = true; + } + + else if (lineBreakSpree && /\S/.test(cc)) { + lineBreakSpree = false; + } + output += cc; } } @@ -219,6 +240,10 @@ export class V2XmlFormatter implements XmlFormatter { return ((options.editorOptions.insertSpaces) ? " ".repeat(options.editorOptions.tabSize) : "\t").repeat(indentLevel); } + private _removeTrailingNonBreakingWhitespace(text: string): string { + return text.replace(/[^\r\n\S]+$/, ""); + } + private _sanitizeComments(xml: string): string { let output = ""; let inComment = false; diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index 45666e7..c09df83 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -80,6 +80,14 @@ describe("V2XmlFormatter", () => { testFormatter(xmlFormatter, options, "issue-189"); }); + it("should not add extra line breaks before closing tags", () => { + testFormatter(xmlFormatter, options, "issue-193"); + }); + + it("should not add extra whitespace before CDATA", () => { + testFormatter(xmlFormatter, options, "issue-194"); + }); + }); }); diff --git a/src/test/test-data/issue-193.formatted.xml b/src/test/test-data/issue-193.formatted.xml new file mode 100644 index 0000000..18b4d70 --- /dev/null +++ b/src/test/test-data/issue-193.formatted.xml @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/src/test/test-data/issue-193.unformatted.xml b/src/test/test-data/issue-193.unformatted.xml new file mode 100644 index 0000000..e157813 --- /dev/null +++ b/src/test/test-data/issue-193.unformatted.xml @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/src/test/test-data/issue-194.formatted.xml b/src/test/test-data/issue-194.formatted.xml new file mode 100644 index 0000000..fb6e5a3 --- /dev/null +++ b/src/test/test-data/issue-194.formatted.xml @@ -0,0 +1,7 @@ + + + + This is ok + + + \ No newline at end of file diff --git a/src/test/test-data/issue-194.unformatted.xml b/src/test/test-data/issue-194.unformatted.xml new file mode 100644 index 0000000..7700a30 --- /dev/null +++ b/src/test/test-data/issue-194.unformatted.xml @@ -0,0 +1 @@ +This is ok \ No newline at end of file