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?
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.
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.
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>