UNPKG

xmlbuilder2

Version:

An XML builder for node.js

222 lines 7.71 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.XMLWriter = void 0; const util_1 = require("@oozcitak/util"); const interfaces_1 = require("@oozcitak/dom/lib/dom/interfaces"); const BaseWriter_1 = require("./BaseWriter"); const util_2 = require("@oozcitak/dom/lib/util"); /** * Serializes XML nodes into strings. */ class XMLWriter extends BaseWriter_1.BaseWriter { _refs; _indentation = {}; _lengthToLastNewline = 0; /** * Initializes a new instance of `XMLWriter`. * * @param builderOptions - XML builder options * @param writerOptions - serialization options */ constructor(builderOptions, writerOptions) { super(builderOptions); // provide default options this._writerOptions = (0, util_1.applyDefaults)(writerOptions, { wellFormed: false, headless: false, prettyPrint: false, indent: " ", newline: "\n", offset: 0, width: 0, allowEmptyTags: false, indentTextOnlyNodes: false, spaceBeforeSlash: false }); } /** * Produces an XML serialization of the given node. * * @param node - node to serialize */ serialize(node) { this._refs = { suppressPretty: false, emptyNode: false, markup: "" }; // Serialize XML declaration if (node.nodeType === interfaces_1.NodeType.Document && !this._writerOptions.headless) { this.declaration(this._builderOptions.version, this._builderOptions.encoding, this._builderOptions.standalone); } // recursively serialize node this.serializeNode(node, this._writerOptions.wellFormed); // remove trailing newline if (this._writerOptions.prettyPrint && this._refs.markup.slice(-this._writerOptions.newline.length) === this._writerOptions.newline) { this._refs.markup = this._refs.markup.slice(0, -this._writerOptions.newline.length); } return this._refs.markup; } /** @inheritdoc */ declaration(version, encoding, standalone) { this._beginLine(); this._refs.markup += "<?xml version=\"" + version + "\""; if (encoding !== undefined) { this._refs.markup += " encoding=\"" + encoding + "\""; } if (standalone !== undefined) { this._refs.markup += " standalone=\"" + (standalone ? "yes" : "no") + "\""; } this._refs.markup += "?>"; this._endLine(); } /** @inheritdoc */ docType(name, publicId, systemId) { this._beginLine(); if (publicId && systemId) { this._refs.markup += "<!DOCTYPE " + name + " PUBLIC \"" + publicId + "\" \"" + systemId + "\">"; } else if (publicId) { this._refs.markup += "<!DOCTYPE " + name + " PUBLIC \"" + publicId + "\">"; } else if (systemId) { this._refs.markup += "<!DOCTYPE " + name + " SYSTEM \"" + systemId + "\">"; } else { this._refs.markup += "<!DOCTYPE " + name + ">"; } this._endLine(); } /** @inheritdoc */ openTagBegin(name) { this._beginLine(); this._refs.markup += "<" + name; } /** @inheritdoc */ openTagEnd(name, selfClosing, voidElement) { // do not indent text only elements or elements with empty text nodes this._refs.suppressPretty = false; this._refs.emptyNode = false; if (this._writerOptions.prettyPrint && !selfClosing && !voidElement) { let textOnlyNode = true; let emptyNode = true; let childNode = this.currentNode.firstChild; let cdataCount = 0; let textCount = 0; while (childNode) { if (util_2.Guard.isExclusiveTextNode(childNode)) { textCount++; } else if (util_2.Guard.isCDATASectionNode(childNode)) { cdataCount++; } else { textOnlyNode = false; emptyNode = false; break; } if (childNode.data !== '') { emptyNode = false; } childNode = childNode.nextSibling; } this._refs.suppressPretty = !this._writerOptions.indentTextOnlyNodes && textOnlyNode && ((cdataCount <= 1 && textCount === 0) || cdataCount === 0); this._refs.emptyNode = emptyNode; } if ((voidElement || selfClosing || this._refs.emptyNode) && this._writerOptions.allowEmptyTags) { this._refs.markup += "></" + name + ">"; } else { this._refs.markup += voidElement ? " />" : (selfClosing || this._refs.emptyNode) ? (this._writerOptions.spaceBeforeSlash ? " />" : "/>") : ">"; } this._endLine(); } /** @inheritdoc */ closeTag(name) { if (!this._refs.emptyNode) { this._beginLine(); this._refs.markup += "</" + name + ">"; } this._refs.suppressPretty = false; this._refs.emptyNode = false; this._endLine(); } /** @inheritdoc */ attribute(name, value) { const str = name + "=\"" + value + "\""; if (this._writerOptions.prettyPrint && this._writerOptions.width > 0 && this._refs.markup.length - this._lengthToLastNewline + 1 + str.length > this._writerOptions.width) { this._endLine(); this._beginLine(); this._refs.markup += this._indent(1) + str; } else { this._refs.markup += " " + str; } } /** @inheritdoc */ text(data) { if (data !== '') { this._beginLine(); this._refs.markup += data; this._endLine(); } } /** @inheritdoc */ cdata(data) { if (data !== '') { this._beginLine(); this._refs.markup += "<![CDATA[" + data + "]]>"; this._endLine(); } } /** @inheritdoc */ comment(data) { this._beginLine(); this._refs.markup += "<!--" + data + "-->"; this._endLine(); } /** @inheritdoc */ instruction(target, data) { this._beginLine(); this._refs.markup += "<?" + (data === "" ? target : target + " " + data) + "?>"; this._endLine(); } /** * Produces characters to be prepended to a line of string in pretty-print * mode. */ _beginLine() { if (this._writerOptions.prettyPrint && !this._refs.suppressPretty) { this._refs.markup += this._indent(this._writerOptions.offset + this.level); } } /** * Produces characters to be appended to a line of string in pretty-print * mode. */ _endLine() { if (this._writerOptions.prettyPrint && !this._refs.suppressPretty) { this._refs.markup += this._writerOptions.newline; this._lengthToLastNewline = this._refs.markup.length; } } /** * Produces an indentation string. * * @param level - depth of the tree */ _indent(level) { if (level <= 0) { return ""; } else if (this._indentation[level] !== undefined) { return this._indentation[level]; } else { const str = this._writerOptions.indent.repeat(level); this._indentation[level] = str; return str; } } } exports.XMLWriter = XMLWriter; //# sourceMappingURL=XMLWriter.js.map