33const marked = require ( 'marked' ) ;
44const highlightjs = require ( 'highlightjs' ) ;
55
6- module . exports = function compileMarkdown ( source , options ) {
7- let tokens ;
8- let config = { highlight } ;
6+ module . exports = function compileMarkdown ( source , config ) {
7+ let tokens = marked . lexer ( source ) ;
8+ let markedOptions = {
9+ highlight,
10+ renderer : new HBSRenderer ( config )
11+ } ;
912
10- if ( options && options . targetHandlebars ) {
11- config . renderer = new HBSRenderer ( ) ;
12- tokens = compactParagraphs ( source ) ;
13- } else {
14- tokens = marked . lexer ( source ) ;
13+ if ( config && config . targetHandlebars ) {
14+ tokens = compactParagraphs ( tokens ) ;
1515 }
1616
17- return `<div class="docs-md">${ marked . parser ( tokens , config ) . trim ( ) } </div>` ;
17+ return `<div class="docs-md">${ marked . parser ( tokens , markedOptions ) . trim ( ) } </div>` ;
1818} ;
1919
2020function highlight ( code , lang ) {
@@ -25,25 +25,29 @@ function highlight(code, lang) {
2525 }
2626}
2727
28- function compactParagraphs ( source ) {
29- let tokens = marked . lexer ( source ) ;
28+ // Whitespace can imply paragraphs in Markdown, which can result
29+ // in interleaving between <p> tags and block component invocations,
30+ // so this scans the Marked tokens to turn things like this:
31+ // <p>{{#my-component}}<p>
32+ // <p>{{/my-component}}</p>
33+ // Into this:
34+ // <p>{{#my-component}} {{/my-component}}</p>
35+ function compactParagraphs ( tokens ) {
3036 let compacted = [ ] ;
3137
3238 compacted . links = tokens . links ;
3339
34- let diff = 0 ;
40+ let balance = 0 ;
3541 for ( let token of tokens ) {
36- let wasBalanced = diff === 0 ;
37-
38- diff += count ( / \{ \{ # / g, token . text ) ;
39- diff -= count ( / \{ \{ \/ / g, token . text ) ;
40-
41- if ( wasBalanced ) {
42+ if ( balance === 0 ) {
4243 compacted . push ( token ) ;
4344 } else {
4445 let last = compacted [ compacted . length - 1 ] ;
4546 last . text = `${ last . text } ${ token . text } ` ;
4647 }
48+
49+ balance += count ( / \{ \{ # / g, token . text ) ;
50+ balance -= count ( / \{ \{ \/ / g, token . text ) ;
4751 }
4852
4953 return compacted ;
@@ -56,21 +60,38 @@ function count(regex, string) {
5660}
5761
5862class HBSRenderer extends marked . Renderer {
59- // Escape curlies in code spans/blocks to avoid treating them as Handlebars
63+ constructor ( config ) {
64+ super ( ) ;
65+ this . config = config || { } ;
66+ }
67+
6068 codespan ( ) {
61- return this . _escapeCurlies ( super . codespan . apply ( this , arguments ) ) ;
69+ return this . _processCode ( super . codespan . apply ( this , arguments ) ) ;
6270 }
6371
6472 code ( ) {
65- let code = this . _escapeCurlies ( super . code . apply ( this , arguments ) ) ;
73+ let code = this . _processCode ( super . code . apply ( this , arguments ) ) ;
6674 return code . replace ( / ^ < p r e > / , '<pre class="docs-md__code">' ) ;
6775 }
6876
6977 // Unescape quotes in text, as they may be part of a Handlebars statement
7078 text ( ) {
71- return super . text . apply ( this , arguments )
72- . replace ( / & q u o t ; | & # 3 4 ; / g, `"` )
73- . replace ( / & a p o s ; | & # 3 9 ; / g, `'` ) ;
79+ let text = super . text . apply ( this , arguments ) ;
80+ if ( this . config . targetHandlebars ) {
81+ text = text
82+ . replace ( / & q u o t ; | & # 3 4 ; / g, `"` )
83+ . replace ( / & a p o s ; | & # 3 9 ; / g, `'` ) ;
84+ }
85+ return text ;
86+ }
87+
88+ // Escape curlies in code spans/blocks to avoid treating them as Handlebars
89+ _processCode ( string ) {
90+ if ( this . config . targetHandlebars ) {
91+ string = this . _escapeCurlies ( string ) ;
92+ }
93+
94+ return string ;
7495 }
7596
7697 _escapeCurlies ( string ) {
0 commit comments