@@ -63,7 +63,7 @@ var PR_TAB_WIDTH = 8;
6363var PR_normalizedHtml ;
6464
6565/** Contains functions for creating and registering new language handlers.
66- * @namespace
66+ * @type { Object }
6767 */
6868var PR ;
6969
@@ -80,11 +80,11 @@ var prettyPrintOne;
8080 */
8181var prettyPrint ;
8282
83- /** browser detection. */
84- function pr_isIE6 ( ) {
83+ /** browser detection. @extern */
84+ function _pr_isIE6 ( ) {
8585 var isIE6 = navigator && navigator . userAgent &&
8686 / \b M S I E 6 \. / . test ( navigator . userAgent ) ;
87- pr_isIE6 = function ( ) { return isIE6 ; } ;
87+ _pr_isIE6 = function ( ) { return isIE6 ; } ;
8888 return isIE6 ;
8989}
9090
@@ -170,6 +170,12 @@ function pr_isIE6() {
170170 /** token style for an sgml attribute value. */
171171 var PR_ATTRIB_VALUE = 'atv' ;
172172
173+ /**
174+ * A class that indicates a section of markup that is not code, e.g. to allow
175+ * embedding of line numbers within code listings.
176+ */
177+ var PR_NOCODE = 'nocode' ;
178+
173179 function isWordChar ( ch ) {
174180 return ( ch >= 'a' && ch <= 'z' ) || ( ch >= 'A' && ch <= 'Z' ) ;
175181 }
@@ -366,7 +372,7 @@ function pr_isIE6() {
366372 /** returns a function that expand tabs to spaces. This function can be fed
367373 * successive chunks of text, and will maintain its own internal state to
368374 * keep track of how tabs are expanded.
369- * @return {function (plainText : string) : string } a function that takes
375+ * @return {function (string) : string } a function that takes
370376 * plain text and return the text with tabs expanded.
371377 * @private
372378 */
@@ -422,6 +428,7 @@ function pr_isIE6() {
422428 var pr_commentPrefix = / ^ < ! - - / ;
423429 var pr_cdataPrefix = / ^ < \[ C D A T A \[ / ;
424430 var pr_brPrefix = / ^ < b r \b / i;
431+ var pr_tagNameRe = / ^ < ( \/ ? ) ( [ a - z A - Z ] + ) / ;
425432
426433 /** split markup into chunks of html tags (style null) and
427434 * plain text (style {@link #PR_PLAIN}), converting tags which are
@@ -454,7 +461,33 @@ function pr_isIE6() {
454461 sourceBuf . push ( '\n' ) ;
455462 ++ sourceBufLen ;
456463 } else {
457- extractedTags . push ( sourceBufLen , match ) ;
464+ if ( match . indexOf ( PR_NOCODE ) >= 0 && isNoCodeTag ( match ) ) {
465+ // A <span class="nocode"> will start a section that should be
466+ // ignored. Continue walking the list until we see a matching end
467+ // tag.
468+ var name = match . match ( pr_tagNameRe ) [ 2 ] ;
469+ var depth = 1 ;
470+ end_tag_loop:
471+ for ( var j = i + 1 ; j < n ; ++ j ) {
472+ var name2 = matches [ j ] . match ( pr_tagNameRe ) ;
473+ if ( name2 && name2 [ 2 ] === name ) {
474+ if ( name2 [ 1 ] === '/' ) {
475+ if ( -- depth === 0 ) { break end_tag_loop; }
476+ } else {
477+ ++ depth ;
478+ }
479+ }
480+ }
481+ if ( j < n ) {
482+ extractedTags . push (
483+ sourceBufLen , matches . slice ( i , j + 1 ) . join ( '' ) ) ;
484+ i = j ;
485+ } else { // Ignore unclosed sections.
486+ extractedTags . push ( sourceBufLen , match ) ;
487+ }
488+ } else {
489+ extractedTags . push ( sourceBufLen , match ) ;
490+ }
458491 }
459492 } else {
460493 var literalText = htmlToText ( match ) ;
@@ -466,6 +499,16 @@ function pr_isIE6() {
466499 return { source : sourceBuf . join ( '' ) , tags : extractedTags } ;
467500 }
468501
502+ /** True if the given tag contains a class attribute with the nocode class. */
503+ function isNoCodeTag ( tag ) {
504+ return ! ! tag
505+ // First canonicalize the representation of attributes
506+ . replace ( / \s ( \w + ) \s * = \s * (?: \" ( [ ^ \" ] * ) \" | ' ( [ ^ \' ] * ) ' | ( \S + ) ) / g,
507+ ' $1="$2$3$4"' )
508+ // Then look for the attribute we want.
509+ . match ( / [ c C ] [ l L ] [ a A ] [ s S ] [ s S ] = \" [ ^ \" ] * \b n o c o d e \b / ) ;
510+ }
511+
469512 /** Given triples of [style, pattern, context] returns a lexing function,
470513 * The lexing function interprets the patterns to find token boundaries and
471514 * returns a decoration list of the form
@@ -494,7 +537,7 @@ function pr_isIE6() {
494537 * @param {Array } fallthroughStylePatterns patterns that will be tried in
495538 * order if the shortcut ones fail. May have shortcuts.
496539 *
497- * @return {function (sourceCode : string) -> Array.<number|string> } a
540+ * @return {function (string, number?) : Array.<number|string> } a
498541 * function that takes source code and returns a list of decorations.
499542 */
500543 function createSimpleLexer ( shortcutStylePatterns ,
@@ -648,7 +691,7 @@ function pr_isIE6() {
648691 * It recognizes C, C++, and shell style comments.
649692 *
650693 * @param {Object } options a set of optional parameters.
651- * @return {function (sourceCode : string) : Array.<string|number> } a
694+ * @return {function (string) : Array.<string|number> } a
652695 * decorator that takes sourceCode as plain text and that returns a
653696 * decoration list
654697 */
@@ -921,6 +964,12 @@ function pr_isIE6() {
921964 var decPos = 0 ; // index into decorations
922965 var tabExpander = makeTabExpander ( PR_TAB_WIDTH ) ;
923966
967+ var adjacentSpaceRe = / ( [ \r \n ] ) / g;
968+ var startOrSpaceRe = / ( ^ | ) / gm;
969+ var newlineRe = / \r \n ? | \n / g;
970+ var trailingSpaceRe = / [ \r \n ] $ / ;
971+ var lastWasSpace = true ; // the last text chunk emitted ended with a space.
972+
924973 // A helper function that is responsible for opening sections of decoration
925974 // and outputing properly escaped chunks of source
926975 function emitTextUpTo ( sourceIdx ) {
@@ -936,17 +985,20 @@ function pr_isIE6() {
936985 }
937986 // This interacts badly with some wikis which introduces paragraph tags
938987 // into pre blocks for some strange reason.
939- // It's necessary for IE though which seems to lose the preformattednes
940-
988+ // It's necessary for IE though which seems to lose the preformattedness
941989 // of <pre> tags when their innerHTML is assigned.
942990 // http://stud3.tuwien.ac.at/~e0226430/innerHtmlQuirk.html
943991 // and it serves to undo the conversion of <br>s to newlines done in
944992 // chunkify.
945993 var htmlChunk = textToHtml (
946994 tabExpander ( sourceText . substring ( outputIdx , sourceIdx ) ) )
947- . replace ( / ( \r \n ? | \n | ) / g, '$1 ' )
948- . replace ( / \r \n ? | \n / g, '<br />' ) ;
949- html . push ( htmlChunk ) ;
995+ . replace ( lastWasSpace
996+ ? startOrSpaceRe
997+ : adjacentSpaceRe , '$1 ' ) ;
998+ // Keep track of whether we need to escape space at the beginning of the
999+ // next chunk.
1000+ lastWasSpace = trailingSpaceRe . test ( htmlChunk ) ;
1001+ html . push ( htmlChunk . replace ( newlineRe , '<br />' ) ) ;
9501002 outputIdx = sourceIdx ;
9511003 }
9521004 }
@@ -996,7 +1048,7 @@ function pr_isIE6() {
9961048 /** Maps language-specific file extensions to handlers. */
9971049 var langHandlerRegistry = { } ;
9981050 /** Register a language handler for the given file extensions.
999- * @param {function (sourceCode : string) : Array.<number|string> } handler
1051+ * @param {function (string) : Array.<number|string> } handler
10001052 * a function from source code to a list of decorations.
10011053 * @param {Array.<string> } fileExtensions
10021054 */
@@ -1092,7 +1144,7 @@ function pr_isIE6() {
10921144 }
10931145
10941146 function prettyPrint ( opt_whenDone ) {
1095- var isIE6 = pr_isIE6 ( ) ;
1147+ var isIE6 = _pr_isIE6 ( ) ;
10961148
10971149 // fetch a list of nodes to rewrite
10981150 var codeSegments = [
@@ -1212,6 +1264,7 @@ function pr_isIE6() {
12121264 'PR_DECLARATION' : PR_DECLARATION ,
12131265 'PR_KEYWORD' : PR_KEYWORD ,
12141266 'PR_LITERAL' : PR_LITERAL ,
1267+ 'PR_NOCODE' : PR_NOCODE ,
12151268 'PR_PLAIN' : PR_PLAIN ,
12161269 'PR_PUNCTUATION' : PR_PUNCTUATION ,
12171270 'PR_SOURCE' : PR_SOURCE ,
0 commit comments