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 ->\n"; $o2 = "\t\t"; } elseif ($tag == 'bc') { $o1 = "pba($att, '', 0).">"; $c2 = "
"; $c1 = "\n\t
";
$o2 = "pba($att, '', 0).">";
$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 graf($text) { // handle normal paragraph text if (!$this->lite) { $text = $this->noTextile($text); $text = $this->code($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->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 ($|[\]}]|(?=[[:punct:]]{1,2}|\s|\))) # tail /x", 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))?([\^!]?)(\+?)\.[\s]*
@U$mod", array(&$this, "fNoteLists"), $text ); return $text; } // ------------------------------------------------------------- function fParseNoteDefs($m) { list(, $label, $link, $att, $content) = $m; # Assign an id if the note reference parse hasn't found the label yet. $id = @$this->notes[$label]['id']; if( !$id ) $this->notes[$label]['id'] = uniqid(rand()); if( empty($this->notes[$label]['def']) ) # Ignores subsequent defs using the same label { $this->notes[$label]['def'] = array( 'atts' => $this->pba($att), 'content' => $this->graf($content), 'link' => $link, ); } return ''; } // ------------------------------------------------------------- function noteRef($text) { $text = preg_replace_callback("/ \[ # start ({$this->c}) # !atts \# ([^\]!]+?) # !label ([!]?) # !nolink \] /Ux", array(&$this, "fParseNoteRefs"), $text); return $text; } // ------------------------------------------------------------- function fParseNoteRefs($m) { # By the time this function is called, all the defs will have been processed # into the notes array. So now we can resolve the link numbers in the order # we process the refs... list(, $atts, $label, $nolink) = $m; $atts = $this->pba($atts); $nolink = ($nolink === '!'); # Assign a sequence number to this reference if there isn't one already... $num = @$this->notes[$label]['seq']; if( !$num ) $num = $this->notes[$label]['seq'] = ($this->note_index++); # Make our anchor point & stash it for possible use in backlinks when the # note list is generated later... $this->notes[$label]['refids'][] = $refid = uniqid(rand()); # If we are referencing a note that hasn't had the definition parsed yet, then assign it an ID... $id = @$this->notes[$label]['id']; if( !$id ) $id = $this->notes[$label]['id'] = uniqid(rand()); # Build the link (if any)... $_ = ''.$num.''; if( !$nolink ) $_ = ''.$_.''; # Build the reference... $_ = ''.$_.''; return $_; } // ------------------------------------------------------------- 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 ); if( !empty($info['def'])) { $id = $info['id']; extract($info['def']); $o[] = "\t".'', '
', '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, '
",(is_array($a)) ? print_r($a) : ((is_bool($a)) ? $bool[(int)$a] : $a), "\n"; return $this; } // ------------------------------------------------------------- function blockLite($text) { $this->btag = array('bq', 'p'); return $this->block($text."\n\n"); } } // end class