Javascript to convert Markdown/Textile to HTML (and, ideally, back to Markdown/Textile)

There are several good Javascript editors for Markdown / Textile (e.g.: http://attacklab.net/showdown/, the one I’m using right now), but all I need is a Javascript function that converts a string from Markdown / Textile -> HTML and back.

What’s the best way to do this? (Ideally it would be jQuery-friendly — e.g., $("#editor").markdown_to_html())

Edit: Another way to put it is that I’m looking for a Javascript implementation of Rails’ textilize() and markdown() text helpers

For Markdown -> HTML, there is Showdown

StackOverflow itself uses Markdown language for questions and answers ; did you try to take a look at how it works ?

Well, it seems it is using PageDown which is available under the MIT License

The question Is there any good Markdown Javascript library or control? and its answers might help, too 🙂

A full editor is, of course, not exactly what you asked for ; but they must use some kind of function to transform the Markdown code to HTML ; and, depending on the license of these editors, you might be able to re-use that function…

Actually, if you take a close look at Showdown, in its code source (file showdown.js), you’ll find this portion of comment :

//
// Showdown usage:
//
//   var text = "Markdown *rocks*.";
//
//   var converter = new Showdown.converter();
//   var html = converter.makeHtml(text);
//
//   alert(html);
//
// Note: move the sample code to the bottom of this
// file before uncommenting it.
//

It’s not jQuery syntax, but should be quite easy to integrate in your application 😉

About Textile, it seems to be a bit harder to find anything useful 🙁

In the other side, HTML -> Markdown, I guess things might be a bit harder…

What I would do is store both Markdown and HTML in my application data store (database ? ), and use one for editing, and the other for rendering… Would take more space, but it seems less risky than “decrypting” HTML…

I thought it would be worthwhile to make a list here of the JavaScript solutions out there and their minified (uncompressed) size and strengths/weaknesses. Compressed size for minified code will be around 50% of uncompressed size. What it comes down to:

  • Use markdown-it (104KB) if you need comprehensive support and will have user edited or arbitrary documents, but are not overly concerned with size/bandwidth.
  • Use my own drawdown (1.3KB) if you need reasonably high quality, and table support, but want feather weight and do not need any features other than conversion, or to have every single edge case addressed.
  • Use one of the others if you need unique capabilities like security or expandability.

All of these use the MIT license, most are on npm.

  • markdown-it: 104KB. Powers StackExchange since the CommonMark migration. Follows the CommonMark spec and is now more or less the gold standard; supports syntax extensions; produces secure output by default. Fast; as robust as showdown, but very large. Has a ton of features (e.g. synced scrolling). Is also the basis for http://dillinger.io/.

  • showdown: 28KB. Has comprehensive CommonMark support and was previously the gold standard; is significantly smaller than Markdown-It but slower. it is the basis for pagedown.

  • pagedown: 8KB. Powered StackExchange before the CommonMark migration. It is very robust but missing tables, definition lists, footnotes, etc. In addition to the 8KB converter script, it also offers editor and sanitizer scripts.

  • drawdown: 1.3KB. Full disclosure, I wrote it. Broader feature scope than any other lightweight converter; handles most but not all of the CommonMark spec. Not recommended for user editing but very useful for presenting information in web apps. No inline HTML.

  • marked: 19KB. Comprehensive; tested against unit test suite; supports custom lexer rules.

  • micromarkdown: 5KB. Supports a lot of features, but is missing some common ones like unordered lists using * and some common ones that aren’t strictly part of the spec like fenced code blocks. Many bugs, throws exceptions on most longer documents. I consider it experimental.

  • nano-markdown: 1.9KB. Feature scope limited to things used by most documents; more robust than micromarkdown but not perfect; uses its own very basic unit test. Reasonably robust but breaks on many edge cases.

  • mmd.js: 800 bytes. The result of an effort to make the smallest possible parser that is still functional. Supports a small subset; document needs to be tailored for it.

  • markdown-js: 54KB (not available for download minified; would probably minify to ~20KB). Looks pretty comprehensive and includes tests, but I’m not very familiar with it.

  • meltdown: 41KB (not available for download minified; would probably minify to ~15KB). jQuery plugin; Markdown Extra (tables, definition lists, footnotes).

  • unified.js: varies, 5-100KB. A plugin-based system for converting between html, markdown, and prose. Depending on what plugins you need (spell-checking, syntax-highlighting, input sanitizing) the file size will vary. Probably used more server-side than client-side.

Textile

You can find a seemingly very fine Javascript implementation of Textile here, and another one there (maybe not so good, but has a nice convert-as-you-type example page).

Note: there is a bug in the first implementation I made a link to : horizontal bars are not rendered correctly. To fix it, you can add the following code in the file.

for(i=0;i<lines.length;i++) {
    // Add code :Start
    if (lines[i].match(/s*-{4,}s*/)){
      html+="<hr/>n";
      continue;
    }
    // Add code :End
    if (lines[i].indexOf("[") == 0) {continue;}
    //...

I am using the tiny minimalistic script – mmd.js, which only supports a subset of Markdown possibilities, but this might be all that one would need anyway, so this script which is less than 1kb is amazing and won’t be an overkill.

Supported features

  • Headers #
  • Blockquotes >
  • Ordered lists 1
  • Unordered lists *
  • Paragraphs
  • Links []()
  • Images ![]()
  • Inline emphasis *
  • Inline emphasis **

Unsupported features

  • References and IDs
  • Escaping of Markdown characters
  • Nesting

The Showdown Attacklab-Link is down so use https://github.com/coreyti/showdown for your conversion needs 🙂

It’s easy to use Showdown with or without jQuery. Here’s a jQuery example:

// See http://mathiasbynens.be/notes/showdown-javascript-jquery for a plain JavaScript version as well
$(function() {
 // When using more than one `textarea` on your page, change the following line to match the one you’re after
 var $textarea = $('textarea'),
     $preview = $('<div id="preview" />').insertAfter($textarea),
     converter = new Showdown.converter();
 $textarea.keyup(function() {
  $preview.html(converter.makeHtml($textarea.val()));
 }).trigger('keyup');
});

This doesn’t address the entire request (it isn’t an editor), but textile-js is a javascript rendering library: https://github.com/borgar/textile-js. A demonstration is available at http://borgar.github.io/textile-js/

I found this question intriguing, so I decided to start something off (only replaces strong and italic markdown tags). Having spent an hour trying to devise a solution using regexes, I gave up and ended up with the following, which seems to work nicely. That said, it can surely be further optimized and I’m not sure as to just how real-world resilient it will be in this form:

function mdToHtml(str) {
    var tempStr = str;
    while(tempStr.indexOf("**") !== -1) {
        var firstPos = tempStr.indexOf("**");
        var nextPos = tempStr.indexOf("**",firstPos + 2);
        if(nextPos !== -1) {
            var innerTxt = tempStr.substring(firstPos + 2,nextPos);
            var strongified = '<strong>' + innerTxt + '</strong>';
            tempStr = tempStr.substring(0,firstPos) + strongified + tempStr.substring(nextPos + 2,tempStr.length);
        //get rid of unclosed '**'
        } else {
            tempStr = tempStr.replace('**','');
        }
    }
     while(tempStr.indexOf("*") !== -1) {
        var firstPos = tempStr.indexOf("*");
        var nextPos = tempStr.indexOf("*",firstPos + 1);
        if(nextPos !== -1) {
            var innerTxt = tempStr.substring(firstPos + 1,nextPos);
            var italicized = '<i>' + innerTxt + '</i>';
            tempStr = tempStr.substring(0,firstPos) + italicized + tempStr.substring(nextPos + 2,tempStr.length);
        //get rid of unclosed '*'
        } else {
            tempStr = tempStr.replace('*','');
        }
    }
    return tempStr;
}

Test code:

    var s = "This would be *italicized* text and this would be **bold** text, This would be *italicized* text and this would be **bold** text, This would be *italicized* text and this would be **bold** text";
    alert(mdToHtml(s));

Output:

This would be <i>italicized</i>text and this would be <strong>bold</strong> text, This would be <i>italicized</i>text and this would be <strong>bold</strong> text, This would be <i>italicized</i>text and this would be <strong>bold</strong> text

EDIT: New in V 0.024 – Automatic removal of unclosed markdown tags

markdown-js is a nice javascript markdown parser, an active project with tests.

Let’s write a simple markdown parser function that will take in a single line of markdown and be translated into the appropriate HTML. To keep it simple, we’ll support only one feature of markdown in syntax: headers.

Headers are designated by (1-6) hashes followed by a space, followed by text. The number of hashes determines the header level of the HTML output.

function markdownParser(markdown) {
  const htmlText = markdown
    .replace(/^# (.*$)/gim, '<h1>$1</h1>')
    .replace(/^## (.*$)/gim, '<h2>$1</h2>')
    .replace(/^### (.*$)/gim, '<h3>$1</h3>')
    .replace(/^#### (.*$)/gim, '<h4>$1</h4>')
    .replace(/^##### (.*$)/gim, '<h5>$1</h5>')
    .replace(/^###### (.*$)/gim, '<h6>$1</h6>')
 return htmlText.trim() 
}

Have you looked at the Eclipse WikiText library that is part of Mylyn. It will convert from many wiki syntax to xhtml and to xdocs/DITA. It looks way cool.

http://help.eclipse.org/galileo/topic/org.eclipse.mylyn.wikitext.help.ui/help/Markup-Conversion.html

Has anyone found a solution to the HTML->textile problem? All of our current documentation is in M$ Word format and we would love to bring it into Redmine Wiki for collaborative maintenance. We have not found any tool that will make the conversion. We have found the Open Office extension that produces mediawiki formatted text but Redmine Wiki uses a subset of textile.

Anyone know of a tool that converts TO textile from mediawiki, Word, XDocs, or HTML?

For Textile:

I’ve recently patched together an HTML to Textile converter: https://github.com/cmroanirgo/to-textile

For the reverse Textile to HTML, I use and recommend https://github.com/borgar/textile-js, which other answers have already mentioned.

Leave a Comment