All Downloads are FREE. Search and download functionalities are using the official Maven repository.

portal.default.redbox.js.jquery-wikitext-0.3.js Maven / Gradle / Ivy

There is a newer version: 1.10.2
Show newest version
/*
 * Kajabity Wiki Text Plugin for jQuery http://www.kajabity.com/jquery-wikitext/
 * 
 * Copyright (c) 2011 Williams Technologies Limited
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 * 
 * Kajabity is a trademark of Williams Technologies Limited.
 * http://www.williams-technologies.co.uk
 */
/**
 * @fileOverview Kajabity Wiki Text Plugin for jQuery
 * @author Simon J. Williams
 * @version: 0.3
 */
(function( jQuery )
{
	/**
	 * jQuery definition to anchor JsDoc comments.
	 *  
	 * @see http://jquery.com/
	 * @name jQuery
	 * @class jQuery Library
	 */

	/**
	 * jQuery Utility Function to convert Wiki formatted text to HTML.
	 * 
	 * @namespace Kajabity Wiki Text
	 * @function
	 * @param {string} text the Wiki text to be converted to HTML.
	 * @return {string} HTML formatted text.
	 * @memberOf jQuery
	 */
	jQuery.wikiText = function( text )
	{
		// The source text with nulls/undefined taken care of.
		var source = (text || '').toString();
		// The resultant HTML string - initially empty.
		var html = '';

		// A regular expression to read the source one line at a time.
		var regex = /([^\r\n]*)(\r\n?|\n)/g;
		var lineMatches;
		var offset = 0;
		var line;

		// Regular expressions to match each kind of line level format mark-up.
		var re_blank = /^([ \t]*)$/;
		var re_heading = /^(={1,6})[ \t]+([^=]+)(={1,6})[ \t]*$/;
		var re_bullet = /^[ \t]+\*[ \t]+(.+)$/;
		var re_numbered = /^[ \t]+#[ \t]+(.+)$/;
		var re_mono_start = /^\{{3}$/;
		var re_mono_end = /^\}{3}$/;
		var re_blockquote = /^[ \t]+(.+)$/;
		var re_hr = /^-{4,}$/;
		var matches;

		// Flags indicating which kind of block we are currently in.
		var paragraph = false;
		var olist = false;
		var ulist = false;
		var bq = false;
		var mono = false;

		// Regular expression to find mark-up tokens in each line.
		var regexToken = /(((ftp|https?):\/\/)[\-\w@:%_\+.~#?,&\/\/=]+)|((mailto:)?[_.\w-]+@([\w][\w\-]+\.)+[a-zA-Z]{2,3})|(!+\[)|(!*((_{2})|(\{{3})|(\}{3})|(~{2})|(\^)|(,{2})|('{2,5}))|(\[{1,2}[^\]]+\]{1,2}))/g;

		// Individual mark-up regular expressions - also see the public ones
		// near the bottom of the file.
		var re_named_link = /^\[((((ftp|https?):\/\/)?[\-\w@:%_\+.~#?,&\/\/=]+)|((mailto:)?([_.\w\-]+@([\w][\w\-]+\.)+[a-zA-Z]{2,3})))([ \t]*([^\]]*))?\]$/;
		var tn_monospace = "{{{";
		var tn_monospace_end = "}}}";
		var tn_bolditalic = "'''''";
		var tn_bold = "'''";
		var tn_italic = "''";
		var tn_superscript = "^";
		var tn_subscript = ",,";
		var tn_underline = "__";
		var tn_strikethrough = "~~";
		var tn_break = "[[BR]]";
		var monospace = false;

		// Keep track of inline format nesting.
		var tagStack = [];
		var poppedStack = [];

		// Inline formatting start tags.
		var beginings =
		{
			bold : "",
			italic : "",
			monospace : "",
			underline : "",
			strikethrough : "",
			superscript : "",
			subscript : ""
		};

		// ...and end tags.
		var endings =
		{
			bold : "",
			italic : "",
			monospace : "",
			underline : "",
			strikethrough : "",
			superscript : "",
			subscript : ""
		};

		/**
		 * Remove inline formatting at end of a block. Puts it on the
		 * poppedStack to add at the start of the next block.
		 * 
		 * @return {string} end tags for any current inline formatting.
		 */
		var endFormatting = function()
		{
			var tags = '';
			var popped;
			while( tagStack.length > 0 )
			{
				popped = tagStack.pop();
				tags += endings[popped];
				poppedStack.push( popped );
			}
			return tags;
		};

		/**
		 * End the current block and, temporarily, any nested inline formatting,
		 * if any.
		 * 
		 * @return {string} the block (and inline formatting) HTML end tags.
		 */
		var endBlock = function()
		{
			html += endFormatting();

			if( paragraph )
			{
				html += "\n";
				paragraph = false;
			}
			if( olist )
			{
				html += "\n\n";
				olist = false;
			}
			if( ulist )
			{
				html += "\n\n";
				ulist = false;
			}
			if( bq )
			{
				html += "\n";
				bq = false;
			}
		};

		/**
		 * Re-add nested formatting removed at the end of the previous block.
		 * 
		 * @return {string} HTML start tags for all continued formatting.
		 */
		var restartFormatting = function()
		{
			var tags = '';
			while( poppedStack.length > 0 )
			{
				var popped = poppedStack.pop();
				tags += beginings[popped];
				tagStack.push( popped );
			}
			return tags;
		};

		/**
		 * As most inline format tags are the same at the start or end, this
		 * toggles the formatting on or off depending if it is currently in the
		 * tagStack.
		 * 
		 * @param {string} label the name of the format to toggle.
		 * @return {string} any HTML start or end tags to toggle the formatting
		 *         with proper nesting.
		 */
		var toggleFormatting = function( label )
		{
			var tags = '';
			if( jQuery.inArray( label, tagStack ) > -1 )
			{
				var popped;
				do
				{
					popped = tagStack.pop();
					tags += endings[popped];
					if( popped === label )
					{
						break;
					}
					poppedStack.push( popped );
				} while( popped !== label );

				tags += restartFormatting();
			}
			else
			{
				tagStack.push( label );
				tags = beginings[label];
			}

			return tags;
		};

		/**
		 * Apply inline formatting to text in a line - and escape any HTML
		 * mark-up tags.
		 * 
		 * @param {string} text the plain text to be formatted and escaped.
		 * @return {string} HTML formatted text.
		 */
		var formatText = function( text )
		{
			var sourceToken = (text || '').toString();
			var formattedText = '';
			var token;
			var offset = 0;
			var tokenArray;
			var linkText;
			var nl_tokenArray;

			// Iterate through any mark-up tokens in the line.
			while( (tokenArray = regexToken.exec( sourceToken )) !== null )
			{
				token = tokenArray[0];
				if( offset < tokenArray.index )
				{
					// Add non-mark-up text.
					formattedText += jQuery.wikiText.safeText( sourceToken
							.substring( offset, tokenArray.index ) );
				}

				if( monospace )
				{
					// Ignore mark-up until end of monospace.
					if( tn_monospace_end === token )
					{
						monospace = false;
						formattedText += toggleFormatting( "monospace" );
					}
					else
					{
						formattedText += jQuery.wikiText.safeText( token );
					}
				}
				else if( tn_monospace === token )
				{
					monospace = true;
					formattedText += toggleFormatting( "monospace" );
				}
				else if( jQuery.wikiText.re_link.test( token ) )
				{
					formattedText += jQuery.wikiText.namedLink( token );
				}
				else if( jQuery.wikiText.re_mail.test( token ) )
				{
					formattedText += jQuery.wikiText.namedLink( token );
				}
				else if( tn_bold === token )
				{
					formattedText += toggleFormatting( "bold" );
				}
				else if( tn_italic === token )
				{
					formattedText += toggleFormatting( "italic" );
				}
				else if( tn_bolditalic === token )
				{
					// Avoid empty tag if nesting is wrong way around.
					if( jQuery.inArray( "bold", tagStack ) > jQuery.inArray(
							"italic", tagStack ) )
					{
						formattedText += toggleFormatting( "bold" );
						formattedText += toggleFormatting( "italic" );
					}
					else
					{
						formattedText += toggleFormatting( "italic" );
						formattedText += toggleFormatting( "bold" );
					}
				}
				else if( tn_superscript === token )
				{
					formattedText += toggleFormatting( "superscript" );
				}
				else if( tn_subscript === token )
				{
					formattedText += toggleFormatting( "subscript" );
				}
				else if( tn_underline === token )
				{
					formattedText += toggleFormatting( "underline" );
				}
				else if( tn_strikethrough === token )
				{
					formattedText += toggleFormatting( "strikethrough" );
				}
				else if( tn_break === token )
				{
					formattedText += "
"; } else if( (nl_tokenArray = re_named_link.exec( token )) !== null ) { formattedText += jQuery.wikiText.namedLink( nl_tokenArray[1], nl_tokenArray[10] ); } else if( token[0] === "!" ) { formattedText += jQuery.wikiText.safeText( token .substring( 1 ) ); } else { formattedText += jQuery.wikiText.safeText( token ); } offset = regexToken.lastIndex; } if( offset < sourceToken.length ) { // Add trailing non-mark-up text. formattedText += jQuery.wikiText.safeText( sourceToken .substring( offset ) ); } return formattedText; }; /** * Get a single line from the input. This resolves the issue where the * last line is not returned because it doesn't end with CR/LF. * * @return {string} a single line of input - or null at end of string. */ var getLine = function() { if( offset < source.length ) { lineMatches = regex.exec( source ); if( lineMatches != null ) { offset = regex.lastIndex; line = lineMatches[1]; } else { line = source.substring( offset ); offset = source.length; } } else { line = null; } return line; }; // -------------------------------------------------------------------- while( getLine() != null ) { if( mono ) { if( line.match( re_mono_end ) ) { mono = false; html += "
\n"; } else { html += jQuery.wikiText.safeText( line ) + "\n"; } } else if( line.length === 0 || re_blank.test( line ) ) { endBlock(); } else if( (matches = line.match( re_heading )) !== null ) { endBlock(); var headingLevel = matches[1].length; html += "\n" + restartFormatting() + formatText( matches[2] ) + endFormatting() + "\n\n"; } else if( (matches = line.match( re_bullet )) !== null ) { if( ulist ) { html += endFormatting() + "\n"; } else { endBlock(); html += "


© 2015 - 2024 Weber Informatics LLC | Privacy Policy