Instantly share code, notes, and snippets.

Embed
What would you like to do?
*[data-markdown] - use markdown, sometimes, in your HTML

*[data-markdown]

I just put some markdown in ur HTML

In prototypes and HTML-based slide decks, it's pleasant to write in markdown sometimes and avoid all those angle brackets.

So the idea is you're operating in an HTML environment but a few shortcuts would help so use markdown here and there.

To use:

  1. Add the following script into your HTML after the content, before other scripts
  1. Add data-markdown attributes to any tags where you're gonna use markdown within. (see example)

Userscript or script-script

This script works fine in your page and can also be used as a userscript. Just click the raw link right below to install.

(As this requires some clientside js and can trigger FOUC, this is not for production use)

// ==UserScript==
// @name Use Markdown, sometimes, in your HTML.
// @author Paul Irish <http://paulirish.com/>
// @link http://git.io/data-markdown
// @match *
// ==/UserScript==
// If you're not using this as a userscript just delete from this line up. It's cool, homey.
(function boom(){
if (!window.Showdown){
var scr = document.createElement('script');
scr.onload = boom;
scr.src = 'https://cdn.rawgit.com/showdownjs/showdown/master/src/showdown.js';
document.body.appendChild(scr);
return;
}
[].forEach.call( document.querySelectorAll('[data-markdown]'), function fn(elem){
// strip leading whitespace so it isn't evaluated as code
var text = elem.innerHTML.replace(/\n\s*\n/g,'\n'),
// set indentation level so your markdown can be indented within your HTML
leadingws = text.match(/^\n?(\s*)/)[1].length,
regex = new RegExp('\\n?\\s{' + leadingws + '}','g'),
md = text.replace(regex,'\n'),
html = (new Showdown.converter()).makeHtml(md);
// here, have sum HTML
elem.innerHTML = html;
});
}());
<div class="slide">
<section class="hbox" data-markdown>
## Who Am I?
* Lead developer of [Modernizr](//modernizr.com)
* Project lead of [HTML5 Boilerplate](//h5bp.com)
* I curate that [page of polyfills](//bit.ly/polyfills)
* Member of jQuery Team
* Developer Relations on Google Chrome team
</section>
</div>
<script src="data-markdown.user.js"></script>
@danielfilho

This comment has been minimized.

danielfilho commented Nov 6, 2011

Now we Can do the slides on markdown as we talked!
Rocks!

@mathiasbynens

This comment has been minimized.

mathiasbynens commented Nov 7, 2011

This would make a fine user script. Could you just add these lines and rename the file as data-markdown.user.js?

// ==UserScript==
// @name Use Markdown, sometimes, in your HTML.
// @author Paul Irish <http://paulirish.com/>
// @link http://git.io/data-markdown
// @match *
// ==/UserScript==
@patik

This comment has been minimized.

patik commented Nov 7, 2011

@mathiasbynens Then it would only work on your browser. The original gist will turn the page into HTML when anyone views it from any browser.

@mathiasbynens

This comment has been minimized.

mathiasbynens commented Nov 7, 2011

@cpatik Exactly. As @paulirish said, this is not intended for production use. But IMHO it would be great as a userscript, especially combined with something like // @match http://slides.local/.

@paulirish

This comment has been minimized.

Owner

paulirish commented Nov 7, 2011

userscriptified. also wired up a document.write dependency. hotttt

@mathiasbynens

This comment has been minimized.

mathiasbynens commented Nov 7, 2011

document.write is the new @require/scriptElement.onload.

@patik

This comment has been minimized.

patik commented Nov 7, 2011

@mathiasbynens Touché, it didn't occur to me that with your change the same script could be used in both ways :)

@niczak

This comment has been minimized.

niczak commented Nov 8, 2011

Brilliant.

@espadrine

This comment has been minimized.

espadrine commented Nov 8, 2011

@mathiasbynens What does the UserScript comment do? Is it something you can then put in a special place in Google Chrome or something?

@lancejpollard

This comment has been minimized.

lancejpollard commented Nov 8, 2011

Nice. This one will load faster since raw is a generated file and isn't cached.

http://github.github.com/github-flavored-markdown/scripts/showdown.js

@SlexAxton

This comment has been minimized.

SlexAxton commented Nov 8, 2011

document.write

more like

document dot right

@patik

This comment has been minimized.

patik commented Nov 8, 2011

@espadrine When you click the "raw" link in the top right of this gist, in either Firefox with Greasemonkey or just plain old Chrome it will prompt you to install the script. That means it'll automatically run on any page matched by the @match line in the script (in this case, any page at all because it's an asterisk).

@timmolendijk

This comment has been minimized.

timmolendijk commented Nov 8, 2011

Did some experimenting with something similar recently. Turns out it's more complicated than what you propose.

Two problems:

HTML entities

elem.textContent will mess up HTML, but Markdown is supposed to be a superset of HTML. So you will need elem.innerHTML, but that will encode certain characters as HTML entities.

For example, the following Markdown in your document will render just fine:

you & me > the *competition*

Result:

<p>you &amp; me &gt; the <em>competition</em></p>

But imagine having something like this in your document:

Our formula: `you & me > the *competition*`

What you want the rendered result to be:

<p>Our formula: <code>you &amp; me &gt; the *competition*</code></p>

What the rendered result is instead:

<p>Our formula: <code>you &amp;amp; me &amp;gt; the *competition*</code></p>

A solution is to manually decode all HTML entities before passing the string on to the Markdown parser. I used something along the following lines (uses jQuery), but it could very well be that there are problems with this approach as well (for example; aren't we decoding a lot of entities that should not be decoded at all here?):

var md = $(elem).html().replace(/&[^;]+;/g, function(entity) {
  return $('<span>' + entity + '</span>').text();
});
var rendered = showdown.makeHtml(md);

Indentation

As soon as you want to include a monospaced block or anything that requires extra indentation, your solution of simply stripping all leading whitespace will mess things up.

@paulirish

This comment has been minimized.

Owner

paulirish commented Nov 8, 2011

@timmolendijk

it's always more complicated. :) yeah i suppose the indentation stripping i'm doing will kill nested lists. ways around that i suppose.

code blocks are already taken care of with the triple-backtick syntax.

for entities, leaving the literals there by themselves would be fine. you don't need to escape either of those.

@timmolendijk

This comment has been minimized.

timmolendijk commented Nov 8, 2011

@paulirish Leaving the literals is not an option because elem.innerHTML will encode them for you.

@Digitalsabre

This comment has been minimized.

Digitalsabre commented Nov 8, 2011

It's not actually doing anything in Chrome or Greasemonkey for Firefox...

@espadrine

This comment has been minimized.

espadrine commented Nov 8, 2011

@Digitalsabre actually, for my version of Google Chrome (which is pretty much the stable on), it tries to install the script, but fails with an "invalid script header" (which makes sense, in a way, I suppose).

@Digitalsabre

This comment has been minimized.

Digitalsabre commented Nov 8, 2011

Correction, after fixing the header (Chrome does not like @match *), the result is a page with no body content.
In Firefox, it just doesn't do anything at all.

@Digitalsabre

This comment has been minimized.

Digitalsabre commented Nov 8, 2011

@espadrine Try removing line 5. It should install, but then it just returns a page with no body content.

@espadrine

This comment has been minimized.

espadrine commented Nov 8, 2011

@Digitalsabre ... which is clearly not what we want ;)

@Digitalsabre

This comment has been minimized.

Digitalsabre commented Nov 8, 2011

@espadrine This is, admittedly, my first time working with user scripts. I really want this to work, so I hope someone comes to help us get it working.

@paulirish, @timmolendijk, @cpatik, any ideas? After forking, I've replaced // @match * with // @include *, but still GreaseMonkey does nothing. I've even added a GM_log('running...'); to the script and it doesn't appear to output that to the console. And since doing this, it will actually install in Chrome, but the result is a blank page. Check my fork for what I've done there, including fleshing out the example page.

@Digitalsabre

This comment has been minimized.

Digitalsabre commented Nov 8, 2011

Now we're getting somewhere:

Uncaught ReferenceError: Showdown is not defined
script.js:20

@espadrine

This comment has been minimized.

espadrine commented Nov 8, 2011

@Digitalsabre Showdown is defined in GitHub Flavored Markdown, in the document.write.

@Digitalsabre

This comment has been minimized.

Digitalsabre commented Nov 8, 2011

@espadrine Sure, but Chrome doesn't seem to think so.

@espadrine

This comment has been minimized.

espadrine commented Nov 8, 2011

@Digitalsabre No more of this bug with this implementation: https://gist.github.com/1349268 (but hey, still doesn't do what we want ey!

@passcod

This comment has been minimized.

passcod commented Nov 9, 2011

@espadrine, @Digitalsabre This works: https://gist.github.com/1349945 The trick is you have to run your code in the context of the page, not of the userscript. Bonus (untested): it should work in Firefox (Greasemonkey or Scriptish), Chrome, and Opera.

@mathiasbynens

This comment has been minimized.

mathiasbynens commented Nov 9, 2011

@espadrine @Digitalsabre @passcod Sounds like you guys need an unsafeWindow polyfill: https://gist.github.com/1143845

@passcod

This comment has been minimized.

passcod commented Nov 9, 2011

@mathiasbynens No we don't, because my version runs the code directly into the page, therefore going out of the GM scope as fast as possible. A few years ago I developed this technique exactly because I was tired of playing with unsafeWindow, polyfill or not.

@greenido

This comment has been minimized.

greenido commented Nov 9, 2011

very cool!! rock on man...

@paulirish

This comment has been minimized.

Owner

paulirish commented Feb 12, 2012

Just updated the code. fixes:

  • Chrome wasn't treating the document.write as synchronous so now we're using a script onload. feels good man
  • indentation level of the source can be arbitrary, which lets you indent the markdown within your HTML. We compute how much indent to treat as default with the first line.
@jeromeetienne

This comment has been minimized.

jeromeetienne commented Apr 24, 2012

and it works as is in html5slide too! excelent.

@jeromeetienne

This comment has been minimized.

jeromeetienne commented Apr 24, 2012

What about using the following to get the markdown content

var text      = elem.innerHTML.replace(/\n\s*\n/g,'\n');

Instead of the following. This would give a better support for html embeded in markdown, no ?

var text      = elem.textContent.replace(/\n\s*\n/g,'\n');
@paulirish

This comment has been minimized.

Owner

paulirish commented Apr 24, 2012

sgtm. changed.

@paulirish

This comment has been minimized.

Owner

paulirish commented Jul 31, 2012

This has now been implemented in the very excellent reveal.js:
https://github.com/hakimel/reveal.js#markdown

@MadcowD

This comment has been minimized.

MadcowD commented Aug 20, 2013

Swag!

@makerimages

This comment has been minimized.

makerimages commented Nov 16, 2014

Does this not work when ran on a local .html page??

@makerimages

This comment has been minimized.

makerimages commented Nov 20, 2014

@paulirish ? Or do we need to call boom();??

@makerimages

This comment has been minimized.

makerimages commented Mar 4, 2015

@Kiodaddy

This comment has been minimized.

Kiodaddy commented Jun 20, 2017

It was working fine for you ? I tried it and zero results.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment