| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 | /*  Module dependencies*/var ElementType = require('domelementtype');var entities = require('entities');/* mixed-case SVG and MathML tags & attributes   recognized by the HTML parser, see   https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inforeign*/var foreignNames = require('./foreignNames.json');foreignNames.elementNames.__proto__ = null; /* use as a simple dictionary */foreignNames.attributeNames.__proto__ = null;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 = '';  var value;  // Loop through the attributes  for (var key in attributes) {    value = attributes[key];    if (output) {      output += ' ';    }    if (opts.xmlMode === 'foreign') {      /* fix up mixed-case attribute names */      key = foreignNames.attributeNames[key] || key;    }    output += key;    if ((value !== null && value !== '') || opts.xmlMode) {      output +=        '="' +        (opts.decodeEntities          ? entities.encodeXML(value)          : value.replace(/\"/g, '"')) +        '"';    }  }  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;});var foreignModeIntegrationPoints = [  'mi',  'mo',  'mn',  'ms',  'mtext',  'annotation-xml',  'foreignObject',  'desc',  'title'];function renderTag(elem, opts) {  // Handle SVG / MathML in HTML  if (opts.xmlMode === 'foreign') {    /* fix up mixed-case element names */    elem.name = foreignNames.elementNames[elem.name] || elem.name;    /* exit foreign mode at integration points */    if (      elem.parent &&      foreignModeIntegrationPoints.indexOf(elem.parent.name) >= 0    )      opts = Object.assign({}, opts, { xmlMode: false });  }  if (!opts.xmlMode && ['svg', 'math'].indexOf(elem.name) >= 0) {    opts = Object.assign({}, opts, { xmlMode: 'foreign' });  }  var tag = '<' + elem.name;  var 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 + '-->';}
 |