/** * downshow.js -- A javascript library to convert HTML to markdown. * * Copyright (c) 2013 Alex Cornejo. * * Original Markdown Copyright (c) 2004-2005 John Gruber * * * Redistributable under a BSD-style open source license. * * downshow has no external dependencies. It has been tested in chrome and * firefox, it probably works in internet explorer, but YMMV. * * Basic Usage: * * downshow(document.getElementById('#yourid').innerHTML); * * TODO: * - Remove extra whitespace between words in headers and other places. */ (function () { var doc; // Use browser DOM with jsdom as a fallback (for node.js) try { doc = document; } catch(e) { var jsdom = require("jsdom").jsdom; doc = jsdom(""); } /** * Returns every element in root in their bfs traversal order. * * In the process it transforms any nested lists to conform to the w3c * standard, see: http://www.w3.org/wiki/HTML_lists#Nesting_lists */ function bfsOrder(root) { var inqueue = [root], outqueue = []; root._bfs_parent = null; while (inqueue.length > 0) { var elem = inqueue.shift(); outqueue.push(elem); var children = elem.childNodes; var liParent = null; for (var i=0 ; i 0) { if (prefix && suffix) node._bfs_text = prefix + content + suffix; else node._bfs_text = content; } else node._bfs_text = ''; } /** * Get a node's content. */ function getContent(node) { var text = '', atom; for (var i = 0; i 0) setContent(node, '[' + text + '](' + href + (title ? ' "' + title + '"' : '') + ')'); else setContent(node, ''); } else if (node.tagName === 'IMG') { var src = node.getAttribute('src') ? nltrim(node.getAttribute('src')) : '', alt = node.alt ? nltrim(node.alt) : '', caption = node.title ? nltrim(node.title) : ''; if (src.length > 0) setContent(node, '![' + alt + '](' + src + (caption ? ' "' + caption + '"' : '') + ')'); else setContent(node, ''); } else if (node.tagName === 'BLOCKQUOTE') { var block_content = getContent(node); if (block_content.length > 0) setContent(node, prefixBlock('> ', block_content), '\n\n', '\n\n'); else setContent(node, ''); } else if (node.tagName === 'CODE') { if (node._bfs_parent.tagName === 'PRE' && node._bfs_parent._bfs_parent !== null) setContent(node, prefixBlock(' ', getContent(node))); else setContent(node, nltrim(getContent(node)), '`', '`'); } else if (node.tagName === 'LI') { var list_content = getContent(node); if (list_content.length > 0) if (node._bfs_parent.tagName === 'OL') setContent(node, trim(prefixBlock(' ', list_content, true)), '1. ', '\n\n'); else setContent(node, trim(prefixBlock(' ', list_content, true)), '- ', '\n\n'); else setContent(node, ''); } else setContent(node, getContent(node)); } function downshow(html, options) { var root = doc.createElement('pre'); root.innerHTML = html; var nodes = bfsOrder(root).reverse(), i; if (options && options.nodeParser) { for (i = 0; i )+[^\n]*)\n+(\n(?:> )+)/g, "$1\n$2") // remove empty blockquotes .replace(/\n((?:> )+[ ]*\n)+/g, '\n\n') // remove extra newlines .replace(/\n[ \t]*(?:\n[ \t]*)+\n/g,'\n\n') // remove trailing whitespace .replace(/\s\s*$/, '') // convert lists to inline when not using paragraphs .replace(/^([ \t]*(?:\d+\.|\+|\-)[^\n]*)\n\n+(?=[ \t]*(?:\d+\.|\+|\-|\*)[^\n]*)/gm, "$1\n") // remove starting newlines .replace(/^\n\n*/, ''); } // Export for use in server and client. if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') module.exports = downshow; else if (typeof define === 'function' && define.amd) define([], function () {return downshow;}); else window.downshow = downshow; })();