1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159 |
- <?php
- if (!defined('entry') || !entry) {
- die('Not a valid page');
- }
- /**
- * 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
- {
- public $hlgn;
- public $vlgn;
- public $clas;
- public $lnge;
- public $styl;
- public $cspn;
- public $rspn;
- public $a;
- public $s;
- public $c;
- public $pnct;
- public $rel;
- public $fn;
-
- public $shelf = array();
- public $restricted = false;
- public $noimage = false;
- public $lite = false;
- public $url_schemes = array();
- public $glyph = array();
- public $hu = '';
-
- public $ver = '2.0.0';
- public $rev = '$Rev: 216 $';
-
- // -------------------------------------------------------------
- public 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;
- }
- }
-
- // -------------------------------------------------------------
- public 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;
- }
- }
-
- // -------------------------------------------------------------
- public 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;
- }
-
- // -------------------------------------------------------------
- public 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 '';
- }
-
- // -------------------------------------------------------------
- public 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;
- }
-
- // -------------------------------------------------------------
- public 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);
- }
-
- // -------------------------------------------------------------
- public 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";
- }
-
- // -------------------------------------------------------------
- public function lists($text)
- {
- return preg_replace_callback("/^([#*]+$this->c .*)$(?![^#*])/smU", array(&$this, "fList"), $text);
- }
-
- // -------------------------------------------------------------
- public 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);
- }
-
- // -------------------------------------------------------------
- public function lT($in)
- {
- return preg_match("/^#+/", $in) ? 'o' : 'u';
- }
-
- // -------------------------------------------------------------
- public function doPBr($in)
- {
- return preg_replace_callback('@<(p)([^>]*?)>(.*)(</\1>)@s', array(&$this, 'doBr'), $in);
- }
-
- // -------------------------------------------------------------
- public function doBr($m)
- {
- $content = preg_replace("@(.+)(?<!<br>|<br />)\n(?![#*\s|])@", '$1<br />', $m[3]);
- return '<'.$m[1].$m[2].'>'.$content.$m[4];
- }
-
- // -------------------------------------------------------------
- public 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);
- }
-
-
-
- // -------------------------------------------------------------
- public 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);
- }
-
- // -------------------------------------------------------------
- public 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");
- }
-
- // -------------------------------------------------------------
- public 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;
- }
-
- // -------------------------------------------------------------
- public 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;
- }
-
- // -------------------------------------------------------------
- public 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);
- }
-
- // -------------------------------------------------------------
- public 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);
- }
-
- // -------------------------------------------------------------
- public function getRefs($text)
- {
- return preg_replace_callback("/(?<=^|\s)\[(.+)\]((?:http:\/\/|\/)\S+)(?=\s|$)/U",
- array(&$this, "refs"), $text);
- }
-
- // -------------------------------------------------------------
- public function refs($m)
- {
- list(, $flag, $url) = $m;
- $this->urlrefs[$flag] = $url;
- return '';
- }
-
- // -------------------------------------------------------------
- public function checkRefs($text)
- {
- return (isset($this->urlrefs[$text])) ? $this->urlrefs[$text] : $text;
- }
-
- // -------------------------------------------------------------
- public 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;
- }
-
- // -------------------------------------------------------------
- public 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);
- }
-
- // -------------------------------------------------------------
- public 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);
- }
-
- // -------------------------------------------------------------
- public function code($text)
- {
- $text = $this->doSpecial($text, '<code>', '</code>', 'fCode');
- $text = $this->doSpecial($text, '@', '@', 'fCode');
- $text = $this->doSpecial($text, '<pre>', '</pre>', 'fPre');
- return $text;
- }
-
- // -------------------------------------------------------------
- public 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;
- }
- }
-
- // -------------------------------------------------------------
- public 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;
- }
- }
- // -------------------------------------------------------------
- public function shelve($val)
- {
- $i = uniqid(rand());
- $this->shelf[$i] = $val;
- return $i;
- }
-
- // -------------------------------------------------------------
- public function retrieve($text)
- {
- if (is_array($this->shelf)) {
- do {
- $old = $text;
- $text = strtr($text, $this->shelf);
- } while ($text != $old);
- }
-
- return $text;
- }
-
- // -------------------------------------------------------------
- // NOTE: deprecated
- public function incomingEntities($text)
- {
- return preg_replace("/&(?![#a-z0-9]+;)/i", "x%x%", $text);
- }
-
- // -------------------------------------------------------------
- // NOTE: deprecated
- public function encodeEntities($text)
- {
- return (function_exists('mb_encode_numericentity'))
- ? $this->encode_high($text)
- : htmlentities($text, ENT_NOQUOTES, "utf-8");
- }
-
- // -------------------------------------------------------------
- // NOTE: deprecated
- public function fixEntities($text)
- {
- /* de-entify any remaining angle brackets or ampersands */
- return str_replace(array(">", "<", "&"),
- array(">", "<", "&"), $text);
- }
-
- // -------------------------------------------------------------
- public 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;
- }
-
- // -------------------------------------------------------------
- public function doSpecial($text, $start, $end, $method='fSpecial')
- {
- return preg_replace_callback('/(^|\s|[[({>])'.preg_quote($start, '/').'(.*?)'.preg_quote($end, '/').'(\s|$|[\])}])?/ms',
- array(&$this, $method), $text);
- }
-
- // -------------------------------------------------------------
- public function fSpecial($m)
- {
- // A special block like notextile or code
- @list(, $before, $text, $after) = $m;
- return $before.$this->shelve($this->encode_html($text)).$after;
- }
-
- // -------------------------------------------------------------
- public function noTextile($text)
- {
- $text = $this->doSpecial($text, '<notextile>', '</notextile>', 'fTextile');
- return $this->doSpecial($text, '==', '==', 'fTextile');
- }
-
- // -------------------------------------------------------------
- public function fTextile($m)
- {
- @list(, $before, $notextile, $after) = $m;
- #$notextile = str_replace(array_keys($modifiers), array_values($modifiers), $notextile);
- return $before.$this->shelve($notextile).$after;
- }
-
- // -------------------------------------------------------------
- public function footnoteRef($text)
- {
- return preg_replace('/\b\[([0-9]+)\](\s)?/Ue',
- '$this->footnoteID(\'\1\',\'\2\')', $text);
- }
-
- // -------------------------------------------------------------
- public 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;
- }
-
- // -------------------------------------------------------------
- public 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);
- }
-
- // -------------------------------------------------------------
- public function iAlign($in)
- {
- $vals = array(
- '<' => 'left',
- '=' => 'center',
- '>' => 'right');
- return (isset($vals[$in])) ? $vals[$in] : '';
- }
-
- // -------------------------------------------------------------
- public function hAlign($in)
- {
- $vals = array(
- '<' => 'left',
- '=' => 'center',
- '>' => 'right',
- '<>' => 'justify');
- return (isset($vals[$in])) ? $vals[$in] : '';
- }
-
- // -------------------------------------------------------------
- public function vAlign($in)
- {
- $vals = array(
- '^' => 'top',
- '-' => 'middle',
- '~' => 'bottom');
- return (isset($vals[$in])) ? $vals[$in] : '';
- }
-
- // -------------------------------------------------------------
- // NOTE: deprecated
- public function encode_high($text, $charset = "UTF-8")
- {
- return mb_encode_numericentity($text, $this->cmap(), $charset);
- }
-
- // -------------------------------------------------------------
- // NOTE: deprecated
- public function decode_high($text, $charset = "UTF-8")
- {
- return mb_decode_numericentity($text, $this->cmap(), $charset);
- }
-
- // -------------------------------------------------------------
- // NOTE: deprecated
- public function cmap()
- {
- $f = 0xffff;
- $cmap = array(
- 0x0080, 0xffff, 0, $f);
- return $cmap;
- }
-
- // -------------------------------------------------------------
- public function encode_html($str, $quotes=1)
- {
- $a = array(
- '&' => '&',
- '<' => '<',
- '>' => '>',
- );
- if ($quotes) {
- $a = $a + array(
- "'" => ''',
- '"' => '"',
- );
- }
-
- return strtr($str, $a);
- }
-
- // -------------------------------------------------------------
- public 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
- public function txtgps($thing)
- {
- if (isset($_POST[$thing])) {
- if (get_magic_quotes_gpc()) {
- return stripslashes($_POST[$thing]);
- } else {
- return $_POST[$thing];
- }
- } else {
- return '';
- }
- }
-
- // -------------------------------------------------------------
- // NOTE: deprecated
- public function dump()
- {
- foreach (func_get_args() as $a) {
- echo "\n<pre>",(is_array($a)) ? print_r($a) : $a, "</pre>\n";
- }
- }
-
- // -------------------------------------------------------------
-
- public function blockLite($text)
- {
- $this->btag = array('bq', 'p');
- return $this->block($text."\n\n");
- }
- } // end class
|