UNPKG

2.64 kBJavaScriptView Raw
1/*
2 Copyright 2012-2015, Yahoo Inc.
3 Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
4 */
5var INDENT = ' ';
6
7/**
8 * a utility class to produce well-formed, indented XML
9 * @param {ContentWriter} contentWriter the content writer that this utility wraps
10 * @constructor
11 */
12function XMLWriter(contentWriter) {
13 this.cw = contentWriter;
14 this.stack = [];
15}
16
17function attrString(attrs) {
18 if (!attrs) {
19 return '';
20 }
21 var ret = [];
22 Object.keys(attrs).forEach(function(k) {
23 var v = attrs[k];
24 ret.push(k + '="' + v + '"');
25 });
26 return ret.length === 0 ? '' : ' ' + ret.join(' ');
27}
28
29XMLWriter.prototype.indent = function(str) {
30 return (
31 this.stack
32 .map(function() {
33 return INDENT;
34 })
35 .join('') + str
36 );
37};
38
39/**
40 * writes the opening XML tag with the supplied attributes
41 * @param {String} name tag name
42 * @param {Object} [attrs=null] attrs attributes for the tag
43 */
44XMLWriter.prototype.openTag = function(name, attrs) {
45 var str = this.indent('<' + name + attrString(attrs) + '>');
46 this.cw.println(str);
47 this.stack.push(name);
48};
49
50/**
51 * closes an open XML tag.
52 * @param {String} name - tag name to close. This must match the writer's
53 * notion of the tag that is currently open.
54 */
55XMLWriter.prototype.closeTag = function(name) {
56 if (this.stack.length === 0) {
57 throw new Error('Attempt to close tag ' + name + ' when not opened');
58 }
59 var stashed = this.stack.pop(),
60 str = '</' + name + '>';
61
62 if (stashed !== name) {
63 throw new Error(
64 'Attempt to close tag ' +
65 name +
66 ' when ' +
67 stashed +
68 ' was the one open'
69 );
70 }
71 this.cw.println(this.indent(str));
72};
73/**
74 * writes a tag and its value opening and closing it at the same time
75 * @param {String} name tag name
76 * @param {Object} [attrs=null] attrs tag attributes
77 * @param {String} [content=null] content optional tag content
78 */
79XMLWriter.prototype.inlineTag = function(name, attrs, content) {
80 var str = '<' + name + attrString(attrs);
81 if (content) {
82 str += '>' + content + '</' + name + '>';
83 } else {
84 str += '/>';
85 }
86 str = this.indent(str);
87 this.cw.println(str);
88};
89/**
90 * closes all open tags and ends the document
91 */
92XMLWriter.prototype.closeAll = function() {
93 var that = this;
94 this.stack
95 .slice()
96 .reverse()
97 .forEach(function(name) {
98 that.closeTag(name);
99 });
100};
101
102module.exports = XMLWriter;