Text Header with CSS class: hn(class). Paragraphs beginning with 'hn(class). ' receive a CSS class attribute. Example:

Text

Paragraph: p. (applied by default) Paragraphs beginning with 'p. ' are wrapped in paragraph tags. Example:

Text

Paragraph with CSS class: p(class). Paragraphs beginning with 'p(class). ' receive a CSS class attribute. Example:

Text

Blockquote: bq. Paragraphs beginning with 'bq. ' are wrapped in block quote tags. Example:
Text
Blockquote with citation: bq(citeurl). Paragraphs beginning with 'bq(citeurl). ' receive a citation attribute. Example:
Text
Numeric list: # Consecutive paragraphs beginning with # are wrapped in ordered list tags. Example:
  1. ordered list
Bulleted list: * Consecutive paragraphs beginning with * are wrapped in unordered list tags. Example: Phrase modifier syntax: _emphasis_ emphasis __italic__ italic *strong* strong **bold** bold ??citation?? citation -deleted text- deleted +inserted text+ inserted ^superscript^ superscript ~subscript~ subscript @code@ computer code ==notextile== leave text alone (do not format) "linktext":url linktext "linktext(title)":url linktext !imageurl! !imageurl(alt text)! alt text !imageurl!:linkurl ABC(Always Be Closing) ABC */ function textile($text) { ### Basic global changes $text = stripslashes($text); # turn any incoming ampersands into a dummy character for now. # This uses a negative lookahead for alphanumerics followed by a semicolon, # implying an incoming html entity, to be skipped $text = preg_replace("/&(?![#a-zA-Z0-9]+;)/","x%x%",$text); # entify everything if (function_exists('mb_encode_numericentity')) { $text = encode_high($text); } else { $text = htmlentities($text,ENT_NOQUOTES,"utf-8"); } # unentify angle brackets and ampersands $text = str_replace(array(">", "<", "&"), array(">", "<", "&"), $text); # zap carriage returns $text = str_replace("\r\n", "\n", $text); # zap tabs $text = str_replace("\t", "", $text); $text = preg_split("/\n/",$text); foreach($text as $line){ $line = trim($line); $lineout[] = $line; } $text = implode("\n",$lineout); ### Find and replace quick tags # double equal signs means $text = preg_replace('/(^|\s)==(.*)==(\s|$)?/msU','$1$2$3',$text); # image qtag $text = preg_replace('/!([^\s\(=]+)\s?(?:\(([^\)]+)\))?!(\s)?/mU','$2$3',$text); # image with hyperlink $text = preg_replace('/():(\S+)(\s)/U','$1$3',$text); # hyperlink qtag $text = preg_replace( '/ ([\s[{(]|[[:punct:]])? # 1 optional space or brackets before " # starting " ([^"\(]+) # 2 text of link \s? # opt space (?:\(([^\(]*)\))? # 3 opt title attribute in parenths ": # dividing ": (\S+\b) # 4 suppose this is the url (\/)? # 5 opt trailing slash ([^[:alnum:]\/;]*) # 6 opt punctuation after the url (\s|$) # 7 either white space or end of string /x', '$1$2$6$7',$text); # arrange qtag delineators and replacements in an array $qtags = array( '\*\*'=>'b', '\*'=>'strong', '\?\?'=>'cite', '-'=>'del', '\+'=>'ins', '~'=>'sub', '@'=>'code'); # loop through the array, replacing qtags with html foreach($qtags as $f=>$r){ $text = preg_replace( '/(^|\s|>)'.$f.'\b(.+)\b([[:punct:]]*)'.$f.'([[:punct:]]{0,2})(\s|$)?/mU', '$1<'.$r.'>$2$3$4$5', $text); } # some weird bs with underscores and \b word boundaries, # so we'll do those on their own $text = preg_replace('/(^|\s)__(.*)__([[:punct:]]{0,2})(\s|$)?/mU','$1$2$3$4',$text); $text = preg_replace('/(^|\s)_(.*)_([[:punct:]]{0,2})(\s|$)?/mU','$1$2$3$4',$text); $text = preg_replace('/\^(.*)\^/mU','$1',$text); ### Find and replace typographic chars and special tags # small problem with double quotes at the end of a string $text = preg_replace('/"$/',"\" ", $text); # NB: all these will wreak havoc inside tags $glyph_search = array( '/([^\s[{(>])?\'(?(1)|(?=\s|s\b))/', # single closing '/\'/', # single opening '/([^\s[{(])?"(?(1)|(?=\s))/', # double closing '/"/', # double opening '/\b( )?\.{3}/', # ellipsis '/\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])/', # 3+ uppercase acronym '/(^|[^"][>\s])([A-Z][A-Z0-9 ]{2,})([^$1', # 3+ uppercase acronym '$1$2$3', # 3+ uppercase caps '—', # em dash ' – ', # en dash '$1×$2', # dimension sign '™', # trademark '®', # registered '©'); # copyright # set toggle for turning off replacements between or
	$codepre = false;

		# if there is no html, do a simple search and replace
	if(!preg_match("/<.*>/",$text)){
		$text = preg_replace($glyph_search,$glyph_replace,$text);
	} else {
	
			# else split the text into an array at <.*>
		$text = preg_split("/(<.*>)/U",$text,-1,PREG_SPLIT_DELIM_CAPTURE);
			foreach($text as $line){
			
					# matches are off if we're between , 
 etc. 
				if(preg_match('/<(code|pre|kbd|notextile)>/i',$line)){$codepre = true; }
				if(preg_match('/<\/(code|pre|kbd|notextile)>/i',$line)){$codepre = false; }
			
				if(!preg_match("/<.*>/",$line) && $codepre == false){
					$line = preg_replace($glyph_search,$glyph_replace,$line);
				}

				# convert htmlspecial if between 
				if ($codepre == true){
					$line = htmlspecialchars($line,ENT_NOQUOTES,"UTF-8");
					$line = str_replace("<pre>","
",$line);
					$line = str_replace("<code>","",$line);
					$line = str_replace("<notextile>","",$line);
					$line = str_replace("<kbd>","",$line);
				}

				# each line gets pushed to a new array
			$glyph_out[] = $line;
		}
			# $text is now the new array, cast to a string 
		$text = implode('',$glyph_out);
	}

	
### Block level formatting

	# deal with forced breaks; this is going to be a problem between
	#  
 tags, but we'll clean them later
	$text = preg_replace("/(\S)(_*)([[:punct:]]*) *\n([^#*\s])/", "$1$2$3
$4", $text); # might be a problem with lists $text = str_replace("l>
", "l>\n", $text); # clear out multiple newlines for now # $text = preg_replace("/\n+/","\n",$text); # split the text into an array by newlines $text = preg_split("/\n/",$text); array_push($text," "); $list = ''; $pre = false; $block_find = array( '/^\s?\*\s(.*)/', # bulleted list * '/^\s?#\s(.*)/', # numeric list # '/^bq\. (.*)/', # blockquote bq. '/^h(\d)\(([[:alnum:]]+)\)\.\s(.*)/', # header hn(class). w/ css class '/^h(\d)\. (.*)/', # plain header hn. '/^p\(([[:alnum:]]+)\)\.\s(.*)/', # para p(class). w/ css class '/^p\. (.*)/i', # plain paragraph '/^([^\t ]+.*)/i' # remaining plain paragraph ); $block_replace = array( "\t\t
  • $1
  • ", "\t\t\t
  • $1
  • ", "\t
    $1
    ", "\t$3$4", "\t$2$3", "\t

    $2

    $3", "\t

    $1

    ", "\t

    $1

    $2" ); # loop through lines foreach($text as $line){ # matches are off if we're between
     or  tags 
    			if(preg_match('/
    /i',$line)){$pre = true; }
    
    			# deal with block replacements first, then see if we're in a list
    			if ($pre == false){
    				$line = preg_replace($block_find,$block_replace,$line);
    			}
    
    			# kill any br tags that slipped in earlier
    			if ($pre == true){
    				$line = str_replace("
    ","\n",$line); } # matches back on after
    if(preg_match('/<\/pre>/i',$line)){$pre = false; } # on entry to a list, $list switches to a value # two tabs means unordered list if ($list == '' && preg_match('/^\t\t
  • /',$line)){ $list = "ul"; $line = preg_replace('/^(\t\t
  • .*)/',"\t
      \n$1",$line); } else if ($list == '' && preg_match('/^\t\t\t
    • /',$line)){ $list = "ol"; $line = preg_replace('/^\t(\t\t
    • .*)/',"\t
        \n$1",$line); # at the end of a ul } else if ($list == 'ul' && !preg_match('/^\t\t
      1. /',$line)){ $list = ''; $line = preg_replace('/^(.*)$/',"\t
    \n$1",$line); # at the end of a ol } else if ($list == 'ol' && !preg_match('/^\t\t\t
  • /',$line)){ $list = ''; $line = preg_replace('/^(.*)$/',"\t\n$1",$line); } # push each line to a new array once processed $block_out[] = $line; } $text = implode("\n",$block_out); #clean up $text = preg_replace('/<\/?notextile>/', "",$text); # turn the temp char back to an ampersand entity $text = str_replace("x%x%","&",$text); # Newline linebreaks, just for markup tidiness $text = str_replace("
    ","
    \n",$text); return $text; } function callback_url($text,$title='',$url) { $out = 'a href="'.$url.'"'; $out.=($title!='')?' title="'.$title.'"':''; $out.='>$text'; return $out; } function textile_popup_help($name,$helpvar,$windowW,$windowH) { $out = $name; $out .= ' ?
    '; print $out; } function encode_high($text) { $cmap = cmap(); return mb_encode_numericentity($text, $cmap, "UTF-8"); } function decode_high($text) { $cmap = cmap(); return mb_decode_numericentity($text, $cmap, "UTF-8"); } function cmap() { $f = 0xffff; $cmap = array( 160, 255, 0, $f, 402, 402, 0, $f, 913, 929, 0, $f, 931, 937, 0, $f, 945, 969, 0, $f, 977, 978, 0, $f, 982, 982, 0, $f, 8226, 8226, 0, $f, 8230, 8230, 0, $f, 8242, 8243, 0, $f, 8254, 8254, 0, $f, 8260, 8260, 0, $f, 8465, 8465, 0, $f, 8472, 8472, 0, $f, 8476, 8476, 0, $f, 8482, 8482, 0, $f, 8501, 8501, 0, $f, 8592, 8596, 0, $f, 8629, 8629, 0, $f, 8656, 8660, 0, $f, 8704, 8704, 0, $f, 8706, 8707, 0, $f, 8709, 8709, 0, $f, 8711, 8713, 0, $f, 8715, 8715, 0, $f, 8719, 8719, 0, $f, 8721, 8722, 0, $f, 8727, 8727, 0, $f, 8730, 8730, 0, $f, 8733, 8734, 0, $f, 8736, 8736, 0, $f, 8743, 8747, 0, $f, 8756, 8756, 0, $f, 8764, 8764, 0, $f, 8773, 8773, 0, $f, 8776, 8776, 0, $f, 8800, 8801, 0, $f, 8804, 8805, 0, $f, 8834, 8836, 0, $f, 8838, 8839, 0, $f, 8853, 8853, 0, $f, 8855, 8855, 0, $f, 8869, 8869, 0, $f, 8901, 8901, 0, $f, 8968, 8971, 0, $f, 9001, 9002, 0, $f, 9674, 9674, 0, $f, 9824, 9824, 0, $f, 9827, 9827, 0, $f, 9829, 9830, 0, $f, 338, 339, 0, $f, 352, 353, 0, $f, 376, 376, 0, $f, 710, 710, 0, $f, 732, 732, 0, $f, 8194, 8195, 0, $f, 8201, 8201, 0, $f, 8204, 8207, 0, $f, 8211, 8212, 0, $f, 8216, 8218, 0, $f, 8218, 8218, 0, $f, 8220, 8222, 0, $f, 8224, 8225, 0, $f, 8240, 8240, 0, $f, 8249, 8250, 0, $f, 8364, 8364, 0, $f ); return $cmap; } function linkit($text,$title,$url){ $url = preg_replace("/&(?!amp;)/","&",$url); $out = ''; return $out; } ?>