@@ -306,28 +306,38 @@ window['_pr_isIE6'] = function () {
306306 return ! whitespace || whitespace === 'pre' ;
307307 }
308308
309- function normalizedHtml ( node , out ) {
309+ function normalizedHtml ( node , out , opt_sortAttrs ) {
310310 switch ( node . nodeType ) {
311311 case 1 : // an element
312312 var name = node . tagName . toLowerCase ( ) ;
313+
313314 out . push ( '<' , name ) ;
314- for ( var i = 0 ; i < node . attributes . length ; ++ i ) {
315- var attr = node . attributes [ i ] ;
316- if ( ! attr . specified ) { continue ; }
317- out . push ( ' ' ) ;
318- normalizedHtml ( attr , out ) ;
315+ var attrs = node . attributes ;
316+ var n = attrs . length ;
317+ if ( n ) {
318+ if ( opt_sortAttrs ) {
319+ var sortedAttrs = [ ] ;
320+ for ( var i = n ; -- i >= 0 ; ) { sortedAttrs [ i ] = attrs [ i ] ; }
321+ sortedAttrs . sort ( function ( a , b ) {
322+ return ( a . name < b . name ) ? - 1 : a . name === b . name ? 0 : 1 ;
323+ } ) ;
324+ attrs = sortedAttrs ;
325+ }
326+ for ( var i = 0 ; i < n ; ++ i ) {
327+ var attr = attrs [ i ] ;
328+ if ( ! attr . specified ) { continue ; }
329+ out . push ( ' ' , attr . name . toLowerCase ( ) ,
330+ '="' , attribToHtml ( attr . value ) , '"' ) ;
331+ }
319332 }
320333 out . push ( '>' ) ;
321334 for ( var child = node . firstChild ; child ; child = child . nextSibling ) {
322- normalizedHtml ( child , out ) ;
335+ normalizedHtml ( child , out , opt_sortAttrs ) ;
323336 }
324337 if ( node . firstChild || ! / ^ (?: b r | l i n k | i m g ) $ / . test ( name ) ) {
325338 out . push ( '<\/' , name , '>' ) ;
326339 }
327340 break ;
328- case 2 : // an attribute
329- out . push ( node . name . toLowerCase ( ) , '="' , attribToHtml ( node . value ) , '"' ) ;
330- break ;
331341 case 3 : case 4 : // text
332342 out . push ( textToHtml ( node . nodeValue ) ) ;
333343 break ;
@@ -1087,11 +1097,37 @@ window['_pr_isIE6'] = function () {
10871097 // Doing this on other browsers breaks lots of stuff since \r\n is
10881098 // treated as two newlines on Firefox.
10891099 ? ( isIE678 === 6 ? ' \r\n' : ' \r' )
1090- // IE collapses multiple adjacient <br>s into 1 line break.
1100+ // IE collapses multiple adjacent <br>s into 1 line break.
10911101 // Prefix every newline with ' ' to prevent such behavior.
10921102 : ' <br />' )
10931103 : '<br />' ) ;
10941104
1105+ // Look for a class like linenums or linenums:<n> where <n> is the 1-indexed
1106+ // number of the first line.
1107+ var numberLines = job . sourceNode . className . match ( / \b l i n e n u m s \b (?: : ( \d + ) ) ? / ) ;
1108+ var lineBreaker ;
1109+ if ( numberLines ) {
1110+ var lineBreaks = [ ] ;
1111+ for ( var i = 0 ; i < 10 ; ++ i ) {
1112+ lineBreaks [ i ] = lineBreakHtml + '</li><li class="L' + i + '">' ;
1113+ }
1114+ var lineNum = numberLines [ 1 ] - 1 || 0 ; // Lines are 1-indexed
1115+ html . push ( '<ol class="linenums"><li class="L' , ( lineNum ) % 10 , '"' ) ;
1116+ if ( lineNum ) {
1117+ html . push ( ' value="' , lineNum + 1 , '"' ) ;
1118+ }
1119+ html . push ( '>' ) ;
1120+ lineBreaker = function ( ) {
1121+ var lb = lineBreaks [ ++ lineNum % 10 ] ;
1122+ // If a decoration is open, we need to close it before closing a list-item
1123+ // and reopen it on the other side of the list item.
1124+ return openDecoration
1125+ ? ( '</span>' + lb + '<span class="' + openDecoration + '">' ) : lb ;
1126+ } ;
1127+ } else {
1128+ lineBreaker = lineBreakHtml ;
1129+ }
1130+
10951131 // A helper function that is responsible for opening sections of decoration
10961132 // and outputing properly escaped chunks of source
10971133 function emitTextUpTo ( sourceIdx ) {
@@ -1120,7 +1156,7 @@ window['_pr_isIE6'] = function () {
11201156 // Keep track of whether we need to escape space at the beginning of the
11211157 // next chunk.
11221158 lastWasSpace = trailingSpaceRe . test ( htmlChunk ) ;
1123- html . push ( htmlChunk . replace ( newlineRe , lineBreakHtml ) ) ;
1159+ html . push ( htmlChunk . replace ( newlineRe , lineBreaker ) ) ;
11241160 outputIdx = sourceIdx ;
11251161 }
11261162 }
@@ -1163,6 +1199,7 @@ window['_pr_isIE6'] = function () {
11631199 if ( openDecoration ) {
11641200 html . push ( '</span>' ) ;
11651201 }
1202+ if ( numberLines ) { html . push ( '</li></ol>' ) ; }
11661203 job . prettyPrintedHtml = html . join ( '' ) ;
11671204 }
11681205
0 commit comments