// Generated by CoffeeScript 2.4.1 (function() { // Converts values to strings var XMLStringifier, hasProp = {}.hasOwnProperty; module.exports = XMLStringifier = (function() { class XMLStringifier { // Initializes a new instance of `XMLStringifier` // `options.version` The version number string of the XML spec to validate against, e.g. 1.0 // `options.noDoubleEncoding` whether existing html entities are encoded: true or false // `options.stringify` a set of functions to use for converting values to strings // `options.noValidation` whether values will be validated and escaped or returned as is constructor(options) { var key, ref, value; // Checks whether the given string contains legal characters // Fails with an exception on error // `str` the string to check this.assertLegalChar = this.assertLegalChar.bind(this); // Checks whether the given string contains legal characters for a name // Fails with an exception on error // `str` the string to check this.assertLegalName = this.assertLegalName.bind(this); options || (options = {}); this.options = options; if (!this.options.version) { this.options.version = '1.0'; } ref = options.stringify || {}; for (key in ref) { if (!hasProp.call(ref, key)) continue; value = ref[key]; this[key] = value; } } // Defaults name(val) { if (this.options.noValidation) { return val; } return this.assertLegalName('' + val || ''); } text(val) { if (this.options.noValidation) { return val; } return this.assertLegalChar(this.textEscape('' + val || '')); } cdata(val) { if (this.options.noValidation) { return val; } val = '' + val || ''; val = val.replace(']]>', ']]]]>'); return this.assertLegalChar(val); } comment(val) { if (this.options.noValidation) { return val; } val = '' + val || ''; if (val.match(/--/)) { throw new Error("Comment text cannot contain double-hypen: " + val); } return this.assertLegalChar(val); } raw(val) { if (this.options.noValidation) { return val; } return '' + val || ''; } attValue(val) { if (this.options.noValidation) { return val; } return this.assertLegalChar(this.attEscape(val = '' + val || '')); } insTarget(val) { if (this.options.noValidation) { return val; } return this.assertLegalChar('' + val || ''); } insValue(val) { if (this.options.noValidation) { return val; } val = '' + val || ''; if (val.match(/\?>/)) { throw new Error("Invalid processing instruction value: " + val); } return this.assertLegalChar(val); } xmlVersion(val) { if (this.options.noValidation) { return val; } val = '' + val || ''; if (!val.match(/1\.[0-9]+/)) { throw new Error("Invalid version number: " + val); } return val; } xmlEncoding(val) { if (this.options.noValidation) { return val; } val = '' + val || ''; if (!val.match(/^[A-Za-z](?:[A-Za-z0-9._-])*$/)) { throw new Error("Invalid encoding: " + val); } return this.assertLegalChar(val); } xmlStandalone(val) { if (this.options.noValidation) { return val; } if (val) { return "yes"; } else { return "no"; } } dtdPubID(val) { if (this.options.noValidation) { return val; } return this.assertLegalChar('' + val || ''); } dtdSysID(val) { if (this.options.noValidation) { return val; } return this.assertLegalChar('' + val || ''); } dtdElementValue(val) { if (this.options.noValidation) { return val; } return this.assertLegalChar('' + val || ''); } dtdAttType(val) { if (this.options.noValidation) { return val; } return this.assertLegalChar('' + val || ''); } dtdAttDefault(val) { if (this.options.noValidation) { return val; } return this.assertLegalChar('' + val || ''); } dtdEntityValue(val) { if (this.options.noValidation) { return val; } return this.assertLegalChar('' + val || ''); } dtdNData(val) { if (this.options.noValidation) { return val; } return this.assertLegalChar('' + val || ''); } assertLegalChar(str) { var regex, res; if (this.options.noValidation) { return str; } regex = ''; if (this.options.version === '1.0') { // Valid characters from https://www.w3.org/TR/xml/#charsets // any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. // #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] // This ES5 compatible Regexp has been generated using the "regenerate" NPM module: // let xml_10_InvalidChars = regenerate() // .addRange(0x0000, 0x0008) // .add(0x000B, 0x000C) // .addRange(0x000E, 0x001F) // .addRange(0xD800, 0xDFFF) // .addRange(0xFFFE, 0xFFFF) regex = /[\0-\x08\x0B\f\x0E-\x1F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/; if (res = str.match(regex)) { throw new Error(`Invalid character in string: ${str} at index ${res.index}`); } } else if (this.options.version === '1.1') { // Valid characters from https://www.w3.org/TR/xml11/#charsets // any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. // [#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] // This ES5 compatible Regexp has been generated using the "regenerate" NPM module: // let xml_11_InvalidChars = regenerate() // .add(0x0000) // .addRange(0xD800, 0xDFFF) // .addRange(0xFFFE, 0xFFFF) regex = /[\0\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/; if (res = str.match(regex)) { throw new Error(`Invalid character in string: ${str} at index ${res.index}`); } } return str; } assertLegalName(str) { var regex; if (this.options.noValidation) { return str; } this.assertLegalChar(str); regex = /^([:A-Z_a-z\xC0-\xD6\xD8-\xF6\xF8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]|[\uD800-\uDB7F][\uDC00-\uDFFF])([\x2D\.0-:A-Z_a-z\xB7\xC0-\xD6\xD8-\xF6\xF8-\u037D\u037F-\u1FFF\u200C\u200D\u203F\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]|[\uD800-\uDB7F][\uDC00-\uDFFF])*$/; if (!str.match(regex)) { throw new Error("Invalid character in name"); } return str; } // Escapes special characters in text // See http://www.w3.org/TR/2000/WD-xml-c14n-20000119.html#charescaping // `str` the string to escape textEscape(str) { var ampregex; if (this.options.noValidation) { return str; } ampregex = this.options.noDoubleEncoding ? /(?!&\S+;)&/g : /&/g; return str.replace(ampregex, '&').replace(//g, '>').replace(/\r/g, ' '); } // Escapes special characters in attribute values // See http://www.w3.org/TR/2000/WD-xml-c14n-20000119.html#charescaping // `str` the string to escape attEscape(str) { var ampregex; if (this.options.noValidation) { return str; } ampregex = this.options.noDoubleEncoding ? /(?!&\S+;)&/g : /&/g; return str.replace(ampregex, '&').replace(/