App-revealup

 view release on metacpan or  search on metacpan

share/revealjs/plugin/highlight/plugin.js  view on Meta::CPAN

			}

			// Re-highlight when focus is lost (for contenteditable code)
			block.addEventListener( 'focusout', function( event ) {
				hljs.highlightElement( event.currentTarget );
			}, false );

		} );

		// Triggers a callback function before we trigger highlighting
		if( typeof config.beforeHighlight === 'function' ) {
			config.beforeHighlight( hljs );
		}

		// Run initial highlighting for all code
		if( config.highlightOnLoad ) {
			Array.from( reveal.getRevealElement().querySelectorAll( 'pre code' ) ).forEach( block => {
				Plugin.highlightBlock( block );
			} );
		}

		// If we're printing to PDF, scroll the code highlights of
		// all blocks in the deck into view at once
		reveal.on( 'pdf-ready', function() {
			[].slice.call( reveal.getRevealElement().querySelectorAll( 'pre code[data-line-numbers].current-fragment' ) ).forEach( function( block ) {
				Plugin.scrollHighlightedLineIntoView( block, {}, true );
			} );
		} );

	},

	/**
	 * Highlights a code block. If the <code> node has the
	 * 'data-line-numbers' attribute we also generate slide
	 * numbers.
	 *
	 * If the block contains multiple line highlight steps,
	 * we clone the block and create a fragment for each step.
	 */
	highlightBlock: function( block ) {

		hljs.highlightElement( block );

		// Don't generate line numbers for empty code blocks
		if( block.innerHTML.trim().length === 0 ) return;

		if( block.hasAttribute( 'data-line-numbers' ) ) {
			hljs.lineNumbersBlock( block, { singleLine: true } );

			var scrollState = { currentBlock: block };

			// If there is more than one highlight step, generate
			// fragments
			var highlightSteps = Plugin.deserializeHighlightSteps( block.getAttribute( 'data-line-numbers' ) );
			if( highlightSteps.length > 1 ) {

				// 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 );

				if( typeof fragmentIndex !== 'number' || isNaN( fragmentIndex ) ) {
					fragmentIndex = null;
				}

				// Generate fragments for all steps except the original block
				highlightSteps.slice(1).forEach( function( highlight ) {

					var fragmentBlock = block.cloneNode( true );
					fragmentBlock.setAttribute( 'data-line-numbers', Plugin.serializeHighlightSteps( [ highlight ] ) );
					fragmentBlock.classList.add( 'fragment' );
					block.parentNode.appendChild( fragmentBlock );
					Plugin.highlightLines( fragmentBlock );

					if( typeof fragmentIndex === 'number' ) {
						fragmentBlock.setAttribute( 'data-fragment-index', fragmentIndex );
						fragmentIndex += 1;
					}
					else {
						fragmentBlock.removeAttribute( 'data-fragment-index' );
					}

					// Scroll highlights into view as we step through them
					fragmentBlock.addEventListener( 'visible', Plugin.scrollHighlightedLineIntoView.bind( Plugin, fragmentBlock, scrollState ) );
					fragmentBlock.addEventListener( 'hidden', Plugin.scrollHighlightedLineIntoView.bind( Plugin, fragmentBlock.previousSibling, scrollState ) );

				} );

				block.removeAttribute( 'data-fragment-index' );
				block.setAttribute( 'data-line-numbers', Plugin.serializeHighlightSteps( [ highlightSteps[0] ] ) );

			}

			// 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() {
					Plugin.scrollHighlightedLineIntoView( block, scrollState, true );
					slide.removeEventListener( 'visible', scrollFirstHighlightIntoView );
				}
				slide.addEventListener( 'visible', scrollFirstHighlightIntoView );
			}

			Plugin.highlightLines( block );

		}

	},

	/**
	 * 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 ) {

share/revealjs/plugin/highlight/plugin.js  view on Meta::CPAN

		if( highlightSteps.length ) {

			highlightSteps[0].forEach( function( highlight ) {

				var elementsToHighlight = [];

				// 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+')' ) );
				}

				if( elementsToHighlight.length ) {
					elementsToHighlight.forEach( function( lineElement ) {
						lineElement.classList.add( 'highlight-line' );
					} );

					block.classList.add( 'has-highlights' );
				}

			} );

		}

	},

	/**
	 * Parses and formats a user-defined string of line
	 * numbers to highlight.
	 *
	 * @example
	 * Plugin.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( Plugin.HIGHLIGHT_STEP_DELIMITER );

		return highlightSteps.map( function( highlights ) {

			return highlights.split( Plugin.HIGHLIGHT_LINE_DELIMITER ).map( function( highlight ) {

				// Parse valid line numbers
				if( /^[\d-]+$/.test( highlight ) ) {

					highlight = highlight.split( Plugin.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 {};

				}

			} );

		} );

	},

	/**
	 * 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 ) {

			return highlights.map( function( highlight ) {

				// Line range
				if( typeof highlight.end === 'number' ) {
					return highlight.start + Plugin.HIGHLIGHT_LINE_RANGE_DELIMITER + highlight.end;
				}
				// Single line
				else if( typeof highlight.start === 'number' ) {
					return highlight.start;
				}
				// All lines
				else {
					return '';
				}

			} ).join( Plugin.HIGHLIGHT_LINE_DELIMITER );

		} ).join( Plugin.HIGHLIGHT_STEP_DELIMITER );

	}

}

// 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



( run in 0.575 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )