Index: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/comments.php
===================================================================
--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/comments.php	(revision 3728)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/comments.php	(working copy)
@@ -85,6 +85,19 @@
 			'title_reply'         =>  '', //'Add Example'
 		) ); ?>
 
+		<!-- Comment Preview -->
+		<div id='comment-preview' class='comment byuser depth-1' style='display:none;'>
+			<article class='comment-body'>
+				<header class='comment-meta'>
+					<div>
+						<?php _e('Preview', 'wporg') ?>
+						<span class='spinner' style='display:none'></span>
+					</div>
+				</header>
+				<div class='comment-content'></div>
+			</article>
+		</div>
+
 	<?php endif; ?>
 
 	<?php if ( ! \DevHub\is_parsed_post_type() && comments_open() ) : ?>
Index: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/functions.php
===================================================================
--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/functions.php	(revision 3728)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/functions.php	(working copy)
@@ -111,6 +111,8 @@
 	add_filter( 'wp_parser_skip_duplicate_hooks', '__return_true' );
 
 	add_filter( 'document_title_separator', __NAMESPACE__ . '\\theme_title_separator', 10, 2 );
+
+	add_filter( 'syntaxhighlighter_htmlresult', __NAMESPACE__ . '\\syntaxhighlighter_htmlresult' );
 }
 
 /**
@@ -276,3 +278,44 @@
 		add_meta_box( 'commentsdiv', __( 'User Contributed Notes', 'wporg' ), 'post_comment_meta_box', $post_type, 'normal', 'high' );
 	}
 }
+
+/**
+ * If a syntax highlighted code block exceeds a given number of lines, wrap the
+ * markup with other markup to trigger the code expansion/collapse JS handling
+ * already implemented for the code reference.
+ *
+ * @param string  $text The pending result of the syntax highlighting.
+ * @return string
+ */
+function syntaxhighlighter_htmlresult( $text ) {
+
+	// is_admin() is true in front end AJAX requests.
+	if ( is_admin() && !( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
+		return $text;
+	}
+
+	$new_text      = '';
+	// Collapse is handled for >10 lines. But just go ahead and show the full
+	// code if that is just barely being exceeded (no one wants to expand to
+	// see one or two more lines).
+	$lines_to_show = 12;
+	$do_collapse   = ( substr_count( $text, "\n" ) - 1 ) > $lines_to_show;
+
+	if ( $do_collapse )  {
+		$new_text .= '<section class="source-content">';
+		$new_text .= '<div class="source-code-container">';
+	}
+
+	$new_text .= $text;
+
+	if ( $do_collapse ) {
+		$new_text .= '</div>';
+		$new_text .= '<p class="source-code-links"><span>';
+		$new_text .= '<a href="#" class="show-complete-source">' . __( 'Expand full source code', 'wporg' ) . '</a>';
+		$new_text .= '<a href="#" class="less-complete-source">' . __( 'Collapse full source code', 'wporg' ) . '</a>';
+		$new_text .= '</span></p>';
+		$new_text .= '</section>';
+	}
+
+	return $new_text;
+}
Index: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/img/loading.gif
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/img/loading.gif
===================================================================
--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/img/loading.gif	(revision 3728)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/img/loading.gif	(working copy)

Property changes on: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/img/loading.gif
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/inc/handbooks.php
===================================================================
--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/inc/handbooks.php	(revision 3728)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/inc/handbooks.php	(working copy)
@@ -49,11 +49,6 @@
 		if ( class_exists( 'WPorg_Handbook_Watchlist' ) && method_exists( 'WPorg_Handbook_Watchlist', 'display_action_link' ) ) {
 			add_action( 'wporg_action_links', array( 'WPorg_Handbook_Watchlist', 'display_action_link' ) );
 		}
-
-		// Modify SyntaxHighlighter Evolved code output to facilitate code collapse/expand.
-		if ( ! is_admin() ) {
-			add_filter( 'syntaxhighlighter_htmlresult', array( __CLASS__, 'syntaxhighlighter_htmlresult' ) );
-		}
 	}
 
 	/**
@@ -91,41 +86,6 @@
 	}
 
 	/**
-	 * If a syntax highlighted code block exceeds a given number of lines, wrap the
-	 * markup with other markup to trigger the code expansion/collapse JS handling
-	 * already implemented for the code reference.
-	 *
-	 * @param string  $text The pending result of the syntax highlighting.
-	 * @return string
-	 */
-	public static function syntaxhighlighter_htmlresult( $text ) {
-		$new_text      = '';
-		// Collapse is handled for >10 lines. But just go ahead and show the full
-		// code if that is just barely being exceeded (no one wants to expand to
-		// see one or two more lines).
-		$lines_to_show = 12;
-		$do_collapse   = ( substr_count( $text, "\n" ) - 1 ) > $lines_to_show;
-
-		if ( $do_collapse )  {
-			$new_text .= '<section class="source-content">';
-			$new_text .= '<div class="source-code-container">';
-		}
-
-		$new_text .= $text;
-
-		if ( $do_collapse ) {
-			$new_text .= '</div>';
-			$new_text .= '<p class="source-code-links"><span>';
-			$new_text .= '<a href="#" class="show-complete-source">' . __( 'Expand full source code', 'wporg' ) . '</a>';
-			$new_text .= '<a href="#" class="less-complete-source">' . __( 'Collapse full source code', 'wporg' ) . '</a>';
-			$new_text .= '</span></p>';
-			$new_text .= '</section>';
-		}
-
-		return $new_text;
-	}
-
-	/**
 	 * Filter handbook post types to create handbooks for: plugins, themes.
 	 *
 	 * @access public
Index: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/inc/user-content.php
===================================================================
--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/inc/user-content.php	(revision 3728)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/inc/user-content.php	(working copy)
@@ -55,6 +55,9 @@
 		// Tweak code contained in shortcode
 		add_filter( 'syntaxhighlighter_precode',       array( __CLASS__, 'syntaxhighlighter_precode' ) );
 
+		// Ajax actions to process preview
+		add_action( "wp_ajax_preview_comment",         array( __CLASS__, "ajax_preview" ) );
+		add_action( "wp_ajax_nopriv_preview_comment",  array( __CLASS__, "ajax_preview" ) );
 	}
 
 	/**
@@ -69,6 +72,12 @@
 			}
 
 			wp_enqueue_script( 'wporg-developer-user-notes', get_template_directory_uri() . '/js/user-notes.js', array( 'quicktags' ), '20160606', true );
+			wp_localize_script( 'wporg-developer-user-notes', 'wporg_user_notes', array(
+					'ajaxurl' => admin_url( 'admin-ajax.php' ),
+					'nonce'   => wp_create_nonce( 'preview_nonce' ),
+					'preview'   => __( 'preview note', 'wporg' ),
+				) );
+
 			if ( get_option( 'thread_comments' ) ) {
 				wp_enqueue_script( 'comment-reply' );
 			}
@@ -120,6 +129,24 @@
 		return ob_get_clean();
 	}
 
+	/**
+	 * Ajax action to update the comment preview.
+	 */
+	public static function ajax_preview( ) {
+		check_ajax_referer( 'preview_nonce', 'preview_nonce' );
+
+		if ( !isset( $_POST['preview_comment'] ) ) {
+			wp_send_json_error( array( 'comment' => '' ) );
+		}
+
+		$comment = apply_filters('pre_comment_content', $_POST['preview_comment'] );
+		$comment = wp_unslash( $comment );
+		$comment = apply_filters('get_comment_text', $comment);
+		$comment = apply_filters('comment_text', $comment);		
+
+		wp_send_json_success( array( 'comment' => $comment ) );
+	}
+
 } // DevHub_User_Submitted_Content
 
 DevHub_User_Submitted_Content::init();
Index: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/js/function-reference.js
===================================================================
--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/js/function-reference.js	(revision 3728)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/js/function-reference.js	(working copy)
@@ -3,7 +3,7 @@
  *
  * Handles all interactivity on the single function page
  */
-( function( $ ) {
+var wporg_developer = ( function( $ ) {
 	'use strict';
 
 	var $sourceCollapsedHeight;
@@ -28,19 +28,37 @@
 		// 1em (margin) + 10 * 17px + 10. Lines are 1.1em which rounds to 17px: calc( 1em + 17px * 10 + 10 ).
 		// Extra 10px added to partially show next line so it's clear there is more.
 		$sourceCollapsedHeight = 196;
+		sourceCodeDisplay();
+	}
 
-		$( '.source-content' ).find( 'table' ).each( function( t ) {
+	function sourceCodeDisplay( element ) {
+		 
+		if ( element !== undefined ) {
+			// Search table inside a specific source code element if passed.
+			var sourceCode = $( '.source-content', element ).find( 'table' );
+		} else {
+			// Search table inside all source code elements.
+			var sourceCode = $( '.source-content' ).find( 'table' );
+		}
+
+		if ( !sourceCode.length ) {
+			return;
+		}
+
+		sourceCode.each( function( t ) {
 			if ( ( $sourceCollapsedHeight - 12 ) < $( this ).height() ) {
 
 				var sourceContent = $( this ).closest( '.source-content' );
 
 				// Do this with javascript so javascript-less can enjoy the total sourcecode
-				sourceContent.find( '.source-code-container' ).css( { height: $sourceCollapsedHeight + 'px' } );
+				sourceContent.find( '.source-code-container' ).css( {
+					height: $sourceCollapsedHeight + 'px'
+				} );
 
-				sourceContent.find( '.source-code-links').find('span:first' ).show();
+				sourceContent.find( '.source-code-links' ).find( 'span:first' ).show();
 				sourceContent.find( '.show-complete-source' ).show();
-				sourceContent.find( '.show-complete-source' ).on( 'click', toggleCompleteSource );
-				sourceContent.find( '.less-complete-source' ).on( 'click', toggleCompleteSource );
+				sourceContent.find( '.show-complete-source' ).off( 'click.togglesource' ).on( 'click.togglesource', toggleCompleteSource );
+				sourceContent.find( '.less-complete-source' ).off( 'click.togglesource' ).on( 'click.togglesource', toggleCompleteSource );
 			}
 		} );
 	}
@@ -101,4 +119,10 @@
 	}
 
 	$( onLoad );
+
+	// Expose the sourceCodeDisplay() function for usage outside of this function.
+	return {
+		sourceCodeDisplay: sourceCodeDisplay
+	};
+
 } )( jQuery );
Index: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/js/user-notes.js
===================================================================
--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/js/user-notes.js	(revision 3728)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/js/user-notes.js	(working copy)
@@ -5,8 +5,16 @@
 
 ( function( $ ) {
 
+	var commentForm = $( '.comment-form textarea' );
+	var preview = $( '#comment-preview' );
+
+	if ( !commentForm.length ) {
+		return;
+	}
+
 	function showCommentForm() {
 		$( '#respond, #add-user-note' ).toggle();
+		toggle_preview();
 
 		if ( pos = $( '#submit' ).position() ) {
 			if ( pos.top < $(window).scrollTop() ) {
@@ -77,4 +85,87 @@
 			e.preventDefault();
 	});
 
+	if ( !preview.length || ( typeof wporg_user_notes === 'undefined' ) ) {
+		return;
+	}
+
+	var previewContent = $( '.comment-content', preview );
+	var spinner = $( '.spinner', preview );
+	var comment = commentForm.val();
+
+	QTags.addButton( 'preview', wporg_user_notes.preview, function() {
+		var pos = preview.position();
+		$( 'html,body' ).animate( {
+			scrollTop: pos.top
+		}, 1000 );
+	} );
+
+	if ( comment.length ) {
+		update_preview( comment );
+	}
+
+	// Display a spinner as soon as the comment form changes input
+	commentForm.bind( 'input propertychange', function( e ) {
+		spinner.show();
+	} );
+
+	// Delay updating the preview by 1.5 seconds to not overload the server
+	commentForm.bind( 'keyup', debounce( function( e ) {
+		update_preview( $( this ).val() );
+	}, 1500 ) );
+
+	function update_preview( content ) {
+		$.post( wporg_user_notes.ajaxurl, {
+			action: "preview_comment",
+			preview_nonce: wporg_user_notes.nonce,
+			preview_comment: content
+		} )
+
+		.done( function( response ) {
+			update_preview_html( response.data.comment );
+		} )
+
+		.fail( function( response ) {
+			//console.log( 'fail', response );
+		} )
+
+		.always( function( response ) {
+			spinner.hide();
+		} );
+	}
+
+	function toggle_preview(){
+		preview.toggle();
+
+		// Add toggle links to source code in preview if needed.
+		// Toggle links were not added (before) because the preview was hidden.
+		wporg_developer.sourceCodeDisplay( preview );
+	}
+
+	function update_preview_html( content ) {
+		// Update preview content
+		previewContent.html( content );
+
+		if ( undefined !== window.SyntaxHighlighter ) {
+			SyntaxHighlighter.highlight();
+		}
+		
+		// Add toggle links to source code in preview if needed.
+		wporg_developer.sourceCodeDisplay( preview );
+		spinner.hide();
+	}
+
+	// https://remysharp.com/2010/07/21/throttling-function-calls
+	function debounce( fn, delay ) {
+		var timer = null;
+		return function() {
+			var context = this,
+				args = arguments;
+			clearTimeout( timer );
+			timer = setTimeout( function() {
+				fn.apply( context, args );
+			}, delay );
+		};
+	}
+
 } )( jQuery );
Index: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/scss/main.scss
===================================================================
--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/scss/main.scss	(revision 3728)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/scss/main.scss	(working copy)
@@ -1182,7 +1182,8 @@
 			padding: 0;
 		}
 
-		.comment-list li {
+		.comment-list li,
+		#comment-preview {
 			margin-top: 2.5rem;
 			background: #fff;
 			overflow: auto;
@@ -1194,6 +1195,20 @@
 			}
 		}
 
+		#comment-preview {
+			clear:both;
+		}
+
+		#comment-preview .comment-content {
+			min-height: 6em;
+		}
+
+		#comment-preview .spinner{
+			background: url("../img/loading.gif") no-repeat scroll 0 50%;
+			margin: 0 1em;
+			padding-left: 16px;
+		}
+
 		.comment-list .avatar {
 			float: left;
 			margin: -2px 1em 0 0;
Index: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/stylesheets/main.css
===================================================================
--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/stylesheets/main.css	(revision 3728)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/stylesheets/main.css	(working copy)
@@ -1554,7 +1554,11 @@
   padding: 0;
 }
 
-.devhub-wrap.single-wp-parser-function .comment-list li, .devhub-wrap.single-wp-parser-method .comment-list li, .devhub-wrap.single-wp-parser-hook .comment-list li, .devhub-wrap.single-wp-parser-class .comment-list li {
+.devhub-wrap.single-wp-parser-function .comment-list li,
+.devhub-wrap.single-wp-parser-function #comment-preview, .devhub-wrap.single-wp-parser-method .comment-list li,
+.devhub-wrap.single-wp-parser-method #comment-preview, .devhub-wrap.single-wp-parser-hook .comment-list li,
+.devhub-wrap.single-wp-parser-hook #comment-preview, .devhub-wrap.single-wp-parser-class .comment-list li,
+.devhub-wrap.single-wp-parser-class #comment-preview {
   margin-top: 2.5rem;
   background: #fff;
   overflow: auto;
@@ -1562,10 +1566,28 @@
   border-radius: 2px;
 }
 
-.devhub-wrap.single-wp-parser-function .comment-list li article, .devhub-wrap.single-wp-parser-method .comment-list li article, .devhub-wrap.single-wp-parser-hook .comment-list li article, .devhub-wrap.single-wp-parser-class .comment-list li article {
+.devhub-wrap.single-wp-parser-function .comment-list li article,
+.devhub-wrap.single-wp-parser-function #comment-preview article, .devhub-wrap.single-wp-parser-method .comment-list li article,
+.devhub-wrap.single-wp-parser-method #comment-preview article, .devhub-wrap.single-wp-parser-hook .comment-list li article,
+.devhub-wrap.single-wp-parser-hook #comment-preview article, .devhub-wrap.single-wp-parser-class .comment-list li article,
+.devhub-wrap.single-wp-parser-class #comment-preview article {
   overflow: auto;
 }
 
+.devhub-wrap.single-wp-parser-function #comment-preview, .devhub-wrap.single-wp-parser-method #comment-preview, .devhub-wrap.single-wp-parser-hook #comment-preview, .devhub-wrap.single-wp-parser-class #comment-preview {
+  clear: both;
+}
+
+.devhub-wrap.single-wp-parser-function #comment-preview .comment-content, .devhub-wrap.single-wp-parser-method #comment-preview .comment-content, .devhub-wrap.single-wp-parser-hook #comment-preview .comment-content, .devhub-wrap.single-wp-parser-class #comment-preview .comment-content {
+  min-height: 6em;
+}
+
+.devhub-wrap.single-wp-parser-function #comment-preview .spinner, .devhub-wrap.single-wp-parser-method #comment-preview .spinner, .devhub-wrap.single-wp-parser-hook #comment-preview .spinner, .devhub-wrap.single-wp-parser-class #comment-preview .spinner {
+  background: url("../img/loading.gif") no-repeat scroll 0 50%;
+  margin: 0 1em;
+  padding-left: 16px;
+}
+
 .devhub-wrap.single-wp-parser-function .comment-list .avatar, .devhub-wrap.single-wp-parser-method .comment-list .avatar, .devhub-wrap.single-wp-parser-hook .comment-list .avatar, .devhub-wrap.single-wp-parser-class .comment-list .avatar {
   float: left;
   margin: -2px 1em 0 0;
