Text
Blockquote: bq. Example: bq. Block quotation... ->Block quotation...Blockquote with citation: bq.:http://citation.url Example: bq.:http://textism.com/ Text... ->
Text...Footnote: fn(1-100). Example: fn1. Footnote... ->
Footnote...
Numeric list: #, ## Consecutive paragraphs beginning with # are wrapped in ordered list tags. Example:computer code
%(bob)span% -> span
==notextile== -> leave text alone (do not format)
"linktext":url -> linktext
"linktext(title)":url -> linktext
!imageurl! -> paragraph
p(#fluid). paragraph ->paragraph
(classes and ids can be combined) p(hector#fluid). paragraph ->paragraph
Curly {brackets} insert arbitrary css style p{line-height:18px}. paragraph ->paragraph
h3{color:red}. header 3 ->paragraph
%[fr]phrase% -> phrase Usually Textile block element syntax requires a dot and space before the block begins, but since lists don't, they can be styled just using braces #{color:blue} one ->/i',$line)) { $pre = true; }
foreach($find as $tag){
$line = ($pre==false)
? preg_replace_callback("/^($tag)($textile_a$textile_c)\.(?::(\S+))? (.*)$/",
"textile_fBlock",$line)
: $line;
}
$line = preg_replace('/^(?!\t|<\/?pre|<\/?code|$| )(.*)/',"\t$1
",$line);
$line=($pre==true) ? str_replace("
","\n",$line):$line;
if (preg_match('/<\/pre>/i',$line)) { $pre = false; }
$out[] = $line;
}
return join("\n",$out);
}
// -------------------------------------------------------------
function textile_fBlock($m)
{
# dump($m);
list(,$tag,$textile_atts,$textile_cite,$textile_content) = $m;
$textile_atts = textile_pba($textile_atts);
if(preg_match("/fn(\d+)/",$tag,$fns)){
$tag = 'p';
$textile_atts.= ' id="fn'.$fns[1].'"';
$textile_content = ''.$fns[1].' '.$textile_content;
}
$textile_start = "\t<$tag";
$end = "$tag>";
if ($tag=="bq") {
$textile_cite = textile_checkRefs($textile_cite);
$textile_cite = ($textile_cite!='') ? ' cite="'.$textile_cite.'"' : '';
$textile_start = "\t\n\t\t\n\t
";
}
return "$textile_start$textile_atts>$textile_content$end";
}
// -------------------------------------------------------------
function textile_span($text)
{
global $textile_c,$textile_pnct;
$qtags = array('\*\*','\*','\?\?','-','__','_','%','\+','~');
foreach($qtags as $f) {
$text = preg_replace_callback(
"/(?<=^|\s|\>|[[:punct:]]|[{(\[])
($f)
($textile_c)
(?::(\S+))?
(\w.+\w)
([[:punct:]]*)
$f
(?=[])}]|[[:punct:]]+|\s|$)
/xmU","textile_fSpan",$text);
}
return $text;
}
// -------------------------------------------------------------
function textile_fSpan($m)
{
# dump($m);
global $textile_c;
$qtags = array(
'*' => 'b',
'**' => 'strong',
'??' => 'cite',
'_' => 'em',
'__' => 'i',
'-' => 'del',
'%' => 'span',
'+' => 'ins',
'~' => 'sub');
list(,$tag,$textile_atts,$textile_cite,$textile_content,$end) = $m;
$tag = $qtags[$tag];
$textile_atts = textile_pba($textile_atts);
$textile_atts.= ($textile_cite!='') ? 'cite="'.$textile_cite.'"' : '';
return "<$tag$textile_atts>$textile_content$end$tag>";
}
// -------------------------------------------------------------
function textile_links($text)
{
global $textile_c;
return preg_replace_callback('/
([\s[{(]|[[:punct:]])? # $pre
("|") # start
('.$textile_c.') # $textile_atts
([^"]+) # $text
\s?
(?:\(([^)]+)\)(?="))? # $title
("|"):
(\S+\b) # $url
(\/)? # $textile_slash
([^\w\/;]*) # $post
(?=\s|$)
/Ux',"textile_fLink",$text);
}
// -------------------------------------------------------------
function textile_fLink($m)
{
list(,$pre,$textile_atts,$text,$title,$url,$textile_slash,$post) = $m;
$url = textile_checkRefs($url);
$textile_atts = textile_pba($textile_atts);
$textile_atts.= ($title!='') ? ' title="'.$title.'"' : '';
$textile_atts = ($textile_atts!='') ? textile_shelve($textile_atts) : '';
if ($text=='_') {
$text = $url;
}
if (preg_match('/^http(s?):\/\//i', $url)) {
$textile_atts.=' class="external"';
}
return $pre.''.$text.''.$post;
}
// -------------------------------------------------------------
function textile_getRefs($text)
{
return preg_replace_callback("/(?<=^|\s)\[(.+)\]((?:http:\/\/|\/)\S+)(?=\s|$)/U",
"textile_refs",$text);
}
// -------------------------------------------------------------
function textile_refs($m)
{
list(,$flag,$url) = $m;
$GLOBALS['urlrefs'][$flag] = $url;
return '';
}
// -------------------------------------------------------------
function textile_checkRefs($text)
{
global $urlrefs;
return (isset($urlrefs[$text])) ? $urlrefs[$text] : $text;
}
// -------------------------------------------------------------
function textile_image($text)
{
global $textile_c;
return preg_replace_callback("/
\! # opening
(\<|\=|\>)? # optional alignment atts
($textile_c) # optional style,class atts
(?:\. )? # optional dot-space
([^\s(!]+) # presume this is the src
\s? # optional space
(?:\(([^\)]+)\))? # optional title
\! # closing
(?::(\S+))? # optional href
(?=\s|$) # lookahead: space or end of string
/Ux","textile_fImage",$text);
}
// -------------------------------------------------------------
function textile_fImage($m)
{
list(,$textile_algn,$textile_atts,$url) = $m;
$textile_atts = textile_pba($textile_atts);
$textile_atts.= ($textile_algn!='') ? ' align="'.textile_iAlign($textile_algn).'"' : '';
$textile_atts.= (isset($m[4])) ? ' title="'.$m[4].'"' : '';
$textile_size = @getimagesize($url);
if($textile_size) $textile_atts.= " $textile_size[3]";
$href = (isset($m[5])) ? textile_checkRefs($m[5]) : '';
$url = textile_checkRefs($url);
$out = '';
$out.= ($href!='') ? '' : '';
$out.= '
';
$out.= ($href!='') ? '' : '';
return $out;
}
// -------------------------------------------------------------
function textile_code($text)
{
global $textile_pnct;
return preg_replace_callback("/
(?:^|(?<=[\s\(])|([[{])) # 1 open bracket?
@ # opening
(?:\|(\w+)\|)? # 2 language
(.+) # 3 code
@ # closing
(?:$|([\]}])|
(?=[[:punct:]]{1,2}|
\s)) # 4 closing bracket?
/Ux","textile_fCode",$text);
}
// -------------------------------------------------------------
function textile_fCode($m)
{
list(,$before,$lang,$textile_code,$textile_after) = $m;
$lang = ($lang!='') ? ' language="'.$lang.'"' : '';
return $before.''.$textile_code.''.$textile_after;
}
// -------------------------------------------------------------
function textile_shelve($val)
{
$GLOBALS['shelf'][] = $val;
return ' <'.count($GLOBALS['shelf']).'>';
}
// -------------------------------------------------------------
function textile_retrieve($text)
{
global $textile_shelf;
$i = 0;
if(is_array($textile_shelf)) {
foreach($textile_shelf as $r){
$i++;
$text = str_replace("<$i>",$r,$text);
}
}
return $text;
}
// -------------------------------------------------------------
function textile_incomingEntities($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 */
return preg_replace("/&(?![#a-z0-9]+;)/i","x%x%",$text);
}
// -------------------------------------------------------------
function textile_encodeEntities($text)
{
/* Convert high and low ascii to entities. If multibyte string functions are
available (on by default in php 4.3+), we convert using unicode mapping as
defined in the function encode_high(). If not, we use php's nasty
built-in htmlentities() */
return (function_exists('mb_encode_numericentity'))
? textile_encode_high($text)
: htmlentities($text,ENT_NOQUOTES,"utf-8");
}
// -------------------------------------------------------------
function textile_fixEntities($text)
{
/* de-entify any remaining angle brackets or ampersands */
return str_replace(array(">", "<", "&"),
array(">", "<", "&"), $text);
}
// -------------------------------------------------------------
function textile_cleanWhiteSpace($text)
{
$out = str_replace(array("\r\n","\t"), array("\n",''), $text);
$out = preg_replace("/\n{3,}/","\n\n",$out);
$out = preg_replace("/\n *\n/","\n\n",$out);
$out = preg_replace('/"$/',"\" ", $out);
return $out;
}
// -------------------------------------------------------------
function textile_noTextile($text)
{
return preg_replace('/(^|\s)==(.*)==(\s|$)?/msU',
'$1$2 $3',$text);
}
// -------------------------------------------------------------
function textile_superscript($text)
{
return preg_replace('/\^(.*)\^/mU','$1',$text);
}
// -------------------------------------------------------------
function textile_footnoteRef($text)
{
return preg_replace('/\b\[([0-9]+)\](\s)?/U',
'$1$2',$text);
}
// -------------------------------------------------------------
function textile_glyphs($text)
{
// fix: hackish
$text = preg_replace('/"\z/',"\" ", $text);
$glyph_search = array(
'/([^\s[{(>])?\'(?(1)|(?=\s|s\b|[[:punct:]]))/', // single closing
'/\'/', // single opening
'/([^\s[{(>])?"(?(1)|(?=\s|[[:punct:]]))/', // 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
$textile_codepre = false;
/* if no html, do a simple search and replace... */
if (!preg_match("/<.*>/",$text)) {
$text = preg_replace($glyph_search,$glyph_replace,$text);
return $text;
} else {
$text = preg_split("/(<.*>)/U",$text,-1,PREG_SPLIT_DELIM_CAPTURE);
foreach($text as $line) {
$offtags = ('code|pre|kbd|notextile');
/* matches are off if we're between , etc. */
if (preg_match('/<('.$offtags.')>/i',$line)) $textile_codepre = true;
if (preg_match('/<\/('.$offtags.')>/i',$line)) $textile_codepre = false;
if (!preg_match("/<.*>/",$line) && $textile_codepre == false) {
$line = preg_replace($glyph_search,$glyph_replace,$line);
}
/* do htmlspecial if between */
if ($textile_codepre == true) {
$line = htmlspecialchars($line,ENT_NOQUOTES,"UTF-8");
$line = preg_replace('/<(\/?'.$offtags.')>/',"<$1>",$line);
}
$glyph_out[] = $line;
}
return join('',$glyph_out);
}
}
// -------------------------------------------------------------
function textile_iAlign($in)
{
$vals = array(
'<'=>'left',
'='=>'center',
'>'=>'right');
return (isset($vals[$in])) ? $vals[$in] : '';
}
// -------------------------------------------------------------
function textile_hAlign($in)
{
$vals = array(
'<'=>'left',
'='=>'center',
'>'=>'right',
'<>'=>'justify');
return (isset($vals[$in])) ? $vals[$in] : '';
}
// -------------------------------------------------------------
function textile_vAlign($in)
{
$vals = array(
'^'=>'top',
'-'=>'middle',
'~'=>'bottom');
return (isset($vals[$in])) ? $vals[$in] : '';
}
// -------------------------------------------------------------
function textile_encode_high($text,$textile_charset="UTF-8")
{
$textile_cmap = textile_cmap();
return mb_encode_numericentity($text, $textile_cmap, $textile_charset);
}
// -------------------------------------------------------------
function textile_decode_high($text,$textile_charset="UTF-8")
{
$textile_cmap = textile_cmap();
return mb_decode_numericentity($text, $textile_cmap, $textile_charset);
}
// -------------------------------------------------------------
function textile_cmap()
{
$f = 0xffff;
$textile_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 $textile_cmap;
}
// -------------------------------------------------------------
function textile_popup_help($name,$helpvar,$windowW,$windowH) {
return ' '.$name.'
';
}
// -------------------------------------------------------------
function textile_txtgps($thing)
{
if (isset($_POST[$thing])){
if (get_magic_quotes_gpc()==1){
return stripslashes($_POST[$thing]);
} else {
return $_POST[$thing];
}
} else {
return '';
}
}
// -------------------------------------------------------------
// The following functions are used to detextile html, a process
// still in development.
// -------------------------------------------------------------
function textile_detextile($text) {
$text = preg_replace("/
\s*/","\n",$text);
$oktags = array('p','ol','ul','li','i','b','em','strong','span','a','h[1-6]',
'table','tr','td','u','del','sup','sub','blockquote');
foreach($oktags as $tag){
$text = preg_replace_callback("/\t*<(".$tag.")\s*([^>]*)>(.*)<\/\\1>/Usi",
"textile_processTag",$text);
}
$glyphs = array(
'’'=>'\'', # single closing
'‘'=>'\'', # single opening
'”'=>'"', # double closing
'“'=>'"', # double opening
'—'=>'--', # em dash
'–'=>' - ', # en dash
'×' =>'x', # dimension sign
'™'=>'(TM)', # trademark
'®' =>'(R)', # registered
'©' =>'(C)', # copyright
'…'=>'...' # ellipsis
);
foreach($glyphs as $f=>$r){
$text = str_replace($f,$r,$text);
}
$list = false;
$text = preg_split("/(<.*>)/U",$text,-1,PREG_SPLIT_DELIM_CAPTURE);
foreach($text as $line){
if ($list == false && preg_match('//U','# ', $line);
} else if ($list == 'u'){
$line = preg_replace('//U','* ', $line);
}
$glyph_out[] = $line;
}
$text = implode('',$glyph_out);
$text = preg_replace('/^\t* *p\. /m','',$text);
return textile_decode_high($text);
}
// -------------------------------------------------------------
function textile_processTag($matches)
{
list($textile_all,$tag,$textile_atts,$textile_content) = $matches;
$textile_a = textile_splat($textile_atts);
# dump($tag); dump($textile_content); dump($textile_a);
$phr = array(
'em'=>'_',
'i'=>'__',
'b'=>'**',
'strong'=>'*',
'cite'=>'??',
'del'=>'-',
'ins'=>'+',
'sup'=>'^',
'sub'=>'~',
'span'=>'%');
$blk = array('p','h1','h2','h3','h4','h5','h6');
if(isset($phr[$tag])) {
return $phr[$tag].textile_sci($textile_a).$textile_content.$phr[$tag];
} elseif($tag=='blockquote') {
return 'bq.'.textile_sci($textile_a).' '.$textile_content;
} elseif(in_array($tag,$blk)) {
return $tag.textile_sci($textile_a).'. '.$textile_content;
} elseif ($tag=='a') {
$t = textile_filterAtts($textile_a,array('href','title'));
$out = '"'.$textile_content;
$out.= (isset($t['title'])) ? ' ('.$t['title'].')' : '';
$out.= '":'.$t['href'];
return $out;
} else {
return $textile_all;
}
}
// -------------------------------------------------------------
function textile_filterAtts($textile_atts,$ok)
{
foreach($textile_atts as $textile_a) {
if(in_array($textile_a['name'],$ok)) {
if($textile_a['att']!='') {
$out[$textile_a['name']] = $textile_a['att'];
}
}
}
# dump($out);
return $out;
}
// -------------------------------------------------------------
function textile_sci($textile_a)
{
$out = '';
foreach($textile_a as $t){
$out.= ($t['name']=='class') ? '(='.$t['att'].')' : '';
$out.= ($t['name']=='id') ? '[='.$t['att'].']' : '';
$out.= ($t['name']=='style') ? '{='.$t['att'].'}' : '';
$out.= ($t['name']=='cite') ? ':'.$t['att'] : '';
}
return $out;
}
// -------------------------------------------------------------
function textile_splat($textile_attr) // returns attributes as an array
{
$textile_arr = array();
$textile_atnm = '';
$mode = 0;
while (strlen($textile_attr) != 0){
$ok = 0;
switch ($mode) {
case 0: // name
if (preg_match('/^([a-z]+)/i', $textile_attr, $match)) {
$textile_atnm = $match[1]; $ok = $mode = 1;
$textile_attr = preg_replace('/^[a-z]+/i', '', $textile_attr);
}
break;
case 1: // =
if (preg_match('/^\s*=\s*/', $textile_attr)) {
$ok = 1; $mode = 2;
$textile_attr = preg_replace('/^\s*=\s*/', '', $textile_attr);
break;
}
if (preg_match('/^\s+/', $textile_attr)) {
$ok = 1; $mode = 0;
$textile_arr[] = array('name'=>$textile_atnm,'whole'=>$textile_atnm,'att'=>$textile_atnm);
$textile_attr = preg_replace('/^\s+/', '', $textile_attr);
}
break;
case 2: // value
if (preg_match('/^("[^"]*")(\s+|$)/', $textile_attr, $match)) {
$textile_arr[]=array('name' =>$textile_atnm,'whole'=>$textile_atnm.'='.$match[1],
'att'=>str_replace('"','',$match[1]));
$ok = 1; $mode = 0;
$textile_attr = preg_replace('/^"[^"]*"(\s+|$)/', '', $textile_attr);
break;
}
if (preg_match("/^('[^']*')(\s+|$)/", $textile_attr, $match)) {
$textile_arr[]=array('name' =>$textile_atnm,'whole'=>$textile_atnm.'='.$match[1],
'att'=>str_replace("'",'',$match[1]));
$ok = 1; $mode = 0;
$textile_attr = preg_replace("/^'[^']*'(\s+|$)/", '', $textile_attr);
break;
}
if (preg_match("/^(\w+)(\s+|$)/", $textile_attr, $match)) {
$textile_arr[]=
array('name'=>$textile_atnm,'whole'=>$textile_atnm.'="'.$match[1].'"',
'att'=>$match[1]);
$ok = 1; $mode = 0;
$textile_attr = preg_replace("/^\w+(\s+|$)/", '', $textile_attr);
}
break;
}
if ($ok == 0){
$textile_attr = preg_replace('/^\S*\s*/', '', $textile_attr);
$mode = 0;
}
}
if ($mode == 1) $textile_arr[] =
array ('name'=>$textile_atnm,'whole'=>$textile_atnm.'="'.$textile_atnm.'"','att'=>$textile_atnm);
return $textile_arr;
}
?>