| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 | 'use strict';/* Copyright 2012-2015, Yahoo Inc. Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. */const INDENT = '  ';function attrString(attrs) {    return Object.entries(attrs || {})        .map(([k, v]) => ` ${k}="${v}"`)        .join('');}/** * a utility class to produce well-formed, indented XML * @param {ContentWriter} contentWriter the content writer that this utility wraps * @constructor */class XMLWriter {    constructor(contentWriter) {        this.cw = contentWriter;        this.stack = [];    }    indent(str) {        return this.stack.map(() => INDENT).join('') + str;    }    /**     * writes the opening XML tag with the supplied attributes     * @param {String} name tag name     * @param {Object} [attrs=null] attrs attributes for the tag     */    openTag(name, attrs) {        const str = this.indent(`<${name + attrString(attrs)}>`);        this.cw.println(str);        this.stack.push(name);    }    /**     * closes an open XML tag.     * @param {String} name - tag name to close. This must match the writer's     *  notion of the tag that is currently open.     */    closeTag(name) {        if (this.stack.length === 0) {            throw new Error(`Attempt to close tag ${name} when not opened`);        }        const stashed = this.stack.pop();        const str = `</${name}>`;        if (stashed !== name) {            throw new Error(                `Attempt to close tag ${name} when ${stashed} was the one open`            );        }        this.cw.println(this.indent(str));    }    /**     * writes a tag and its value opening and closing it at the same time     * @param {String} name tag name     * @param {Object} [attrs=null] attrs tag attributes     * @param {String} [content=null] content optional tag content     */    inlineTag(name, attrs, content) {        let str = '<' + name + attrString(attrs);        if (content) {            str += `>${content}</${name}>`;        } else {            str += '/>';        }        str = this.indent(str);        this.cw.println(str);    }    /**     * closes all open tags and ends the document     */    closeAll() {        this.stack            .slice()            .reverse()            .forEach(name => {                this.closeTag(name);            });    }}module.exports = XMLWriter;
 |