2020-01-29 14:51:28 +01:00
/*! highlight.js v9.18.0 | BSD3 License | git.io/hljslicense */
! function ( e ) { var n = "object" == typeof window && window || "object" == typeof self && self ; "undefined" == typeof exports || exports . nodeType ? n && ( n . hljs = e ( { } ) , "function" == typeof define && define . amd && define ( [ ] , function ( ) { return n . hljs } ) ) : e ( exports ) } ( function ( a ) { var f = [ ] , o = Object . keys , _ = { } , g = { } , C = ! 0 , n = /^(no-?highlight|plain|text)$/i , E = /\blang(?:uage)?-([\w-]+)\b/i , t = /((^(<[^>]+>|\t|)+|(?:\n)))/gm , r = { case _insensitive : "cI" , lexemes : "l" , contains : "c" , keywords : "k" , subLanguage : "sL" , className : "cN" , begin : "b" , beginKeywords : "bK" , end : "e" , endsWithParent : "eW" , illegal : "i" , excludeBegin : "eB" , excludeEnd : "eE" , returnBegin : "rB" , returnEnd : "rE" , variants : "v" , IDENT _RE : "IR" , UNDERSCORE _IDENT _RE : "UIR" , NUMBER _RE : "NR" , C _NUMBER _RE : "CNR" , BINARY _NUMBER _RE : "BNR" , RE _STARTERS _RE : "RSR" , BACKSLASH _ESCAPE : "BE" , APOS _STRING _MODE : "ASM" , QUOTE _STRING _MODE : "QSM" , PHRASAL _WORDS _MODE : "PWM" , C _LINE _COMMENT _MODE : "CLCM" , C _BLOCK _COMMENT _MODE : "CBCM" , HASH _COMMENT _MODE : "HCM" , NUMBER _MODE : "NM" , C _NUMBER _MODE : "CNM" , BINARY _NUMBER _MODE : "BNM" , CSS _NUMBER _MODE : "CSSNM" , REGEXP _MODE : "RM" , TITLE _MODE : "TM" , UNDERSCORE _TITLE _MODE : "UTM" , COMMENT : "C" , beginRe : "bR" , endRe : "eR" , illegalRe : "iR" , lexemesRe : "lR" , terminators : "t" , terminator _end : "tE" } , m = "</span>" , O = "Could not find the language '{}', did you forget to load/include a language module?" , B = { classPrefix : "hljs-" , tabReplace : null , useBR : ! 1 , languages : void 0 } , c = "of and for in not or if then" . split ( " " ) ; function x ( e ) { return e . replace ( /&/g , "&" ) . replace ( /</g , "<" ) . replace ( />/g , ">" ) } function d ( e ) { return e . nodeName . toLowerCase ( ) } function R ( e ) { return n . test ( e ) } function i ( e ) { var n , t = { } , r = Array . prototype . slice . call ( arguments , 1 ) ; for ( n in e ) t [ n ] = e [ n ] ; return r . forEach ( function ( e ) { for ( n in e ) t [ n ] = e [ n ] } ) , t } function p ( e ) { var a = [ ] ; return function e ( n , t ) { for ( var r = n . firstChild ; r ; r = r . nextSibling ) 3 === r . nodeType ? t += r . nodeValue . length : 1 === r . nodeType && ( a . push ( { event : "start" , offset : t , node : r } ) , t = e ( r , t ) , d ( r ) . match ( /br|hr|img|input/ ) || a . push ( { event : "stop" , offset : t , node : r } ) ) ; return t } ( e , 0 ) , a } function v ( e , n , t ) { var r = 0 , a = "" , i = [ ] ; function o ( ) { return e . length && n . length ? e [ 0 ] . offset !== n [ 0 ] . offset ? e [ 0 ] . offset < n [ 0 ] . offset ? e : n : "start" === n [ 0 ] . event ? e : n : e . length ? e : n } function c ( e ) { a += "<" + d ( e ) + f . map . call ( e . attributes , function ( e ) { return " " + e . nodeName + '="' + x ( e . value ) . replace ( /"/g , """ ) + '"' } ) . join ( "" ) + ">" } function l ( e ) { a += "</" + d ( e ) + ">" } function u ( e ) { ( "start" === e . event ? c : l ) ( e . node ) } for ( ; e . length || n . length ; ) { var s = o ( ) ; if ( a += x ( t . substring ( r , s [ 0 ] . offset ) ) , r = s [ 0 ] . offset , s === e ) { for ( i . reverse ( ) . forEach ( l ) ; u ( s . splice ( 0 , 1 ) [ 0 ] ) , ( s = o ( ) ) === e && s . length && s [ 0 ] . offset === r ; ) ; i . reverse ( ) . forEach ( c ) } else "start" === s [ 0 ] . event ? i . push ( s [ 0 ] . node ) : i . pop ( ) , u ( s . splice ( 0 , 1 ) [ 0 ] ) } return a + x ( t . substr ( r ) ) } function l ( n ) { return n . v && ! n . cached _variants && ( n . cached _variants = n . v . map ( function ( e ) { return i ( n , { v : null } , e ) } ) ) , n . cached _variants ? n . cached _variants : function e ( n ) { return ! ! n && ( n . eW || e ( n . starts ) ) } ( n ) ? [ i ( n , { starts : n . starts ? i ( n . starts ) : null } ) ] : Object . isFrozen ( n ) ? [ i ( n ) ] : [ n ] } function u ( e ) { if ( r && ! e . langApiRestored ) { for ( var n in e . langApiRestored = ! 0 , r ) e [ n ] && ( e [ r [ n ] ] = e [ n ] ) ; ( e . c || [ ] ) . concat ( e . v || [ ] ) . forEach ( u ) } } function M ( n , t ) { var i = { } ; return "string" == typeof n ? r ( "keyword" , n ) : o ( n ) . forEach ( function ( e ) { r ( e , n [ e ] ) } ) , i ; function r ( a , e ) { t && ( e = e . toLowerCase ( ) ) , e . split ( " " ) . forEach ( function ( e ) { var n , t , r = e . split ( "|" ) ; i [ r [ 0 ] ] = [ a , ( n = r [ 0 ] , ( t = r [ 1 ] ) ? Number ( t ) : function ( e ) { return - 1 != c . indexOf ( e . toLowerCase ( ) ) } ( n ) ? 0 : 1 ) ] } ) } } function S ( r ) { function s ( e ) { return e && e . source || e } function f ( e , n ) { return new RegExp ( s ( e ) , "m" + ( r . cI ? "i" : "" ) + ( n ? "g" : "" ) ) } function a ( a ) { var i , e , o = { } , c = [ ] , l = { } , t = 1 ; function n ( e , n ) { o [ t ] = e , c . push ( [ e , n ] ) , t += new RegExp ( n . toString ( ) + "|" ) . exec ( "" ) . length - 1 + 1 } for ( var r = 0 ; r < a . c . length ; r ++ ) { n ( e = a . c [ r ] , e . bK ? "\\.?(?:" + e . b + ")\\.?" : e . b ) } a . tE && n ( "end" , a . tE ) , a . i && n ( "illegal" , a . i ) ; var u = c . map ( function ( e ) { return e [ 1 ] } ) ; return i = f ( function ( e , n ) { for ( var t = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./ , r = 0 , a = "" , i = 0 ; i < e . length ; i ++ ) { var o = r += 1 , c = s ( e [ i ] ) ; for ( 0 < i && ( a += n ) , a += "(" ; 0 < c . length ; ) { var l = t . exec ( c ) ; if ( null == l ) { a += c ; break } a += c . substring ( 0 , l . index ) , c = c . substring ( l . index + l [ 0 ] . length ) , "\\" == l [ 0 ] [ 0 ] && l [ 1 ] ? a += "\\" + String ( Number ( l [ 1 ] ) + o ) : ( a += l [ 0 ] , "(" == l [ 0 ] && r ++ ) } a +=
2019-03-04 14:32:38 +01:00
2019-03-08 15:07:59 +01:00
/* highlightjs-line-numbers.js 2.6.0 | (C) 2018 Yauheni Pakala | MIT License | github.com/wcoder/highlightjs-line-numbers.js */
2019-04-05 19:49:17 +02:00
/* Edited by Hakim for reveal.js; removed async timeout */
! function ( n , e ) { "use strict" ; function t ( ) { var n = e . createElement ( "style" ) ; n . type = "text/css" , n . innerHTML = g ( ".{0}{border-collapse:collapse}.{0} td{padding:0}.{1}:before{content:attr({2})}" , [ v , L , b ] ) , e . getElementsByTagName ( "head" ) [ 0 ] . appendChild ( n ) } function r ( t ) { "interactive" === e . readyState || "complete" === e . readyState ? i ( t ) : n . addEventListener ( "DOMContentLoaded" , function ( ) { i ( t ) } ) } function i ( t ) { try { var r = e . querySelectorAll ( "code.hljs,code.nohighlight" ) ; for ( var i in r ) r . hasOwnProperty ( i ) && l ( r [ i ] , t ) } catch ( o ) { n . console . error ( "LineNumbers error: " , o ) } } function l ( n , e ) { "object" == typeof n && f ( function ( ) { n . innerHTML = s ( n , e ) } ) } function o ( n , e ) { if ( "string" == typeof n ) { var t = document . createElement ( "code" ) ; return t . innerHTML = n , s ( t , e ) } } function s ( n , e ) { e = e || { singleLine : ! 1 } ; var t = e . singleLine ? 0 : 1 ; return c ( n ) , a ( n . innerHTML , t ) } function a ( n , e ) { var t = u ( n ) ; if ( "" === t [ t . length - 1 ] . trim ( ) && t . pop ( ) , t . length > e ) { for ( var r = "" , i = 0 , l = t . length ; i < l ; i ++ ) r += g ( '<tr><td class="{0}"><div class="{1} {2}" {3}="{5}"></div></td><td class="{4}"><div class="{1}">{6}</div></td></tr>' , [ j , m , L , b , p , i + 1 , t [ i ] . length > 0 ? t [ i ] : " " ] ) ; return g ( '<table class="{0}">{1}</table>' , [ v , r ] ) } return n } function c ( n ) { var e = n . childNodes ; for ( var t in e ) if ( e . hasOwnProperty ( t ) ) { var r = e [ t ] ; h ( r . textContent ) > 0 && ( r . childNodes . length > 0 ? c ( r ) : d ( r . parentNode ) ) } } function d ( n ) { var e = n . className ; if ( /hljs-/ . test ( e ) ) { for ( var t = u ( n . innerHTML ) , r = 0 , i = "" ; r < t . length ; r ++ ) { var l = t [ r ] . length > 0 ? t [ r ] : " " ; i += g ( '<span class="{0}">{1}</span>\n' , [ e , l ] ) } n . innerHTML = i . trim ( ) } } function u ( n ) { return 0 === n . length ? [ ] : n . split ( y ) } function h ( n ) { return ( n . trim ( ) . match ( y ) || [ ] ) . length } function f ( e ) { e ( ) } function g ( n , e ) { return n . replace ( /\{(\d+)\}/g , function ( n , t ) { return e [ t ] ? e [ t ] : n } ) } var v = "hljs-ln" , m = "hljs-ln-line" , p = "hljs-ln-code" , j = "hljs-ln-numbers" , L = "hljs-ln-n" , b = "data-line-number" , y = /\r\n|\r|\n/g ; n . hljs ? ( n . hljs . initLineNumbersOnLoad = r , n . hljs . lineNumbersBlock = l , n . hljs . lineNumbersValue = o , t ( ) ) : n . console . error ( "highlight.js not detected!" ) } ( window , document ) ;
2019-03-08 15:07:59 +01:00
2019-03-12 13:17:50 +01:00
/ * *
* This reveal . js plugin is wrapper around the highlight . js
* syntax highlighting library .
* /
( function ( root , factory ) {
if ( typeof define === 'function' && define . amd ) {
root . RevealHighlight = factory ( ) ;
} else if ( typeof exports === 'object' ) {
module . exports = factory ( ) ;
} else {
// Browser globals (root is window)
root . RevealHighlight = factory ( ) ;
}
} ( this , function ( ) {
2016-11-22 23:42:21 +01:00
// Function to perform a better "data-trim" on code snippets
// Will slice an indentation amount on each line of the snippet (amount based on the line having the lowest indentation length)
function betterTrim ( snippetEl ) {
// Helper functions
function trimLeft ( val ) {
// Adapted from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill
return val . replace ( /^[\s\uFEFF\xA0]+/g , '' ) ;
}
function trimLineBreaks ( input ) {
var lines = input . split ( '\n' ) ;
// Trim line-breaks from the beginning
for ( var i = 0 ; i < lines . length ; i ++ ) {
if ( lines [ i ] . trim ( ) === '' ) {
lines . splice ( i -- , 1 ) ;
} else break ;
}
// Trim line-breaks from the end
for ( var i = lines . length - 1 ; i >= 0 ; i -- ) {
if ( lines [ i ] . trim ( ) === '' ) {
lines . splice ( i , 1 ) ;
} else break ;
}
return lines . join ( '\n' ) ;
}
// Main function for betterTrim()
return ( function ( snippetEl ) {
var content = trimLineBreaks ( snippetEl . innerHTML ) ;
var lines = content . split ( '\n' ) ;
// Calculate the minimum amount to remove on each line start of the snippet (can be 0)
var pad = lines . reduce ( function ( acc , line ) {
if ( line . length > 0 && trimLeft ( line ) . length > 0 && acc > line . length - trimLeft ( line ) . length ) {
return line . length - trimLeft ( line ) . length ;
}
return acc ;
} , Number . POSITIVE _INFINITY ) ;
// Slice each line with this amount
return lines . map ( function ( line , index ) {
return line . slice ( pad ) ;
} )
. join ( '\n' ) ;
} ) ( snippetEl ) ;
}
2019-03-12 13:17:50 +01:00
var RevealHighlight = {
2019-04-05 07:59:28 +02:00
HIGHLIGHT _STEP _DELIMITER : '|' ,
HIGHLIGHT _LINE _DELIMITER : ',' ,
HIGHLIGHT _LINE _RANGE _DELIMITER : '-' ,
2019-03-04 14:32:38 +01:00
init : function ( ) {
2013-04-28 20:12:31 +02:00
2019-03-12 13:17:50 +01:00
// Read the plugin config options and provide fallbacks
var config = Reveal . getConfig ( ) . highlight || { } ;
config . highlightOnLoad = typeof config . highlightOnLoad === 'boolean' ? config . highlightOnLoad : true ;
config . escapeHTML = typeof config . escapeHTML === 'boolean' ? config . escapeHTML : true ;
[ ] . slice . call ( document . querySelectorAll ( '.reveal pre code' ) ) . forEach ( function ( block ) {
2019-03-04 14:32:38 +01:00
2019-03-12 13:17:50 +01:00
// Trim whitespace if the "data-trim" attribute is present
if ( block . hasAttribute ( 'data-trim' ) && typeof block . innerHTML . trim === 'function' ) {
block . innerHTML = betterTrim ( block ) ;
2019-03-04 14:32:38 +01:00
}
2013-04-28 20:12:31 +02:00
2019-03-12 13:17:50 +01:00
// Escape HTML tags unless the "data-noescape" attrbute is present
if ( config . escapeHTML && ! block . hasAttribute ( 'data-noescape' ) ) {
block . innerHTML = block . innerHTML . replace ( /</g , "<" ) . replace ( />/g , '>' ) ;
2019-03-04 14:32:38 +01:00
}
2019-03-12 13:17:50 +01:00
// Re-highlight when focus is lost (for contenteditable code)
block . addEventListener ( 'focusout' , function ( event ) {
2019-03-04 14:32:38 +01:00
hljs . highlightBlock ( event . currentTarget ) ;
} , false ) ;
2013-05-01 21:44:53 +02:00
2019-03-12 13:17:50 +01:00
if ( config . highlightOnLoad ) {
RevealHighlight . highlightBlock ( block ) ;
}
2020-03-12 17:08:20 +01:00
} ) ;
// If we're printing to PDF, scroll the code highlights of
// all blocks in the deck into view at once
2020-04-07 09:05:56 +02:00
Reveal . on ( 'pdf-ready' , function ( ) {
2020-03-12 17:08:20 +01:00
[ ] . slice . call ( document . querySelectorAll ( '.reveal pre code[data-line-numbers].current-fragment' ) ) . forEach ( function ( block ) {
RevealHighlight . scrollHighlightedLineIntoView ( block , { } , true ) ;
} ) ;
2019-03-08 15:07:59 +01:00
} ) ;
2019-03-04 14:32:38 +01:00
2019-03-08 15:07:59 +01:00
} ,
/ * *
* Highlights a code block . If the < code > node has the
2019-04-01 14:29:26 +02:00
* 'data-line-numbers' attribute we also generate slide
* numbers .
2019-04-05 07:59:28 +02:00
*
2019-04-05 19:49:17 +02:00
* If the block contains multiple line highlight steps ,
* we clone the block and create a fragment for each step .
2019-03-08 15:07:59 +01:00
* /
highlightBlock : function ( block ) {
hljs . highlightBlock ( block ) ;
2019-05-27 07:30:08 +02:00
// Don't generate line numbers for empty code blocks
if ( block . innerHTML . trim ( ) . length === 0 ) return ;
2019-03-11 15:48:03 +01:00
if ( block . hasAttribute ( 'data-line-numbers' ) ) {
2019-03-12 13:17:50 +01:00
hljs . lineNumbersBlock ( block , { singleLine : true } ) ;
2019-03-08 15:07:59 +01:00
2020-03-12 17:08:20 +01:00
var scrollState = { currentBlock : block } ;
2019-04-05 19:49:17 +02:00
// If there is at least one highlight step, generate
// fragments
var highlightSteps = RevealHighlight . deserializeHighlightSteps ( block . getAttribute ( 'data-line-numbers' ) ) ;
if ( highlightSteps . length > 1 ) {
2019-04-05 07:59:28 +02:00
2019-04-05 19:49:17 +02:00
// If the original code block has a fragment-index,
// each clone should follow in an incremental sequence
var fragmentIndex = parseInt ( block . getAttribute ( 'data-fragment-index' ) , 10 ) ;
2020-03-12 17:08:20 +01:00
2019-04-05 19:49:17 +02:00
if ( typeof fragmentIndex !== 'number' || isNaN ( fragmentIndex ) ) {
fragmentIndex = null ;
}
2019-04-05 07:59:28 +02:00
2019-04-05 19:49:17 +02:00
// Generate fragments for all steps except the original block
highlightSteps . slice ( 1 ) . forEach ( function ( highlight ) {
2019-04-05 07:59:28 +02:00
2019-04-05 19:49:17 +02:00
var fragmentBlock = block . cloneNode ( true ) ;
fragmentBlock . setAttribute ( 'data-line-numbers' , RevealHighlight . serializeHighlightSteps ( [ highlight ] ) ) ;
fragmentBlock . classList . add ( 'fragment' ) ;
block . parentNode . appendChild ( fragmentBlock ) ;
RevealHighlight . highlightLines ( fragmentBlock ) ;
2019-04-05 07:59:28 +02:00
2019-04-10 10:09:41 +02:00
if ( typeof fragmentIndex === 'number' ) {
2019-04-05 19:49:17 +02:00
fragmentBlock . setAttribute ( 'data-fragment-index' , fragmentIndex ) ;
fragmentIndex += 1 ;
}
else {
fragmentBlock . removeAttribute ( 'data-fragment-index' ) ;
}
2019-04-05 07:59:28 +02:00
2020-03-12 17:08:20 +01:00
// Scroll highlights into view as we step through them
fragmentBlock . addEventListener ( 'visible' , RevealHighlight . scrollHighlightedLineIntoView . bind ( RevealHighlight , fragmentBlock , scrollState ) ) ;
fragmentBlock . addEventListener ( 'hidden' , RevealHighlight . scrollHighlightedLineIntoView . bind ( RevealHighlight , fragmentBlock . previousSibling , scrollState ) ) ;
2019-04-05 19:49:17 +02:00
} ) ;
2019-04-05 07:59:28 +02:00
2019-04-05 19:49:17 +02:00
block . removeAttribute ( 'data-fragment-index' )
block . setAttribute ( 'data-line-numbers' , RevealHighlight . serializeHighlightSteps ( [ highlightSteps [ 0 ] ] ) ) ;
2019-04-05 07:59:28 +02:00
2019-04-05 19:49:17 +02:00
}
2019-04-05 07:59:28 +02:00
2020-03-12 17:08:20 +01:00
// Scroll the first highlight into view when the slide
// becomes visible. Note supported in IE11 since it lacks
// support for Element.closest.
var slide = typeof block . closest === 'function' ? block . closest ( 'section:not(.stack)' ) : null ;
if ( slide ) {
var scrollFirstHighlightIntoView = function ( ) {
RevealHighlight . scrollHighlightedLineIntoView ( block , scrollState , true ) ;
slide . removeEventListener ( 'visible' , scrollFirstHighlightIntoView ) ;
}
slide . addEventListener ( 'visible' , scrollFirstHighlightIntoView ) ;
}
2019-04-05 19:49:17 +02:00
RevealHighlight . highlightLines ( block ) ;
2019-04-05 07:59:28 +02:00
2019-03-08 15:07:59 +01:00
}
} ,
2020-03-12 17:08:20 +01:00
/ * *
* Animates scrolling to the first highlighted line
* in the given code block .
* /
scrollHighlightedLineIntoView : function ( block , scrollState , skipAnimation ) {
cancelAnimationFrame ( scrollState . animationFrameID ) ;
// Match the scroll position of the currently visible
// code block
if ( scrollState . currentBlock ) {
block . scrollTop = scrollState . currentBlock . scrollTop ;
}
// Remember the current code block so that we can match
// its scroll position when showing/hiding fragments
scrollState . currentBlock = block ;
var highlightBounds = this . getHighlightedLineBounds ( block )
var viewportHeight = block . offsetHeight ;
// Subtract padding from the viewport height
var blockStyles = getComputedStyle ( block ) ;
viewportHeight -= parseInt ( blockStyles . paddingTop ) + parseInt ( blockStyles . paddingBottom ) ;
// Scroll position which centers all highlights
var startTop = block . scrollTop ;
var targetTop = highlightBounds . top + ( Math . min ( highlightBounds . bottom - highlightBounds . top , viewportHeight ) - viewportHeight ) / 2 ;
// Account for offsets in position applied to the
// <table> that holds our lines of code
var lineTable = block . querySelector ( '.hljs-ln' ) ;
if ( lineTable ) targetTop += lineTable . offsetTop - parseInt ( blockStyles . paddingTop ) ;
// Make sure the scroll target is within bounds
targetTop = Math . max ( Math . min ( targetTop , block . scrollHeight - viewportHeight ) , 0 ) ;
if ( skipAnimation === true || startTop === targetTop ) {
block . scrollTop = targetTop ;
}
else {
// Don't attempt to scroll if there is no overflow
if ( block . scrollHeight <= viewportHeight ) return ;
var time = 0 ;
var animate = function ( ) {
time = Math . min ( time + 0.02 , 1 ) ;
// Update our eased scroll position
block . scrollTop = startTop + ( targetTop - startTop ) * RevealHighlight . easeInOutQuart ( time ) ;
// Keep animating unless we've reached the end
if ( time < 1 ) {
scrollState . animationFrameID = requestAnimationFrame ( animate ) ;
}
} ;
animate ( ) ;
}
} ,
/ * *
* The easing function used when scrolling .
* /
easeInOutQuart : function ( t ) {
// easeInOutQuart
return t < . 5 ? 8 * t * t * t * t : 1 - 8 * ( -- t ) * t * t * t ;
} ,
getHighlightedLineBounds : function ( block ) {
var highlightedLines = block . querySelectorAll ( '.highlight-line' ) ;
if ( highlightedLines . length === 0 ) {
return { top : 0 , bottom : 0 } ;
}
else {
var firstHighlight = highlightedLines [ 0 ] ;
var lastHighlight = highlightedLines [ highlightedLines . length - 1 ] ;
return {
top : firstHighlight . offsetTop ,
bottom : lastHighlight . offsetTop + lastHighlight . offsetHeight
}
}
} ,
2019-03-08 15:07:59 +01:00
/ * *
* Visually emphasize specific lines within a code block .
2019-04-01 14:29:26 +02:00
* This only works on blocks with line numbering turned on .
2019-03-08 15:07:59 +01:00
*
* @ param { HTMLElement } block a < code > block
* @ param { String } [ linesToHighlight ] The lines that should be
* highlighted in this format :
* "1" = highlights line 1
* "2,5" = highlights lines 2 & 5
* "2,5-7" = highlights lines 2 , 5 , 6 & 7
* /
highlightLines : function ( block , linesToHighlight ) {
2019-04-05 07:59:28 +02:00
var highlightSteps = RevealHighlight . deserializeHighlightSteps ( linesToHighlight || block . getAttribute ( 'data-line-numbers' ) ) ;
2019-03-08 15:07:59 +01:00
2019-04-05 07:59:28 +02:00
if ( highlightSteps . length ) {
2019-03-08 15:07:59 +01:00
2019-04-05 07:59:28 +02:00
highlightSteps [ 0 ] . forEach ( function ( highlight ) {
2019-03-08 15:07:59 +01:00
2019-04-05 07:59:28 +02:00
var elementsToHighlight = [ ] ;
2019-03-14 13:05:01 +01:00
2019-04-05 07:59:28 +02:00
// Highlight a range
if ( typeof highlight . end === 'number' ) {
elementsToHighlight = [ ] . slice . call ( block . querySelectorAll ( 'table tr:nth-child(n+' + highlight . start + '):nth-child(-n+' + highlight . end + ')' ) ) ;
}
// Highlight a single line
else if ( typeof highlight . start === 'number' ) {
elementsToHighlight = [ ] . slice . call ( block . querySelectorAll ( 'table tr:nth-child(' + highlight . start + ')' ) ) ;
}
2019-03-08 15:07:59 +01:00
2019-04-05 19:49:17 +02:00
if ( elementsToHighlight . length ) {
elementsToHighlight . forEach ( function ( lineElement ) {
lineElement . classList . add ( 'highlight-line' ) ;
} ) ;
block . classList . add ( 'has-highlights' ) ;
}
2019-03-08 15:07:59 +01:00
2019-04-05 07:59:28 +02:00
} ) ;
2019-03-11 16:12:25 +01:00
2019-04-05 07:59:28 +02:00
}
} ,
/ * *
* Parses and formats a user - defined string of line
* numbers to highlight .
*
* @ example
* RevealHighlight . deserializeHighlightSteps ( '1,2|3,5-10' )
* // [
* // [ { start: 1 }, { start: 2 } ],
* // [ { start: 3 }, { start: 5, end: 10 } ]
* // ]
* /
deserializeHighlightSteps : function ( highlightSteps ) {
// Remove whitespace
highlightSteps = highlightSteps . replace ( /\s/g , '' ) ;
// Divide up our line number groups
highlightSteps = highlightSteps . split ( RevealHighlight . HIGHLIGHT _STEP _DELIMITER ) ;
return highlightSteps . map ( function ( highlights ) {
return highlights . split ( RevealHighlight . HIGHLIGHT _LINE _DELIMITER ) . map ( function ( highlight ) {
// Parse valid line numbers
if ( /^[\d-]+$/ . test ( highlight ) ) {
highlight = highlight . split ( RevealHighlight . HIGHLIGHT _LINE _RANGE _DELIMITER ) ;
var lineStart = parseInt ( highlight [ 0 ] , 10 ) ,
lineEnd = parseInt ( highlight [ 1 ] , 10 ) ;
if ( isNaN ( lineEnd ) ) {
return {
start : lineStart
} ;
}
else {
return {
start : lineStart ,
end : lineEnd
} ;
}
}
// If no line numbers are provided, no code will be highlighted
else {
return { } ;
2019-03-11 16:12:25 +01:00
}
2019-03-08 15:07:59 +01:00
} ) ;
2019-04-05 07:59:28 +02:00
} ) ;
} ,
/ * *
* Serializes parsed line number data into a string so
* that we can store it in the DOM .
* /
serializeHighlightSteps : function ( highlightSteps ) {
return highlightSteps . map ( function ( highlights ) {
2019-04-05 19:49:17 +02:00
2019-04-05 07:59:28 +02:00
return highlights . map ( function ( highlight ) {
2019-04-05 19:49:17 +02:00
// Line range
2019-04-05 07:59:28 +02:00
if ( typeof highlight . end === 'number' ) {
return highlight . start + RevealHighlight . HIGHLIGHT _LINE _RANGE _DELIMITER + highlight . end ;
}
2019-04-05 19:49:17 +02:00
// Single line
2019-04-05 07:59:28 +02:00
else if ( typeof highlight . start === 'number' ) {
return highlight . start ;
}
2019-04-05 19:49:17 +02:00
// All lines
2019-04-05 07:59:28 +02:00
else {
return '' ;
}
2019-04-05 19:49:17 +02:00
2019-04-05 07:59:28 +02:00
} ) . join ( RevealHighlight . HIGHLIGHT _LINE _DELIMITER ) ;
2019-04-05 19:49:17 +02:00
2019-04-05 07:59:28 +02:00
} ) . join ( RevealHighlight . HIGHLIGHT _STEP _DELIMITER ) ;
2019-03-08 15:07:59 +01:00
2013-04-28 20:12:31 +02:00
}
2019-04-05 07:59:28 +02:00
2013-04-28 20:12:31 +02:00
}
2012-10-28 23:09:54 +01:00
2019-03-12 13:17:50 +01:00
Reveal . registerPlugin ( 'highlight' , RevealHighlight ) ;
return RevealHighlight ;
} ) ) ;