123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- /*
- 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 + '-->';
- }
|