devexpress-richedit
Version:
DevExpress Rich Text Editor is an advanced word-processing tool designed for working with rich text documents.
152 lines (151 loc) • 6.37 kB
JavaScript
import { Stack } from '@devexpress/utils/lib/class/stack';
import { StringUtils } from '@devexpress/utils/lib/utils/string';
import { ContentType } from '../utils/constants';
export var XmlReaderState;
(function (XmlReaderState) {
XmlReaderState[XmlReaderState["Ok"] = 0] = "Ok";
XmlReaderState[XmlReaderState["Error"] = 1] = "Error";
XmlReaderState[XmlReaderState["EndOfFile"] = 2] = "EndOfFile";
})(XmlReaderState || (XmlReaderState = {}));
export var XmlNodeType;
(function (XmlNodeType) {
XmlNodeType[XmlNodeType["None"] = 0] = "None";
XmlNodeType[XmlNodeType["Element"] = 1] = "Element";
XmlNodeType[XmlNodeType["EndElement"] = 2] = "EndElement";
XmlNodeType[XmlNodeType["Text"] = 3] = "Text";
XmlNodeType[XmlNodeType["CDATA"] = 4] = "CDATA";
XmlNodeType[XmlNodeType["SignificantWhitespace"] = 5] = "SignificantWhitespace";
XmlNodeType[XmlNodeType["Whitespace"] = 6] = "Whitespace";
XmlNodeType[XmlNodeType["Comment"] = 7] = "Comment";
})(XmlNodeType || (XmlNodeType = {}));
var ElementStages;
(function (ElementStages) {
ElementStages[ElementStages["ElementStart"] = 0] = "ElementStart";
ElementStages[ElementStages["ChildElements"] = 1] = "ChildElements";
ElementStages[ElementStages["ElementEnd"] = 2] = "ElementEnd";
ElementStages[ElementStages["ToNextNode"] = 3] = "ToNextNode";
})(ElementStages || (ElementStages = {}));
class ElementInfo {
get localName() { return this.node.localName; }
get name() { return this.node.nodeName; }
get namespaceURI() { return this.node.namespaceURI; }
constructor(node, nodeType) {
this.elementStage = ElementStages.ElementStart;
this.node = node;
this.nodeType = nodeType;
}
}
export class XmlReader {
get elementInfo() { return this.elementStack.last; }
get nodeType() { return this.elementInfo.nodeType; }
get localName() { return this.elementInfo.localName; }
get name() { return this.elementInfo.name; }
get namespaceURI() { return this.elementInfo.namespaceURI; }
get attributes() { return this.elementInfo.node.attributes; }
get value() { return this.elementInfo.node.nodeValue; }
constructor(str, options, filePath) {
str = StringUtils.trimStart(str);
this.filePath = filePath;
this.document = new DOMParser().parseFromString(str, ContentType.xml);
this.state = XmlReaderState.Ok;
this.elementStack = new Stack();
this.elementStack.push(new ElementInfo(this.document.firstChild, XmlNodeType.None));
this.handleNewNode(this.document.firstChild);
this.options = options;
}
getAttribute(name) {
return this.elementInfo.node.getAttribute(name);
}
getAttributeNS(name, namespaceUri) {
return this.elementInfo.node.getAttributeNS(namespaceUri, name);
}
skipElement() {
this.elementInfo.elementStage = ElementStages.ToNextNode;
}
readToFollowingNS(name, ns) {
do {
if (this.nodeType == XmlNodeType.Element && this.localName == name && this.namespaceURI == ns)
return true;
} while (this.read());
return false;
}
readToFollowing(name) {
do {
if (this.nodeType == XmlNodeType.Element && this.localName == name && this.handleNewNode(this.elementInfo.node))
return true;
} while (this.read());
return false;
}
read() {
const info = this.elementInfo;
if (!info)
return false;
switch (info.elementStage) {
case ElementStages.ElementStart: {
info.elementStage++;
switch (info.node.nodeType) {
case Node.COMMENT_NODE:
info.nodeType = XmlNodeType.Comment;
if (this.options.ignoreComments) {
this.elementInfo.elementStage = ElementStages.ToNextNode;
return this.read();
}
this.elementInfo.elementStage = ElementStages.ToNextNode;
break;
case Node.TEXT_NODE:
info.nodeType = XmlNodeType.Text;
info.elementStage = ElementStages.ToNextNode;
break;
default:
info.nodeType = XmlNodeType.Element;
break;
}
if (info.node.nodeName == '#cdata-section') {
info.nodeType = XmlNodeType.CDATA;
this.elementInfo.elementStage = ElementStages.ToNextNode;
}
break;
}
case ElementStages.ChildElements: {
info.elementStage++;
const child = this.elementInfo.node.firstChild;
if (child) {
if (!this.handleNewNode(child))
return false;
this.elementStack.push(new ElementInfo(child, XmlNodeType.None));
}
return this.read();
}
case ElementStages.ElementEnd: {
info.elementStage++;
info.nodeType = XmlNodeType.EndElement;
break;
}
case ElementStages.ToNextNode: {
const nextNode = info.node.nextSibling;
if (nextNode) {
this.elementStack.pop();
if (!this.handleNewNode(nextNode))
return false;
this.elementStack.push(new ElementInfo(nextNode, XmlNodeType.None));
}
else {
this.elementStack.pop();
if (!this.elementStack.count) {
this.state = XmlReaderState.EndOfFile;
return false;
}
}
return this.read();
}
}
return true;
}
handleNewNode(node) {
if (node.nodeName == 'parsererror') {
this.state = XmlReaderState.Error;
return false;
}
return true;
}
}