You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					96 lines
				
				2.5 KiB
			
		
		
			
		
	
	
					96 lines
				
				2.5 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 Copyright 2012-2015, Yahoo Inc.
							 | 
						||
| 
								 | 
							
								 Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								const INDENT = '  ';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * a utility class to produce well-formed, indented XML
							 | 
						||
| 
								 | 
							
								 * @param {ContentWriter} contentWriter the content writer that this utility wraps
							 | 
						||
| 
								 | 
							
								 * @constructor
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								function XMLWriter(contentWriter) {
							 | 
						||
| 
								 | 
							
								    this.cw = contentWriter;
							 | 
						||
| 
								 | 
							
								    this.stack = [];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function attrString(attrs) {
							 | 
						||
| 
								 | 
							
								    if (!attrs) {
							 | 
						||
| 
								 | 
							
								        return '';
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    const ret = [];
							 | 
						||
| 
								 | 
							
								    Object.keys(attrs).forEach(k => {
							 | 
						||
| 
								 | 
							
								        const v = attrs[k];
							 | 
						||
| 
								 | 
							
								        ret.push(k + '="' + v + '"');
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								    return ret.length === 0 ? '' : ' ' + ret.join(' ');
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								XMLWriter.prototype.indent = function(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
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								XMLWriter.prototype.openTag = function(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.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								XMLWriter.prototype.closeTag = function(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
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								XMLWriter.prototype.inlineTag = function(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
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								XMLWriter.prototype.closeAll = function() {
							 | 
						||
| 
								 | 
							
								    this.stack
							 | 
						||
| 
								 | 
							
								        .slice()
							 | 
						||
| 
								 | 
							
								        .reverse()
							 | 
						||
| 
								 | 
							
								        .forEach(name => {
							 | 
						||
| 
								 | 
							
								            this.closeTag(name);
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = XMLWriter;
							 |