/*

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 + '-->';

}