Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to preserve whitespace indentation of text enclosed in HTML <pre> tags excluding the current indentation level of the <pre> tag in the document?

I'm trying to display my code on a website but I'm having problems preserving the whitespace indentation correctly.

For instance given the following snippet:

<html>  <body>    Here is my code:    <pre>      def some_funtion        return 'Hello, World!'      end    </pre>  <body> </html> 

This is displayed in the browser as:

Here is my code:       def some_funtion        return 'Hello, World!'      end 

When I would like it displayed as:

Here is my code:  def some_funtion  return 'Hello, World!' end 

The difference is that that current indentation level of the HTML pre tag is being added to the indentation of the code. I'm using nanoc as a static website generator and I'm using google prettify to also add syntax highlighting.

Can anyone offer any suggestions?

like image 213
Michael Barton Avatar asked Jan 08 '11 00:01

Michael Barton


People also ask

How do you maintain indentation in HTML?

Many developers choose to use 4-space or 2-space indentation. In HTML, each nested tag should be indented exactly once inside of its parent tag. Place a line break after every block element. Do not place more than one block element on the same line.

Which tag can preserve the whitespace in text?

The HTML <pre> tag defines preformatted text preserving both whitespace and line breaks in the HTML document. This tag is also commonly referred to as the <pre> element.

How do you preserve text formatting in HTML?

The <pre> tag in HTML is used to define the block of preformatted text which preserves the text spaces, line breaks, tabs, and other formatting characters which are ignored by web browsers.

Does HTML have indentation?

No. HTML code does not need to be indented, and all browsers and search engines ignore indentation and extra spacing. However, for any human reader, it's a good idea to indent your text because it makes the code easier to scan and read.


1 Answers

PRE is intended to preserve whitespace exactly as it appears (unless altered by white-space in CSS, which doesn't have enough flexibility to support formatting code).

Before

Formatting is preserved, but so is all the indentation outside of the PRE tag. It would be nice to have whitespace preservation that used the location of the tag as a starting point.

enter image description here

After

Contents are still formatted as declared, but the extraneous leading whitespace caused by the position of the PRE tag within the document is removed.

enter image description here

I have come up with the following plugin to solve the issue of wanting to remove superfluous whitespace caused by the indentation of the document outline. This code uses the first line inside the PRE tag to determine how much it has been indented purely due to the indentation of the document.

This code works in IE7, IE8, IE9, Firefox, and Chrome. I have tested it briefly with the Prettify library to combine the preserved formatting with pretty printing. Make sure that the first line inside the PRE actually represents the baseline level of indenting that you want to ignore (or, you can modify the plugin to be more intelligent).

This is rough code. If you find a mistake or it does not work the way you want, please fix/comment; don't just downvote. I wrote this code to fix a problem that I was having and I am actively using it so I would like it to be as solid as possible!

/*! *** prettyPre ***/  (function( $ ) {      $.fn.prettyPre = function( method ) {          var defaults = {             ignoreExpression: /\s/ // what should be ignored?         };          var methods = {             init: function( options ) {                 this.each( function() {                     var context = $.extend( {}, defaults, options );                     var $obj = $( this );                     var usingInnerText = true;                     var text = $obj.get( 0 ).innerText;                      // some browsers support innerText...some don't...some ONLY work with innerText.                     if ( typeof text == "undefined" ) {                         text = $obj.html();                         usingInnerText = false;                     }                      // use the first line as a baseline for how many unwanted leading whitespace characters are present                     var superfluousSpaceCount = 0;                     var currentChar = text.substring( 0, 1 );                      while ( context.ignoreExpression.test( currentChar ) ) {                         currentChar = text.substring( ++superfluousSpaceCount, superfluousSpaceCount + 1 );                     }                      // split                     var parts = text.split( "\n" );                     var reformattedText = "";                      // reconstruct                     var length = parts.length;                     for ( var i = 0; i < length; i++ ) {                         // cleanup, and don't append a trailing newline if we are on the last line                         reformattedText += parts[i].substring( superfluousSpaceCount ) + ( i == length - 1 ? "" : "\n" );                     }                      // modify original                     if ( usingInnerText ) {                         $obj.get( 0 ).innerText = reformattedText;                     }                     else {                         // This does not appear to execute code in any browser but the onus is on the developer to not                          // put raw input from a user anywhere on a page, even if it doesn't execute!                         $obj.html( reformattedText );                     }                 } );             }         }          if ( methods[method] ) {             return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ) );         }         else if ( typeof method === "object" || !method ) {             return methods.init.apply( this, arguments );         }         else {             $.error( "Method " + method + " does not exist on jQuery.prettyPre." );         }     } } )( jQuery ); 

This plugin can then be applied using a standard jQuery selector:

<script>     $( function() { $("PRE").prettyPre(); } ); </script> 
like image 126
Tim M. Avatar answered Oct 06 '22 08:10

Tim M.