From ecb4348aad2e5c23c66a0e83d70fac4e7dbb06db Mon Sep 17 00:00:00 2001 From: Jason McCarrell Date: Sat, 22 Aug 2015 18:53:49 -0400 Subject: [PATCH 1/5] provided support for ReactJS components Using map and reduce --- lib/index.js | 12 +++++++++--- lib/renderer.js | 43 ++++++++++++++++++++++++++++++------------- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/lib/index.js b/lib/index.js index 6b301e8..0766e4d 100644 --- a/lib/index.js +++ b/lib/index.js @@ -57,7 +57,7 @@ function normalizeLink(url) { if (!parsed.protocol || RECODE_HOSTNAME_FOR.indexOf(parsed.protocol) >= 0) { try { parsed.hostname = punycode.toASCII(parsed.hostname); - } catch (er) { /**/ } + } catch(er) {} } } @@ -77,7 +77,7 @@ function normalizeLinkText(url) { if (!parsed.protocol || RECODE_HOSTNAME_FOR.indexOf(parsed.protocol) >= 0) { try { parsed.hostname = punycode.toUnicode(parsed.hostname); - } catch (er) { /**/ } + } catch(er) {} } } @@ -483,7 +483,7 @@ MarkdownIt.prototype.use = function (plugin /*, params, ... */) { * AST). * * `env` is used to pass data between "distributed" rules and return additional - * metadata like reference info, needed for the renderer. It also can be used to + * metadata like reference info, needed for for renderer. It also can be used to * inject data in specific cases. Usually, you will be ok to pass `{}`, * and then pass updated object to renderer. **/ @@ -513,6 +513,12 @@ MarkdownIt.prototype.render = function (src, env) { return this.renderer.render(this.parse(src, env), this.options, env); }; +MarkdownIt.prototype.renderTokens = function (src, env) { + env = env || {}; + + return this.renderer.renderTokens(this.parse(src, env), this.options, env); +}; + /** internal * MarkdownIt.parseInline(src, env) -> Array diff --git a/lib/renderer.js b/lib/renderer.js index b1000d5..a9ac904 100644 --- a/lib/renderer.js +++ b/lib/renderer.js @@ -28,7 +28,7 @@ default_rules.code_block = function (tokens, idx /*, options, env */) { }; -default_rules.fence = function (tokens, idx, options, env, slf) { +default_rules.fence = function (tokens, idx, options, env, self) { var token = tokens[idx], info = token.info ? unescapeAll(token.info).trim() : '', langName = '', @@ -45,13 +45,13 @@ default_rules.fence = function (tokens, idx, options, env, slf) { highlighted = escapeHtml(token.content); } - return '
'
+  return  '
'
         + highlighted
         + '
\n'; }; -default_rules.image = function (tokens, idx, options, env, slf) { +default_rules.image = function (tokens, idx, options, env, self) { var token = tokens[idx]; // "alt" attr MUST be set, even if empty. Because it's mandatory and @@ -60,9 +60,9 @@ default_rules.image = function (tokens, idx, options, env, slf) { // Replace content with actual value token.attrs[token.attrIndex('alt')][1] = - slf.renderInlineAsText(token.children, options, env); + self.renderInlineAsText(token.children, options, env); - return slf.renderToken(tokens, idx, options); + return self.renderToken(tokens, idx, options); }; @@ -228,6 +228,16 @@ Renderer.prototype.renderInline = function (tokens, options, env) { var type, result = '', rules = this.rules; + + return tokens.map(function(token, i) { + type = token.type; + + if (typeof rules[type] !== 'undefined') { + return rules[type](tokens, i, options, env, this); + } else { + return this.renderToken(tokens, i, options); + } + }, this); for (var i = 0, len = tokens.length; i < len; i++) { type = tokens[i].type; @@ -279,23 +289,30 @@ Renderer.prototype.renderInlineAsText = function (tokens, options, env) { * this method directly. **/ Renderer.prototype.render = function (tokens, options, env) { + return this.renderTokens(tokens, options, env).reduce(function(collector, token) { + return collector + token; + }, ''); +}; + +Renderer.prototype.renderTokens = function (tokens, options, env) { var i, len, type, result = '', rules = this.rules; - for (i = 0, len = tokens.length; i < len; i++) { - type = tokens[i].type; + return tokens.reduce(function(collector, token, i) { + type = token.type; if (type === 'inline') { - result += this.renderInline(tokens[i].children, options, env); + console.log('inline: ', this.renderInline(token.children, options, env)); + return collector.concat(this.renderInline(token.children, options, env)); } else if (typeof rules[type] !== 'undefined') { - result += rules[tokens[i].type](tokens, i, options, env, this); + collector.push(rules[type](tokens, i, options, env, this)); + return collector; } else { - result += this.renderToken(tokens, i, options, env); + collector.push(this.renderToken(tokens, i, options, env)); + return collector; } - } - - return result; + }.bind(this), []); }; module.exports = Renderer; From 86cc0ec083e46dd583e9981e9187498d105fa40c Mon Sep 17 00:00:00 2001 From: Jason McCarrell Date: Sat, 22 Aug 2015 19:00:23 -0400 Subject: [PATCH 2/5] added comments to new methods --- lib/index.js | 9 +++++++++ lib/renderer.js | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/lib/index.js b/lib/index.js index 0766e4d..ebf7f2e 100644 --- a/lib/index.js +++ b/lib/index.js @@ -513,6 +513,15 @@ MarkdownIt.prototype.render = function (src, env) { return this.renderer.render(this.parse(src, env), this.options, env); }; + +/** + * MarkdownIt.renderTokens(src [, env]) -> String + * - src (String): source string + * - env (Object): environment sandbox + * + * Render markdown string into an array of html-like tokens. + * If you want to render each token separately (for example with React) + **/ MarkdownIt.prototype.renderTokens = function (src, env) { env = env || {}; diff --git a/lib/renderer.js b/lib/renderer.js index a9ac904..c907860 100644 --- a/lib/renderer.js +++ b/lib/renderer.js @@ -294,6 +294,16 @@ Renderer.prototype.render = function (tokens, options, env) { }, ''); }; + +/** + * Renderer.renderTokens(tokens, options, env) -> String + * - tokens (Array): list on block tokens to renter + * - options (Object): params of parser instance + * - env (Object): additional data from parsed input (references, for example) + * + * Takes token stream and generates html-like tokens. Probably, you will never need to call + * this method directly. + **/ Renderer.prototype.renderTokens = function (tokens, options, env) { var i, len, type, result = '', From 72f5fa37016492a14515398e8179bcaa0689da1c Mon Sep 17 00:00:00 2001 From: Jason McCarrell Date: Sun, 23 Aug 2015 18:53:57 -0400 Subject: [PATCH 3/5] added and got test working for renderTokens --- test/misc.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/misc.js b/test/misc.js index 82e2381..f4e5a6c 100644 --- a/test/misc.js +++ b/test/misc.js @@ -213,6 +213,13 @@ describe('Misc', function () { assert.strictEqual(md.render('[foo](bar)'), '

foo

\n'); }); + it('Should render tokens into an array', function() { + var md = markdownit() + + console.log(md.renderTokens('foo')); + assert.deepEqual(md.renderTokens('foo'), ['

', 'foo', '

\n']); + }); + }); From ab815d5ee5b7c7e1d6dd548a60992f202c6a50ba Mon Sep 17 00:00:00 2001 From: Jason McCarrell Date: Sun, 23 Aug 2015 19:03:45 -0400 Subject: [PATCH 4/5] cleaned up the rendered file. Loose code. --- lib/renderer.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/lib/renderer.js b/lib/renderer.js index c907860..7c46955 100644 --- a/lib/renderer.js +++ b/lib/renderer.js @@ -238,18 +238,6 @@ Renderer.prototype.renderInline = function (tokens, options, env) { return this.renderToken(tokens, i, options); } }, this); - - for (var i = 0, len = tokens.length; i < len; i++) { - type = tokens[i].type; - - if (typeof rules[type] !== 'undefined') { - result += rules[type](tokens, i, options, env, this); - } else { - result += this.renderToken(tokens, i, options); - } - } - - return result; }; From 0937ab3d743c200bf67a30dcafbcc821d3b4d132 Mon Sep 17 00:00:00 2001 From: Jason McCarrell Date: Sun, 23 Aug 2015 19:59:39 -0400 Subject: [PATCH 5/5] fixed stuff for travis thingy --- lib/index.js | 4 ++-- lib/renderer.js | 32 +++++++++++++++----------------- test/misc.js | 7 +++---- 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/lib/index.js b/lib/index.js index ebf7f2e..a3dd099 100644 --- a/lib/index.js +++ b/lib/index.js @@ -57,7 +57,7 @@ function normalizeLink(url) { if (!parsed.protocol || RECODE_HOSTNAME_FOR.indexOf(parsed.protocol) >= 0) { try { parsed.hostname = punycode.toASCII(parsed.hostname); - } catch(er) {} + } catch(er) { /**/ } } } @@ -77,7 +77,7 @@ function normalizeLinkText(url) { if (!parsed.protocol || RECODE_HOSTNAME_FOR.indexOf(parsed.protocol) >= 0) { try { parsed.hostname = punycode.toUnicode(parsed.hostname); - } catch(er) {} + } catch(er) { /**/ } } } diff --git a/lib/renderer.js b/lib/renderer.js index 7c46955..0db3bc6 100644 --- a/lib/renderer.js +++ b/lib/renderer.js @@ -28,7 +28,7 @@ default_rules.code_block = function (tokens, idx /*, options, env */) { }; -default_rules.fence = function (tokens, idx, options, env, self) { +default_rules.fence = function (tokens, idx, options, env, slf) { var token = tokens[idx], info = token.info ? unescapeAll(token.info).trim() : '', langName = '', @@ -45,13 +45,13 @@ default_rules.fence = function (tokens, idx, options, env, self) { highlighted = escapeHtml(token.content); } - return '
'
+  return  '
'
         + highlighted
         + '
\n'; }; -default_rules.image = function (tokens, idx, options, env, self) { +default_rules.image = function (tokens, idx, options, env, slf) { var token = tokens[idx]; // "alt" attr MUST be set, even if empty. Because it's mandatory and @@ -60,9 +60,9 @@ default_rules.image = function (tokens, idx, options, env, self) { // Replace content with actual value token.attrs[token.attrIndex('alt')][1] = - self.renderInlineAsText(token.children, options, env); + slf.renderInlineAsText(token.children, options, env); - return self.renderToken(tokens, idx, options); + return slf.renderToken(tokens, idx, options); }; @@ -226,17 +226,15 @@ Renderer.prototype.renderToken = function renderToken(tokens, idx, options) { **/ Renderer.prototype.renderInline = function (tokens, options, env) { var type, - result = '', rules = this.rules; - + return tokens.map(function(token, i) { type = token.type; if (typeof rules[type] !== 'undefined') { return rules[type](tokens, i, options, env, this); - } else { - return this.renderToken(tokens, i, options); - } + + return this.renderToken(tokens, i, options); }, this); }; @@ -293,23 +291,23 @@ Renderer.prototype.render = function (tokens, options, env) { * this method directly. **/ Renderer.prototype.renderTokens = function (tokens, options, env) { - var i, len, type, + var len, type, result = '', rules = this.rules; return tokens.reduce(function(collector, token, i) { type = token.type; - if (type === 'inline') { - console.log('inline: ', this.renderInline(token.children, options, env)); + if (type === 'inline') return collector.concat(this.renderInline(token.children, options, env)); - } else if (typeof rules[type] !== 'undefined') { + + if (typeof rules[type] !== 'undefined') { collector.push(rules[type](tokens, i, options, env, this)); return collector; - } else { - collector.push(this.renderToken(tokens, i, options, env)); - return collector; } + + collector.push(this.renderToken(tokens, i, options, env)); + return collector; }.bind(this), []); }; diff --git a/test/misc.js b/test/misc.js index f4e5a6c..e22dbce 100644 --- a/test/misc.js +++ b/test/misc.js @@ -214,10 +214,9 @@ describe('Misc', function () { }); it('Should render tokens into an array', function() { - var md = markdownit() - - console.log(md.renderTokens('foo')); - assert.deepEqual(md.renderTokens('foo'), ['

', 'foo', '

\n']); + var md = markdownit(); + + assert.deepEqual(md.renderTokens('foo'), [ '

', 'foo', '

\n' ]); }); });