diff --git a/js/core/markdown.js b/js/core/markdown.js
new file mode 100644
index 0000000000..448abe500b
--- /dev/null
+++ b/js/core/markdown.js
@@ -0,0 +1,208 @@
+// Module core/markdown
+// Handles the optional markdown processing.
+//
+// Markdown support is optional. It is enabled by setting the `format`
+// property of the configuration object to "markdown."
+//
+// We use marked for parsing Markkdown.
+//
+// Note that the content of SECTION elements, and P elements with a
+// class name of "note" or "issue" is also parsed.
+//
+// The HTML created by the Markdown parser is turned into a nested
+// structure of SECTION elements, following the strucutre given by
+// the headings. For example, the following markup:
+//
+// Title
+// -----
+//
+// ### Subtitle ###
+//
+// Here's some text.
+//
+// ### Another subtitle ###
+//
+// More text.
+//
+// will be transformed into:
+//
+// Here's some text. More text.Title
+// Subtitle
+// Another subtitle
+//
And this more text.
+ // + //This is a title
+ // ---------------
+ //
+ // And this more text.
+ // current) {
+ min = current
+ }
+ }
+
+ var re = new RegExp("\n[ ]{0," + min + "}", "g");
+ text = text.replace(re, '\n');
+ }
+ return text;
+ },
+
+ processBody: function(doc) {
+ var fragment = doc.createDocumentFragment()
+ , div = doc.createElement('div')
+ , node
+ ;
+
+ div.innerHTML = this.toHTML(doc.body.innerHTML);
+ while (node = div.firstChild) {
+ fragment.appendChild(node);
+ }
+ return fragment;
+ },
+
+ processSections: function(doc) {
+ var self = this;
+ $('section', doc).each(function() {
+ this.innerHTML = self.toHTML(this.innerHTML);
+ });
+ },
+
+ processIssuesAndNotes: function(doc) {
+ var div = doc.createElement('div');
+ var self = this;
+ $('.issue, .note', doc).each(function() {
+ div.innerHTML = self.toHTML(this.innerHTML);
+ this.innerHTML = '';
+ var node = div.firstChild;
+ while (node.firstChild) {
+ this.appendChild(node.firstChild);
+ }
+ });
+ },
+
+ structure: function(fragment, doc) {
+ var output = doc.createDocumentFragment()
+ , current = output
+ , stack = [output]
+ , node
+ , tagName
+ ;
+
+ function newSection(node, position) {
+ var section = doc.createElement('section');
+ section.appendChild(node);
+ findParent(position).appendChild(section);
+ stack[position] = section;
+ current = section;
+ }
+
+ function findParent(position) {
+ while (1) {
+ position--
+ parent = stack[position];
+ if (parent) return parent;
+ }
+ }
+
+ while (node = fragment.firstChild) {
+ if (node.nodeType !== 1) {
+ fragment.removeChild(node);
+ continue;
+ }
+ tagName = node.tagName.toLowerCase();
+ switch (tagName) {
+ case 'h1':
+ newSection(node, 1);
+ break;
+ case 'h2':
+ newSection(node, 2);
+ break;
+ case 'h3':
+ newSection(node, 3);
+ break;
+ case 'h4':
+ newSection(node, 4);
+ break;
+ case 'h5':
+ newSection(node, 5);
+ break;
+ case 'h6':
+ newSection(node, 6);
+ break;
+ default:
+ current.appendChild(node);
+ }
+ }
+
+ return output;
+ },
+
+ run: function (conf, doc, cb, msg) {
+ msg.pub("start", "core/markdown");
+ if (conf.format === 'markdown') {
+ this.processIssuesAndNotes(doc);
+ this.processSections(doc);
+ fragment = this.structure(this.processBody(doc), doc);
+ doc.body.innerHTML = '';
+ doc.body.appendChild(fragment)
+ }
+ msg.pub("end", "core/markdown");
+ cb();
+ }
+ };
+ }
+);
diff --git a/js/core/marked.js b/js/core/marked.js
new file mode 100644
index 0000000000..62a5eb9993
--- /dev/null
+++ b/js/core/marked.js
@@ -0,0 +1,781 @@
+/**
+ * marked - A markdown parser (https://github.com/chjj/marked)
+ * Copyright (c) 2011-2012, Christopher Jeffrey. (MIT Licensed)
+ */
+
+;(function() {
+
+/**
+ * Block-Level Grammar
+ */
+
+var block = {
+ newline: /^\n+/,
+ code: /^( {4}[^\n]+\n*)+/,
+ fences: noop,
+ hr: /^( *[-*_]){3,} *(?:\n+|$)/,
+ heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
+ lheading: /^([^\n]+)\n *(=|-){3,} *\n*/,
+ blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/,
+ list: /^( *)(bull) [^\0]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
+ html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,
+ def: /^ *\[([^\]]+)\]: *([^\s]+)(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
+ paragraph: /^([^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+\n*/,
+ text: /^[^\n]+/
+};
+
+block.bullet = /(?:[*+-]|\d+\.)/;
+block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
+block.item = replace(block.item, 'gm')
+ (/bull/g, block.bullet)
+ ();
+
+block.list = replace(block.list)
+ (/bull/g, block.bullet)
+ ('hr', /\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/)
+ ();
+
+block.html = replace(block.html)
+ ('comment', //)
+ ('closed', /<(tag)[^\0]+?<\/\1>/)
+ ('closing', /'
+ + escape(cap[2], true)
+ + '
';
+ continue;
+ }
+
+ // br
+ if (cap = inline.br.exec(src)) {
+ src = src.substring(cap[0].length);
+ out += ''
+ + token.text
+ + '
\n';
+ }
+ case 'blockquote_start': {
+ var body = '';
+
+ while (next().type !== 'blockquote_end') {
+ body += tok();
+ }
+
+ return '\n' + + body + + '\n'; + } + case 'list_start': { + var type = token.ordered ? 'ol' : 'ul' + , body = ''; + + while (next().type !== 'list_end') { + body += tok(); + } + + return '<' + + type + + '>\n' + + body + + '' + + type + + '>\n'; + } + case 'list_item_start': { + var body = ''; + + while (next().type !== 'list_item_end') { + body += token.type === 'text' + ? parseText() + : tok(); + } + + return '
' + + inline.lexer(token.text) + + '
\n'; + } + case 'text': { + return '' + + parseText() + + '
\n'; + } + } +} + +function parseText() { + var body = token.text + , top; + + while ((top = tokens[tokens.length-1]) + && top.type === 'text') { + body += '\n' + next().text; + } + + return inline.lexer(body); +} + +function parse(src) { + tokens = src.reverse(); + + var out = ''; + while (next()) { + out += tok(); + } + + tokens = null; + token = null; + + return out; +} + +/** + * Helpers + */ + +function escape(html, encode) { + return html + .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +function mangle(text) { + var out = '' + , l = text.length + , i = 0 + , ch; + + for (; i < l; i++) { + ch = text.charCodeAt(i); + if (Math.random() > 0.5) { + ch = 'x' + ch.toString(16); + } + out += '' + ch + ';'; + } + + return out; +} + +function tag() { + var tag = '(?!(?:' + + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code' + + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo' + + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b'; + + return tag; +} + +function replace(regex, opt) { + regex = regex.source; + opt = opt || ''; + return function self(name, val) { + if (!name) return new RegExp(regex, opt); + val = val.source || val; + val = val.replace(/(^|[^\[])\^/g, '$1'); + regex = regex.replace(name, val); + return self; + }; +} + +function noop() {} +noop.exec = noop; + +/** + * Marked + */ + +function marked(src, opt) { + setOptions(opt); + return parse(block.lexer(src)); +} + +/** + * Options + */ + +var options + , defaults; + +function setOptions(opt) { + if (!opt) opt = defaults; + if (options === opt) return; + options = opt; + + if (options.gfm) { + block.fences = block.gfm.fences; + block.paragraph = block.gfm.paragraph; + inline.text = inline.gfm.text; + inline.url = inline.gfm.url; + } else { + block.fences = block.normal.fences; + block.paragraph = block.normal.paragraph; + inline.text = inline.normal.text; + inline.url = inline.normal.url; + } + + if (options.pedantic) { + inline.em = inline.pedantic.em; + inline.strong = inline.pedantic.strong; + } else { + inline.em = inline.normal.em; + inline.strong = inline.normal.strong; + } +} + +marked.options = +marked.setOptions = function(opt) { + defaults = opt; + setOptions(opt); + return marked; +}; + +marked.setOptions({ + gfm: true, + pedantic: false, + sanitize: false, + highlight: null +}); + +/** + * Expose + */ + +marked.parser = function(src, opt) { + setOptions(opt); + return parse(src); +}; + +marked.lexer = function(src, opt) { + setOptions(opt); + return block.lexer(src); +}; + +marked.parse = marked; + +if (typeof module !== 'undefined') { + module.exports = marked; +} else { + this.marked = marked; +} + +}).call(function() { + return this || (typeof window !== 'undefined' ? window : global); +}()); \ No newline at end of file diff --git a/js/profile-w3c-common.js b/js/profile-w3c-common.js index 41a3f19ed7..56d9dab7f0 100644 --- a/js/profile-w3c-common.js +++ b/js/profile-w3c-common.js @@ -4,6 +4,7 @@ define([ , "core/base-runner" , "core/override-configuration" , "core/default-root-attr" + , "core/markdown" , "core/style" , "w3c/style" , "w3c/headers"