Support xml:space="preserve"

This commit is contained in:
Josh Johnson 2020-07-01 23:43:34 -04:00
parent f156845afb
commit 69d862b48d
2 changed files with 44 additions and 13 deletions

View File

@ -66,7 +66,7 @@ export class ClassicXmlFormatter implements XmlFormatter {
} }
minifyXml(xml: string, options: XmlFormattingOptions): string { minifyXml(xml: string, options: XmlFormattingOptions): string {
xml = this._stripLineBreaks(options, xml); // all line breaks outside of CDATA elements xml = this._stripLineBreaks(options, xml); // all line breaks outside of CDATA elements and comments
xml = (options.removeCommentsOnMinify) ? xml.replace(/\<![ \r\n\t]*(--([^\-]|[\r\n]|-[^\-])*--[ \r\n\t]*)\>/g, "") : xml; xml = (options.removeCommentsOnMinify) ? xml.replace(/\<![ \r\n\t]*(--([^\-]|[\r\n]|-[^\-])*--[ \r\n\t]*)\>/g, "") : xml;
xml = xml.replace(/>\s{0,}</g, "><"); // insignificant whitespace between tags xml = xml.replace(/>\s{0,}</g, "><"); // insignificant whitespace between tags
xml = xml.replace(/"\s+(?=[^\s]+=)/g, "\" "); // spaces between attributes xml = xml.replace(/"\s+(?=[^\s]+=)/g, "\" "); // spaces between attributes
@ -87,28 +87,62 @@ export class ClassicXmlFormatter implements XmlFormatter {
return `${options.newLine}${indentPattern.repeat(level)}${trailingValue}`; return `${options.newLine}${indentPattern.repeat(level)}${trailingValue}`;
} }
/**
* Removes line breaks outside of CDATA, comment, and xml:space="preserve" blocks.
*/
private _stripLineBreaks(options: XmlFormattingOptions, xml: string): string { private _stripLineBreaks(options: XmlFormattingOptions, xml: string): string {
let output = ""; let output = "";
const inTag = false; const inTag = false;
const inTagName = false; const inTagName = false;
let inCdata = false; let inCdataOrComment = false;
const inAttribute = false; const inAttribute = false;
let preserveSpace = false;
let level = 0;
let levelpreserveSpaceActivated = 0;
for (let i = 0; i < xml.length; i++) { for (let i = 0; i < xml.length; i++) {
const char: string = xml.charAt(i); const char: string = xml.charAt(i);
const prev: string = xml.charAt(i - 1); const prev: string = xml.charAt(i - 1);
const next: string = xml.charAt(i + 1); const next: string = xml.charAt(i + 1);
// CDATA and comments
if (char === "!" && (xml.substr(i, 8) === "![CDATA[" || xml.substr(i, 3) === "!--")) { if (char === "!" && (xml.substr(i, 8) === "![CDATA[" || xml.substr(i, 3) === "!--")) {
inCdata = true; inCdataOrComment = true;
} else if (char === "]" && (xml.substr(i, 3) === "]]>")) { }
inCdata = false;
} else if (char === "-" && (xml.substr(i, 3) === "-->")) { else if (char === "]" && (xml.substr(i, 3) === "]]>")) {
inCdata = false; inCdataOrComment = false;
} else if (char.search(/[\r\n]/g) > -1 && !inCdata) { }
else if (char === "-" && (xml.substr(i, 3) === "-->")) {
inCdataOrComment = false;
}
// xml:space="preserve"
if (char === ">" && prev !== "/") {
level++;
}
else if (!inCdataOrComment && char === "/" && (prev === "<" || next === ">")) {
level--;
}
if (char === "x" && (xml.substr(i, 20).toLowerCase() === `xml:space="preserve"`)) {
preserveSpace = true;
levelpreserveSpaceActivated = level;
}
else if (!inCdataOrComment && preserveSpace && (char === "/" && (prev === "<" || next === ">")) && (level === levelpreserveSpaceActivated)) {
preserveSpace = false;
}
if (char.search(/[\r\n]/g) > -1 && !inCdataOrComment && !preserveSpace) {
if (/\r/.test(char) && /\S|\r|\n/.test(prev) && /\S|\r|\n/.test(xml.charAt(i + options.newLine.length))) { if (/\r/.test(char) && /\S|\r|\n/.test(prev) && /\S|\r|\n/.test(xml.charAt(i + options.newLine.length))) {
output += char; output += char;
} else if (/\n/.test(char) && /\S|\r|\n/.test(xml.charAt(i - options.newLine.length)) && /\S|\r|\n/.test(next)) { }
else if (/\n/.test(char) && /\S|\r|\n/.test(xml.charAt(i - options.newLine.length)) && /\S|\r|\n/.test(next)) {
output += char; output += char;
} }

View File

@ -4,10 +4,7 @@
4.</test><test xml:space="preserve">1. 4.</test><test xml:space="preserve">1.
2. 2.
3. 3.
4.</test><test>1. 4.</test><test>1. 2. 3. 4.</test><test xml:space="preserve">1.
2.
3.
4.</test><test xml:space="preserve">1.
2. 2.
3. 3.
4.</test></tests> 4.</test></tests>