123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708 |
- /*
- ===============================================================================
- Chili is the jQuery code highlighter plugin
- ...............................................................................
- LICENSE: http://www.opensource.org/licenses/mit-license.php
- WEBSITE: http://noteslog.com/chili/
- Copyright 2008 / Andrea Ercolino
- ===============================================================================
- */
- ( function($) {
- ChiliBook = { //implied global
- version: "2.2" // 2008-07-06
- // options --------------------------------------------------------------------
- , automatic: true
- , automaticSelector: "code"
- , lineNumbers: !true
- , codeLanguage: function( el ) {
- var recipeName = $( el ).attr( "class" );
- return recipeName ? recipeName : '';
- }
- , recipeLoading: true
- , recipeFolder: "" // used like: recipeFolder + recipeName + '.js'
- // IE and FF convert   to " ", Safari and Opera do not
- , replaceSpace: " "
- , replaceTab: "    "
- , replaceNewLine: " <br/>"
- , selectionStyle: [ "position:absolute; z-index:3000; overflow:scroll;"
- , "width:16em;"
- , "height:9em;"
- , "border:1px solid gray;"
- , "padding:15px;"
- , "background-color:yellow;"
- ].join( ' ' )
- // ------------------------------------------------------------- end of options
- , defaultReplacement: '<span class="$0">$$</span>' // TODO: make this an option again
- , recipes: {} //repository
- , queue: {} //registry
- , unique: function() {
- return (new Date()).valueOf();
- }
- };
- $.fn.chili = function( options ) {
- var book = $.extend( {}, ChiliBook, options || {} );
- function cook( ingredients, recipe, blockName ) {
- function prepareBlock( recipe, blockName ) {
- var steps = [];
- for( var stepName in recipe[ blockName ] ) {
- steps.push( prepareStep( recipe, blockName, stepName ) );
- }
- return steps;
- } // prepareBlock
- function prepareStep( recipe, blockName, stepName ) {
- var step = recipe[ blockName ][ stepName ];
- var exp = ( typeof step._match == "string" ) ? step._match : step._match.source;
- return {
- recipe: recipe
- , blockName: blockName
- , stepName: stepName
- , exp: "(" + exp + ")"
- , length: 1 // add 1 to account for the newly added parentheses
- + (exp // count number of submatches in here
- .replace( /\\./g, "%" ) // disable any escaped character
- .replace( /\[.*?\]/g, "%" ) // disable any character class
- .match( /\((?!\?)/g ) // match any open parenthesis, not followed by a ?
- || [] // make sure it is an empty array if there are no matches
- ).length // get the number of matches
- , replacement: step._replace ? step._replace : book.defaultReplacement
- };
- } // prepareStep
-
- function knowHow( steps ) {
- var prevLength = 1;
- var exps = [];
- for (var i = 0; i < steps.length; i++) {
- var exp = steps[ i ].exp;
- // adjust backreferences
- exp = exp.replace( /\\\\|\\(\d+)/g, function( m, aNum ) {
- return !aNum ? m : "\\" + ( prevLength + 1 + parseInt( aNum, 10 ) );
- } );
- exps.push( exp );
- prevLength += steps[ i ].length;
- }
- var prolog = '((?:\\s|\\S)*?)';
- var epilog = '((?:\\s|\\S)+)';
- var source = '(?:' + exps.join( "|" ) + ')';
- source = prolog + source + '|' + epilog;
- return new RegExp( source, recipe._case ? "g" : "gi" );
- } // knowHow
- function escapeHTML( str ) {
- return str.replace( /&/g, "&" ).replace( /</g, "<" );
- } // escapeHTML
- function replaceSpaces( str ) {
- return str.replace( / +/g, function( spaces ) {
- return spaces.replace( / /g, replaceSpace );
- } );
- } // replaceSpaces
- function filter( str ) {
- str = escapeHTML( str );
- if( replaceSpace ) {
- str = replaceSpaces( str );
- }
- return str;
- } // filter
- function applyRecipe( subject, recipe ) {
- return cook( subject, recipe );
- } // applyRecipe
- function applyBlock( subject, recipe, blockName ) {
- return cook( subject, recipe, blockName );
- } // applyBlock
- function applyStep( subject, recipe, blockName, stepName ) {
- var replaceSpace = book.replaceSpace;
- var step = prepareStep( recipe, blockName, stepName );
- var steps = [step];
- var perfect = subject.replace( knowHow( steps ), function() {
- return chef.apply( { steps: steps }, arguments );
- } );
- return perfect;
- } // applyStep
- function applyModule( subject, module, context ) {
- if( ! module ) {
- return filter( subject );
- }
- var sub = module.split( '/' );
- var recipeName = '';
- var blockName = '';
- var stepName = '';
- switch( sub.length ) {
- case 1:
- recipeName = sub[0];
- break;
- case 2:
- recipeName = sub[0]; blockName = sub[1];
- break;
- case 3:
- recipeName = sub[0]; blockName = sub[1]; stepName = sub[2];
- break;
- default:
- return filter( subject );
- }
- function getRecipe( recipeName ) {
- var path = getPath( recipeName );
- var recipe = book.recipes[ path ];
- if( ! recipe ) {
- throw {msg:"recipe not available"};
- }
- return recipe;
- }
- try {
- var recipe;
- if ( '' == stepName ) {
- if ( '' == blockName ) {
- if ( '' == recipeName ) {
- //nothing to do
- }
- else { // ( '' != recipeName )
- recipe = getRecipe( recipeName );
- return applyRecipe( subject, recipe );
- }
- }
- else { // ( '' != blockName )
- if( '' == recipeName ) {
- recipe = context.recipe;
- }
- else {
- recipe = getRecipe( recipeName );
- }
- if( ! (blockName in recipe) ) {
- return filter( subject );
- }
- return applyBlock( subject, recipe, blockName );
- }
- }
- else { // ( '' != stepName )
- if( '' == recipeName ) {
- recipe = context.recipe;
- }
- else {
- recipe = getRecipe( recipeName );
- }
- if( '' == blockName ) {
- blockName = context.blockName;
- }
- if( ! (blockName in recipe) ) {
- return filter( subject );
- }
- if( ! (stepName in recipe[blockName]) ) {
- return filter( subject );
- }
- return applyStep( subject, recipe, blockName, stepName );
- }
- }
- catch( e ) {
- if (e.msg && e.msg == "recipe not available") {
- var cue = 'chili_' + book.unique();
- if( book.recipeLoading ) {
- var path = getPath( recipeName );
- if( ! book.queue[ path ] ) {
- /* this is a new recipe to download */
- try {
- book.queue[ path ] = [ {cue: cue, subject: subject, module: module, context: context} ];
- $.getJSON( path, function( recipeLoaded ) {
- book.recipes[ path ] = recipeLoaded;
- var q = book.queue[ path ];
- for( var i = 0, iTop = q.length; i < iTop; i++ ) {
- var replacement = applyModule( q[ i ].subject, q[ i ].module, q[ i ].context );
- if( book.replaceTab ) {
- replacement = replacement.replace( /\t/g, book.replaceTab );
- }
- if( book.replaceNewLine ) {
- replacement = replacement.replace( /\n/g, book.replaceNewLine );
- }
- $( '#' + q[ i ].cue ).replaceWith( replacement );
- }
- } );
- }
- catch( recipeNotAvailable ) {
- alert( "the recipe for '" + recipeName + "' was not found in '" + path + "'" );
- }
- }
- else {
- /* not a new recipe, so just enqueue this element */
- book.queue[ path ].push( {cue: cue, subject: subject, module: module, context: context} );
- }
- return '<span id="' + cue + '">' + filter( subject ) + '</span>';
- }
- return filter( subject );
- }
- else {
- return filter( subject );
- }
- }
- } // applyModule
- function addPrefix( prefix, replacement ) {
- var aux = replacement.replace( /(<span\s+class\s*=\s*(["']))((?:(?!__)\w)+\2\s*>)/ig, "$1" + prefix + "__$3" );
- return aux;
- } // addPrefix
- function chef() {
- if (! arguments[ 0 ]) {
- return '';
- }
- var steps = this.steps;
- var i = 0; // iterate steps
- var j = 2; // iterate chef's arguments
- var prolog = arguments[ 1 ];
- var epilog = arguments[ arguments.length - 3 ];
- if (! epilog) {
- var step;
- while( step = steps[ i++ ] ) {
- var aux = arguments; // this unmasks chef's arguments inside the next function
- if( aux[ j ] ) {
- var replacement = '';
- if( $.isFunction( step.replacement ) ) {
- var matches = []; //Array.slice.call( aux, j, step.length );
- for (var k = 0, kTop = step.length; k < kTop; k++) {
- matches.push( aux[ j + k ] );
- }
- matches.push( aux[ aux.length - 2 ] );
- matches.push( aux[ aux.length - 1 ] );
- replacement = step.replacement
- .apply( {
- x: function() {
- var subject = arguments[0];
- var module = arguments[1];
- var context = {
- recipe: step.recipe
- , blockName: step.blockName
- };
- return applyModule( subject, module, context );
- }
- }, matches );
- }
- else { //we expect step.replacement to be a string
- replacement = step.replacement
- .replace( /(\\\$)|(?:\$\$)|(?:\$(\d+))/g, function( m, escaped, K ) {
- if( escaped ) { /* \$ */
- return "$";
- }
- else if( !K ) { /* $$ */
- return filter( aux[ j ] );
- }
- else if( K == "0" ) { /* $0 */
- return step.stepName;
- }
- else { /* $K */
- return filter( aux[ j + parseInt( K, 10 ) ] );
- }
- } );
- }
- replacement = addPrefix( step.recipe._name, replacement );
- return filter( prolog ) + replacement;
- }
- else {
- j+= step.length;
- }
- }
- }
- else {
- return filter( epilog );
- }
- } // chef
- if( ! blockName ) {
- blockName = '_main';
- checkSpices( recipe );
- }
- if( ! (blockName in recipe) ) {
- return filter( ingredients );
- }
- var replaceSpace = book.replaceSpace;
- var steps = prepareBlock( recipe, blockName );
- var kh = knowHow( steps );
- var perfect = ingredients.replace( kh, function() {
- return chef.apply( { steps: steps }, arguments );
- } );
- return perfect;
- } // cook
- function loadStylesheetInline( sourceCode ) {
- if( document.createElement ) {
- var e = document.createElement( "style" );
- e.type = "text/css";
- if( e.styleSheet ) { // IE
- e.styleSheet.cssText = sourceCode;
- }
- else {
- var t = document.createTextNode( sourceCode );
- e.appendChild( t );
- }
- document.getElementsByTagName( "head" )[0].appendChild( e );
- }
- } // loadStylesheetInline
-
- function checkSpices( recipe ) {
- var name = recipe._name;
- if( ! book.queue[ name ] ) {
- var content = ['/* Chili -- ' + name + ' */'];
- for (var blockName in recipe) {
- if( blockName.search( /^_(?!main\b)/ ) < 0 ) {
- for (var stepName in recipe[ blockName ]) {
- var step = recipe[ blockName ][ stepName ];
- if( '_style' in step ) {
- if( step[ '_style' ].constructor == String ) {
- content.push( '.' + name + '__' + stepName + ' { ' + step[ '_style' ] + ' }' );
- }
- else {
- for (var className in step[ '_style' ]) {
- content.push( '.' + name + '__' + className + ' { ' + step[ '_style' ][ className ] + ' }' );
- }
- }
- }
- }
- }
- }
- content = content.join('\n');
- loadStylesheetInline( content );
- book.queue[ name ] = true;
- }
- } // checkSpices
- function askDish( el ) {
- var recipeName = book.codeLanguage( el );
- if( '' != recipeName ) {
- var path = getPath( recipeName );
- if( book.recipeLoading ) {
- /* dynamic setups come here */
- if( ! book.queue[ path ] ) {
- /* this is a new recipe to download */
- try {
- book.queue[ path ] = [ el ];
- $.getJSON( path, function( recipeLoaded ) {
- book.recipes[ path ] = recipeLoaded;
- var q = book.queue[ path ];
- for( var i = 0, iTop = q.length; i < iTop; i++ ) {
- makeDish( q[ i ], path );
- }
- } );
- }
- catch( recipeNotAvailable ) {
- alert( "the recipe for '" + recipeName + "' was not found in '" + path + "'" );
- }
- }
- else {
- /* not a new recipe, so just enqueue this element */
- book.queue[ path ].push( el );
- }
- /* a recipe could have been already downloaded */
- makeDish( el, path );
- }
- else {
- /* static setups come here */
- makeDish( el, path );
- }
- }
- } // askDish
- function makeDish( el, recipePath ) {
- var recipe = book.recipes[ recipePath ];
- if( ! recipe ) {
- return;
- }
- var $el = $( el );
- var ingredients = $el.text();
- if( ! ingredients ) {
- return;
- }
- //fix for msie: \r (13) is used instead of \n (10)
- //fix for opera: \r\n is used instead of \n
- ingredients = ingredients.replace(/\r\n?/g, "\n");
- //reverse fix for safari: msie, mozilla and opera render the initial \n
- if( $el.parent().is('pre') ) {
- if( ! $.browser.safari ) {
- ingredients = ingredients.replace(/^\n/g, "");
- }
- }
- var dish = cook( ingredients, recipe ); // all happens here
-
- if( book.replaceTab ) {
- dish = dish.replace( /\t/g, book.replaceTab );
- }
- if( book.replaceNewLine ) {
- dish = dish.replace( /\n/g, book.replaceNewLine );
- }
- el.innerHTML = dish; //much faster than $el.html( dish );
- //tried also the function replaceHtml from http://blog.stevenlevithan.com/archives/faster-than-innerhtml
- //but it was not faster nor without sideffects (it was not possible to count spans into el)
- //opera and safari select PRE text correctly
- if( $.browser.msie || $.browser.mozilla ) {
- enableSelectionHelper( el );
- }
- var $that = $el.parent();
- var classes = $that.attr( 'class' );
- var ln = /ln-(\d+)-([\w][\w\-]*)|ln-(\d+)|ln-/.exec( classes );
- if( ln ) {
- addLineNumbers( el );
- var start = 0;
- if( ln[1] ) {
- start = parseInt( ln[1], 10 );
- var $pieces = $( '.ln-' + ln[1] + '-' + ln[2] );
- var pos = $pieces.index( $that[0] );
- $pieces.slice( 0, pos ).each( function() {
- start += $( this ).find( 'li' ).length;
- } );
- }
- else if( ln[3] ) {
- start = parseInt( ln[3], 10 );
- }
- else {
- start = 1;
- }
- $el.find( 'ol' )[0].start = start;
- $('body').width( $('body').width() - 1 ).width( $('body').width() + 1 );
- }
- else if( book.lineNumbers ) {
- addLineNumbers( el );
- }
- } // makeDish
- function enableSelectionHelper( el ) {
- var element = null;
- $( el )
- .parents()
- .filter( "pre" )
- .bind( "mousedown", function() {
- element = this;
- if( $.browser.msie ) {
- document.selection.empty();
- }
- else {
- window.getSelection().removeAllRanges();
- }
- } )
- .bind( "mouseup", function( event ) {
- if( element && (element == this) ) {
- element = null;
- var selected = '';
- if( $.browser.msie ) {
- selected = document.selection.createRange().htmlText;
- if( '' == selected ) {
- return;
- }
- selected = preserveNewLines( selected );
- var container_tag = '<textarea style="STYLE">';
- }
- else {
- selected = window.getSelection().toString(); //opera doesn't select new lines
- if( '' == selected ) {
- return;
- }
- selected = selected
- .replace( /\r/g, '' )
- .replace( /^# ?/g, '' )
- .replace( /\n# ?/g, '\n' )
- ;
- var container_tag = '<pre style="STYLE">';
- }
- var $container = $( container_tag.replace( /\bSTYLE\b/, ChiliBook.selectionStyle ) )
- .appendTo( 'body' )
- .text( selected )
- .attr( 'id', 'chili_selection' )
- .click( function() { $(this).remove(); } )
- ;
- var top = event.pageY - Math.round( $container.height() / 2 ) + "px";
- var left = event.pageX - Math.round( $container.width() / 2 ) + "px";
- $container.css( { top: top, left: left } );
- if( $.browser.msie ) {
- // window.clipboardData.setData( 'Text', selected ); //I couldn't find anything similar for Mozilla
- $container[0].focus();
- $container[0].select();
- }
- else {
- var s = window.getSelection();
- s.removeAllRanges();
- var r = document.createRange();
- r.selectNodeContents( $container[0] );
- s.addRange( r );
- }
- }
- } )
- ;
- } // enableSelectionHelper
- function getPath( recipeName ) {
- return book.recipeFolder + recipeName + ".js";
- } // getPath
- function getSelectedText() {
- var text = '';
- if( $.browser.msie ) {
- text = document.selection.createRange().htmlText;
- }
- else {
- text = window.getSelection().toString();
- }
- return text;
- } // getSelectedText
- function preserveNewLines( html ) {
- do {
- var newline_flag = ChiliBook.unique();
- }
- while( html.indexOf( newline_flag ) > -1 );
- var text = '';
- if (/<br/i.test(html) || /<li/i.test(html)) {
- if (/<br/i.test(html)) {
- html = html.replace( /\<br[^>]*?\>/ig, newline_flag );
- }
- else if (/<li/i.test(html)) {
- html = html.replace( /<ol[^>]*?>|<\/ol>|<li[^>]*?>/ig, '' ).replace( /<\/li>/ig, newline_flag );
- }
- var el = $( '<pre>' ).appendTo( 'body' ).hide()[0];
- el.innerHTML = html;
- text = $( el ).text().replace( new RegExp( newline_flag, "g" ), '\r\n' );
- $( el ).remove();
- }
- return text;
- } // preserveNewLines
- function addLineNumbers( el ) {
- function makeListItem1( not_last_line, not_last, last, open ) {
- var close = open ? '</span>' : '';
- var aux = '';
- if( not_last_line ) {
- aux = '<li>' + open + not_last + close + '</li>';
- }
- else if( last ) {
- aux = '<li>' + open + last + close + '</li>';
- }
- return aux;
- } // makeListItem1
- function makeListItem2( not_last_line, not_last, last, prev_li ) {
- var aux = '';
- if( prev_li ) {
- aux = prev_li;
- }
- else {
- aux = makeListItem1( not_last_line, not_last, last, '' )
- }
- return aux;
- } // makeListItem2
- var html = $( el ).html();
- var br = /<br>/.test(html) ? '<br>' : '<BR>';
- var empty_line = '<li>' + book.replaceSpace + '</li>';
- var list_items = html
- //extract newlines at the beginning of a span
- .replace( /(<span [^>]+>)((?:(?: |\xA0)<br>)+)(.*?)(<\/span>)/ig, '$2$1$3$4' ) // I don't know why <span .*?> does not work here
- //transform newlines inside of a span
- .replace( /(.*?)(<span .*?>)(.*?)(?:<\/span>(?: |\xA0)<br>|<\/span>)/ig, // but here it does
- function( all, before, open, content ) {
- if (/<br>/i.test(content)) {
- var pieces = before.split( br );
- var lastPiece = pieces.pop();
- before = pieces.join( br );
- var aux = (before ? before + br : '') //+ replace1( lastPiece + content, open );
- + (lastPiece + content).replace( /((.*?)(?: |\xA0)<br>)|(.*)/ig,
- function( tmp, not_last_line, not_last, last ) {
- var aux2 = makeListItem1( not_last_line, not_last, last, open );
- return aux2;
- }
- );
- return aux;
- }
- else {
- return all;
- }
- }
- )
- //transform newlines outside of a span
- .replace( /(<li>.*?<\/li>)|((.*?)(?: |\xA0)<br>)|(.+)/ig,
- function( tmp, prev_li, not_last_line, not_last, last ) {
- var aux2 = makeListItem2( not_last_line, not_last, last, prev_li );
- return aux2;
- }
- )
- //fix empty lines for Opera
- .replace( /<li><\/li>/ig, empty_line )
- ;
- el.innerHTML = '<ol>' + list_items + '</ol>';
- } // addLineNumbers
- function revealChars( tmp ) {
- return $
- .map( tmp.split(''),
- function(n, i) {
- return ' ' + n + ' ' + n.charCodeAt( 0 ) + ' ';
- } )
- .join(' ');
- } // revealChars
- //-----------------------------------------------------------------------------
- // the coloring starts here
- this
- .each( function() {
- var $this = $( this );
- $this.trigger( 'chili.before_coloring' );
- askDish( this );
- $this.trigger( 'chili.after_coloring' );
- } );
- return this;
- //-----------------------------------------------------------------------------
- };
- //main
- $( function() {
- if( ChiliBook.automatic ) {
- $( ChiliBook.automaticSelector ).chili();
- }
- } );
- } ) ( jQuery );
- //YCODASLIDER DEMO BASIC SETTING
- ChiliBook.recipeFolder = "../../lib/chili/";
- ChiliBook
|