55const hljs = require ( 'highlight.js' ) ;
66const nunjucks = require ( 'nunjucks' ) ;
77
8+ function highlight ( code , lang ) {
9+ if ( hljs . getLanguage ( lang ) ) {
10+ return hljs . highlight ( lang , code ) . value ;
11+ } else {
12+ return hljs . highlightAuto ( code ) . value ;
13+ }
14+ } //highlight()
15+
16+ function stripIndent ( str ) {
17+ const match = str . match ( / ^ [ \t ] * (? = \S ) / gm) ;
18+
19+ if ( ! match ) {
20+ return str ;
21+ }
22+
23+ const indent = Math . min . apply ( Math , match . map ( x => x . length ) ) ;
24+ const re = new RegExp ( `^[ \\t]{${ indent } }` , 'gm' ) ;
25+
26+ return indent > 0 ? str . replace ( re , '' ) : str ;
27+ } //stripIndent()
28+
829function CodeTag ( ) {
930 this . tags = [ 'code' ] ;
1031
@@ -20,70 +41,17 @@ function CodeTag () {
2041 // parse the body and possibly the error block, which is optional
2142 var body = parser . parseUntilBlocks ( 'endcode' ) ;
2243
23- // I found Nunjucks to be incredibly convoluted on how to just get some data into the BlockTag function,
24- // this finally worked by faking another template node.
25- var tabStart = new nodes . NodeList ( 0 , 0 , [
26- new nodes . Output ( 0 , 0 , [
27- new nodes . TemplateData ( 0 , 0 , ( tok . colno - 1 ) )
28- ] )
29- ] ) ;
30-
3144 parser . advanceAfterBlockEnd ( ) ;
3245
3346 // See above for notes about CallExtension
34- return new nodes . CallExtension ( this , 'render' , args , [ body , tabStart ] ) ;
47+ return new nodes . CallExtension ( this , 'render' , args , [ body ] ) ;
3548 } ; //parse()
3649
37- // code rendering for the block. Pretty simple, just get the body text and pass
38- // it through the code renderer.
39- this . render = function ( context , blockBody , blockTabStart ) {
40- let body = blockBody ( ) ;
41- let spacesRegex = / ^ [ \s ] + / ;
42- let tabStart = blockTabStart ( ) ; // The column postion of the {% code %} tag.
43-
44- // TODO: Update to automatically normalize indentation to least indentation needed.
45- // - This still adds unnecessary indentation to beginning of output.
46- if ( tabStart > 0 ) { // If the {% code %} tag is tabbed in, normalize the content to the same depth.
47- body = body . split ( / \r ? \n / ) ; // Split into lines.
48- body = body . map ( line => {
49- let startSpaces = line . match ( spacesRegex ) ;
50- // If the content is not at the same or greater tab depth, do nothing..
51- if ( startSpaces && startSpaces [ 0 ] . length >= tabStart ) {
52- return line . slice ( tabStart ) ; // Subtract the column position from the start of the string.
53- } else {
54- return line ;
55- }
56- } ) ;
57-
58- // Remove blank start line
59- if ( body [ 0 ] === '' ) {
60- body = body . slice ( 1 ) ;
61- }
62- // Remove blank end line
63- if ( body [ body . length - 1 ] === '' ) {
64- body = body . slice ( 0 , body . length - 1 ) ;
65- }
66-
67- body = body . join ( '\n' ) ; // Rejoin into one string.
68- }
69-
70- // remove line break from start and end of string
71- // <http://stackoverflow.com/a/14572494>
72- body = body . replace ( / ^ \s + | \s + $ / , '' ) ;
73-
74- // get the first line of the body to see if we have a file type specified
75- var value = hljs . highlightAuto ( body ) . value ;
76- if ( body . split ( '\n' ) . length > 1 ) {
77- var lang = hljs . getLanguage ( body . split ( "\n" ) [ 0 ] ) ;
78- if ( lang ) {
79- lang = body . split ( '\n' ) [ 0 ] ;
80- body = body . split ( '\n' ) . slice ( 1 ) . join ( '\n' ) ;
81- value = hljs . highlight ( lang , body ) . value ;
82- }
83- }
84-
85- let template = `<pre class="highlight"><code class="hljs">${ value } </code></pre>` ;
86-
50+ // Code rendering for the block.
51+ this . render = function ( context , lang , blockBody ) {
52+ let body = stripIndent ( blockBody ( ) ) ;
53+ let highlightedBody = highlight ( body , lang ) ;
54+ let template = `<pre><code class="${ lang } ">${ highlightedBody } </code></pre>` ;
8755 return new nunjucks . runtime . SafeString ( template ) ;
8856 } ; //render();
8957} //CodeTag
0 commit comments