12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136 |
- <?php
-
- /**
- * Example: get XHTML from a given Textile-markup string ($string)
- *
- * $textile = new Textile;
- * echo $textile->TextileThis($string);
- *
- */
-
- /*
- $Id: classTextile.php 216 2006-10-17 22:31:53Z zem $
- $LastChangedRevision: 216 $
- */
-
- /*
-
- _____________
- T E X T I L E
-
- A Humane Web Text Generator
-
- Version 2.0
-
- Copyright (c) 2003-2004, Dean Allen <dean@textism.com>
- All rights reserved.
-
- Thanks to Carlo Zottmann <carlo@g-blog.net> for refactoring
- Textile's procedural code into a class framework
-
- Additions and fixes Copyright (c) 2006 Alex Shiels http://thresholdstate.com/
-
- _____________
- L I C E N S E
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
- * Neither the name Textile nor the names of its contributors may be used to
- endorse or promote products derived from this software without specific
- prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
-
- _________
- U S A G E
-
- Block modifier syntax:
-
- Header: h(1-6).
- Paragraphs beginning with 'hn. ' (where n is 1-6) are wrapped in header tags.
- Example: h1. Header... -> <h1>Header...</h1>
-
- Paragraph: p. (also applied by default)
- Example: p. Text -> <p>Text</p>
-
- Blockquote: bq.
- Example: bq. Block quotation... -> <blockquote>Block quotation...</blockquote>
-
- Blockquote with citation: bq.:http://citation.url
- Example: bq.:http://textism.com/ Text...
- -> <blockquote cite="http://textism.com">Text...</blockquote>
-
- Footnote: fn(1-100).
- Example: fn1. Footnote... -> <p id="fn1">Footnote...</p>
-
- Numeric list: #, ##
- Consecutive paragraphs beginning with # are wrapped in ordered list tags.
- Example: <ol><li>ordered list</li></ol>
-
- Bulleted list: *, **
- Consecutive paragraphs beginning with * are wrapped in unordered list tags.
- Example: <ul><li>unordered list</li></ul>
-
- Phrase modifier syntax:
-
- _emphasis_ -> <em>emphasis</em>
- __italic__ -> <i>italic</i>
- *strong* -> <strong>strong</strong>
- **bold** -> <b>bold</b>
- ??citation?? -> <cite>citation</cite>
- -deleted text- -> <del>deleted</del>
- +inserted text+ -> <ins>inserted</ins>
- ^superscript^ -> <sup>superscript</sup>
- ~subscript~ -> <sub>subscript</sub>
- @code@ -> <code>computer code</code>
- %(bob)span% -> <span class="bob">span</span>
-
- ==notextile== -> leave text alone (do not format)
-
- "linktext":url -> <a href="url">linktext</a>
- "linktext(title)":url -> <a href="url" title="title">linktext</a>
-
- !imageurl! -> <img src="imageurl" />
- !imageurl(alt text)! -> <img src="imageurl" alt="alt text" />
- !imageurl!:linkurl -> <a href="linkurl"><img src="imageurl" /></a>
-
- ABC(Always Be Closing) -> <acronym title="Always Be Closing">ABC</acronym>
-
-
- Table syntax:
-
- Simple tables:
-
- |a|simple|table|row|
- |And|Another|table|row|
-
- |_. A|_. table|_. header|_.row|
- |A|simple|table|row|
-
- Tables with attributes:
-
- table{border:1px solid black}.
- {background:#ddd;color:red}. |{}| | | |
-
-
- Applying Attributes:
-
- Most anywhere Textile code is used, attributes such as arbitrary css style,
- css classes, and ids can be applied. The syntax is fairly consistent.
-
- The following characters quickly alter the alignment of block elements:
-
- < -> left align ex. p<. left-aligned para
- > -> right align h3>. right-aligned header 3
- = -> centred h4=. centred header 4
- <> -> justified p<>. justified paragraph
-
- These will change vertical alignment in table cells:
-
- ^ -> top ex. |^. top-aligned table cell|
- - -> middle |-. middle aligned|
- ~ -> bottom |~. bottom aligned cell|
-
- Plain (parentheses) inserted between block syntax and the closing dot-space
- indicate classes and ids:
-
- p(hector). paragraph -> <p class="hector">paragraph</p>
-
- p(#fluid). paragraph -> <p id="fluid">paragraph</p>
-
- (classes and ids can be combined)
- p(hector#fluid). paragraph -> <p class="hector" id="fluid">paragraph</p>
-
- Curly {brackets} insert arbitrary css style
-
- p{line-height:18px}. paragraph -> <p style="line-height:18px">paragraph</p>
-
- h3{color:red}. header 3 -> <h3 style="color:red">header 3</h3>
-
- Square [brackets] insert language attributes
-
- p[no]. paragraph -> <p lang="no">paragraph</p>
-
- %[fr]phrase% -> <span lang="fr">phrase</span>
-
- 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 -> <ol style="color:blue">
- # big <li>one</li>
- # list <li>big</li>
- <li>list</li>
- </ol>
-
- Using the span tag to style a phrase
-
- It goes like this, %{color:red}the fourth the fifth%
- -> It goes like this, <span style="color:red">the fourth the fifth</span>
-
- */
-
- // define these before including this file to override the standard glyphs
- @define('txt_quote_single_open', '‘');
- @define('txt_quote_single_close', '’');
- @define('txt_quote_double_open', '“');
- @define('txt_quote_double_close', '”');
- @define('txt_apostrophe', '’');
- @define('txt_prime', '′');
- @define('txt_prime_double', '″');
- @define('txt_ellipsis', '…');
- @define('txt_emdash', '—');
- @define('txt_endash', '–');
- @define('txt_dimension', '×');
- @define('txt_trademark', '™');
- @define('txt_registered', '®');
- @define('txt_copyright', '©');
-
- class Textile
- {
- var $hlgn;
- var $vlgn;
- var $clas;
- var $lnge;
- var $styl;
- var $cspn;
- var $rspn;
- var $a;
- var $s;
- var $c;
- var $pnct;
- var $rel;
- var $fn;
-
- var $shelf = array();
- var $restricted = false;
- var $noimage = false;
- var $lite = false;
- var $url_schemes = array();
- var $glyph = array();
- var $hu = '';
-
- var $ver = '2.0.0';
- var $rev = '$Rev: 216 $';
-
- // -------------------------------------------------------------
- function Textile()
- {
- $this->hlgn = "(?:\<(?!>)|(?<!<)\>|\<\>|\=|[()]+(?! ))";
- $this->vlgn = "[\-^~]";
- $this->clas = "(?:\([^)]+\))";
- $this->lnge = "(?:\[[^]]+\])";
- $this->styl = "(?:\{[^}]+\})";
- $this->cspn = "(?:\\\\\d+)";
- $this->rspn = "(?:\/\d+)";
- $this->a = "(?:{$this->hlgn}|{$this->vlgn})*";
- $this->s = "(?:{$this->cspn}|{$this->rspn})*";
- $this->c = "(?:{$this->clas}|{$this->styl}|{$this->lnge}|{$this->hlgn})*";
-
- $this->pnct = '[\!"#\$%&\'()\*\+,\-\./:;<=>\?@\[\\\]\^_`{\|}\~]';
- $this->urlch = '[\w"$\-_.+!*\'(),";\/?:@=&%#{}|\\^~\[\]`]';
-
- $this->url_schemes = array('http','https','ftp','mailto');
-
- $this->btag = array('bq', 'bc', 'notextile', 'pre', 'h[1-6]', 'fn\d+', 'p');
-
- $this->glyph = array(
- 'quote_single_open' => txt_quote_single_open,
- 'quote_single_close' => txt_quote_single_close,
- 'quote_double_open' => txt_quote_double_open,
- 'quote_double_close' => txt_quote_double_close,
- 'apostrophe' => txt_apostrophe,
- 'prime' => txt_prime,
- 'prime_double' => txt_prime_double,
- 'ellipsis' => txt_ellipsis,
- 'emdash' => txt_emdash,
- 'endash' => txt_endash,
- 'dimension' => txt_dimension,
- 'trademark' => txt_trademark,
- 'registered' => txt_registered,
- 'copyright' => txt_copyright,
- );
-
- if (defined('hu'))
- $this->hu = hu;
-
- }
-
- // -------------------------------------------------------------
- function TextileThis($text, $lite='', $encode='', $noimage='', $strict='', $rel='')
- {
- if ($rel)
- $this->rel = ' rel="'.$rel.'" ';
- $this->lite = $lite;
- $this->noimage = $noimage;
-
- if ($encode) {
- $text = $this->incomingEntities($text);
- $text = str_replace("x%x%", "&", $text);
- return $text;
- } else {
-
- if(!$strict) {
- $text = $this->cleanWhiteSpace($text);
- }
-
- $text = $this->getRefs($text);
-
- if (!$lite) {
- $text = $this->block($text);
- }
-
- $text = $this->retrieve($text);
-
- // just to be tidy
- $text = str_replace("<br />", "<br />\n", $text);
-
- return $text;
- }
- }
-
- // -------------------------------------------------------------
- function TextileRestricted($text, $lite=1, $noimage=1, $rel='nofollow')
- {
- $this->restricted = true;
- $this->lite = $lite;
- $this->noimage = $noimage;
- if ($rel)
- $this->rel = ' rel="'.$rel.'" ';
-
- // escape any raw html
- $text = $this->encode_html($text, 0);
-
- $text = $this->cleanWhiteSpace($text);
- $text = $this->getRefs($text);
-
- if ($lite) {
- $text = $this->blockLite($text);
- }
- else {
- $text = $this->block($text);
- }
-
- $text = $this->retrieve($text);
-
- // just to be tidy
- $text = str_replace("<br />", "<br />\n", $text);
-
- return $text;
- }
-
- // -------------------------------------------------------------
- function pba($in, $element = "") // "parse block attributes"
- {
- $style = '';
- $class = '';
- $lang = '';
- $colspan = '';
- $rowspan = '';
- $id = '';
- $atts = '';
-
- if (!empty($in)) {
- $matched = $in;
- if ($element == 'td') {
- if (preg_match("/\\\\(\d+)/", $matched, $csp)) $colspan = $csp[1];
- if (preg_match("/\/(\d+)/", $matched, $rsp)) $rowspan = $rsp[1];
- }
-
- if ($element == 'td' or $element == 'tr') {
- if (preg_match("/($this->vlgn)/", $matched, $vert))
- $style[] = "vertical-align:" . $this->vAlign($vert[1]) . ";";
- }
-
- if (preg_match("/\{([^}]*)\}/", $matched, $sty)) {
- $style[] = rtrim($sty[1], ';') . ';';
- $matched = str_replace($sty[0], '', $matched);
- }
-
- if (preg_match("/\[([^]]+)\]/U", $matched, $lng)) {
- $lang = $lng[1];
- $matched = str_replace($lng[0], '', $matched);
- }
-
- if (preg_match("/\(([^()]+)\)/U", $matched, $cls)) {
- $class = $cls[1];
- $matched = str_replace($cls[0], '', $matched);
- }
-
- if (preg_match("/([(]+)/", $matched, $pl)) {
- $style[] = "padding-left:" . strlen($pl[1]) . "em;";
- $matched = str_replace($pl[0], '', $matched);
- }
-
- if (preg_match("/([)]+)/", $matched, $pr)) {
- // $this->dump($pr);
- $style[] = "padding-right:" . strlen($pr[1]) . "em;";
- $matched = str_replace($pr[0], '', $matched);
- }
-
- if (preg_match("/($this->hlgn)/", $matched, $horiz))
- $style[] = "text-align:" . $this->hAlign($horiz[1]) . ";";
-
- if (preg_match("/^(.*)#(.*)$/", $class, $ids)) {
- $id = $ids[2];
- $class = $ids[1];
- }
-
- if ($this->restricted)
- return ($lang) ? ' lang="' . $lang .'"':'';
-
- return join('',array(
- ($style) ? ' style="' . join("", $style) .'"':'',
- ($class) ? ' class="' . $class .'"':'',
- ($lang) ? ' lang="' . $lang .'"':'',
- ($id) ? ' id="' . $id .'"':'',
- ($colspan) ? ' colspan="' . $colspan .'"':'',
- ($rowspan) ? ' rowspan="' . $rowspan .'"':''
- ));
- }
- return '';
- }
-
- // -------------------------------------------------------------
- function hasRawText($text)
- {
- // checks whether the text has text not already enclosed by a block tag
- $r = trim(preg_replace('@<(p|blockquote|div|form|table|ul|ol|pre|h\d)[^>]*?>.*</\1>@s', '', trim($text)));
- $r = trim(preg_replace('@<(hr|br)[^>]*?/>@', '', $r));
- return '' != $r;
- }
-
- // -------------------------------------------------------------
- function table($text)
- {
- $text = $text . "\n\n";
- return preg_replace_callback("/^(?:table(_?{$this->s}{$this->a}{$this->c})\. ?\n)?^({$this->a}{$this->c}\.? ?\|.*\|)\n\n/smU",
- array(&$this, "fTable"), $text);
- }
-
- // -------------------------------------------------------------
- function fTable($matches)
- {
- $tatts = $this->pba($matches[1], 'table');
-
- foreach(preg_split("/\|$/m", $matches[2], -1, PREG_SPLIT_NO_EMPTY) as $row) {
- if (preg_match("/^($this->a$this->c\. )(.*)/m", ltrim($row), $rmtch)) {
- $ratts = $this->pba($rmtch[1], 'tr');
- $row = $rmtch[2];
- } else $ratts = '';
-
- $cells = array();
- foreach(explode("|", $row) as $cell) {
- $ctyp = "d";
- if (preg_match("/^_/", $cell)) $ctyp = "h";
- if (preg_match("/^(_?$this->s$this->a$this->c\. )(.*)/", $cell, $cmtch)) {
- $catts = $this->pba($cmtch[1], 'td');
- $cell = $cmtch[2];
- } else $catts = '';
-
- $cell = $this->graf($this->span($cell));
-
- if (trim($cell) != '')
- $cells[] = "\t\t\t<t$ctyp$catts>$cell</t$ctyp>";
- }
- $rows[] = "\t\t<tr$ratts>\n" . join("\n", $cells) . ($cells ? "\n" : "") . "\t\t</tr>";
- unset($cells, $catts);
- }
- return "\t<table$tatts>\n" . join("\n", $rows) . "\n\t</table>\n\n";
- }
-
- // -------------------------------------------------------------
- function lists($text)
- {
- return preg_replace_callback("/^([#*]+$this->c .*)$(?![^#*])/smU", array(&$this, "fList"), $text);
- }
-
- // -------------------------------------------------------------
- function fList($m)
- {
- $text = explode("\n", $m[0]);
- foreach($text as $line) {
- $nextline = next($text);
- if (preg_match("/^([#*]+)($this->a$this->c) (.*)$/s", $line, $m)) {
- list(, $tl, $atts, $content) = $m;
- $nl = '';
- if (preg_match("/^([#*]+)\s.*/", $nextline, $nm))
- $nl = $nm[1];
- if (!isset($lists[$tl])) {
- $lists[$tl] = true;
- $atts = $this->pba($atts);
- $line = "\t<" . $this->lT($tl) . "l$atts>\n\t\t<li>" . $this->graf($content);
- } else {
- $line = "\t\t<li>" . $this->graf($content);
- }
-
- if(strlen($nl) <= strlen($tl)) $line .= "</li>";
- foreach(array_reverse($lists) as $k => $v) {
- if(strlen($k) > strlen($nl)) {
- $line .= "\n\t</" . $this->lT($k) . "l>";
- if(strlen($k) > 1)
- $line .= "</li>";
- unset($lists[$k]);
- }
- }
- }
- $out[] = $line;
- }
- return join("\n", $out);
- }
-
- // -------------------------------------------------------------
- function lT($in)
- {
- return preg_match("/^#+/", $in) ? 'o' : 'u';
- }
-
- // -------------------------------------------------------------
- function doPBr($in)
- {
- return preg_replace_callback('@<(p)([^>]*?)>(.*)(</\1>)@s', array(&$this, 'doBr'), $in);
- }
-
- // -------------------------------------------------------------
- function doBr($m)
- {
- $content = preg_replace("@(.+)(?<!<br>|<br />)\n(?![#*\s|])@", '$1<br />', $m[3]);
- return '<'.$m[1].$m[2].'>'.$content.$m[4];
- }
-
- // -------------------------------------------------------------
- function block($text)
- {
- $find = $this->btag;
- $tre = join('|', $find);
-
- $text = explode("\n\n", $text);
-
- $tag = 'p';
- $atts = $cite = $graf = $ext = '';
-
- foreach($text as $line) {
- $anon = 0;
- if (preg_match("/^($tre)($this->a$this->c)\.(\.?)(?::(\S+))? (.*)$/s", $line, $m)) {
- // last block was extended, so close it
- if ($ext)
- $out[count($out)-1] .= $c1;
- // new block
- list(,$tag,$atts,$ext,$cite,$graf) = $m;
- list($o1, $o2, $content, $c2, $c1) = $this->fBlock(array(0,$tag,$atts,$ext,$cite,$graf));
-
- // leave off c1 if this block is extended, we'll close it at the start of the next block
- if ($ext)
- $line = $o1.$o2.$content.$c2;
- else
- $line = $o1.$o2.$content.$c2.$c1;
- }
- else {
- // anonymous block
- $anon = 1;
- if ($ext or !preg_match('/^ /', $line)) {
- list($o1, $o2, $content, $c2, $c1) = $this->fBlock(array(0,$tag,$atts,$ext,$cite,$line));
- // skip $o1/$c1 because this is part of a continuing extended block
- if ($tag == 'p' and !$this->hasRawText($content)) {
- $line = $content;
- }
- else {
- $line = $o2.$content.$c2;
- }
- }
- else {
- $line = $this->graf($line);
- }
- }
-
- $line = $this->doPBr($line);
- $line = preg_replace('/<br>/', '<br />', $line);
-
- if ($ext and $anon)
- $out[count($out)-1] .= "\n".$line;
- else
- $out[] = $line;
-
- if (!$ext) {
- $tag = 'p';
- $atts = '';
- $cite = '';
- $graf = '';
- }
- }
- if ($ext) $out[count($out)-1] .= $c1;
- return join("\n\n", $out);
- }
-
-
-
- // -------------------------------------------------------------
- function fBlock($m)
- {
- // $this->dump($m);
- list(, $tag, $atts, $ext, $cite, $content) = $m;
- $atts = $this->pba($atts);
-
- $o1 = $o2 = $c2 = $c1 = '';
-
- if (preg_match("/fn(\d+)/", $tag, $fns)) {
- $tag = 'p';
- $fnid = empty($this->fn[$fns[1]]) ? $fns[1] : $this->fn[$fns[1]];
- $atts .= ' id="fn' . $fnid . '"';
- if (strpos($atts, 'class=') === false)
- $atts .= ' class="footnote"';
- $content = '<sup>' . $fns[1] . '</sup> ' . $content;
- }
-
- if ($tag == "bq") {
- $cite = $this->checkRefs($cite);
- $cite = ($cite != '') ? ' cite="' . $cite . '"' : '';
- $o1 = "\t<blockquote$cite$atts>\n";
- $o2 = "\t\t<p$atts>";
- $c2 = "</p>";
- $c1 = "\n\t</blockquote>";
- }
- elseif ($tag == 'bc') {
- $o1 = "<pre$atts>";
- $o2 = "<code$atts>";
- $c2 = "</code>";
- $c1 = "</pre>";
- $content = $this->shelve($this->encode_html(rtrim($content, "\n")."\n"));
- }
- elseif ($tag == 'notextile') {
- $content = $this->shelve($content);
- $o1 = $o2 = '';
- $c1 = $c2 = '';
- }
- elseif ($tag == 'pre') {
- $content = $this->shelve($this->encode_html(rtrim($content, "\n")."\n"));
- $o1 = "<pre$atts>";
- $o2 = $c2 = '';
- $c1 = "</pre>";
- }
- else {
- $o2 = "\t<$tag$atts>";
- $c2 = "</$tag>";
- }
-
- $content = $this->graf($content);
-
- return array($o1, $o2, $content, $c2, $c1);
- }
-
- // -------------------------------------------------------------
- function graf($text)
- {
- // handle normal paragraph text
- if (!$this->lite) {
- $text = $this->noTextile($text);
- $text = $this->code($text);
- }
-
- $text = $this->links($text);
- if (!$this->noimage)
- $text = $this->image($text);
-
- if (!$this->lite) {
- $text = $this->lists($text);
- $text = $this->table($text);
- }
-
- $text = $this->span($text);
- $text = $this->footnoteRef($text);
- $text = $this->glyphs($text);
- return rtrim($text, "\n");
- }
-
- // -------------------------------------------------------------
- function span($text)
- {
- $qtags = array('\*\*','\*','\?\?','-','__','_','%','\+','~','\^');
- $pnct = ".,\"'?!;:";
-
- foreach($qtags as $f) {
- $text = preg_replace_callback("/
- (?:^|(?<=[\s>$pnct])|([{[]))
- ($f)(?!$f)
- ({$this->c})
- (?::(\S+))?
- ([^\s$f]+|\S[^$f\n]*[^\s$f\n])
- ([$pnct]*)
- $f
- (?:$|([\]}])|(?=[[:punct:]]{1,2}|\s))
- /x", array(&$this, "fSpan"), $text);
- }
- return $text;
- }
-
- // -------------------------------------------------------------
- function fSpan($m)
- {
- $qtags = array(
- '*' => 'strong',
- '**' => 'b',
- '??' => 'cite',
- '_' => 'em',
- '__' => 'i',
- '-' => 'del',
- '%' => 'span',
- '+' => 'ins',
- '~' => 'sub',
- '^' => 'sup',
- );
-
- list(,, $tag, $atts, $cite, $content, $end) = $m;
- $tag = $qtags[$tag];
- $atts = $this->pba($atts);
- $atts .= ($cite != '') ? 'cite="' . $cite . '"' : '';
-
- $out = "<$tag$atts>$content$end</$tag>";
-
- // $this->dump($out);
-
- return $out;
-
- }
-
- // -------------------------------------------------------------
- function links($text)
- {
- return preg_replace_callback('/
- (?:^|(?<=[\s>.$pnct\(])|([{[])) # $pre
- " # start
- (' . $this->c . ') # $atts
- ([^"]+) # $text
- \s?
- (?:\(([^)]+)\)(?="))? # $title
- ":
- ('.$this->urlch.'+) # $url
- (\/)? # $slash
- ([^\w\/;]*) # $post
- (?:([\]}])|(?=\s|$|\)))
- /Ux', array(&$this, "fLink"), $text);
- }
-
- // -------------------------------------------------------------
- function fLink($m)
- {
- list(, $pre, $atts, $text, $title, $url, $slash, $post) = $m;
-
- $url = $this->checkRefs($url);
-
- $atts = $this->pba($atts);
- $atts .= ($title != '') ? ' title="' . $this->encode_html($title) . '"' : '';
-
- if (!$this->noimage)
- $text = $this->image($text);
-
- $text = $this->span($text);
- $text = $this->glyphs($text);
-
- $url = $this->relURL($url);
-
- $out = '<a href="' . $this->encode_html($url . $slash) . '"' . $atts . $this->rel . '>' . $text . '</a>' . $post;
-
- // $this->dump($out);
- return $this->shelve($out);
-
- }
-
- // -------------------------------------------------------------
- function getRefs($text)
- {
- return preg_replace_callback("/(?<=^|\s)\[(.+)\]((?:http:\/\/|\/)\S+)(?=\s|$)/U",
- array(&$this, "refs"), $text);
- }
-
- // -------------------------------------------------------------
- function refs($m)
- {
- list(, $flag, $url) = $m;
- $this->urlrefs[$flag] = $url;
- return '';
- }
-
- // -------------------------------------------------------------
- function checkRefs($text)
- {
- return (isset($this->urlrefs[$text])) ? $this->urlrefs[$text] : $text;
- }
-
- // -------------------------------------------------------------
- function relURL($url)
- {
- $parts = parse_url($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 image($text)
- {
- return preg_replace_callback("/
- (?:[[{])? # pre
- \! # opening !
- (\<|\=|\>)?? # optional alignment atts
- ($this->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", array(&$this, "fImage"), $text);
- }
-
- // -------------------------------------------------------------
- function fImage($m)
- {
- list(, $algn, $atts, $url) = $m;
- $atts = $this->pba($atts);
- $atts .= ($algn != '') ? ' align="' . $this->iAlign($algn) . '"' : '';
- $atts .= (isset($m[4])) ? ' title="' . $m[4] . '"' : '';
- $atts .= (isset($m[4])) ? ' alt="' . $m[4] . '"' : ' alt=""';
- $size = @getimagesize($url);
- if ($size) $atts .= " $size[3]";
-
- $href = (isset($m[5])) ? $this->checkRefs($m[5]) : '';
- $url = $this->checkRefs($url);
-
- $url = $this->relURL($url);
-
- $out = array(
- ($href) ? '<a href="' . $href . '">' : '',
- '<img src="' . $url . '"' . $atts . ' />',
- ($href) ? '</a>' : ''
- );
-
- return join('',$out);
- }
-
- // -------------------------------------------------------------
- function code($text)
- {
- $text = $this->doSpecial($text, '<code>', '</code>', 'fCode');
- $text = $this->doSpecial($text, '@', '@', 'fCode');
- $text = $this->doSpecial($text, '<pre>', '</pre>', 'fPre');
- return $text;
- }
-
- // -------------------------------------------------------------
- function fCode($m)
- {
- @list(, $before, $text, $after) = $m;
- if ($this->restricted)
- // $text is already escaped
- return $before.$this->shelve('<code>'.$text.'</code>').$after;
- else
- return $before.$this->shelve('<code>'.$this->encode_html($text).'</code>').$after;
- }
-
- // -------------------------------------------------------------
- function fPre($m)
- {
- @list(, $before, $text, $after) = $m;
- if ($this->restricted)
- // $text is already escaped
- return $before.'<pre>'.$this->shelve($text).'</pre>'.$after;
- else
- return $before.'<pre>'.$this->shelve($this->encode_html($text)).'</pre>'.$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 = str_replace("\r\n", "\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 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, '<notextile>', '</notextile>', '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('/\b\[([0-9]+)\](\s)?/Ue',
- '$this->footnoteID(\'\1\',\'\2\')', $text);
- }
-
- // -------------------------------------------------------------
- function footnoteID($id, $t)
- {
- if (empty($this->fn[$id]))
- $this->fn[$id] = uniqid(rand());
- $fnid = $this->fn[$id];
- return '<sup class="footnote"><a href="#fn'.$fnid.'">'.$id.'</a></sup>'.$t;
- }
-
- // -------------------------------------------------------------
- function glyphs($text)
- {
- // fix: hackish
- $text = preg_replace('/"\z/', "\" ", $text);
- $pnc = '[[:punct:]]';
-
- $glyph_search = array(
- '/(\w)\'(\w)/', // apostrophe's
- '/(\s)\'(\d+\w?)\b(?!\')/', // back in '88
- '/(\S)\'(?=\s|'.$pnc.'|<|$)/', // single closing
- '/\'/', // single opening
- '/(\S)\"(?=\s|'.$pnc.'|<|$)/', // double closing
- '/"/', // double opening
- '/\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])/', // 3+ uppercase acronym
- '/\b([A-Z][A-Z\'\-]+[A-Z])(?=[\s.,\)>])/', // 3+ uppercase
- '/\b( )?\.{3}/', // ellipsis
- '/(\s?)--(\s?)/', // em dash
- '/\s-(?:\s|$)/', // en dash
- '/(\d+)( ?)x( ?)(?=\d+)/', // dimension sign
- '/\b ?[([]TM[])]/i', // trademark
- '/\b ?[([]R[])]/i', // registered
- '/\b ?[([]C[])]/i', // copyright
- );
-
- extract($this->glyph, EXTR_PREFIX_ALL, 'txt');
-
- $glyph_replace = array(
- '$1'.$txt_apostrophe.'$2', // apostrophe's
- '$1'.$txt_apostrophe.'$2', // back in '88
- '$1'.$txt_quote_single_close, // single closing
- $txt_quote_single_open, // single opening
- '$1'.$txt_quote_double_close, // double closing
- $txt_quote_double_open, // double opening
- '<acronym title="$2">$1</acronym>', // 3+ uppercase acronym
- '<span class="caps">$1</span>', // 3+ uppercase
- '$1'.$txt_ellipsis, // ellipsis
- '$1'.$txt_emdash.'$2', // em dash
- ' '.$txt_endash.' ', // en dash
- '$1$2'.$txt_dimension.'$3', // dimension sign
- $txt_trademark, // trademark
- $txt_registered, // registered
- $txt_copyright, // copyright
- );
-
- $text = preg_split("/(<.*>)/U", $text, -1, PREG_SPLIT_DELIM_CAPTURE);
- foreach($text as $line) {
- if (!preg_match("/<.*>/", $line)) {
- $line = preg_replace($glyph_search, $glyph_replace, $line);
- }
- $glyph_out[] = $line;
- }
- return join('', $glyph_out);
- }
-
- // -------------------------------------------------------------
- function iAlign($in)
- {
- $vals = array(
- '<' => 'left',
- '=' => 'center',
- '>' => 'right');
- return (isset($vals[$in])) ? $vals[$in] : '';
- }
-
- // -------------------------------------------------------------
- function hAlign($in)
- {
- $vals = array(
- '<' => '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: deprecated
- function encode_high($text, $charset = "UTF-8")
- {
- return mb_encode_numericentity($text, $this->cmap(), $charset);
- }
-
- // -------------------------------------------------------------
- // NOTE: deprecated
- function decode_high($text, $charset = "UTF-8")
- {
- return mb_decode_numericentity($text, $this->cmap(), $charset);
- }
-
- // -------------------------------------------------------------
- // NOTE: deprecated
- function cmap()
- {
- $f = 0xffff;
- $cmap = array(
- 0x0080, 0xffff, 0, $f);
- return $cmap;
- }
-
- // -------------------------------------------------------------
- function encode_html($str, $quotes=1)
- {
- $a = array(
- '&' => '&',
- '<' => '<',
- '>' => '>',
- );
- if ($quotes) $a = $a + array(
- "'" => ''',
- '"' => '"',
- );
-
- return strtr($str, $a);
- }
-
- // -------------------------------------------------------------
- function textile_popup_help($name, $helpvar, $windowW, $windowH)
- {
- return ' <a target="_blank" href="http://www.textpattern.com/help/?item=' . $helpvar . '" onclick="window.open(this.href, \'popupwindow\', \'width=' . $windowW . ',height=' . $windowH . ',scrollbars,resizable\'); return false;">' . $name . '</a><br />';
-
- return $out;
- }
-
- // -------------------------------------------------------------
- // 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()
- {
- foreach (func_get_args() as $a)
- echo "\n<pre>",(is_array($a)) ? print_r($a) : $a, "</pre>\n";
- }
-
- // -------------------------------------------------------------
-
- function blockLite($text)
- {
- $this->btag = array('bq', 'p');
- return $this->block($text."\n\n");
- }
-
-
- } // end class
-
- ?>
|