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
"$":url -> url
"$(title)":url -> url
!imageurl! ->
!imageurl(alt text)! ->
!imageurl!:linkurl ->
ABC(Always Be Closing) -> ABC
Linked Notes:
============
Allows the generation of an automated list of notes with links.
Linked notes are composed of three parts, a set of named _definitions_, a set of
_references_ to those definitions and one or more _placeholders_ indicating where
the consolidated list of notes is to be placed in your document.
Definitions.
-----------
Each note definition must occur in its own paragraph and should look like this...
note#mynotelabel. Your definition text here.
You are free to use whatever label you wish after the # as long as it is made up
of letters, numbers, colon(:) or dash(-).
References.
----------
Each note reference is marked in your text like this[#mynotelabel] and
it will be replaced with a superscript reference that links into the list of
note definitions.
List Placeholder(s).
-------------------
The note list can go anywhere in your document. You have to indicate where
like this...
notelist.
notelist can take attributes (class#id) like this: notelist(class#id).
By default, the note list will show each definition in the order that they
are referenced in the text by the _references_. It will show each definition with
a full list of backlinks to each reference. If you do not want this, you can choose
to override the backlinks like this...
notelist(class#id)!. Produces a list with no backlinks.
notelist(class#id)^. Produces a list with only the first backlink.
Should you wish to have a specific definition display backlinks differently to this
then you can override the backlink method by appending a link override to the
_definition_ you wish to customise.
note#label. Uses the citelist's setting for backlinks.
note#label!. Causes that definition to have no backlinks.
note#label^. Causes that definition to have one backlink (to the first ref.)
note#label*. Causes that definition to have all backlinks.
Any unreferenced notes will be left out of the list unless you explicitly state
you want them by adding a '+'. Like this...
notelist(class#id)!+. Giving a list of all notes without any backlinks.
You can mix and match the list backlink control and unreferenced links controls
but the backlink control (if any) must go first. Like so: notelist^+. , not
like this: notelist+^.
Example...
Scientists say[#lavader] the moon is small.
note#other. An unreferenced note.
note#lavader(myliclass). "Proof":url of a small moon.
notelist(myclass#myid)+.
Would output (the actual IDs used would be randomised)...
Scientists say1 the moon is small.
The 'a b c' backlink characters can be altered too. For example if you wanted the notes to have numeric backlinks starting from 1: notelist:1. Table syntax: Simple tables: |a|simple|table|row| |And|Another|table|row| |With an||empty|cell| |=. My table caption goes here |_. A|_. table|_. header|_.row| |A|simple|table|row| Tables with attributes: table{border:1px solid black}. My table summary here {background:#ddd;color:red}. |{}| | | | To specify thead / tfoot / tbody groups, add one of these on its own line above the row(s) you wish to wrap (you may specify attributes before the dot): |^. # thead |-. # tbody |~. # tfoot Column groups: |:\3. 100| Becomes: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 ->' . $def . '
'; $term = $this->graf($term); $def = $this->graf($def); $out[] = "\t\n"; $o2 = "\t\t"; } elseif ($tag == 'bc') { $o1 = "pba($att, '', 0).">"; $c2 = "
"; $c1 = "\n\t
";
$o2 = "";
$c2 = "
";
$c1 = "
";
$content = $this->shelve($this->r_encode_html(rtrim($content, "\n")."\n"));
}
elseif ($tag == 'notextile') {
$content = $this->shelve($content);
$o1 = $o2 = '';
$c1 = $c2 = '';
}
elseif ($tag == 'pre') {
$content = $this->shelve($this->r_encode_html(rtrim($content, "\n")."\n"));
$o1 = ""; $o2 = $c2 = ''; $c1 = ""; } elseif ($tag == '###') { $eat = true; } else { $o2 = "\t<$tag$atts>"; $c2 = "$tag>"; } $content = (!$eat) ? $this->graf($content) : ''; return array($o1, $o2, $content, $c2, $c1, $eat); } // ------------------------------------------------------------- function fParseHTMLComments($m) { list( , $content ) = $m; if( $this->restricted ) $content = $this->shelve($this->r_encode_html($content)); else $content = $this->shelve($content); return ""; } function getHTMLComments($text) { $text = preg_replace_callback("/ \ # end /sx", array(&$this, "fParseHTMLComments"), $text); return $text; } // ------------------------------------------------------------- function graf($text) { // handle normal paragraph text if (!$this->lite) { $text = $this->noTextile($text); $text = $this->code($text); } $text = $this->getHTMLComments($text); $text = $this->getRefs($text); $text = $this->links($text); if (!$this->noimage) $text = $this->image($text); if (!$this->lite) { $text = $this->table($text); $text = $this->redcloth_lists($text); $text = $this->lists($text); } $text = $this->span($text); $text = $this->footnoteRef($text); $text = $this->noteRef($text); $text = $this->glyphs($text); return rtrim($text, "\n"); } // ------------------------------------------------------------- function span($text) { $qtags = array('\*\*','\*','\?\?','-','__','_','%','\+','~','\^'); $pnct = ".,\"'?!;:‹›«»„“”‚‘’"; $this->span_depth++; if( $this->span_depth <= $this->max_span_depth ) { foreach($qtags as $f) { $text = preg_replace_callback("/ (^|(?<=[\s>$pnct\(])|[{[]) # pre ($f)(?!$f) # tag ({$this->c}) # atts (?::(\S+))? # cite ([^\s$f]+|\S.*?[^\s$f\n]) # content ([$pnct]*) # end $f ($|[\[\]}<]|(?=[$pnct]{1,2}|\s|\))) # tail /x".$this->regex_snippets['mod'], array(&$this, "fSpan"), $text); } } $this->span_depth--; return $text; } // ------------------------------------------------------------- function fSpan($m) { $qtags = array( '*' => 'strong', '**' => 'b', '??' => 'cite', '_' => 'em', '__' => 'i', '-' => 'del', '%' => 'span', '+' => 'ins', '~' => 'sub', '^' => 'sup', ); list(, $pre, $tag, $atts, $cite, $content, $end, $tail) = $m; $tag = $qtags[$tag]; $atts = $this->pba($atts); $atts .= ($cite != '') ? 'cite="' . $cite . '"' : ''; $content = $this->span($content); $opentag = '<'.$tag.$atts.'>'; $closetag = ''.$tag.'>'; $tags = $this->storeTags($opentag, $closetag); $out = "{$tags['open']}{$content}{$end}{$tags['close']}"; if (($pre and !$tail) or ($tail and !$pre)) $out = $pre.$out.$tail; return $out; } // ------------------------------------------------------------- function storeTags($opentag,$closetag='') { $key = ($this->tag_index++); $key = str_pad( (string)$key, 10, '0', STR_PAD_LEFT ); # $key must be of fixed length to allow proper matching in retrieveTags $this->tagCache[$key] = array('open'=>$opentag, 'close'=>$closetag); $tags = array( 'open' => "textileopentag{$key} ", 'close' => " textileclosetag{$key}", ); return $tags; } // ------------------------------------------------------------- function retrieveTags($text) { $text = preg_replace_callback('/textileopentag([\d]{10}) /' , array(&$this, 'fRetrieveOpenTags'), $text); $text = preg_replace_callback('/ textileclosetag([\d]{10})/', array(&$this, 'fRetrieveCloseTags'), $text); return $text; } // ------------------------------------------------------------- function fRetrieveOpenTags($m) { list(, $key ) = $m; return $this->tagCache[$key]['open']; } // ------------------------------------------------------------- function fRetrieveCloseTags($m) { list(, $key ) = $m; return $this->tagCache[$key]['close']; } // ------------------------------------------------------------- function placeNoteLists($text) { extract($this->regex_snippets); # Sequence all referenced definitions... if( !empty($this->notes) ) { $o = array(); foreach( $this->notes as $label=>$info ) { $i = @$info['seq']; if( !empty($i) ) { $info['seq'] = $label; $o[$i] = $info; } else { $this->unreferencedNotes[] = $info; # unreferenced definitions go here for possible future use. } } if( !empty($o) ) ksort($o); $this->notes = $o; } # Replace list markers... $text = preg_replace_callback("@
notelist({$this->c})(?:\:([$wrd|{$this->syms}]))?([\^!]?)(\+?)\.?[\s]*
@U$mod", array(&$this, "fNoteLists"), $text ); return $text; } // ------------------------------------------------------------- function fNoteLists($m) { list(, $att, $start_char, $g_links, $extras) = $m; if( !$start_char ) $start_char = 'a'; $index = $g_links.$extras.$start_char; if( empty($this->notelist_cache[$index]) ) { # If not in cache, build the entry... $o = array(); if( !empty($this->notes)) { foreach($this->notes as $seq=>$info) { $links = $this->makeBackrefLink($info, $g_links, $start_char ); $atts = ''; if( !empty($info['def'])) { $id = $info['id']; extract($info['def']); $o[] = "\t".''.$this->quote_starts.')"(?P.) /'.$this->regex_snippets['mod'], array(&$this, "fGlyphQuotedQuote"), $text); } function fGlyphQuotedQuote($m) { // Check the correct closing character was found... if($m['post'] !== @$this->quotes[$m['pre']]) return $m[0]; $glyph = ' ' . strtr($m['pre'], array( '"'=>'“', "'"=>'‘', ' '=>' ' )) . '"' . strtr($m['post'], array( '"'=> '”', "'"=>'’', ' '=>' ' )) . ' '; return $this->shelve($glyph); } // ------------------------------------------------------------- function links($text) { // Treat quoted quote as a special glyph $text = $this->glyphQuotedQuote($text); $t = preg_split('/":/', $text); // Split on '":' boundaries try { if(count($t) > 1) { $lastpart = array_pop($t); // There are no start of links in the last part, so pop it off (we'll glue it back later) foreach($t as $i=>$snippet) { // Cut this snippet into parts wherever we find a '"' character. // Any of these parts could represent the start of the link text, we need to find which part. $f = explode('"', $snippet); $n = count($f); // Cleanup situations like "He said it is "very unlikely" the stimulus works ":url // Space at end ----------^ $f[$n-1] = rtrim($f[$n-1]); // Init the balanced count. If this is still zero at the end of our do loop we'll mark the " that caused it to balance and move on to the next link $balanced = 0; // Vars we need in our balance checking loop... $linkparts = array(); $iter = 0; do { // Starting at the end, pop off the next part of the snippet's fragments $p = array_pop($f); if( null === $p ) throw new exception("Malformed link found."); // add this part to those parts that make up the link text $linkparts[] = $p; $len = strlen($p) > 0; $first = substr($p, 0, 1); $last = substr($p, -1, 1); if( $len ) { // did this part inc or dec the balanced count? if( !ctype_space( $first ) ) $balanced--; if( '=' == $last ) $balanced--; if( !ctype_space( $last ) ) $balanced++; } // If quotes occur next to each other, we get zero length strings eg. ...""Open the door, HAL!"":url... // In this case we count a zero length in the last position as a closing quote and others as opening quotes if( !$len ) $balanced = (!$iter++) ? $balanced+1 : $balanced-1; } while( 0 != $balanced ); // rebuild the link's text by reversing the parts and glueing them back together with quotes $link_start = implode('"', array_reverse($linkparts)); // rebuild the remaining stuff that goes before the link but that's already in order $pre_link = implode('"', $f); // Re-assemble the link starts with a specific ':"' marker for the regex $t[$i] = $pre_link . ':"' . $link_start; } // Add the last part back array_push($t, $lastpart); } // Re-assemble the full text with the start and end markers $text = implode('":', $t); $starts = preg_split( '/(\[?:")/', $text, NULL, PREG_SPLIT_DELIM_CAPTURE ); // << Try simple split on ':' if next char is a '"' it's a link and look back for preceeding char if(1 === count($starts)) return $text; /* echo var_export( $starts, true ), "\n\n"; */ /* foreach($starts as $link) { */ /* } */ // die(); } catch(exception $e) { // If we got an exception pre-parsing the links then let the regex try sorting it out... } // Process it return $this->links2($text); } // ------------------------------------------------------------- function links2($text) { $w = $this->regex_snippets['wrd']; $stopchars = "\s|^';\"*"; return preg_replace_callback('/ (?P \[)? # Optionally open with a square bracket eg. Look ["here":url] :" # literal :" marks start of the link (?P.+?) # capture the content of the inner "..." part of the link, can be anything but # do not worry about matching class, id, lang or title yet ": # literal ": marks end of atts + text + title block (?P [^'.$stopchars.']*) # url upto a stopchar /x'.$this->regex_snippets['mod'], array(&$this, "fLink"), $text); #(?P [\w\.\/?#]{1}) # first character following end of displayed chars } // ------------------------------------------------------------- function fLink($m) { $in = $m[0]; $pre = $m['pre']; $inner = $m['inner']; $url = $m['urlx']; // . $m['urlx']; $m = array(); // Reject invalid urls such as "linktext": which has no url part. if('' === $url) return strtr($in, array(':"'=>'"')); // Split inner into $atts, $text and $title.. preg_match( '/ ^ (?P ' . $this->c . ') # $atts (if any) (?P # $text is... (!.+!) # an image | # else... \(?[^(]+? # link text ) # end of $text (?:\((?P [^)]+?)\))? # $title (if any) $ /x'.$this->regex_snippets['mod'], $inner, $m ); $atts = isset($m['atts']) ? $m['atts'] : ''; $text = isset($m['text']) ? trim($m['text']) : $inner; $title = isset($m['title']) ? $m['title'] : ''; $m = array(); // In cases like; "(myclass) (just in case you were wondering)":http://slashdot.org/ // Where the middle text field is empty and there is a valid title field, we use that for the text. if(!$text && $title) { $text = "($title)"; $title = ''; } $pop = $tight = ''; $url_chars = array(); $counts = array( '[' => null, ']' => substr_count($url, ']'), # We need to know how many closing square brackets we have '(' => null, ')' => null, ); // Look for footnotes or other square-bracket delimieted stuff at the end of the url... // eg. "text":url][otherstuff... will have "[otherstuff" popped back out. // "text":url?q[]=x][123] will have "[123]" popped off the back, the remaining closing square brackets // will later be tested for balance if( $counts[']'] ) { if( 1 === preg_match( '@(?P ^.*\])(?P \[.*?)$@' . $this->regex_snippets['mod'], $url, $m ) ) { $url = $m['url']; $tight = $m['tight']; $m = array(); } } // Split off any trailing text that isn't part of an array assignment. // eg. "text":...?q[]=value1&q[]=value2 ... is ok // "text":...?q[]=value1]following ... would have "following" popped back out and the remaining square bracket // will later be tested for balance if( $counts[']']) { if( 1 === preg_match( '@(?P ^.*\])(?!=)(?P .*?)$@' . $this->regex_snippets['mod'], $url, $m) ) { $url = $m['url']; $tight = $m['end'] . $tight; $m = array(); } } // Does this need to be mb_ enabled? We are only searching for text in the ASCII charset anyway // Create an array of (possibly) multi-byte characters. // This is going to allow us to pop off any non-matched or nonsense chars from the url $len = strlen($url); for($i = 0; $i < $len; $i++) { $url_chars[] = substr( $url, $i, 1 ); } // Now we have the array of all the multi-byte chars in the url we will parse the uri backwards and pop off // any chars that don't belong there (like . or , or unmatched brackets of various kinds)... $first = true; do { $c = array_pop($url_chars); $popped = false; switch( $c ) { // URL shouldn't end in these characters, so pop them off and return them after the link. case '!' : case '.' : // url shouldn't end in '.' so pop it off (also matches things like "text":link...) case ',' : // url shouldn't end in ',' this is very probably punctuation following the url part (eg. blah "text"link, blah) $pop = $c . $pop; $popped = true; break; case ']' : // If we find a closing square bracket we are going to see if it's balanced... if(null===$counts['[']) { $counts['['] = substr_count($url, '['); } if( $counts['['] === $counts[']'] ) array_push($url_chars, $c); // balanced so keep it else { // In the case of un-matched closing square brackets we just eat it $popped = true; $counts[']'] -= 1; if( $first ) $pre = ''; } break; case ')' : if(null===$counts[')']) { $counts['('] = substr_count($url, '('); $counts[')'] = substr_count($url, ')'); } if( $counts['('] === $counts[')'] ) array_push($url_chars, $c); // balanced so keep it else { $pop = $c . $pop; // unbalanced so spit it out the back end $counts[')'] -= 1; $popped = true; } break; default: // An acceptable character for the end of the url so push it back and exit the character popping loop array_push($url_chars, $c); } $first = false; } while( $popped ); // Pull the possibly truncated URL back together... $url = implode('', $url_chars); // Parse the url into constituent parts... $this->parseURI( $url, $uri_parts ); // Check this is a valid uri scheme... $scheme = $uri_parts['scheme']; $scheme_in_list = in_array( $scheme, $this->url_schemes ); $scheme_ok = '' === $scheme || $scheme_in_list; if( !$scheme_ok ) return strtr($in, array(':"'=>'"')); // Handle self-referencing links... if( '$' === $text ) { if( $scheme_in_list ) $text = ltrim( $this->rebuildURI( $uri_parts, 'authority,path,query,fragment', false ), '/' ); else { if (isset($this->urlrefs[$url])) $url = urldecode($this->urlrefs[$url]); $text = $url; } } $atts = $this->pba($atts); $atts .= ($title != '') ? ' title="' . $this->encode_html($title) . '"' : ''; if (!$this->noimage) $text = $this->image($text); // Prep the text... $text = $this->span($text); $text = $this->glyphs($text); $url = $this->rebuildURI( $uri_parts ); $url = $this->shelveURL( $url ); $opentag = 'rel . '>'; $closetag = ''; $tags = $this->storeTags($opentag, $closetag); $out = $tags['open'].trim($text).$tags['close']; $out = $this->shelve($out); // Shelve the link we just built return $pre . $out . $pop . $tight; // return the shelf id and the $pop'd characters } // ------------------------------------------------------------- function getRefs($text) { if( $this->restricted ) $pattern = "/^\[(.+)\]((?:http:\/\/|https:\/\/|\/)\S+)(?=\s|$)/Um"; else $pattern = "/^\[(.+)\]((?:http:\/\/|https:\/\/|tel:|file:|ftp:\/\/|sftp:\/\/|mailto:|callto:|\/)\S+)(?=\s|$)/Um"; return preg_replace_callback( $pattern, array(&$this, "refs"), $text); } // ------------------------------------------------------------- function refs($m) { list(, $flag, $url) = $m; $uri_parts = array(); $this->parseURI( $url, $uri_parts ); $url = ltrim( $this->rebuildURI( $uri_parts ) ); // encodes URL if needed. $this->urlrefs[$flag] = $url; return ''; } // ------------------------------------------------------------- function shelveURL($text) { if ('' === $text) return ''; $ref = md5($text); $this->urlshelf[$ref] = $text; return 'urlref:'.$ref; } // ------------------------------------------------------------- function retrieveURLs($text) { return preg_replace_callback('/urlref:(\w{32})/', array(&$this, "retrieveURL"), $text); } // ------------------------------------------------------------- function retrieveURL($m) { $ref = $m[1]; if (!isset($this->urlshelf[$ref])) return $ref; $url = $this->urlshelf[$ref]; if (isset($this->urlrefs[$url])) $url = $this->urlrefs[$url]; return $this->r_encode_html($this->relURL($url)); } // ------------------------------------------------------------- function relURL($url) { $parts = @parse_url(urldecode($url)); if ((empty($parts['scheme']) or @$parts['scheme'] == 'http') and empty($parts['host']) and preg_match('/^\w/', @$parts['path'])) $url = $this->hu.$url; if ($this->restricted and !empty($parts['scheme']) and !in_array($parts['scheme'], $this->url_schemes)) return '#'; return $url; } // ------------------------------------------------------------- function isRelURL($url) { $parts = @parse_url($url); return (empty($parts['scheme']) and empty($parts['host'])); } // ------------------------------------------------------------- function image($text) { return preg_replace_callback("/ (?:[[{])? # pre \! # opening ! (\<|\=|\>)? # algn optional alignment atts ($this->c) # atts optional style,class atts (\. )? # period optional dot-space ([^\s(!]+) # url presume this is the src \s? # optional space (?:\(([^\)]+)\))? # title optional title \! # closing (?::(\S+))? # optional href (?:[\]}]|(?=\s|$|\))) # lookahead: space or end of string /x", array(&$this, "fImage"), $text); } // ------------------------------------------------------------- function fImage($m) { list(, $algn, $atts, $period, $url, $title, $href) = array_pad($m, 7, ''); if( '.' === $period ) $url = ".$url"; $extras = $align = ''; if( '' !== $algn ) { $vals = array( '<' => 'left', '=' => 'center', '>' => 'right'); if ( isset($vals[$algn]) ) { if( 'html5' === $this->doctype ) $extras = "align-{$vals[$algn]}"; else $align = " align=\"{$vals[$algn]}\""; } } $atts = $this->pba($atts , '' , 1 , $extras) . $align; if ('' !== $title) { $title = htmlspecialchars($title); $atts .= ' title="' . $title . '" alt="' . $title . '"'; } else $atts .= ' alt=""'; $size = false; if ($this->isRelUrl($url)) $size = @getimagesize(realpath($this->doc_root.ltrim($url, $this->ds))); if ($size) $atts .= " $size[3]"; $href = ($href) ? $this->shelveURL($href) : ''; $url = $this->shelveURL($url); $out = array( ($href) ? 'rel .'>' : '', '', ($href) ? '' : '' ); return $this->shelve(join('',$out)); } // ------------------------------------------------------------- function code($text) { $text = $this->doSpecial($text, ' ', '
', 'fCode'); $text = $this->doSpecial($text, '@', '@', 'fCode'); $text = $this->doSpecial($text, '', '', 'fPre'); return $text; } // ------------------------------------------------------------- function fCode($m) { @list(, $before, $text, $after) = $m; return $before.$this->shelve(''.$this->r_encode_html($text).'
').$after; } // ------------------------------------------------------------- function fPre($m) { @list(, $before, $text, $after) = $m; return $before.''.$this->shelve($this->r_encode_html($text)).''.$after; } // ------------------------------------------------------------- function shelve($val) { $i = uniqid(rand()); $this->shelf[$i] = $val; return $i; } // ------------------------------------------------------------- function retrieve($text) { if (is_array($this->shelf)) do { $old = $text; $text = strtr($text, $this->shelf); } while ($text != $old); return $text; } // ------------------------------------------------------------- // NOTE: deprecated function incomingEntities($text) { return preg_replace("/&(?![#a-z0-9]+;)/i", "x%x%", $text); } // ------------------------------------------------------------- // NOTE: deprecated function encodeEntities($text) { return (function_exists('mb_encode_numericentity')) ? $this->encode_high($text) : htmlentities($text, ENT_NOQUOTES, "utf-8"); } // ------------------------------------------------------------- // NOTE: deprecated function fixEntities($text) { /* de-entify any remaining angle brackets or ampersands */ return str_replace(array(">", "<", "&"), array(">", "<", "&"), $text); } // ------------------------------------------------------------- function cleanWhiteSpace($text) { $out = preg_replace("/^\xEF\xBB\xBF|\x1A/", '', $text); # Byte order mark (if present) $out = preg_replace("/\r\n?/", "\n", $out); # DOS and MAC line endings to *NIX style endings $out = preg_replace("/^[ \t]*\n/m", "\n", $out); # lines containing only whitespace $out = preg_replace("/\n{3,}/", "\n\n", $out); # 3 or more line ends $out = preg_replace("/^\n*/", "", $out); # leading blank lines return $out; } // ------------------------------------------------------------- function doSpecial($text, $start, $end, $method='fSpecial') { return preg_replace_callback('/(^|\s|[[({>])'.preg_quote($start, '/').'(.*?)'.preg_quote($end, '/').'(\s|$|[\])}])?/ms', array(&$this, $method), $text); } // ------------------------------------------------------------- function fSpecial($m) { // A special block like notextile or code @list(, $before, $text, $after) = $m; return $before.$this->shelve($this->encode_html($text)).$after; } // ------------------------------------------------------------- function noTextile($text) { $text = $this->doSpecial($text, '', ' ', 'fTextile'); return $this->doSpecial($text, '==', '==', 'fTextile'); } // ------------------------------------------------------------- function fTextile($m) { @list(, $before, $notextile, $after) = $m; #$notextile = str_replace(array_keys($modifiers), array_values($modifiers), $notextile); return $before.$this->shelve($notextile).$after; } // ------------------------------------------------------------- function footnoteRef($text) { return preg_replace('/(?<=\S)\[([0-9]+)([\!]?)\](\s)?/Ue', '$this->footnoteID(\'\1\',\'\2\',\'\3\')', $text); } // ------------------------------------------------------------- function footnoteID($id, $nolink, $t) { $backref = ' '; if (empty($this->fn[$id])) { $this->fn[$id] = $a = uniqid(rand()); $backref = ' id="fnrev'.$a.'" '; } $fnid = $this->fn[$id]; $footref = ( '!' == $nolink ) ? $id : ''.$id.''; $backref .= 'class="footnote"'; $footref = $this->formatFootnote( $footref, $backref, false ); return $footref; } // ------------------------------------------------------------- function glyphs($text) { // fix: hackish -- adds a space if final char of text is a double quote. $text = preg_replace('/"\z/', "\" ", $text); $text = preg_split("@(<[\w/!?].*>)@Us", $text, -1, PREG_SPLIT_DELIM_CAPTURE); $i = 0; foreach($text as $line) { // text tag text tag text ... if (++$i % 2) { // raw < > & chars are already entity encoded in restricted mode if (!$this->restricted) { $line = $this->encode_raw_amp($line); $line = $this->encode_lt_gt($line); } $line = preg_replace($this->glyph_search, $this->glyph_replace, $line); } $glyph_out[] = $line; } return join('', $glyph_out); } // ------------------------------------------------------------- function replaceGlyphs($text) { return preg_replace('/glyph:([^<]+)/','$1',$text); } // ------------------------------------------------------------- function hAlign($in) { $vals = array( '<' => 'left', '>' => 'right', '<>' => 'justify', '<' => 'left', '=' => 'center', '>' => 'right', '<>' => 'justify'); return (isset($vals[$in])) ? $vals[$in] : ''; } // ------------------------------------------------------------- function vAlign($in) { $vals = array( '^' => 'top', '-' => 'middle', '~' => 'bottom'); return (isset($vals[$in])) ? $vals[$in] : ''; } // ------------------------------------------------------------- // NOTE: used in notelists function encode_high($text, $charset = "UTF-8") { return mb_encode_numericentity($text, $this->cmap(), $charset); } // ------------------------------------------------------------- // NOTE: used in notelists function decode_high($text, $charset = "UTF-8") { return mb_decode_numericentity($text, $this->cmap(), $charset); } // ------------------------------------------------------------- function cmap() { $f = 0xffff; $cmap = array( 0x0080, 0xffff, 0, $f); return $cmap; } // ------------------------------------------------------------- function encode_raw_amp($text) { return preg_replace('/&(?!#?[a-z0-9]+;)/i', '&', $text); } // ------------------------------------------------------------- function encode_lt_gt($text) { return strtr($text, array('<' => '<', '>' => '>')); } // ------------------------------------------------------------- function encode_quot($text) { return str_replace('"', '"', $text); } // ------------------------------------------------------------- function encode_html($str, $quotes=1) { $a = array( '&' => '&', '<' => '<', '>' => '>', ); if ($quotes) $a = $a + array( "'" => ''', // numeric, as in htmlspecialchars '"' => '"', ); return strtr($str, $a); } // ------------------------------------------------------------- function r_encode_html($str, $quotes=1) { // in restricted mode, all input but quotes has already been escaped if ($this->restricted) return $this->encode_quot($str); return $this->encode_html($str, $quotes); } // ------------------------------------------------------------- function textile_popup_help($name, $helpvar, $windowW, $windowH) { return ' ' . $name . '
'; } // ------------------------------------------------------------- // NOTE: deprecated function txtgps($thing) { if (isset($_POST[$thing])) { if (get_magic_quotes_gpc()) { return stripslashes($_POST[$thing]); } else { return $_POST[$thing]; } } else { return ''; } } // ------------------------------------------------------------- // NOTE: deprecated function dump() { static $bool = array( 0=>'false', 1=>'true' ); foreach (func_get_args() as $a) echo "\n",(is_array($a)) ? print_r($a) : ((is_bool($a)) ? $bool[(int)$a] : $a), "\n"; return $this; } } // end class