@@ -3,24 +3,51 @@ const marked = require('marked');
33const Prism = require ( 'prismjs' ) ;
44const renderer = new marked . Renderer ( ) ;
55
6+ const singleReplaceChars = {
7+ '\(' : '(' ,
8+ '\)' : ')' ,
9+ '\{' : '{' ,
10+ '\}' : '}' ,
11+ }
12+ const regexString = `[${ Object . keys ( singleReplaceChars ) . join ( '' ) } ]` ;
13+ const regex = new RegExp ( regexString , 'gm' ) ;
14+
15+ function replaceReact ( string ) {
16+ return string
17+ . replace ( regex , m => singleReplaceChars [ m ] )
18+ . replace ( / c l a s s = " / g, 'className="' )
19+ }
20+
21+ const reactSafe = ( fn ) => {
22+ return function ( ) {
23+ let original = fn . apply ( renderer , [ ...arguments ] ) ;
24+ let replaced = replaceReact ( original ) ;
25+ return replaced ;
26+ }
27+ }
628
7- renderer . code = function ( code , lang ) {
29+ function processCodeBlock ( code , lang ) {
830 let className , highlighter , replaced ;
931
1032 // users can easily type in any language they want,
1133 // we don't want the app to blow up in case of bad input.
1234 try {
13- require ( `prismjs/components/prism-${ lang } ` ) ;
14- className = `language-${ lang } ` ;
15- highlighter = Prism . languages [ lang ] ;
35+ if ( typeof lang === 'undefined' ) {
36+ className = '' ;
37+ highlighter = '' ;
38+ } else {
39+ require ( `prismjs/components/prism-${ lang } ` ) ;
40+ className = `language-${ lang } ` ;
41+ highlighter = Prism . languages [ lang ] ;
42+ }
1643 } catch ( e ) {
17- console . warn ( `Could not find PrismJS language ${ lang } ` ) ;
44+ console . warn ( `Could not find PrismJS language ${ lang } ` , e ) ;
1845 className = '' ;
1946 highlighter = '' ;
2047 }
2148
2249 try {
23- const wrapped = Prism . highlight ( code , highlighter ) ;
50+ const wrapped = Prism . highlight ( code , highlighter ) ;
2451 replaced = wrapped . replace ( / \n / g, '<br />' ) ;
2552 } catch ( e ) {
2653 console . error ( `Failed to highlight syntax for language ${ lang } ` ) ;
@@ -31,15 +58,46 @@ renderer.code = function(code, lang) {
3158 }
3259
3360 return `
34- <pre class="${ className } ">
35- <code class="${ className } ">
36- ${ replaced }
37- </code>
38- </pre>
39- ` ;
40- } ;
61+ <pre class="${ className } ">
62+ <code class="${ className } ">
63+ ${ replaced }
64+ </code>
65+ </pre>
66+ ` ;
67+ }
68+
69+ /**
70+ * Block level renderer methods
71+ * https://marked.js.org/#/USING_PRO.md#block-level-renderer-methods
72+ */
73+ renderer . code = reactSafe ( processCodeBlock ) ;
74+ renderer . blockquote = reactSafe ( renderer . blockquote ) ;
75+ renderer . paragraph = reactSafe ( renderer . paragraph ) ;
76+ renderer . heading = reactSafe ( renderer . heading ) ;
77+ renderer . html = renderer . html ;
78+ renderer . hr = reactSafe ( renderer . hr ) ;
79+ renderer . list = reactSafe ( renderer . list ) ;
80+ renderer . listitem = reactSafe ( renderer . listitem ) ;
81+ renderer . checkbox = reactSafe ( renderer . checkbox ) ;
82+ renderer . paragraph = reactSafe ( renderer . paragraph ) ;
83+ renderer . table = reactSafe ( renderer . table ) ;
84+ renderer . tablerow = reactSafe ( renderer . tablerow ) ;
85+ renderer . tablecell = reactSafe ( renderer . tablecell ) ;
4186
42- const extraExports = extra => {
87+ /**
88+ * Inline level renderer methods
89+ * https://marked.js.org/#/USING_PRO.md#inline-level-renderer-methods
90+ */
91+ renderer . strong = reactSafe ( renderer . strong ) ;
92+ renderer . em = reactSafe ( renderer . em ) ;
93+ renderer . codespan = reactSafe ( renderer . codespan ) ;
94+ renderer . br = reactSafe ( renderer . br ) ;
95+ renderer . del = reactSafe ( renderer . del ) ;
96+ renderer . link = reactSafe ( renderer . link ) ;
97+ renderer . image = reactSafe ( renderer . image ) ;
98+ renderer . text = reactSafe ( renderer . text ) ;
99+
100+ function extraExports ( extra ) {
43101 let ret = '' ;
44102 for ( var key in extra ) {
45103 ret += `
@@ -66,18 +124,11 @@ module.exports = function (source, map) {
66124 return acc ;
67125 } , { } ) ;
68126
69- const replaced = html
70- . replace ( / c l a s s = " / g, 'className="' )
71- . replace ( / \( / g, '(' )
72- . replace ( / \) / g, ')' )
73- . replace ( / \{ / g, '{' )
74- . replace ( / \} / g, '}' ) ;
75-
76127 const processed = `
77128 import React, { Fragment } from 'react';
78129 ${ parsed . attributes . imports ? parsed . attributes . imports : '' }
79130 ${ extraExports ( extra ) }
80- const Markdown = () => (<Fragment>${ replaced } </Fragment>);
131+ const Markdown = () => (<Fragment>${ html } </Fragment>);
81132 export default Markdown;
82133 ` ;
83134
0 commit comments