diff --git a/package-lock.json b/package-lock.json
index 37c5472..e719b30 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -894,9 +894,9 @@
"dev": true
},
"fstream": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
- "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
+ "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.2",
diff --git a/src/formatting/formatters/v2-xml-formatter.ts b/src/formatting/formatters/v2-xml-formatter.ts
index 8eed3d7..8b0fcbb 100644
--- a/src/formatting/formatters/v2-xml-formatter.ts
+++ b/src/formatting/formatters/v2-xml-formatter.ts
@@ -7,9 +7,9 @@ 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);
+ // this replaces all "<" brackets inside of comments and CDATA to a magical string
+ // so the following minification steps don't mess with comment and CDATA formatting
+ xml = this._sanitizeCommentsAndCDATA(xml);
// remove whitespace from between tags, except for line breaks
xml = xml.replace(/>\s{0,} {
@@ -25,7 +25,7 @@ export class V2XmlFormatter implements XmlFormatter {
});
// the coast is clear - we can drop those "<" brackets back in
- xml = this._unsanitizeComments(xml);
+ xml = this._unsanitizeCommentsAndCDATA(xml);
let output = "";
@@ -298,9 +298,9 @@ export class V2XmlFormatter implements XmlFormatter {
return text.replace(/[^\r\n\S]+$/, "");
}
- private _sanitizeComments(xml: string): string {
+ private _sanitizeCommentsAndCDATA(xml: string): string {
let output = "";
- let inComment = false;
+ let inCommentOrCDATA = false;
for (let i = 0; i < xml.length; i++) {
const cc = xml[i];
@@ -308,20 +308,20 @@ export class V2XmlFormatter implements XmlFormatter {
const nnc = xml.charAt(i + 2);
const pc = xml.charAt(i - 1);
- if (!inComment && cc === "<" && nc === "!" && nnc === "-") {
- inComment = true;
- output += "";
+ else if (inCommentOrCDATA && (cc === "-" && nc === "-" && nnc === ">") || (cc === "]" && nc === "]" && nnc === ">")) {
+ inCommentOrCDATA = false;
+ output += (cc === "-") ? "-->" : "]]>";
i += 2;
}
@@ -334,7 +334,7 @@ export class V2XmlFormatter implements XmlFormatter {
return output;
}
- private _unsanitizeComments(xml: string): string {
+ private _unsanitizeCommentsAndCDATA(xml: string): string {
return xml.replace(new RegExp(MagicalStringOfWonders, "g"), "<");
}
}
diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts
index 640ec47..31f44e7 100644
--- a/src/test/extension.test.ts
+++ b/src/test/extension.test.ts
@@ -99,6 +99,10 @@ describe("V2XmlFormatter", () => {
it("should handle mixed content as a child of another element", () => {
testFormatter(xmlFormatter, options, "issue-257");
});
+
+ it("should not touch CDATA content", () => {
+ testFormatter(xmlFormatter, options, "issue-293");
+ });
});
describe("#minifyXml(xml, options)", () => {
@@ -130,7 +134,7 @@ function testFormatter(xmlFormatter: XmlFormatter, options: XmlFormattingOptions
const actualFormattedXml = xmlFormatter.formatXml(unformattedXml, options).replace(/\r/g, "");
// tslint:disable-next-line
- assert.ok((actualFormattedXml === expectedFormattedXml), `Actual formatted XML does not match expected formatted XML.\n\nACTUAL\n${actualFormattedXml.replace(/\s/, "~ws~")}\n\nEXPECTED\n${expectedFormattedXml.replace(/\s/, "~ws~")}`);
+ assert.ok((actualFormattedXml === expectedFormattedXml), `Actual formatted XML does not match expected formatted XML.\n\nACTUAL\n${actualFormattedXml.replace(/\s/g, "~ws~")}\n\nEXPECTED\n${expectedFormattedXml.replace(/\s/g, "~ws~")}`);
}
function testMinifier(xmlFormatter: XmlFormatter, options: XmlFormattingOptions, fileLabel: string): void {
@@ -140,5 +144,5 @@ function testMinifier(xmlFormatter: XmlFormatter, options: XmlFormattingOptions,
const actualMinifiedXml = xmlFormatter.minifyXml(unminifiedXml, options).replace(/\r/g, "");
// tslint:disable-next-line
- assert.ok((actualMinifiedXml === expectedMinifiedXml), `Actual minified XML does not match expected minified XML.\n\nACTUAL\n${actualMinifiedXml.replace(/\s/, "~ws~")}\n\nEXPECTED\n${expectedMinifiedXml.replace(/\s/, "~ws~")}`);
+ assert.ok((actualMinifiedXml === expectedMinifiedXml), `Actual minified XML does not match expected minified XML.\n\nACTUAL\n${actualMinifiedXml.replace(/\s/g, "~ws~")}\n\nEXPECTED\n${expectedMinifiedXml.replace(/\s/g, "~ws~")}`);
}
diff --git a/src/test/test-data/issue-293.formatted.xml b/src/test/test-data/issue-293.formatted.xml
new file mode 100644
index 0000000..f238eb5
--- /dev/null
+++ b/src/test/test-data/issue-293.formatted.xml
@@ -0,0 +1,6 @@
+
+
+
+ val
+]]>
+
\ No newline at end of file
diff --git a/src/test/test-data/issue-293.unformatted.xml b/src/test/test-data/issue-293.unformatted.xml
new file mode 100644
index 0000000..f238eb5
--- /dev/null
+++ b/src/test/test-data/issue-293.unformatted.xml
@@ -0,0 +1,6 @@
+
+
+
+ val
+]]>
+
\ No newline at end of file