diff options
Diffstat (limited to 'node_modules/dom-serializer/index.js')
-rw-r--r-- | node_modules/dom-serializer/index.js | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/node_modules/dom-serializer/index.js b/node_modules/dom-serializer/index.js new file mode 100644 index 000000000..3316dfebb --- /dev/null +++ b/node_modules/dom-serializer/index.js @@ -0,0 +1,178 @@ +/* + Module dependencies +*/ +var ElementType = require('domelementtype'); +var entities = require('entities'); + +/* + Boolean Attributes +*/ +var booleanAttributes = { + __proto__: null, + allowfullscreen: true, + async: true, + autofocus: true, + autoplay: true, + checked: true, + controls: true, + default: true, + defer: true, + disabled: true, + hidden: true, + ismap: true, + loop: true, + multiple: true, + muted: true, + open: true, + readonly: true, + required: true, + reversed: true, + scoped: true, + seamless: true, + selected: true, + typemustmatch: true +}; + +var unencodedElements = { + __proto__: null, + style: true, + script: true, + xmp: true, + iframe: true, + noembed: true, + noframes: true, + plaintext: true, + noscript: true +}; + +/* + Format attributes +*/ +function formatAttrs(attributes, opts) { + if (!attributes) return; + + var output = '', + value; + + // Loop through the attributes + for (var key in attributes) { + value = attributes[key]; + if (output) { + output += ' '; + } + + if (!value && booleanAttributes[key]) { + output += key; + } else { + output += key + '="' + (opts.decodeEntities ? entities.encodeXML(value) : value) + '"'; + } + } + + return output; +} + +/* + Self-enclosing tags (stolen from node-htmlparser) +*/ +var singleTag = { + __proto__: null, + area: true, + base: true, + basefont: true, + br: true, + col: true, + command: true, + embed: true, + frame: true, + hr: true, + img: true, + input: true, + isindex: true, + keygen: true, + link: true, + meta: true, + param: true, + source: true, + track: true, + wbr: true, +}; + + +var render = module.exports = function(dom, opts) { + if (!Array.isArray(dom) && !dom.cheerio) dom = [dom]; + opts = opts || {}; + + var output = ''; + + for(var i = 0; i < dom.length; i++){ + var elem = dom[i]; + + if (elem.type === 'root') + output += render(elem.children, opts); + else if (ElementType.isTag(elem)) + output += renderTag(elem, opts); + else if (elem.type === ElementType.Directive) + output += renderDirective(elem); + else if (elem.type === ElementType.Comment) + output += renderComment(elem); + else if (elem.type === ElementType.CDATA) + output += renderCdata(elem); + else + output += renderText(elem, opts); + } + + return output; +}; + +function renderTag(elem, opts) { + // Handle SVG + if (elem.name === "svg") opts = {decodeEntities: opts.decodeEntities, xmlMode: true}; + + var tag = '<' + elem.name, + attribs = formatAttrs(elem.attribs, opts); + + if (attribs) { + tag += ' ' + attribs; + } + + if ( + opts.xmlMode + && (!elem.children || elem.children.length === 0) + ) { + tag += '/>'; + } else { + tag += '>'; + if (elem.children) { + tag += render(elem.children, opts); + } + + if (!singleTag[elem.name] || opts.xmlMode) { + tag += '</' + elem.name + '>'; + } + } + + return tag; +} + +function renderDirective(elem) { + return '<' + elem.data + '>'; +} + +function renderText(elem, opts) { + var data = elem.data || ''; + + // if entities weren't decoded, no need to encode them back + if (opts.decodeEntities && !(elem.parent && elem.parent.name in unencodedElements)) { + data = entities.encodeXML(data); + } + + return data; +} + +function renderCdata(elem) { + return '<![CDATA[' + elem.children[0].data + ']]>'; +} + +function renderComment(elem) { + return '<!--' + elem.data + '-->'; +} |