diff --git a/src/formatting/formatters/v2-xml-formatter.ts b/src/formatting/formatters/v2-xml-formatter.ts index e6d21b7..c462a9d 100644 --- a/src/formatting/formatters/v2-xml-formatter.ts +++ b/src/formatting/formatters/v2-xml-formatter.ts @@ -2,11 +2,17 @@ import { XmlFormatter } from "../xml-formatter"; import { XmlFormattingOptions } from "../xml-formatting-options"; import { ClassicXmlFormatter } from "./classic-xml-formatter"; +const MagicalStringOfWonders = "~::~MAAAGIC~::~"; + /* tslint:disable no-use-before-declare */ export class V2XmlFormatter implements XmlFormatter { formatXml(xml: string, options: XmlFormattingOptions): string { + // this replaces all "<" brackets inside of comments to a magical string + // so the following minification steps don't mess with comment formatting + xml = this._sanitizeComments(xml); + // remove whitespace from between tags, except for line breaks - xml = xml.replace(/>\s{0,} { // spaces between the node name and the first attribute + xml = xml.replace(/>\s{0,} { return match.replace(/[^\S\r\n]/g, ""); }); @@ -18,6 +24,9 @@ export class V2XmlFormatter implements XmlFormatter { return match.replace(/\s+/g, " "); }); + // the coast is clear - we can drop those "<" brackets back in + xml = this._unsanitizeComments(xml); + let output = ""; let indentLevel = 0; @@ -185,6 +194,46 @@ export class V2XmlFormatter implements XmlFormatter { private _getIndent(options: XmlFormattingOptions, indentLevel: number): string { return ((options.editorOptions.insertSpaces) ? " ".repeat(options.editorOptions.tabSize) : "\t").repeat(indentLevel); } + + private _sanitizeComments(xml: string): string { + let output = ""; + let inComment = false; + + for (let i = 0; i < xml.length; i++) { + const cc = xml[i]; + const nc = xml.charAt(i + 1); + const nnc = xml.charAt(i + 2); + const pc = xml.charAt(i - 1); + + if (!inComment && cc === "<" && nc === "!" && nnc === "-") { + inComment = true; + output += ""; + + i += 2; + } + + else { + output += cc; + } + } + + return output; + } + + private _unsanitizeComments(xml: string): string { + return xml.replace(new RegExp(MagicalStringOfWonders, "g"), "<"); + } } enum Location { diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index 8d12984..0b14435 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -48,6 +48,10 @@ describe("V2XmlFormatter", () => { testFormatter(xmlFormatter, options, "preserve-breaks"); }); + it("should maintain comment formatting", () => { + testFormatter(xmlFormatter, options, "maintain-comment-formatting"); + }); + }); }); diff --git a/src/test/test-data/maintain-comment-formatting.formatted.xml b/src/test/test-data/maintain-comment-formatting.formatted.xml new file mode 100644 index 0000000..160f0c9 --- /dev/null +++ b/src/test/test-data/maintain-comment-formatting.formatted.xml @@ -0,0 +1,13 @@ + + text + + \ No newline at end of file diff --git a/src/test/test-data/maintain-comment-formatting.unformatted.xml b/src/test/test-data/maintain-comment-formatting.unformatted.xml new file mode 100644 index 0000000..160f0c9 --- /dev/null +++ b/src/test/test-data/maintain-comment-formatting.unformatted.xml @@ -0,0 +1,13 @@ + + text + + \ No newline at end of file