|
1 | | -module.exports = function(grunt) { |
| 1 | +module.exports = function( grunt ) { |
2 | 2 | "use strict"; |
3 | 3 |
|
4 | | -function htmlEscape(text) { |
| 4 | +function htmlEscape( text ) { |
5 | 5 | return text |
6 | 6 | // supports keeping markup in source file, but drop from inline sample |
7 | | - .replace(/<!-- @placeholder-start\((.+)\) -->[\s\S]+@placeholder-end -->/g, function(match, input) { |
| 7 | + .replace( /<!-- @placeholder-start\((.+)\) -->[\s\S]+@placeholder-end -->/g, function( match, input ) { |
8 | 8 | return "<-- " + input + " -->"; |
9 | 9 | }) |
10 | | - .replace(/&/g,'&') |
11 | | - .replace(/</g, '<') |
12 | | - .replace(/>/g, '>') |
13 | | - .replace(/"/g, '"') |
14 | | - .replace(/'/g, '''); |
| 10 | + .replace( /&/g, "&" ) |
| 11 | + .replace( /</g, "<" ) |
| 12 | + .replace( />/g, ">" ) |
| 13 | + .replace( /"/g, """ ) |
| 14 | + .replace( /'/g, "'" ); |
15 | 15 | } |
16 | 16 |
|
17 | | -var // modules |
18 | | - fs = require( "fs" ), |
19 | | - cheerio = require( "cheerio" ), |
| 17 | +var cheerio = require( "cheerio" ), |
20 | 18 | hljs = require( "highlight.js" ), |
21 | | - path = require( "path" ), |
22 | 19 | ent = require( "ent" ), |
23 | 20 | yaml = require( "js-yaml" ); |
24 | 21 |
|
@@ -48,8 +45,7 @@ grunt.registerHelper( "wordpress-parse-post-flex", function( path ) { |
48 | 45 | }); |
49 | 46 |
|
50 | 47 | grunt.registerMultiTask( "build-pages", "Process html and markdown files as pages, include @partials and syntax higlight code snippets", function() { |
51 | | - var content, |
52 | | - task = this, |
| 48 | + var task = this, |
53 | 49 | taskDone = task.async(), |
54 | 50 | files = this.data, |
55 | 51 | targetDir = grunt.config( "wordpress.dir" ) + "/posts/page/"; |
@@ -138,100 +134,104 @@ grunt.registerMultiTask( "build-resources", "Copy resources", function() { |
138 | 134 | }); |
139 | 135 | }); |
140 | 136 |
|
141 | | -var lineNumberTemplate = grunt.file.read( grunt.task.getFile("jquery-build/lineNumberTemplate.jst") ); |
142 | | -grunt.registerHelper( "syntax-highlight", function( options ) { |
| 137 | +grunt.registerHelper( "syntax-highlight", (function() { |
| 138 | + var lineNumberTemplate = grunt.file.read( |
| 139 | + grunt.task.getFile( "jquery-build/lineNumberTemplate.jst" ) ); |
143 | 140 |
|
144 | | - // receives the innerHTML of a <code> element and if the first character |
145 | | - // is an encoded left angle bracket, we'll assume the language is html |
146 | | - function crudeHtmlCheck ( input ) { |
147 | | - var first = input.trim().charAt( 0 ); |
148 | | - return ( first === "<" || first === "<" ) ? "xml" : ""; |
149 | | - } |
| 141 | + return function( options ) { |
150 | 142 |
|
151 | | - // when parsing the class attribute, make sure a class matches an actually |
152 | | - // highlightable language, instead of being presentational (e.g. 'example') |
153 | | - function getLanguageFromClass( str ) { |
154 | | - str = str || ""; |
155 | | - var classes = str.split(" "), |
156 | | - i = 0, |
157 | | - length = classes.length; |
158 | | - for ( ; i < length; i++ ) { |
159 | | - if ( hljs.LANGUAGES[ classes[i].replace( /^lang-/, "" ) ] ) { |
160 | | - return classes[i].replace( /^lang-/, "" ); |
161 | | - } |
| 143 | + // receives the innerHTML of a <code> element and if the first character |
| 144 | + // is an encoded left angle bracket, we'll assume the language is html |
| 145 | + function crudeHtmlCheck ( input ) { |
| 146 | + var first = input.trim().charAt( 0 ); |
| 147 | + return ( first === "<" || first === "<" ) ? "xml" : ""; |
162 | 148 | } |
163 | | - return ""; |
164 | | - } |
165 | | - |
166 | | - function outdent( string ) { |
167 | | - var rOutdent, |
168 | | - adjustedLines = [], |
169 | | - minTabs = Infinity, |
170 | | - rLeadingTabs = /^\t+/; |
171 | 149 |
|
172 | | - string.split( "\n" ).forEach(function( line, i, arr ) { |
173 | | - // Don't include first or last line if it's nothing but whitespace |
174 | | - if ( (i === 0 || i === arr.length - 1) && !line.trim().length ) { |
175 | | - return; |
176 | | - } |
177 | | - |
178 | | - // For empty lines inside the snippet, push a space so the line renders properly |
179 | | - if ( !line.trim().length ) { |
180 | | - adjustedLines.push(" "); |
181 | | - return; |
| 150 | + // when parsing the class attribute, make sure a class matches an actually |
| 151 | + // highlightable language, instead of being presentational (e.g. 'example') |
| 152 | + function getLanguageFromClass( str ) { |
| 153 | + str = str || ""; |
| 154 | + var classes = str.split( " " ), |
| 155 | + i = 0, |
| 156 | + length = classes.length; |
| 157 | + for ( ; i < length; i++ ) { |
| 158 | + if ( hljs.LANGUAGES[ classes[ i ].replace( /^lang-/, "" ) ] ) { |
| 159 | + return classes[i].replace( /^lang-/, "" ); |
| 160 | + } |
182 | 161 | } |
| 162 | + return ""; |
| 163 | + } |
183 | 164 |
|
184 | | - // Count how many leading tabs there are and update the global minimum |
185 | | - var match = line.match( rLeadingTabs ), |
186 | | - tabs = match ? match[0].length : 0; |
187 | | - minTabs = Math.min( minTabs, tabs ); |
| 165 | + function outdent( string ) { |
| 166 | + var rOutdent, |
| 167 | + adjustedLines = [], |
| 168 | + minTabs = Infinity, |
| 169 | + rLeadingTabs = /^\t+/; |
| 170 | + |
| 171 | + string.split( "\n" ).forEach(function( line, i, arr ) { |
| 172 | + // Don't include first or last line if it's nothing but whitespace |
| 173 | + if ( (i === 0 || i === arr.length - 1) && !line.trim().length ) { |
| 174 | + return; |
| 175 | + } |
| 176 | + |
| 177 | + // For empty lines inside the snippet, push a space so the line renders properly |
| 178 | + if ( !line.trim().length ) { |
| 179 | + adjustedLines.push(" "); |
| 180 | + return; |
| 181 | + } |
| 182 | + |
| 183 | + // Count how many leading tabs there are and update the global minimum |
| 184 | + var match = line.match( rLeadingTabs ), |
| 185 | + tabs = match ? match[0].length : 0; |
| 186 | + minTabs = Math.min( minTabs, tabs ); |
| 187 | + |
| 188 | + adjustedLines.push( line ); |
| 189 | + }); |
188 | 190 |
|
189 | | - adjustedLines.push( line ); |
190 | | - }); |
| 191 | + if ( minTabs !== Infinity ) { |
| 192 | + // Outdent the lines as much as possible |
| 193 | + rOutdent = new RegExp( "^\t{" + minTabs + "}" ); |
| 194 | + adjustedLines = adjustedLines.map(function( line ) { |
| 195 | + return line.replace( rOutdent, "" ); |
| 196 | + }); |
| 197 | + } |
191 | 198 |
|
192 | | - if ( minTabs !== Infinity ) { |
193 | | - // Outdent the lines as much as possible |
194 | | - rOutdent = new RegExp( "^\t{" + minTabs + "}" ); |
195 | | - adjustedLines = adjustedLines.map(function( line ) { |
196 | | - return line.replace( rOutdent, "" ); |
197 | | - }); |
| 199 | + return adjustedLines.join( "\n" ); |
198 | 200 | } |
199 | 201 |
|
200 | | - return adjustedLines.join( "\n" ); |
201 | | - } |
202 | | - |
203 | | - var html = options.file ? grunt.file.read( options.file ) : options.content, |
204 | | - $ = cheerio.load( html ); |
205 | | - |
206 | | - $( "pre > code" ).each( function( index, el ) { |
207 | | - var $t = $( this ), |
208 | | - code = ent.decode( outdent( $t.html() ) ), |
209 | | - lang = $t.attr( "data-lang" ) || |
210 | | - getLanguageFromClass( $t.attr( "class" ) ) || |
211 | | - crudeHtmlCheck( code ) || |
212 | | - "javascript", |
213 | | - linenumAttr = $t.attr( "data-linenum" ), |
214 | | - linenum = (linenumAttr === "true" ? 1 : parseInt( linenumAttr, 10 ) ) || 1, |
215 | | - gutter = linenumAttr === undefined ? false : true, |
216 | | - highlighted = hljs.highlight( lang, code ), |
217 | | - fixed = hljs.fixMarkup( highlighted.value, " " ); |
218 | | - |
219 | | - // Handle multi-line comments (#32) |
220 | | - fixed = fixed.replace( /<span class="comment">\/\*([^<]+)\*\/<\/span>/g, function( full, comment ) { |
221 | | - return "<span class=\"comment\">/*" + |
222 | | - comment.split( "\n" ).join( "</span>\n<span class=\"comment\">" ) + |
223 | | - "*/</span>"; |
| 202 | + var html = options.file ? grunt.file.read( options.file ) : options.content, |
| 203 | + $ = cheerio.load( html ); |
| 204 | + |
| 205 | + $( "pre > code" ).each(function() { |
| 206 | + var $t = $( this ), |
| 207 | + code = ent.decode( outdent( $t.html() ) ), |
| 208 | + lang = $t.attr( "data-lang" ) || |
| 209 | + getLanguageFromClass( $t.attr( "class" ) ) || |
| 210 | + crudeHtmlCheck( code ) || |
| 211 | + "javascript", |
| 212 | + linenumAttr = $t.attr( "data-linenum" ), |
| 213 | + linenum = (linenumAttr === "true" ? 1 : parseInt( linenumAttr, 10 ) ) || 1, |
| 214 | + gutter = linenumAttr === undefined ? false : true, |
| 215 | + highlighted = hljs.highlight( lang, code ), |
| 216 | + fixed = hljs.fixMarkup( highlighted.value, " " ); |
| 217 | + |
| 218 | + // Handle multi-line comments (#32) |
| 219 | + fixed = fixed.replace( /<span class="comment">\/\*([^<]+)\*\/<\/span>/g, function( full, comment ) { |
| 220 | + return "<span class=\"comment\">/*" + |
| 221 | + comment.split( "\n" ).join( "</span>\n<span class=\"comment\">" ) + |
| 222 | + "*/</span>"; |
| 223 | + }); |
| 224 | + $t.parent().replaceWith( grunt.template.process( lineNumberTemplate, { |
| 225 | + lines: fixed.split("\n"), |
| 226 | + startAt: linenum, |
| 227 | + gutter: gutter, |
| 228 | + lang: lang |
| 229 | + })); |
224 | 230 | }); |
225 | | - $t.parent().replaceWith( grunt.template.process( lineNumberTemplate, { |
226 | | - lines: fixed.split("\n"), |
227 | | - startAt: linenum, |
228 | | - gutter: gutter, |
229 | | - lang: lang |
230 | | - })); |
231 | | - }); |
232 | 231 |
|
233 | | - return $.html(); |
234 | | -}); |
| 232 | + return $.html(); |
| 233 | + }; |
| 234 | +})() ); |
235 | 235 |
|
236 | 236 | grunt.registerHelper( "parse-markdown", function( src, generateToc ) { |
237 | 237 | var toc = "", |
|
0 commit comments