Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- From 3cd5a9e53fd4d6ab6a784547a7097a6b2e0c5e39 Mon Sep 17 00:00:00 2001
- From: that0n3guy <peter@quadputer>
- Date: Mon, 10 Oct 2011 10:28:02 -0500
- Subject: [PATCH] added textile class
- ---
- include/classTextile.php | 1717 ++++++++++++++++++++++++++++++++++++++++++++++
- 1 files changed, 1717 insertions(+), 0 deletions(-)
- create mode 100644 include/classTextile.php
- diff --git include/classTextile.php b/include/classTextile.php
- new file mode 100644
- index 0000000..e32e337
- --- /dev/null
- +++ include/classTextile.php
- @@ -0,0 +1,1717 @@
- +<?php
- +
- +/**
- + * Example: get XHTML from a given Textile-markup string ($string)
- + *
- + * $textile = new Textile;
- + * echo $textile->TextileThis($string);
- + *
- + */
- +
- +/*
- +$HeadURL: https://textpattern.googlecode.com/svn/releases/4.4.1/source/textpattern/lib/classTextile.php $
- +$LastChangedRevision: 3566 $
- +*/
- +
- +/*
- +
- +_____________
- +T E X T I L E
- +
- +A Humane Web Text Generator
- +
- +Version 2.2
- +
- +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>
- +
- + Definition list:
- + Terms ;, ;;
- + Definitions :, ::
- + Consecutive paragraphs beginning with ; or : are wrapped in definition list tags.
- + Example: <dl><dt>term</dt><dd>definition</dd></dl>
- +
- +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>
- + "$":url -> <a href="url">url</a>
- + "$(title)":url -> <a href="url" title="title">url</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>
- +
- +
- +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)...
- +
- + <p>Scientists say<sup><a href="#def_id_1" id="ref_id_1a">1</sup> the moon is small.</p>
- +
- + <ol class="myclass" id="myid">
- + <li class="myliclass"><a href="#ref_id_1a"><sup>a</sup></a><span id="def_id_1"> </span><a href="url">Proof</a> of a small moon.</li>
- + <li>An unreferenced note.</li>
- + </ol>
- +
- + 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:
- + <colgroup span="3" width="100"></colgroup>
- +
- + You can omit either of the \N or width values. You may also
- + add cells after the colgroup definition to specify span/width/attributes:
- +
- + |:\5. 50 |(firstcol). |\2. 250||300|
- +
- + Becomes:
- + <colgroup span="5" width="50">
- + <col class="firstcol" />
- + <col span="2" width="250" />
- + <col />
- + <col width="300" />
- + </colgroup>
- +
- +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', '©');
- +@define('txt_half', '½');
- +@define('txt_quarter', '¼');
- +@define('txt_threequarters', '¾');
- +@define('txt_degrees', '°');
- +@define('txt_plusminus', '±');
- +@define('txt_has_unicode', @preg_match('/\pL/u', 'a')); // Detect if Unicode is compiled into PCRE
- +
- +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 $max_span_depth = 5;
- +
- + var $ver = '2.2.0';
- + var $rev = '$Rev: 3566 $';
- +
- + var $doc_root;
- +
- +// -------------------------------------------------------------
- + function Textile()
- + {
- + $this->hlgn = "(?:\<(?!>)|(?<!<)\>|\<\>|\=|[()]+(?! ))";
- + $this->vlgn = "[\-^~]";
- + $this->clas = "(?:\([^)\n]+\))"; # Don't allow classes/ids/languages/styles to span across newlines
- + $this->lnge = "(?:\[[^]\n]+\])";
- + $this->styl = "(?:\{[^}\n]+\})";
- + $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->lc = "(?:{$this->clas}|{$this->styl}|{$this->lnge})*";
- +
- + $this->pnct = '[\!"#\$%&\'()\*\+,\-\./:;<=>\?@\[\\\]\^_`{\|}\~]';
- + $this->urlch = '[\w"$\-_.+!*\'(),";\/?:@=&%#{}|\\^~\[\]`]';
- + $pnc = '[[:punct:]]';
- +
- + $this->url_schemes = array('http','https','ftp','mailto');
- +
- + $this->btag = array('bq', 'bc', 'notextile', 'pre', 'h[1-6]', 'fn\d+', 'p', '###' );
- +
- + if (txt_has_unicode) {
- + $this->regex_snippets = array(
- + 'acr' => '\p{Lu}\p{Nd}',
- + 'abr' => '\p{Lu}',
- + 'nab' => '\p{Ll}',
- + 'wrd' => '(?:\p{L}|\p{M}|\p{N}|\p{Pc})',
- + 'mod' => 'u', # Make sure to mark the unicode patterns as such, Some servers seem to need this.
- + );
- + } else {
- + $this->regex_snippets = array(
- + 'acr' => 'A-Z0-9',
- + 'abr' => 'A-Z',
- + 'nab' => 'a-z',
- + 'wrd' => '\w',
- + 'mod' => '',
- + );
- + }
- + extract( $this->regex_snippets );
- +
- + $this->glyph_search = array(
- + '/('.$wrd.')\'('.$wrd.')/'.$mod, // I'm an apostrophe
- + '/(\s)\'(\d+'.$wrd.'?)\b(?![.]?['.$wrd.']*?\')/'.$mod, // back in '88/the '90s but not in his '90s', '1', '1.' '10m' or '5.png'
- + '/(\S)\'(?=\s|'.$pnc.'|<|$)/', // single closing
- + '/\'/', // single opening
- + '/(\S)\"(?=\s|'.$pnc.'|<|$)/', // double closing
- + '/"/', // double opening
- + '/\b(['.$abr.']['.$acr.']{2,})\b(?:[(]([^)]*)[)])/'.$mod, // 3+ uppercase acronym
- + '/(?<=\s|^|[>(;-])(['.$abr.']{3,})(['.$nab.']*)(?=\s|'.$pnc.'|<|$)(?=[^">]*?(<|$))/'.$mod, // 3+ uppercase
- + '/([^.]?)\.{3}/', // ellipsis
- + '/(\s?)--(\s?)/', // em dash
- + '/\s-(?:\s|$)/', // en dash
- + '/(\d+)( ?)x( ?)(?=\d+)/', // dimension sign
- + '/(\b ?|\s|^)[([]TM[])]/i', // trademark
- + '/(\b ?|\s|^)[([]R[])]/i', // registered
- + '/(\b ?|\s|^)[([]C[])]/i', // copyright
- + '/[([]1\/4[])]/', // 1/4
- + '/[([]1\/2[])]/', // 1/2
- + '/[([]3\/4[])]/', // 3/4
- + '/[([]o[])]/', // degrees -- that's a small 'oh'
- + '/[([]\+\/-[])]/', // plus minus
- + );
- +
- + $this->glyph_replace = array(
- + '$1'.txt_apostrophe.'$2', // I'm an apostrophe
- + '$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">glyph:$1</span>$2', // 3+ uppercase
- + '$1'.txt_ellipsis, // ellipsis
- + '$1'.txt_emdash.'$2', // em dash
- + ' '.txt_endash.' ', // en dash
- + '$1$2'.txt_dimension.'$3', // dimension sign
- + '$1'.txt_trademark, // trademark
- + '$1'.txt_registered, // registered
- + '$1'.txt_copyright, // copyright
- + txt_quarter, // 1/4
- + txt_half, // 1/2
- + txt_threequarters, // 3/4
- + txt_degrees, // degrees
- + txt_plusminus, // plus minus
- + );
- +
- + if (defined('hu'))
- + $this->hu = hu;
- +
- + if (defined('DIRECTORY_SEPARATOR'))
- + $this->ds = constant('DIRECTORY_SEPARATOR');
- + else
- + $this->ds = '/';
- +
- + $this->doc_root = @$_SERVER['DOCUMENT_ROOT'];
- + if (!$this->doc_root)
- + $this->doc_root = @$_SERVER['PATH_TRANSLATED']; // IIS
- +
- + $this->doc_root = rtrim($this->doc_root, $this->ds).$this->ds;
- + }
- +
- +// -------------------------------------------------------------
- +
- + function TextileThis($text, $lite = '', $encode = '', $noimage = '', $strict = '', $rel = '')
- + {
- + $this->span_depth = 0;
- + $this->tag_index = 1;
- + $this->notes = $this->unreferencedNotes = $this->notelist_cache = array();
- + $this->note_index = 1;
- + $this->rel = ($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);
- + }
- +
- + if(!$lite) {
- + $text = $this->block($text);
- + $text = $this->placeNoteLists($text);
- + }
- +
- + $text = $this->retrieve($text);
- + $text = $this->replaceGlyphs($text);
- + $text = $this->retrieveTags($text);
- + $text = $this->retrieveURLs($text);
- + $this->span_depth = 0;
- +
- + // 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;
- +
- + $this->span_depth = 0;
- + $this->tag_index = 1;
- + $this->notes = $this->unreferencedNotes = $this->notelist_cache = array();
- + $this->note_index = 1;
- +
- + $this->rel = ($rel) ? ' rel="'.$rel.'"' : '';
- +
- + // escape any raw html
- + $text = $this->encode_html($text, 0);
- +
- + $text = $this->cleanWhiteSpace($text);
- +
- + if($lite) {
- + $text = $this->blockLite($text);
- + } else {
- + $text = $this->block($text);
- + $text = $this->placeNoteLists($text);
- + }
- +
- + $text = $this->retrieve($text);
- + $text = $this->replaceGlyphs($text);
- + $text = $this->retrieveTags($text);
- + $text = $this->retrieveURLs($text);
- + $this->span_depth = 0;
- +
- + // just to be tidy
- + $text = str_replace("<br />", "<br />\n", $text);
- +
- + return $text;
- + }
- +
- +// -------------------------------------------------------------
- + function pba($in, $element = "", $include_id = 1) // "parse block attributes"
- + {
- + $style = '';
- + $class = '';
- + $lang = '';
- + $colspan = '';
- + $rowspan = '';
- + $span = '';
- + $width = '';
- + $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)) {
- + $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 ($element == 'col') {
- + if (preg_match("/(?:\\\\(\d+))?\s*(\d+)?/", $matched, $csp)) {
- + $span = isset($csp[1]) ? $csp[1] : '';
- + $width = isset($csp[2]) ? $csp[2] : '';
- + }
- + }
- +
- + if ($this->restricted)
- + return ($lang) ? ' lang="' . $lang . '"':'';
- +
- + $o = '';
- + if( $style ) {
- + foreach($style as $s) {
- + $parts = explode(';', $s);
- + foreach( $parts as $p ) {
- + $p = trim($p, '; ');
- + if( !empty( $p ) )
- + $o .= $p.'; ';
- + }
- + }
- + $style = trim( strtr($o, array("\n"=>'',';;'=>';')) );
- + }
- +
- + return join('',array(
- + ($style) ? ' style="' . $style .'"':'',
- + ($class) ? ' class="' . $class .'"':'',
- + ($lang) ? ' lang="' . $lang .'"':'',
- + ($id and $include_id) ? ' id="' . $id .'"':'',
- + ($colspan) ? ' colspan="' . $colspan .'"':'',
- + ($rowspan) ? ' rowspan="' . $rowspan .'"':'',
- + ($span) ? ' span="' . $span .'"':'',
- + ($width) ? ' width="' . $width .'"':'',
- + ));
- + }
- + 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|dl|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}\.? ?\|.*\|)[\s]*\n\n/smU",
- + array(&$this, "fTable"), $text);
- + }
- +
- +// -------------------------------------------------------------
- + function fTable($matches)
- + {
- + $tatts = $this->pba($matches[1], 'table');
- +
- + $sum = trim($matches[2]) ? ' summary="'.htmlspecialchars(trim($matches[2])).'"' : '';
- + $cap = '';
- + $colgrp = $last_rgrp = '';
- + foreach(preg_split("/\|\s*?$/m", $matches[3], -1, PREG_SPLIT_NO_EMPTY) as $row) {
- + // Caption
- + if (preg_match("/^\|\=($this->s$this->a$this->c)\. ([^\|\n]*)(.*)/s", ltrim($row), $cmtch)) {
- + $capts = $this->pba($cmtch[1]);
- + $cap = "\t<caption".$capts.">".trim($cmtch[2])."</caption>\n";
- + $row = $cmtch[3];
- + }
- +
- + // Colgroup
- + if (preg_match("/^\|:($this->s$this->a$this->c\. .*)/m", ltrim($row), $gmtch)) {
- + $idx=0;
- + foreach (explode('|', str_replace('.', '', $gmtch[1])) as $col) {
- + $gatts = $this->pba(trim($col), 'col');
- + $colgrp .= "\t<col".(($idx==0) ? "group".$gatts.">" : $gatts." />")."\n";
- + $idx++;
- + }
- + $colgrp .= "\t</colgroup>\n";
- + continue;
- + }
- +
- + preg_match("/(:?^\|($this->vlgn)($this->s$this->a$this->c)\.\s*$\n)?^(.*)/sm", ltrim($row), $grpmatch);
- +
- + // Row group
- + $rgrp = isset($grpmatch[2]) ? (($grpmatch[2] == '^') ? 'head' : ( ($grpmatch[2] == '~') ? 'foot' : (($grpmatch[2] == '-') ? 'body' : '' ) ) ) : '';
- + $rgrpatts = isset($grpmatch[3]) ? $this->pba($grpmatch[3]) : '';
- + $row = $grpmatch[4];
- +
- + if (preg_match("/^($this->a$this->c\. )(.*)/m", ltrim($row), $rmtch)) {
- + $ratts = $this->pba($rmtch[1], 'tr');
- + $row = $rmtch[2];
- + } else $ratts = '';
- +
- + $cells = array();
- + $cellctr = 0;
- + 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($cell);
- +
- + if ($cellctr>0) // Ignore first 'cell': it precedes the opening pipe
- + $cells[] = $this->doTagBr("t$ctyp", "\t\t\t<t$ctyp$catts>$cell</t$ctyp>");
- +
- + $cellctr++;
- + }
- + $grp = (($rgrp && $last_rgrp) ? "\t</t".$last_rgrp.">\n" : '') . (($rgrp) ? "\t<t".$rgrp.$rgrpatts.">\n" : '');
- + $last_rgrp = ($rgrp) ? $rgrp : $last_rgrp;
- + $rows[] = $grp."\t\t<tr$ratts>\n" . join("\n", $cells) . ($cells ? "\n" : "") . "\t\t</tr>";
- + unset($cells, $catts);
- + }
- +
- + return "\t<table{$tatts}{$sum}>\n" .$cap. $colgrp. join("\n", $rows) . "\n".(($last_rgrp) ? "\t</t".$last_rgrp.">\n" : '')."\t</table>\n\n";
- + }
- +
- +// -------------------------------------------------------------
- + function lists($text)
- + {
- + return preg_replace_callback("/^([#*;:]+$this->lc[ .].*)$(?![^#*;:])/smU", array(&$this, "fList"), $text);
- + }
- +
- +// -------------------------------------------------------------
- + function fList($m)
- + {
- + $text = preg_split('/\n(?=[*#;:])/m', $m[0]);
- + $pt = '';
- + foreach($text as $nr => $line) {
- + $nextline = isset($text[$nr+1]) ? $text[$nr+1] : false;
- + if (preg_match("/^([#*;:]+)($this->lc)[ .](.*)$/s", $line, $m)) {
- + list(, $tl, $atts, $content) = $m;
- + $content = trim($content);
- + $nl = '';
- + $ltype = $this->lT($tl);
- + $litem = (strpos($tl, ';') !== false) ? 'dt' : ((strpos($tl, ':') !== false) ? 'dd' : 'li');
- + $showitem = (strlen($content) > 0);
- +
- + if (preg_match("/^([#*;:]+)($this->lc)[ .].*/", $nextline, $nm))
- + $nl = $nm[1];
- +
- + if ((strpos($pt, ';') !== false) && (strpos($tl, ':') !== false)) {
- + $lists[$tl] = 2; // We're already in a <dl> so flag not to start another
- + }
- +
- + $atts = $this->pba($atts);
- + if (!isset($lists[$tl])) {
- + $lists[$tl] = 1;
- + $line = "\t<" . $ltype . "l$atts>" . (($showitem) ? "\n\t\t<$litem>" . $content : '');
- + } else {
- + $line = ($showitem) ? "\t\t<$litem$atts>" . $content : '';
- + }
- +
- + if((strlen($nl) <= strlen($tl))) $line .= (($showitem) ? "</$litem>" : '');
- + foreach(array_reverse($lists) as $k => $v) {
- + if(strlen($k) > strlen($nl)) {
- + $line .= ($v==2) ? '' : "\n\t</" . $this->lT($k) . "l>";
- + if((strlen($k) > 1) && ($v != 2))
- + $line .= "</".$litem.">";
- + unset($lists[$k]);
- + }
- + }
- + $pt = $tl; // Remember the current Textile tag
- + }
- + else {
- + $line .= "\n";
- + }
- + $out[] = $line;
- + }
- + return $this->doTagBr($litem, join("\n", $out));
- + }
- +
- +// -------------------------------------------------------------
- + function lT($in)
- + {
- + return preg_match("/^#+/", $in) ? 'o' : ((preg_match("/^\*+/", $in)) ? 'u' : 'd');
- + }
- +
- +// -------------------------------------------------------------
- + function doTagBr($tag, $in)
- + {
- + return preg_replace_callback('@<('.preg_quote($tag).')([^>]*?)>(.*)(</\1>)@s', array(&$this, 'fBr'), $in);
- + }
- +
- +// -------------------------------------------------------------
- + function doPBr($in)
- + {
- + return preg_replace_callback('@<(p)([^>]*?)>(.*)(</\1>)@s', array(&$this, 'fPBr'), $in);
- + }
- +
- +// -------------------------------------------------------------
- + function fPBr($m)
- + {
- + # Less restrictive version of fBr() ... used only in paragraphs where the next
- + # row may start with a smiley or perhaps something like '#8 bolt...' or '*** stars...'
- + $content = preg_replace("@(.+)(?<!<br>|<br />)\n(?![\s|])@", '$1<br />', $m[3]);
- + return '<'.$m[1].$m[2].'>'.$content.$m[4];
- + }
- +
- +// -------------------------------------------------------------
- + function fBr($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 = '';
- + $eat = false;
- +
- + $out = array();
- +
- + 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, $eat) = $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, $eat) = $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;
- + elseif(!$eat)
- + $out[] = $line;
- +
- + if (!$ext) {
- + $tag = 'p';
- + $atts = '';
- + $cite = '';
- + $graf = '';
- + $eat = false;
- + }
- + }
- + if ($ext) $out[count($out)-1] .= $c1;
- + return join("\n\n", $out);
- + }
- +
- +// -------------------------------------------------------------
- + function fBlock($m)
- + {
- + extract($this->regex_snippets);
- + list(, $tag, $att, $ext, $cite, $content) = $m;
- + $atts = $this->pba($att);
- +
- + $o1 = $o2 = $c2 = $c1 = '';
- + $eat = false;
- +
- + if( $tag === 'p' ) {
- + # Is this an anonymous block with a note definition?
- + $notedef = preg_replace_callback("/
- + ^note\# # start of note def marker
- + ([$wrd:-]+) # !label
- + ([*!^]?) # !link
- + ({$this->c}) # !att
- + \.[\s]+ # end of def marker
- + (.*)$ # !content
- + /x$mod", array(&$this, "fParseNoteDefs"), $content);
- + if( empty($notedef) ) # It will be empty if the regex matched and ate it.
- + return array($o1, $o2, $notedef, $c2, $c1, true);
- + }
- +
- + if (preg_match("/fn(\d+)/", $tag, $fns)) {
- + $tag = 'p';
- + $fnid = empty($this->fn[$fns[1]]) ? $fns[1] : $this->fn[$fns[1]];
- +
- + # If there is an author-specified ID goes on the wrapper & the auto-id gets pushed to the <sup>
- + $supp_id = '';
- + if (strpos($atts, ' id=') === false)
- + $atts .= ' id="fn' . $fnid . '"';
- + else
- + $supp_id = ' id="fn' . $fnid . '"';
- +
- + if (strpos($atts, 'class=') === false)
- + $atts .= ' class="footnote"';
- +
- + $backlink = (strpos($att, '^') === false) ? $fns[1] : '<a href="#fnrev' . $fnid . '">'.$fns[1].'</a>';
- + $sup = "<sup$supp_id>$backlink</sup>";
- +
- + $content = $sup . ' ' . $content;
- + }
- +
- + if ($tag == "bq") {
- + $cite = $this->shelveURL($cite);
- + $cite = ($cite != '') ? ' cite="' . $cite . '"' : '';
- + $o1 = "\t<blockquote$cite$atts>\n";
- + $o2 = "\t\t<p".$this->pba($att, '', 0).">";
- + $c2 = "</p>";
- + $c1 = "\n\t</blockquote>";
- + }
- + elseif ($tag == 'bc') {
- + $o1 = "<pre$atts>";
- + $o2 = "<code".$this->pba($att, '', 0).">";
- + $c2 = "</code>";
- + $c1 = "</pre>";
- + $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 = "<pre$atts>";
- + $o2 = $c2 = '';
- + $c1 = "</pre>";
- + }
- + 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("@<p>notelist({$this->c})(?:\:($wrd))?([\^!]?)(\+?)\.[\s]*</p>@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)...
- + $_ = '<span id="noteref'.$refid.'">'.$num.'</span>';
- + if( !$nolink )
- + $_ = '<a href="#note'.$id.'">'.$_.'</a>';
- +
- + # Build the reference...
- + $_ = '<sup'.$atts.'>'.$_.'</sup>';
- +
- + 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".'<li'.$atts.'>'.$links.'<span id="note'.$id.'"> </span>'.$content.'</li>';
- + } else {
- + $o[] = "\t".'<li'.$atts.'>'.$links.' Undefined Note [#'.$info['seq'].'].</li>';
- + }
- + }
- + }
- + if( '+' == $extras && !empty($this->unreferencedNotes) ) {
- + foreach($this->unreferencedNotes as $seq=>$info) {
- + if( !empty($info['def'])) {
- + extract($info['def']);
- + $o[] = "\t".'<li'.$atts.'>'.$content.'</li>';
- + }
- + }
- + }
- +
- + $this->notelist_cache[$index] = join("\n",$o);
- + }
- +
- + $_ = ($this->notelist_cache[$index]) ? $this->notelist_cache[$index] : '';
- +
- + if( !empty($_) ) {
- + $list_atts = $this->pba($att);
- + $_ = "<ol$list_atts>\n$_\n</ol>";
- + }
- +
- + return $_;
- + }
- +
- +// -------------------------------------------------------------
- + function makeBackrefLink( &$info, $g_links, $i )
- + {
- + $atts = $content = $id = $link = '';
- + @extract( $info['def'] );
- + $backlink_type = ($link) ? $link : $g_links;
- +
- + $i_ = strtr( $this->encode_high($i) , array('&'=>'', ';'=>'', '#'=>''));
- + $decode = (strlen($i) !== strlen($i_));
- +
- + if( $backlink_type === '!' )
- + return '';
- + elseif( $backlink_type === '^' )
- + return '<a href="#noteref'.$info['refids'][0].'"><sup>'.$i.'</sup></a>';
- + else {
- + $_ = array();
- + foreach( $info['refids'] as $id ) {
- + $_[] = '<a href="#noteref'.$id.'"><sup>'. ( ($decode) ? $this->decode_high('&#'.$i_.';') : $i_ ) .'</sup></a>';
- + $i_++;
- + }
- + $_ = join( ' ', $_ );
- + return $_;
- + }
- +
- + return '';
- + }
- +
- +// -------------------------------------------------------------
- + function links($text)
- + {
- + return preg_replace_callback('/
- + (^|(?<=[\s>.\(])|[{[]) # $pre
- + " # start
- + (' . $this->c . ') # $atts
- + ([^"]+?) # $text
- + (?:\(([^)]+?)\)(?="))? # $title
- + ":
- + ('.$this->urlch.'+?) # $url
- + (\/)? # $slash
- + ([^\w\/;]*?) # $post
- + ([\]}]|(?=\s|$|\)))
- + /x', array(&$this, "fLink"), $text);
- + }
- +
- +// -------------------------------------------------------------
- + function fLink($m)
- + {
- + list(, $pre, $atts, $text, $title, $url, $slash, $post, $tail) = $m;
- +
- + if( '$' === $text ) $text = $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->shelveURL($url.$slash);
- +
- + $opentag = '<a href="' . $url . '"' . $atts . $this->rel . '>';
- + $closetag = '</a>';
- + $tags = $this->storeTags($opentag, $closetag);
- + $out = $tags['open'].trim($text).$tags['close'];
- +
- + if (($pre and !$tail) or ($tail and !$pre))
- + {
- + $out = $pre.$out.$post.$tail;
- + $post = '';
- + }
- +
- + return $this->shelve($out).$post;
- + }
- +
- +// -------------------------------------------------------------
- + function getRefs($text)
- + {
- + return preg_replace_callback("/^\[(.+)\]((?:http:\/\/|\/)\S+)(?=\s|$)/Um",
- + array(&$this, "refs"), $text);
- + }
- +
- +// -------------------------------------------------------------
- + function refs($m)
- + {
- + list(, $flag, $url) = $m;
- + $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 !
- + (\<|\=|\>)? # 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
- + /x", array(&$this, "fImage"), $text);
- + }
- +
- +// -------------------------------------------------------------
- + function fImage($m)
- + {
- + list(, $algn, $atts, $url) = $m;
- + $url = htmlspecialchars($url);
- + $atts = $this->pba($atts);
- + $atts .= ($algn != '') ? ' align="' . $this->iAlign($algn) . '"' : '';
- + if (isset($m[4])) {
- + $m[4] = htmlspecialchars($m[4]);
- + $atts .= ' title="' . $m[4] . '" alt="' . $m[4] . '"';
- + } 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 = (isset($m[5])) ? $this->shelveURL($m[5]) : '';
- + $url = $this->shelveURL($url);
- +
- + $out = array(
- + ($href) ? '<a href="' . $href . '">' : '',
- + '<img src="' . $url . '"' . $atts . ' />',
- + ($href) ? '</a>' : ''
- + );
- +
- + return $this->shelve(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;
- + return $before.$this->shelve('<code>'.$this->r_encode_html($text).'</code>').$after;
- + }
- +
- +// -------------------------------------------------------------
- + function fPre($m)
- + {
- + @list(, $before, $text, $after) = $m;
- + return $before.'<pre>'.$this->shelve($this->r_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 = 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, '<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('/(?<=\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 : '<a href="#fn'.$fnid.'">'.$id.'</a>';
- + $footref = '<sup '.$backref.'class="footnote">'.$footref.'</sup>';
- +
- + 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 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: 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);
- + }
- +
- +// -------------------------------------------------------------
- +// NOTE: deprecated
- + 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_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, input has already been escaped
- + if ($this->restricted)
- + return $str;
- + return $this->encode_html($str, $quotes);
- + }
- +
- +// -------------------------------------------------------------
- + 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()
- + {
- + static $bool = array( 0=>'false', 1=>'true' );
- + foreach (func_get_args() as $a)
- + echo "\n<pre>",(is_array($a)) ? print_r($a) : ((is_bool($a)) ? $bool[(int)$a] : $a), "</pre>\n";
- + return $this;
- + }
- +
- +// -------------------------------------------------------------
- +
- + function blockLite($text)
- + {
- + $this->btag = array('bq', 'p');
- + return $this->block($text."\n\n");
- + }
- +
- +
- +} // end class
- --
- 1.7.0.4
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement