vNext Rewrite

This commit cleans up and reorganizes the code base, as well as fixes some issues. The intent of the vNext branch is to make the extension more conducive to an open-source environment.
This commit is contained in:
Josh Johnson 2016-01-06 15:55:11 -05:00
parent 1b9caa3265
commit eb43a467c8
16 changed files with 617 additions and 192 deletions

View file

@ -0,0 +1,23 @@
'use strict';
import * as xpath from 'xpath';
let DOMParser = require('xmldom').DOMParser;
export class XPathEvaluator {
static evaluate(query: string, xml: string): Node[] {
let nodes: Node[] = new Array<Node>();
let xdoc: Document = new DOMParser().parseFromString(xml, 'text/xml');
let resolver: xpath.XPathNSResolver = xpath.createNSResolver(xdoc);
let expression: xpath.XPathExpression = xpath.createExpression(query, resolver);
let result: xpath.XPathResult = expression.evaluate(xdoc, xpath.XPathResult.ORDERED_NODE_ITERATOR_TYPE);
let node: Node;
while (node = result.iterateNext()) {
nodes.push(node);
}
return nodes;
}
}

View file

@ -0,0 +1,122 @@
'use strict';
// Based on pretty-data (https://github.com/vkiryukhin/pretty-data)
export class XmlFormatter {
constructor(preferSpaces?: boolean, tabSize?: number, newLine?: string) {
if (typeof preferSpaces === 'undefined') {
preferSpaces = false;
}
tabSize = tabSize || 4;
newLine = newLine || '\n';
this.newLine = newLine || '\n';
this.indentPattern = (preferSpaces) ? ' '.repeat(tabSize) : '\t';
}
newLine: string;
indentPattern: string;
format(xml: string): string {
xml = this.minify(xml, false);
let parts: string[] = xml
.replace(/</g,"~::~<")
.replace(/xmlns\:/g,"~::~xmlns:")
.replace(/xmlns\=/g,"~::~xmlns=")
.split('~::~');
let inComment: boolean = false;
let level: number = 0;
let output: string = '';
for (let i = 0; i < parts.length; i++) {
// <!
if (parts[i].search(/<!/) > -1) {
output += this._getIndent(level, parts[i]);
inComment = true;
// end <!
if (parts[i].search(/-->/) > -1 || parts[i].search(/\]>/) > -1 || parts[i].search(/!DOCTYPE/) > -1) {
inComment = false;
}
}
// end <!
else if (parts[i].search(/-->/) > -1 || parts[i].search(/\]>/) > -1) {
output += parts[i];
inComment = false;
}
// <elm></elm>
else if (/^<\w/.test(parts[i - 1]) && /^<\/\w/.test(parts[i])
&& /^<[\w:\-\.\,]+/.exec(parts[i - 1])[0] == /^<\/[\w:\-\.\,]+/.exec(parts[i])[0].replace('/', '')) {
output += parts[i];
if (!inComment) level--;
}
// <elm>
else if (parts[i].search(/<\w/) > -1 && parts[i].search(/<\//) == -1 && parts[i].search(/\/>/) == -1) {
output = (!inComment) ? output += this._getIndent(level++, parts[i]) : output += parts[i];
}
// <elm>...</elm>
else if (parts[i].search(/<\w/) > -1 && parts[i].search(/<\//) > -1) {
output = (!inComment) ? output += this._getIndent(level, parts[i]) : output += parts[i];
}
// </elm>
else if (parts[i].search(/<\//) > -1) {
output = (!inComment) ? output += this._getIndent(--level, parts[i]) : output += parts[i];
}
// <elm />
else if (parts[i].search(/\/>/) > -1) {
output = (!inComment) ? output += this._getIndent(level, parts[i]) : output += parts[i];
}
// <?xml ... ?>
else if (parts[i].search(/<\?/) > -1) {
output += this._getIndent(level, parts[i]);
}
// xmlns
else if (parts[i].search(/xmlns\:/) > -1 || parts[i].search(/xmlns\=/) > -1) {
output += this._getIndent(level, parts[i]);
}
else {
output += parts[i];
}
}
// remove leading newline
if (output[0] == this.newLine) {
output = output.slice(1);
}
else if (output.substring(0, 1) == this.newLine) {
output = output.slice(2);
}
return output;
}
minify(xml: string, removeComments?: boolean): string {
if (typeof removeComments === 'undefined') {
removeComments = false;
}
xml = (removeComments) ? xml.replace(/\<![ \r\n\t]*(--([^\-]|[\r\n]|-[^\-])*--[ \r\n\t]*)\>/g, '') : xml;
xml = xml.replace(/>\s{0,}</g, '><');
return xml;
}
private _getIndent(level: number, trailingValue?: string): string {
trailingValue = trailingValue || '';
return `${this.newLine}${this.indentPattern.repeat(level)}${trailingValue}`;
}
}