12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082 |
- <?php
- // @(#) $Id: Textile.php,v 1.13 2005/03/21 15:26:55 jhriggs Exp $
-
- /* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
- /**
- * The Textile class serves as a wrapper for all Textile
- * functionality. It is not inherently necessary that Textile be a
- * class; however, this is as close as one can get to a namespace in
- * PHP. Wrapping the functionality in a class prevents name
- * collisions and dirtying of the global namespace. The Textile class
- * uses no global variables and will not have any side-effects on
- * other code.
- *
- * @brief Class wrapper for the Textile functionality.
- */
- class Textile {
- /**
- * The @c array containing all of the Textile options for this
- * object.
- *
- * @private
- */
- var $options = array();
-
- /**
- * The @c string containing the regular expression pattern for a
- * URL. This variable is initialized by @c _create_re() which is
- * called in the contructor.
- *
- * @private
- */
- var $urlre;
-
- /**
- * The @c string containing the regular expression pattern for
- * punctuation characters. This variable is initialized by
- * @c _create_re() which is called in the contructor.
- *
- * @private
- */
- var $punct;
-
- /**
- * The @c string containing the regular expression pattern for the
- * valid vertical alignment codes. This variable is initialized by
- * @c _create_re() which is called in the contructor.
- *
- * @private
- */
- var $valignre;
-
- /**
- * The @c string containing the regular expression pattern for the
- * valid table alignment codes. This variable is initialized by
- * @c _create_re() which is called in the contructor.
- *
- * @private
- */
- var $tblalignre;
-
- /**
- * The @c string containing the regular expression pattern for the
- * valid horizontal alignment codes. This variable is initialized by
- * @c _create_re() which is called in the contructor.
- *
- * @private
- */
- var $halignre;
-
- /**
- * The @c string containing the regular expression pattern for the
- * valid alignment codes. This variable is initialized by
- * @c _create_re() which is called in the contructor.
- *
- * @private
- */
- var $alignre;
-
- /**
- * The @c string containing the regular expression pattern for the
- * valid image alignment codes. This variable is initialized by
- * @c _create_re() which is called in the contructor.
- *
- * @private
- */
- var $imgalignre;
-
- /**
- * The @c string containing the regular expression pattern for a
- * class, ID, and/or padding specification. This variable is
- * initialized by @c _create_re() which is called in the contructor.
- *
- * @private
- */
- var $clstypadre;
-
- /**
- * The @c string containing the regular expression pattern for a
- * class and/or ID specification. This variable is initialized by
- * @c _create_re() which is called in the contructor.
- *
- * @private
- */
- var $clstyre;
-
- /**
- * The @c string containing the regular expression pattern for a
- * class, ID, and/or filter specification. This variable is
- * initialized by @c _create_re() which is called in the contructor.
- *
- * @private
- */
- var $clstyfiltre;
-
- /**
- * The @c string containing the regular expression pattern for a
- * code block. This variable is initialized by @c _create_re() which
- * is called in the contructor.
- *
- * @private
- */
- var $codere;
-
- /**
- * The @c string containing the regular expression pattern for all
- * block tags. This variable is initialized by @c _create_re() which
- * is called in the contructor.
- *
- * @private
- */
- var $blocktags;
-
- /**
- * The @c array containing the list of lookup links.
- *
- * @private
- */
- var $links = array();
-
- /**
- * The @c array containing <code>array</code>s of replacement blocks
- * of text that are temporary removed from the input text to avoid
- * processing. Different functions use this replacement
- * functionality, and each shifts its own replacement array into
- * position 0 and removes it when finished. This avoids having
- * several replacement variables and/or functions clobbering
- * eachothers' replacement blocks.
- *
- * @private
- */
- var $repl = array();
-
- /**
- * The @c array containing temporary <code>string</code>s used in
- * replacement callbacks. *JHR*
- *
- * @private
- */
- var $tmp = array();
-
- /**
- * Instantiates a new Textile object. Optional options
- * can be passed to initialize the object. Attributes for the
- * options key are the same as the get/set method names
- * documented here.
- *
- * @param $options The @c array specifying the options to use for
- * this object.
- *
- * @public
- */
- function Textile($options = array()) {
- $this->options = $options;
- $this->options['filters'] = ($this->options['filters'] ? $this->options['filters'] : array());
- $this->options['charset'] = ($this->options['charset'] ? $this->options['charset'] : 'utf-8');
- $this->options['char_encoding'] = (isset($this->options['char_encoding']) ? $this->options['char_encoding'] : 1);
- $this->options['do_quotes'] = (isset($this->options['do_quotes']) ? $this->options['do_quotes'] : 1);
- $this->options['trim_spaces'] = (isset($this->options['trim_spaces']) ? $this->options['trim_spaces'] : 0);
- $this->options['smarty_mode'] = (isset($this->options['smarty_mode']) ? $this->options['smarty_mode'] : 1);
- $this->options['preserve_spaces'] = (isset($this->options['preserve_spaces']) ? $this->options['preserve_spaaces'] : 0);
- $this->options['head_offset'] = (isset($this->options['head_offset']) ? $this->options['head_offset'] : 0);
-
- if (is_array($this->options['css'])) {
- $this->css($this->options['css']);
- }
- $this->options['macros'] = ($this->options['macros'] ? $this->options['macros'] : $this->default_macros());
- if (isset($this->options['flavor'])) {
- $this->flavor($this->options['flavor']);
- } else {
- $this->flavor('xhtml1/css');
- }
- $this->_create_re();
- } // function Textile
-
- // getter/setter methods...
-
- /**
- * Used to set Textile attributes. Attribute names are the same
- * as the get/set method names documented here.
- *
- * @param $opt A @c string specifying the name of the option to
- * change or an @c array specifying options and values.
- * @param $value The value for the provided option name.
- *
- * @public
- */
- function set($opt, $value = NULL) {
- if (is_array($opt)) {
- foreach ($opt as $opt => $value) {
- $this->set($opt, $value);
- }
- } else {
- // the following options have special set methods
- // that activate upon setting:
- if ($opt == 'charset') {
- $this->charset($value);
- } elseif ($opt == 'css') {
- $this->css($value);
- } elseif ($opt == 'flavor') {
- $this->flavor($value);
- } else {
- $this->options[$opt] = $value;
- }
- }
- } // function set
-
- /**
- * Used to get Textile attributes. Attribute names are the same
- * as the get/set method names documented here.
- *
- * @param $opt A @c string specifying the name of the option to get.
- *
- * @return The value for the provided option.
- *
- * @public
- */
- function get($opt) {
- return $this->options[$opt];
- } // function get
-
- /**
- * Gets or sets the "disable html" control, which allows you to
- * prevent HTML tags from being used within the text processed.
- * Any HTML tags encountered will be removed if disable html is
- * enabled. Default behavior is to allow HTML.
- *
- * @param $disable_html If provided, a @c bool indicating whether or
- * not this object should disable HTML.
- *
- * @return A true value if this object disables HTML; a false value
- * otherwise.
- *
- * @public
- */
- function disable_html($disable_html = NULL) {
- if ($disable_html != NULL) {
- $this->options['disable_html'] = $disable_html;
- }
- return ($this->options['disable_html'] ? $this->options['disable_html'] : 0);
- } // function disable_html
-
- /**
- * Gets or sets the relative heading offset, which allows you to
- * change the heading level used within the text processed. For
- * example, if the heading offset is '2' and the text contains an
- * 'h1' block, an \<h3\> block will be output.
- *
- * @param $head_offset If provided, an @c integer specifying the
- * heading offset for this object.
- *
- * @return An @c integer containing the heading offset for this
- * object.
- *
- * @public
- */
- function head_offset($head_offset = NULL) {
- if ($head_offset != NULL) {
- $this->options['head_offset'] = $head_offset;
- }
- return ($this->options['head_offset'] ? $this->options['head_offset'] : 0);
- } // function head_offset
-
- /**
- * Assigns the HTML flavor of output from Textile. Currently
- * these are the valid choices: html, xhtml (behaves like "xhtml1"),
- * xhtml1, xhtml2. Default flavor is "xhtml1".
- *
- * Note that the xhtml2 flavor support is experimental and incomplete
- * (and will remain that way until the XHTML 2.0 draft becomes a
- * proper recommendation).
- *
- * @param $flavor If provided, a @c string specifying the flavor to
- * be used for this object.
- *
- * @return A @c string containing the flavor for this object.
- *
- * @public
- */
- function flavor($flavor = NULL) {
- if ($flavor != NULL) {
- $this->options['flavor'] = $flavor;
- if (preg_match('/^xhtml(\d)?(\D|$)/', $flavor, $matches)) {
- if ($matches[1] == '2') {
- $this->options['_line_open'] = '<l>';
- $this->options['_line_close'] = '</l>';
- $this->options['_blockcode_open'] = '<blockcode>';
- $this->options['_blockcode_close'] = '</blockcode>';
- $this->options['css_mode'] = 1;
- } else {
- // xhtml 1.x
- $this->options['_line_open'] = '';
- $this->options['_line_close'] = '<br />';
- $this->options['_blockcode_open'] = '<pre><code>';
- $this->options['_blockcode_close'] = '</code></pre>';
- $this->options['css_mode'] = 1;
- }
- } elseif (preg_match('/^html/', $flavor)) {
- $this->options['_line_open'] = '';
- $this->options['_line_close'] = '<br>';
- $this->options['_blockcode_open'] = '<pre><code>';
- $this->options['_blockcode_close'] = '</code></pre>';
- $this->options['css_mode'] = preg_match('/\/css/', $flavor);
- }
- if ($this->options['css_mode'] && !isset($this->options['css'])) { $this->_css_defaults(); }
- }
- return $this->options['flavor'];
- } // function flavor
-
- /**
- * Gets or sets the css support for Textile. If css is enabled,
- * Textile will emit CSS rules. You may pass a 1 or 0 to enable
- * or disable CSS behavior altogether. If you pass an associative array,
- * you may assign the CSS class names that are used by
- * Textile. The following key names for such an array are
- * recognized:
- *
- * <ul>
- * <li><b>class_align_right</b>
- *
- * defaults to 'right'</li>
- *
- * <li><b>class_align_left</b>
- *
- * defaults to 'left'</li>
- *
- * <li><b>class_align_center</b>
- *
- * defaults to 'center'</li>
- *
- * <li><b>class_align_top</b>
- *
- * defaults to 'top'</li>
- *
- * <li><b>class_align_bottom</b>
- *
- * defaults to 'bottom'</li>
- *
- * <li><b>class_align_middle</b>
- *
- * defaults to 'middle'</li>
- *
- * <li><b>class_align_justify</b>
- *
- * defaults to 'justify'</li>
- *
- * <li><b>class_caps</b>
- *
- * defaults to 'caps'</li>
- *
- * <li><b>class_footnote</b>
- *
- * defaults to 'footnote'</li>
- *
- * <li><b>id_footnote_prefix</b>
- *
- * defaults to 'fn'</li>
- *
- * </ul>
- *
- * @param $css If provided, either a @c bool indicating whether or
- * not this object should use css or an associative @c array
- * specifying class names to use.
- *
- * @return Either an associative @c array containing class names
- * used by this object, or a true or false value indicating
- * whether or not this object uses css.
- *
- * @public
- */
- function css($css = NULL) {
- if ($css != NULL) {
- if (is_array($css)) {
- $this->options['css'] = $css;
- $this->options['css_mode'] = 1;
- } else {
- $this->options['css_mode'] = $css;
- if ($this->options['css_mode'] && !isset($this->options['css'])) { $this->_css_defaults(); }
- }
- }
- return ($this->options['css_mode'] ? $this->options['css'] : 0);
- } // function css
-
- /**
- * Gets or sets the character set targetted for publication.
- * At this time, Textile only changes its behavior
- * if the 'utf-8' character set is assigned.
- *
- * Specifically, if utf-8 is requested, any special characters
- * created by Textile will be output as native utf-8 characters
- * rather than HTML entities.
- *
- * @param $charset If provided, a @c string specifying the
- * characater set to be used for this object.
- *
- * @return A @c string containing the character set for this object.
- *
- * @public
- */
- function charset($charset = NULL) {
- if ($charset != NULL) {
- $this->options['charset'] = $charset;
- if (preg_match('/^utf-?8$/i', $this->options['charset'])) {
- $this->char_encoding(0);
- } else {
- $this->char_encoding(1);
- }
- }
- return $this->options['charset'];
- } // function charset
-
- /**
- * Gets or sets the physical file path to root of document files.
- * This path is utilized when images are referenced and size
- * calculations are needed (the getimagesize() function is used to read
- * the image dimensions).
- *
- * @param $docroot If provided, a @c string specifying the document
- * root to use for this object.
- *
- * @return A @c string containing the docroot for this object.
- *
- * @public
- */
- function docroot($docroot = NULL) {
- if ($docroot != NULL) {
- $this->options['docroot'] = $docroot;
- }
- return $this->options['docroot'];
- } // function docroot
-
- /**
- * Gets or sets the 'trim spaces' control flag. If enabled, this
- * will clear any lines that have only spaces on them (the newline
- * itself will remain).
- *
- * @param $trim_spaces If provided, a @c bool indicating whether or
- * not this object should trim spaces.
- *
- * @return A true value if this object trims spaces; a false value
- * otherwise.
- *
- * @public
- */
- function trim_spaces($trim_spaces = NULL) {
- if ($trim_spaces != NULL) {
- $this->options['trim_spaces'] = $trim_spaces;
- }
- return $this->options['trim_spaces'];
- } // function trim_spaces
-
- /**
- * Gets or sets a parameter that is passed to filters.
- *
- * @param $filter_param If provided, a parameter that this object
- * should pass to filters.
- *
- * @return The parameter this object passes to filters.
- *
- * @public
- */
- function filter_param($filter_param = NULL) {
- if ($filter_param != NULL) {
- $this->options['filter_param'] = $filter_param;
- }
- return $this->options['filter_param'];
- } // function filter_param
-
- /**
- * Gets or sets the 'preserve spaces' control flag. If enabled, this
- * will replace any double spaces within the paragraph data with the
- * \&#8195; HTML entity (wide space). The default is 0. Spaces will
- * pass through to the browser unchanged and render as a single space.
- * Note that this setting has no effect on spaces within \<pre\>,
- * \<code\> blocks or \<script\> sections.
- *
- * @param $preserve_spaces If provided, a @c bool indicating whether
- * or not this object should preserve spaces.
- *
- * @return A true value if this object preserves spaces; a false
- * value otherwise.
- *
- * @public
- */
- function preserve_spaces($preserve_spaces = NULL) {
- if ($preserve_spaces != NULL) {
- $this->options['preserve_spaces'] = $preserve_spaces;
- }
- return $this->options['preserve_spaces'];
- } // function preserve_spaces
-
- /**
- * Gets or sets a list of filters to make available for
- * Textile to use. Returns a hash reference of the currently
- * assigned filters.
- *
- * @param $filters If provided, an @c array of filters to be used
- * for this object.
- *
- * @return An @c array containing the filters for this object.
- *
- * @public
- */
- function filters($filters = NULL) {
- if ($filters != NULL) {
- $this->options['filters'] = $filters;
- }
- return $this->options['filters'];
- } // function filters
-
- /**
- * Gets or sets the character encoding logical flag. If character
- * encoding is enabled, the htmlentities function is used to
- * encode special characters. If character encoding is disabled,
- * only \<, \>, " and & are encoded to HTML entities.
- *
- * @param $char_encoding If provided, a @c bool indicating whether
- * or not this object should encode special characters.
- *
- * @return A true value if this object encodes special characters; a
- * false value otherwise.
- *
- * @public
- */
- function char_encoding($char_encoding = NULL) {
- if ($char_encoding !== NULL) {
- $this->options['char_encoding'] = $char_encoding;
- }
- return $this->options['char_encoding'];
- } // function char_encoding
-
- /**
- * Gets or sets the "smart quoting" control flag. Returns the
- * current setting.
- *
- * @param $do_quotes If provided, a @c bool indicating whether or
- * not this object should use smart quoting.
- *
- * @return A true value if this object uses smart quoting; a false
- * value otherwise.
- *
- * @public
- */
- function handle_quotes($do_quotes = NULL) {
- if ($do_quotes != NULL) {
- $this->options['do_quotes'] = $do_quotes;
- }
- return $this->options['do_quotes'];
- } // function handle_quotes
-
- // end of getter/setter methods
-
- /**
- * Creates the class variable regular expression patterns used by
- * Textile. They are not initialized in the declaration, because
- * some rely on the others, requiring a @c $this reference.
- *
- * PHP does not have the Perl qr operator to quote or precompile
- * patterns, so to avoid escaping and matching problems, all
- * patterns must use the same delimiter; this implementation uses
- * {}. Every use of these patterns within this class has been
- * changed to use these delimiters. *JHR*
- *
- * @private
- */
- function _create_re() {
- // a URL discovery regex. This is from Mastering Regex from O'Reilly.
- // Some modifications by Brad Choate <brad at bradchoate dot com>
- $this->urlre = '(?:
- # Must start out right...
- (?=[a-zA-Z0-9./#])
- # Match the leading part (proto://hostname, or just hostname)
- (?:
- # ftp://, http://, or https:// leading part
- (?:ftp|https?|telnet|nntp)://(?:\w+(?::\w+)?@)?[-\w]+(?:\.\w[-\w]*)+
- |
- (?:mailto:)?[-\+\w]+@[-\w]+(?:\.\w[-\w]*)+
- |
- # or, try to find a hostname with our more specific sub-expression
- (?i: [a-z0-9] (?:[-a-z0-9]*[a-z0-9])? \. )+ # sub domains
- # Now ending .com, etc. For these, require lowercase
- (?-i: com\b
- | edu\b
- | biz\b
- | gov\b
- | in(?:t|fo)\b # .int or .info
- | mil\b
- | net\b
- | org\b
- | museum\b
- | aero\b
- | coop\b
- | name\b
- | pro\b
- | [a-z][a-z]\b # two-letter country codes
- )
- )?
-
- # Allow an optional port number
- (?: : \d+ )?
-
- # The rest of the URL is optional, and begins with / . . .
- (?:
- /?
- # The rest are heuristics for what seems to work well
- [^.!,?;:"\'<>()\[\]{}\s\x7F-\xFF]*
- (?:
- [.!,?;:]+ [^.!,?;:"\'<>()\[\]{}\s\x7F-\xFF]+ #\'"
- )*
- )?
- )';
-
- $this->punct = '[\!"\#\$%&\'()\*\+,\-\./:;<=>\?@\[\\\\\]\^_`{\|}\~]';
- $this->valignre = '[\-^~]';
- $this->tblalignre = '[<>=]';
- $this->halignre = '(?:<>|[<>=])';
- $this->alignre = '(?:(?:' . $this->valignre . '|<>' . $this->valignre . '?|' . $this->valignre . '?<>|' . $this->valignre . '?' . $this->halignre . '?|' . $this->halignre . '?' . $this->valignre . '?)(?!\w))';
- $this->imgalignre = '(?:(?:[<>]|' . $this->valignre . '){1,2})';
-
- $this->clstypadre = '(?:
- (?:\([A-Za-z0-9_\- \#]+\))
- |
- (?:{
- (?: \( [^)]+ \) | [^\}] )+
- })
- |
- (?:\(+? (?![A-Za-z0-9_\-\#]) )
- |
- (?:\)+?)
- |
- (?: \[ [a-zA-Z\-]+? \] )
- )';
-
- $this->clstyre = '(?:
- (?:\([A-Za-z0-9_\- \#]+\))
- |
- (?:{
- [A-Za-z0-9_\-](?: \( [^)]+ \) | [^\}] )+
- })
- |
- (?: \[ [a-zA-Z\-]+? \] )
- )';
-
- $this->clstyfiltre = '(?:
- (?:\([A-Za-z0-9_\- \#]+\))
- |
- (?:{
- [A-Za-z0-9_\-](?: \( [^)]+ \) | [^\}] )+
- })
- |
- (?:\|[^\|]+\|)
- |
- (?:\(+?(?![A-Za-z0-9_\-\#]))
- |
- (?:\)+)
- |
- (?: \[ [a-zA-Z]+? \] )
- )';
-
- $this->codere = '(?:
- (?:
- [\[{]
- @ # opening
- (?:\[([A-Za-z0-9]+)\])? # $1: language id
- (.+?) # $2: code
- @ # closing
- [\]}]
- )
- |
- (?:
- (?:^|(?<=[\s\(]))
- @ # opening
- (?:\[([A-Za-z0-9]+)\])? # $3: language id
- ([^\s].+?[^\s]) # $4: code itself
- @ # closing
- (?:$|(?=' . $this->punct . '{1,2}|\s))
- )
- )';
-
- $this->blocktags = '
- <
- (( /? ( h[1-6]
- | p
- | pre
- | div
- | table
- | t[rdh]
- | [ou]l
- | li
- | block(?:quote|code)
- | form
- | input
- | select
- | option
- | textarea
- )
- [ >]
- )
- | !--
- )
- ';
- } // function _create_re
-
- /**
- * Transforms the provided text using Textile markup rules.
- *
- * @param $str The @c string specifying the text to process.
- *
- * @return A @c string containing the processed (X)HTML.
- *
- * @public
- */
- function process($str) {
- /*
- * Function names in PHP are case insensitive, so function
- * textile() cannot be redefined. Thus, this PHP implementation
- * will only use process().
- *
- * return $this->textile($str);
- * } // function process
- *
- * function textile($str) {
- */
-
- $this->charset('utf8');
- // quick translator for abbreviated block names
- // to their tag
- $macros = array('bq' => 'blockquote');
-
- // an array to hold any portions of the text to be preserved
- // without further processing by Textile
- array_unshift($this->repl, array());
-
- // strip out extra newline characters. we're only matching for \n herein
- //$str = preg_replace('!(?:\r?\n|\r)!', "\n", $str);
- $str = preg_replace('!(?:\015?\012|\015)!', "\n", $str);
-
- // optionally remove trailing spaces
- if ($this->options['trim_spaces']) { $str = preg_replace('/ +$/m', '', $str); }
-
- // preserve contents of the '==', 'pre', 'blockcode' sections
- $str = preg_replace_callback('{(^|\n\n)==(.+?)==($|\n\n)}s',
- $this->_cb('"$m[1]\n\n" . $me->_repl($me->repl[0], $me->format_block(array("text" => $m[2]))) . "\n\n$m[3]"'), $str);
-
- if (!$this->disable_html()) {
- // preserve style, script tag contents
- $str = preg_replace_callback('!(<(style|script)(?:>| .+?>).*?</\2>)!s', $this->_cb('$me->_repl($me->repl[0], $m[1])'), $str);
-
- // preserve HTML comments
- $str = preg_replace_callback('|(<!--.+?-->)|s', $this->_cb('$me->_repl($me->repl[0], $m[1])'), $str);
-
- // preserve pre block contents, encode contents by default
- $pre_start = count($this->repl[0]);
- $str = preg_replace_callback('{(<pre(?: [^>]*)?>)(.+?)(</pre>)}s',
- $this->_cb('"\n\n" . $me->_repl($me->repl[0], $m[1] . $me->encode_html($m[2], 1) . $m[3]) . "\n\n"'), $str);
- // fix code tags within pre blocks we just saved.
- for ($i = $pre_start; $i < count($this->repl[0]); $i++) {
- $this->repl[0][$i] = preg_replace('|<(/?)code(.*?)>|s', '<$1code$2>', $this->repl[0][$i]);
- }
-
- // preserve code blocks by default, encode contents
- $str = preg_replace_callback('{(<code(?: [^>]+)?>)(.+?)(</code>)}s',
- $this->_cb('$me->_repl($me->repl[0], $m[1] . $me->encode_html($m[2], 1) . $m[3])'), $str);
-
- // encode blockcode tag (an XHTML 2 tag) and encode it's
- // content by default
- $str = preg_replace_callback('{(<blockcode(?: [^>]+)?>)(.+?)(</blockcode>)}s',
- $this->_cb('"\n\n" . $me->_repl($me->repl[0], $m[1] . $me->encode_html($m[2], 1) . $m[3]) . "\n\n"'), $str);
-
- // preserve PHPish, ASPish code
- $str = preg_replace_callback('!(<([\?%]).*?(\2)>)!s', $this->_cb('$me->_repl($me->repl[0], $m[1])'), $str);
- }
-
- // pass through and remove links that follow this format
- // [id_without_spaces (optional title text)]url
- // lines like this are stripped from the content, and can be
- // referred to using the "link text":id_without_spaces syntax
- //$links = array();
- $str = preg_replace_callback('{(?:\n|^) [ ]* \[ ([^ ]+?) [ ]*? (?:\( (.+?) \) )? \] ((?:(?:ftp|https?|telnet|nntp)://|/)[^ ]+?) [ ]* (\n|$)}mx',
- $this->_cb('($me->links[$m[1]] = array("url" => $m[3], "title" => $m[2])) ? $m[4] : $m[4]'), $str);
- //$this->links = $links;
-
- // eliminate starting/ending blank lines
- $str = preg_replace('/^\n+/s', '', $str, 1);
- $str = preg_replace('/\n+$/s', '', $str, 1);
-
- // split up text into paragraph blocks, capturing newlines too
- $para = preg_split('/(\n{2,})/', $str, -1, PREG_SPLIT_DELIM_CAPTURE);
- unset($block, $bqlang, $filter, $class, $sticky, $lines,
- $style, $stickybuff, $lang, $clear);
-
- $out = '';
-
- foreach ($para as $para) {
- if (preg_match('/^\n+$/s', $para)) {
- if ($sticky && $stickybuff) {
- $stickybuff .= $para;
- } else {
- $out .= $para;
- }
- continue;
- }
-
- if ($sticky) {
- $sticky++;
- } else {
- unset($block);
- unset($class);
- $style = '';
- unset($lang);
- }
-
- unset($id, $cite, $align, $padleft, $padright, $lines, $buffer);
- if (preg_match('{^(h[1-6]|p|bq|bc|fn\d+)
- ((?:' . $this->clstyfiltre . '*|' . $this->halignre . ')*)
- (\.\.?)
- (?::(\d+|' . $this->urlre . '))?\ (.*)$}sx', $para, $matches)) {
- if ($sticky) {
- if ($block == 'bc') {
- // close our blockcode section
- $out = preg_replace('/\n\n$/', '', $out, 1);
- $out .= $this->options['_blockcode_close'] . "\n\n";
- } elseif ($block == 'bq') {
- $out = preg_replace('/\n\n$/', '', $out, 1);
- $out .= '</blockquote>' . "\n\n";
- } elseif ($block == 'table') {
- $table_out = $this->format_table(array('text' => $stickybuff));
- if (!$table_out) { $table_out = ''; }
- $out .= $table_out;
- unset($stickybuff);
- } elseif ($block == 'dl') {
- $dl_out = $this->format_deflist(array('text' => $stickybuff));
- if (!$dl_out) { $dl_out = ''; }
- $out .= $dl_out;
- unset($stickybuff);
- }
- $sticky = 0;
- }
- // block macros: h[1-6](class)., bq(class)., bc(class)., p(class).
- //warn "paragraph: [[$para]]\n\tblock: $1\n\tparams: $2\n\tcite: $4";
- $block = $matches[1];
- $params = $matches[2];
- $cite = $matches[4];
- if ($matches[3] == '..') {
- $sticky = 1;
- } else {
- $sticky = 0;
- unset($class);
- unset($bqlang);
- unset($lang);
- $style = '';
- unset($filter);
- }
- if (preg_match('/^h([1-6])$/', $block, $matches2)) {
- if ($this->options['head_offset']) {
- $block = 'h' . ($matches2[1] + $this->options['head_offset']);
- }
- }
- if (preg_match('{(' . $this->halignre . '+)}', $params, $matches2)) {
- $align = $matches2[1];
- $params = preg_replace('{' . $this->halignre . '+}', '', $params, 1);
- }
- if ($params) {
- if (preg_match('/\|(.+)\|/', $params, $matches2)) {
- $filter = $matches2[1];
- $params = preg_replace('/\|.+?\|/', '', $params, 1);
- }
- if (preg_match('/{([^}]+)}/', $params, $matches2)) {
- $style = $matches2[1];
- $style = preg_replace('/\n/', ' ', $style);
- $params = preg_replace('/{[^}]+}/', '', $params);
- }
- if (preg_match('/\(([A-Za-z0-9_\-\ ]+?)(?:\#(.+?))?\)/', $params, $matches2) ||
- preg_match('/\(([A-Za-z0-9_\-\ ]+?)?(?:\#(.+?))\)/', $params, $matches2)) {
- if ($matches2[1] || $matches2[2]) {
- $class = $matches2[1];
- $id = $matches2[2];
- if ($class) {
- $params = preg_replace('/\([A-Za-z0-9_\-\ ]+?(#.*?)?\)/', '', $params);
- } elseif ($id) {
- $params = preg_replace('/\(#.+?\)/', '', $params);
- }
- }
- }
- if (preg_match('/(\(+)/', $params, $matches2)) {
- $padleft = strlen($matches2[1]);
- $params = preg_replace('/\(+/', '', $params, 1);
- }
- if (preg_match('/(\)+)/', $params, $matches2)) {
- $padright = strlen($matches2[1]);
- $params = preg_replace('/\)+/', '', $params, 1);
- }
- if (preg_match('/\[(.+?)\]/', $params, $matches2)) {
- $lang = $matches2[1];
- if ($block == 'bc') {
- $bqlang = $lang;
- unset($lang);
- }
- $params = preg_replace('/\[.+?\]/', '', $params, 1);
- }
- }
- // warn "settings:\n\tblock: $block\n\tpadleft: $padleft\n\tpadright: $padright\n\tclass: $class\n\tstyle: $style\n\tid: $id\n\tfilter: $filter\n\talign: $align\n\tlang: $lang\n\tsticky: $sticky";
- $para = $matches[5];
- } elseif (preg_match('|^<textile#(\d+)>$|', $para, $matches)) {
- $buffer = $this->repl[0][$matches[1] - 1];
- } elseif (preg_match('/^clear([<>]+)?\.$/', $para, $matches)) {
- if ($matches[1] == '<') {
- $clear = 'left';
- } elseif ($matches[1] == '>') {
- $clear = 'right';
- } else {
- $clear = 'both';
- }
- continue;
- } elseif ($sticky && $stickybuff &&
- ($block == 'table' || $block == 'dl')) {
- $stickybuff .= $para;
- continue;
- } elseif (preg_match('{^(?:' . $this->halignre . '|' . $this->clstypadre . '*)*
- [\*\#]
- (?:' . $this->halignre . '|' . $this->clstypadre . '*)*
- \ }x', $para)) {
- // '*', '#' prefix means a list
- $buffer = $this->format_list(array('text' => $para));
- } elseif (preg_match('{^(?:table(?:' . $this->tblalignre . '|' . $this->clstypadre . '*)*
- (\.\.?)\s+)?
- (?:_|' . $this->alignre . '|' . $this->clstypadre . '*)*\|}x', $para, $matches)) {
- // handle wiki-style tables
- if ($matches[1] && ($matches[1] == '..')) {
- $block = 'table';
- $stickybuff = $para;
- $sticky = 1;
- continue;
- } else {
- $buffer = $this->format_table(array('text' => $para));
- }
- } elseif (preg_match('{^(?:dl(?:' . $this->clstyre . ')*(\.\.?)\s+)}x', $para, $matches)) {
- // handle definition lists
- if ($matches[1] && ($matches[1] == '..')) {
- $block = 'dl';
- $stickybuff = $para;
- $sticky = 1;
- continue;
- } else {
- $buffer = $this->format_deflist(array('text' => $para));
- }
- }
- if ($buffer) {
- $out .= $buffer;
- continue;
- }
- $lines = preg_split('/\n/', $para);
- if ((count($lines) == 1) && ($lines[0] == '')) {
- continue;
- }
-
- $block = ($block ? $block : 'p');
-
- $buffer = '';
- $pre = '';
- $post = '';
-
- if ($block == 'bc') {
- if ($sticky <= 1) {
- $pre .= $this->options['_blockcode_open'];
- $pre = preg_replace('/>$/s', '', $pre, 1);
- if ($bqlang) { $pre .= " language=\"$bqlang\""; }
- if ($align) {
- $alignment = $this->_halign($align);
- if ($this->options['css_mode']) {
- if (($padleft || $padright) &&
- (($alignment == 'left') || ($alignment == 'right'))) {
- $style .= ';float:' . $alignment;
- } else {
- $style .= ';text-align:' . $alignment;
- }
- $class .= ' ' . ($this->options['css']["class_align_$alignment"] ? $this->options['css']["class_align_$alignment"] : $alignment);
- } else {
- if ($alignment) { $pre .= " align=\"$alignment\""; }
- }
- }
- if ($padleft) { $style .= ";padding-left:${padleft}em"; }
- if ($padright) { $style .= ";padding-right:${padright}em"; }
- if ($clear) { $style .= ";clear:${clear}"; }
- if ($class) { $class = preg_replace('/^ /', '', $class, 1); }
- if ($class) { $pre .= " class=\"$class\""; }
- if ($id) { $pre .= " id=\"$id\""; }
- if ($style) { $style = preg_replace('/^;/', '', $style, 1); }
- if ($style) { $pre .= " style=\"$style\""; }
- if ($lang) { $pre .= " lang=\"$lang\""; }
- $pre .= '>';
- unset($lang);
- unset($bqlang);
- unset($clear);
- }
- $para = preg_replace_callback('{(?:^|(?<=[\s>])|([{[]))
- ==(.+?)==
- (?:$|([\]}])|(?=' . $this->punct . '{1,2}|\s))}sx',
- $this->_cb('$me->_repl($me->repl[0], $me->format_block(array("text" => $m[2], "inline" => 1, "pre" => $m[1], "post" => $m[3])))'), $para);
- $buffer .= $this->encode_html_basic($para, 1);
- $buffer = preg_replace('/<textile#(\d+)>/', '<textile#$1>', $buffer);
- if ($sticky == 0) {
- $post .= $this->options['_blockcode_close'];
- }
- $out .= $pre . $buffer . $post;
- continue;
- } elseif ($block == 'bq') {
- if ($sticky <= 1) {
- $pre .= '<blockquote';
- if ($align) {
- $alignment = $this->_halign($align);
- if ($this->options['css_mode']) {
- if (($padleft || $padright) &&
- (($alignment == 'left') || ($alignment == 'right'))) {
- $style .= ';float:' . $alignment;
- } else {
- $style .= ';text-align:' . $alignment;
- }
- $class .= ' ' . ($this->options['css']["class_align_$alignment"] ? $this->options['css']["class_align_$alignment"] : $alignment);
- } else {
- if ($alignment) { $pre .= " align=\"$alignment\""; }
- }
- }
- if ($padleft) { $style .= ";padding-left:${padleft}em"; }
- if ($padright) { $style .= ";padding-right:${padright}em"; }
- if ($clear) { $style .= ";clear:${clear}"; }
- if ($class) { $class = preg_replace('/^ /', '', $class, 1); }
- if ($class) { $pre .= " class=\"$class\""; }
- if ($id) { $pre .= " id=\"$id\""; }
- if ($style) { $style = preg_replace('/^;/', '', $style, 1); }
- if ($style) { $pre .= " style=\"$style\""; }
- if ($lang) { $pre .= " lang=\"$lang\""; }
- if ($cite) { $pre .= ' cite="' . $this->format_url(array('url' => $cite)) . '"'; }
- $pre .= '>';
- unset($clear);
- }
- $pre .= '<p>';
- } elseif (preg_match('/fn(\d+)/', $block, $matches)) {
- $fnum = $matches[1];
- $pre .= '<p';
- if ($this->options['css']['class_footnote']) { $class .= ' ' . $this->options['css']['class_footnote']; }
- if ($align) {
- $alignment = $this->_halign($align);
- if ($this->options['css_mode']) {
- if (($padleft || $padright) &&
- (($alignment == 'left') || ($alignment == 'right'))) {
- $style .= ';float:' . $alignment;
- } else {
- $style .= ';text-align:' . $alignment;
- }
- $class .= ($this->options['css']["class_align_$alignment"] ? $this->options['css']["class_align_$alignment"] : $alignment);
- } else {
- $pre .= " align=\"$alignment\"";
- }
- }
- if ($padleft) { $style .= ";padding-left:${padleft}em"; }
- if ($padright) { $style .= ";padding-right:${padright}em"; }
- if ($clear) { $style .= ";clear:${clear}"; }
- if ($class) { $class = preg_replace('/^ /', '', $class, 1); }
- if ($class) { $pre .= " class=\"$class\""; }
- $pre .= ' id="' . ($this->options['css']['id_footnote_prefix'] ? $this->options['css']['id_footnote_prefix'] : 'fn') . $fnum . '"';
- if ($style) { $style = preg_replace('/^;/', '', $style, 1); }
- if ($style) { $pre .= " style=\"$style\""; }
- if ($lang) { $pre .= " lang=\"$lang\""; }
- $pre .= '>';
- $pre .= '<sup>' . $fnum . '</sup> ';
- // we can close like a regular paragraph tag now
- $block = 'p';
- unset($clear);
- } else {
- $pre .= '<' . ($macros[$block] ? $macros[$block] : $block);
- if ($align) {
- $alignment = $this->_halign($align);
- if ($this->options['css_mode']) {
- if (($padleft || $padright) &&
- (($alignment == 'left') || ($alignment == 'right'))) {
- $style .= ';float:' . $alignment;
- } else {
- $style .= ';text-align:' . $alignment;
- }
- $class .= ' ' . ($this->options['css']["class_align_$alignment"] ? $this->options['css']["class_align_$alignment"] : $alignment);
- } else {
- $pre .= " align=\"$alignment\"";
- }
- }
- if ($padleft) { $style .= ";padding-left:${padleft}em"; }
- if ($padright) { $style .= ";padding-right:${padright}em"; }
- if ($clear) { $style .= ";clear:${clear}"; }
- if ($class) { $class = preg_replace('/^ /', '', $class, 1); }
- if ($class) { $pre .= " class=\"$class\""; }
- if ($id) { $pre .= " id=\"$id\""; }
- if ($style) { $style = preg_replace('/^;/', '', $style, 1); }
- if ($style) { $pre .= " style=\"$style\""; }
- if ($lang) { $pre .= " lang=\"$lang\""; }
- if ($cite && ($block == 'bq')) { $pre .= ' cite="' . $this->format_url(array('url' => $cite)) . '"'; }
- $pre .= '>';
- unset($clear);
- }
-
- $buffer = $this->format_paragraph(array('text' => $para));
-
- if ($block == 'bq') {
- if (!preg_match('/<p[ >]/', $buffer)) { $post .= '</p>'; }
- if ($sticky == 0) {
- $post .= '</blockquote>';
- }
- } else {
- $post .= '</' . $block . '>';
- }
-
- if (preg_match('{' . $this->blocktags . '}x', $buffer)) {
- $buffer = preg_replace('/^\n\n/s', '', $buffer, 1);
- $out .= $buffer;
- } else {
- if ($filter) { $buffer = $this->format_block(array('text' => "|$filter|" . $buffer, 'inline' => 1)); }
- $out .= $pre . $buffer . $post;
- }
- }
-
- if ($sticky) {
- if ($block == 'bc') {
- // close our blockcode section
- $out .= $this->options['_blockcode_close']; // . "\n\n";
- } elseif ($block == 'bq') {
- $out .= '</blockquote>'; // . "\n\n";
- } elseif (($block == 'table') && $stickybuff) {
- $table_out = $this->format_table(array('text' => $stickybuff));
- if ($table_out) { $out .= $table_out; }
- } elseif (($block == 'dl') && $stickybuff) {
- $dl_out = $this->format_deflist(array('text' => $stickybuff));
- if ($dl_out) { $out .= $dl_out; }
- }
- }
-
- // cleanup-- restore preserved blocks
- for ($i = count($this->repl[0]); $i > 0; $i--) {
- $out = preg_replace('!(?:<|<)textile#' . $i . '(?:>|>)!', str_replace('$', '\\$', $this->repl[0][$i - 1]), $out, 1);
- }
- array_shift($this->repl);
-
- // scan for br, hr tags that are not closed and close them
- // only for xhtml! just the common ones -- don't fret over input
- // and the like.
- if (preg_match('/^xhtml/i', $this->flavor())) {
- $out = preg_replace('/(<(?:img|br|hr)[^>]*?(?<!\/))>/', '$1 />', $out);
- }
-
- return $out;
- } // function process
-
- /**
- * Processes a single paragraph. The following attributes are
- * allowed:
- *
- * <ul>
- *
- * <li><b>text</b>
- *
- * The text to be processed.</li>
- *
- * </ul>
- *
- * @param $args An @c array specifying the attributes for formatting
- * the paragraph.
- *
- * @return A @c string containing the formatted paragraph.
- *
- * @private
- */
- function format_paragraph($args) {
- $buffer = (isset($args['text']) ? $args['text'] : '');
-
- array_unshift($this->repl, array());
- $buffer = preg_replace_callback('{(?:^|(?<=[\s>])|([{[]))
- ==(.+?)==
- (?:$|([\]}])|(?=' . $this->punct . '{1,2}|\s))}sx',
- $this->_cb('$me->_repl($me->repl[0], $me->format_block(array("text" => $m[2], "inline" => 1, "pre" => $m[1], "post" => $m[3])))'), $buffer);
-
- unset($tokens);
- if (preg_match('/</', $buffer) && (!$this->disable_html())) { // optimization -- no point in tokenizing if we
- // have no tags to tokenize
- $tokens = $this->_tokenize($buffer);
- } else {
- $tokens = array(array('text', $buffer));
- }
- $result = '';
- foreach ($tokens as $token) {
- $text = $token[1];
- if ($token[0] == 'tag') {
- $text = preg_replace('/&(?!amp;)/', '&', $text);
- $result .= $text;
- } else {
- $text = $this->format_inline(array('text' => $text));
- $result .= $text;
- }
- }
-
- // now, add line breaks for lines that contain plaintext
- $lines = preg_split('/\n/', $result);
- $result = '';
- $needs_closing = 0;
- foreach ($lines as $line) {
- if (!preg_match('{(' . $this->blocktags . ')}x', $line)
- && ((preg_match('/^[^<]/', $line) || preg_match('/>[^<]/', $line))
- || !preg_match('/<img /', $line))) {
- if ($this->options['_line_open']) {
- if ($result != '') { $result .= "\n"; }
- $result .= $this->options['_line_open'] . $line . $this->options['_line_close'];
- } else {
- if ($needs_closing) {
- $result .= $this->options['_line_close'] . "\n";
- } else {
- $needs_closing = 1;
- if ($result != '') { $result .= "\n"; }
- }
- $result .= $line;
- }
- } else {
- if ($needs_closing) {
- $result .= $this->options['_line_close'] . "\n";
- } else {
- if ($result != '') { $result .= "\n"; }
- }
- $result .= $line;
- $needs_closing = 0;
- }
- }
-
- // at this point, we will restore the \001's to \n's (reversing
- // the step taken in _tokenize).
- //$result = preg_replace('/\r/', "\n", $result);
- $result = preg_replace('/\001/', "\n", $result);
-
- for ($i = count($this->repl[0]); $i > 0; $i--) {
- $result = preg_replace("|<textile#$i>|", str_replace('$', '\\$', $this->repl[0][$i - 1]), $result, 1);
- }
- array_shift($this->repl);
-
- // quotalize
- if ($this->options['do_quotes']) {
- $result = $this->process_quotes($result);
- }
-
- return $result;
- } // function format_paragraph
-
- /**
- * Processes an inline string (plaintext) for Textile syntax.
- * The following attributes are allowed:
- *
- * <ul>
- *
- * <li><b>text</b>
- *
- * The text to be processed.</li>
- *
- * </ul>
- *
- * @param $args An @c array specifying the attributes for formatting
- * the inline string.
- *
- * @return A @c string containing the formatted inline string.
- *
- * @private
- */
- function format_inline($args) {
- $qtags = array(array('**', 'b', '(?<!\*)\*\*(?!\*)', '\*'),
- array('__', 'i', '(?<!_)__(?!_)', '_'),
- array('??', 'cite', '\?\?(?!\?)', '\?'),
- array('*', 'strong', '(?<!\*)\*(?!\*)', '\*'),
- array('_', 'em', '(?<!_)_(?!_)', '_'),
- array('-', 'del', '(?<!\-)\-(?!\-)', '-'),
- array('+', 'ins', '(?<!\+)\+(?!\+)', '\+'),
- array('++', 'big', '(?<!\+)\+\+(?!\+)', '\+\+'),
- array('--', 'small', '(?<!\-)\-\-(?!\-)', '\-\-'),
- array('~', 'sub', '(?<!\~)\~(?![\\\\/~])', '\~'));
- $text = (isset($args['text']) ? $args['text'] : '');
-
- array_unshift($this->repl, array());
-
- $text = preg_replace_callback('{' . $this->codere . '}mx', $this->_cb('$me->_repl($me->repl[0], $me->format_code(array("text" => $m[2] . $m[4], "lang" => $m[1] . $m[3])))'), $text);
-
- // images must be processed before encoding the text since they might
- // have the <, > alignment specifiers...
-
- // !blah (alt)! -> image
- $text = preg_replace_callback('{(?:^|(?<=[\s>])|([{[])) # $1: open brace/bracket
- ! # opening
- (' . $this->imgalignre . '?) # $2: optional alignment
- (' . $this->clstypadre . '*) # $3: optional CSS class/id
- (' . $this->imgalignre . '?) # $4: optional alignment
- (?:\s*) # space between alignment/css stuff
- ([^\s\(!]+) # $5: filename
- (\s*[^\(!]*(?:\([^\)]+\))?[^!]*) # $6: extras (alt text)
- ! # closing
- (?::(\d+|' . $this->urlre . '))? # $7: optional URL
- (?:$|([\]}])|(?=' . $this->punct . '{1,2}|\s)) # $8: closing brace/bracket
- }mx', $this->_cb('$me->_repl($me->repl[0], $me->format_image(array("pre" => $m[1], "src" => $m[5], "align" => ($m[2] ? $m[2] : $m[4]), "extra" => $m[6], "url" => $m[7], "clsty" => $m[3], "post" => $m[8])))'), $text);
-
- $text = preg_replace_callback('{(?:^|(?<=[\s>])|([{[])) # $1: open brace/bracket
- % # opening
- (' . $this->halignre . '?) # $2: optional alignment
- (' . $this->clstyre . '*) # $3: optional CSS class/id
- (' . $this->halignre . '?) # $4: optional alignment
- (?:\s*) # spacing
- ([^%]+?) # $5: text
- % # closing
- (?::(\d+|' . $this->urlre . '))? # $6: optional URL
- (?:$|([]}])|(?=' . $this->punct . '{1,2}|\s)) # $7: closing brace/bracket
- }mx', $this->_cb('$me->_repl($me->repl[0], $me->format_span(array("pre" => $m[1], "text" => $m[5], "align" => ($m[2] ? $m[2] : $m[4]), "cite" => $m[6], "clsty" => $m[3], "post" => $m[7])))'), $text);
-
- $text = $this->encode_html($text);
- $text = preg_replace('!<textile#(\d+)>!', '<textile#$1>', $text);
- $text = preg_replace('!&quot;!', '"', $text);
- $text = preg_replace('!&(([a-z]+|#\d+);)!', '&$1', $text);
- $text = preg_replace('!"!', '"', $text);
-
- // These create markup with entities. Do first and 'save' result for later:
- // "text":url -> hyperlink
- // links with brackets surrounding
- $parenre = '\( (?: [^()] )* \)';
- $text = preg_replace_callback('{(
- [{[]
- (?:
- (?:" # quote character
- (' . $this->clstyre . '*)? # $2: optional CSS class/id
- ([^"]+?) # $3: link text
- (?:\( ( (?:[^()]|' . $parenre . ')*) \))? # $4: optional link title
- " # closing quote
- )
- |
- (?:\' # open single quote
- (' . $this->clstyre . '*)? # $5: optional CSS class/id
- ([^\']+?) # $6: link text
- (?:\( ( (?:[^()]|' . $parenre . ')*) \))? # $7: optional link title
- \' # closing quote
- )
- )
- :(.+?) # $8: URL suffix
- [\]}]
- )
- }mx', $this->_cb('$me->_repl($me->repl[0], $me->format_link(array("text" => $m[1], "linktext" => $m[3] . $m[6], "title" => $me->encode_html_basic($m[4] . $m[7]), "url" => $m[8], "clsty" => $m[2] . $m[5])))'), $text);
-
- $text = preg_replace_callback('{((?:^|(?<=[\s>\(])) # $1: open brace/bracket
- (?: (?:" # quote character "
- (' . $this->clstyre . '*)? # $2: optional CSS class/id
- ([^"]+?) # $3: link text "
- (?:\( ( (?:[^()]|' . $parenre . ')*) \))? # $4: optional link title
- " # closing quote # "
- )
- |
- (?:\' # open single quote \'
- (' . $this->clstyre . '*)? # $5: optional CSS class/id
- ([^\']+?) # $6: link text \'
- (?:\( ( (?:[^()]|' . $parenre . ')*) \))? # $7: optional link title
- \' # closing quote \'
- )
- )
- :(\d+|' . $this->urlre . ') # $8: URL suffix
- (?:$|(?=' . $this->punct . '{1,2}|\s))) # $9: closing brace/bracket
- }mx', $this->_cb('$me->_repl($me->repl[0], $me->format_link(array("text" => $m[1], "linktext" => $m[3] . $m[6], "title" => $me->encode_html_basic($m[4] . $m[7]), "url" => $m[8], "clsty" => $m[2] . $m[5])))'), $text);
-
- if (preg_match('/^xhtml2/', $this->flavor())) {
- // citation with cite link
- $text = preg_replace_callback('{(?:^|(?<=[\s>\'"\(])|([{[])) # $1: open brace/bracket \'
- \?\? # opening \'??\'
- ([^\?]+?) # $2: characters (can\'t contain \'?\')
- \?\? # closing \'??\'
- :(\d+|' . $this->urlre . ') # $3: optional citation URL
- (?:$|([\]}])|(?=' . $this->punct . '{1,2}|\s)) # $4: closing brace/bracket
- }mx', $this->_cb('$me->_repl($me->repl[0], $me->format_cite(array("pre" => $m[1], "text" => $m[2], "cite" => $m[3], "post" => $m[4])))'), $text);
- }
-
- // footnotes
- if (preg_match('/[^ ]\[\d+\]/', $text)) {
- $fntag = '<sup';
- if ($this->options['css']['class_footnote']) { $fntag .= ' class="' . $this->options['css']['class_footnote'] . '"'; }
- $fntag .= '><a href="#' . ($this->options['css']['id_footnote_prefix'] ? $this->options['css']['id_footnote_prefix'] : 'fn');
- $text = preg_replace('|([^ ])\[(\d+)\]|', '$1' . $fntag . '$2">$2</a></sup>', $text);
- }
-
- // translate macros:
- $text = preg_replace_callback('{(\{)(.+?)(\})}x',
- $this->_cb('$me->format_macro(array("pre" => $m[1], "post" => $m[3], "macro" => $m[2]))'), $text);
-
- // these were present with textile 1 and are common enough
- // to not require macro braces...
- // (tm) -> ™
- $text = preg_replace('|[\(\[]TM[\)\]]|i', '™', $text);
- // (c) -> ©
- $text = preg_replace('|[\(\[]C[\)\]]|i', '©', $text);
- // (r) -> ®
- $text = preg_replace('|[\(\[]R[\)\]]|i', '®', $text);
-
- if ($this->preserve_spaces()) {
- // replace two spaces with an em space
- $text = preg_replace('/(?<!\s)\ \ (?!=\s)/', ' ', $text);
- }
-
- $redo = preg_match('/[\*_\?\-\+\^\~]/', $text);
- $last = $text;
- while ($redo) {
- // simple replacements...
- $redo = 0;
- foreach ($qtags as $tag) {
- list ($this->tmp['f'][], $this->tmp['r'][], $qf, $cls) = $tag;
- if ($last != ($text = preg_replace_callback('{(?:^|(?<=[\s>\'"])|([{[])) # "\' $1 - pre
- ' . $qf . ' #
- (?:(' . $this->clstyre . '*))? # $2 - attributes
- ([^' . $cls . '\s].*?) # $3 - content
- (?<=\S)' . $qf . ' #
- (?:$|([\]}])|(?=' . $this->punct . '{1,2}|\s)) # $4 - post
- }mx', $this->_cb('$me->format_tag(array("tag" => end($me->tmp["r"]), "marker" => end($me->tmp["f"]), "pre" => $m[1], "text" => $m[3], "clsty" => $m[2], "post" => $m[4]))'), $text))) {
- $redo = ($redo || ($last != $text));
- $last = $text;
- }
- array_pop($this->tmp['f']); array_pop($this->tmp['r']);
- }
- }
-
- // superscript is an even simpler replacement...
- $text = preg_replace('/(?<!\^)\^(?!\^)(.+?)(?<!\^)\^(?!\^)/', '<sup>$1</sup>', $text);
-
- // ABC(Aye Bee Cee) -> acronym
- $text = preg_replace_callback('{\b([A-Z][A-Za-z0-9]*?[A-Z0-9]+?)\b(?:[(]([^)]*)[)])}',
- $this->_cb('$me->_repl($me->repl[0],"<acronym title=\"" . $me->encode_html_basic($m[2]) . "\">$m[1]</acronym>")'), $text);
-
- // ABC -> 'capped' span
- if ($this->tmp['caps'][] = $this->options['css']['class_caps']) {
- $text = preg_replace_callback('/(^|[^"][>\s]) # "
- ((?:[A-Z](?:[A-Z0-9\.,\']|\&){2,}\ *)+?) # \'
- (?=[^A-Z\.0-9]|$)
- /mx', $this->_cb('$m[1] . $me->_repl($me->repl[0], "<span class=\"" . end($me->tmp["caps"]) . "\">$m[2]</span>")'), $text);
- }
- array_pop($this->tmp['caps']);
-
- // nxn -> n×n
- $text = preg_replace('!((?:[0-9\.]0|[1-9]|\d[\'"])\ ?)x(\ ?\d)!', '$1×$2', $text);
-
- // translate these entities to the Unicode equivalents:
- $text = preg_replace('/…/', '…', $text);
- $text = preg_replace('/‘/', '‘', $text);
- $text = preg_replace('/’/', '’', $text);
- $text = preg_replace('/“/', '“', $text);
- $text = preg_replace('/”/', '”', $text);
- $text = preg_replace('/–/', '–', $text);
- $text = preg_replace('/—/', '—', $text);
-
- // Restore replacements done earlier:
- for ($i = count($this->repl[0]); $i > 0; $i--) {
- $text = preg_replace("|<textile#$i>|", str_replace('$', '\\$', $this->repl[0][$i - 1]), $text);
- }
- array_shift($this->repl);
-
- // translate entities to characters for highbit stuff since
- // we're using utf8
- // removed for backward compatability with older versions of Perl
- //if (preg_match('/^utf-?8$/i', $this->options['charset'])) {
- // // translate any unicode entities to native UTF-8
- // $text = preg_replace('/\&\#(\d+);/e', '($1 > 127) ? pack('U', $1) : chr($1)', $text);
- //}
-
- return $text;
- } // function format_inline
-
- /**
- * Responsible for processing a particular macro. Arguments passed
- * include:
- *
- * <ul>
- *
- * <li><b>pre</b>
- *
- * open brace character</li>
- *
- * <li><b>post</b>
- *
- * close brace character</li>
- *
- * <li><b>macro</b>
- *
- * the macro to be executed</li>
- *
- * </ul>
- *
- * The return value from this method would be the replacement
- * text for the macro given. If the macro is not defined, it will
- * return pre + macro + post, thereby preserving the original
- * macro string.
- *
- * @param $attrs An @c array containing the attributes for
- * formatting the macro.
- *
- * @return A @c string containing the formatted macro.
- *
- * @private
- */
- function format_macro($attrs) {
- $macro = $attrs['macro'];
- if ($this->options['macros'][$macro]) {
- return $this->options['macros'][$macro];
- }
-
- return $attrs['pre'] . $macro . $attrs['post'];
- } // function format_macro
-
- /**
- * Processes text for a citation tag. The following attributes
- * are allowed:
- *
- * <ul>
- *
- * <li><b>pre</b>
- *
- * Any text that comes before the citation.</li>
- *
- * <li><b>text</b>
- *
- * The text that is being cited.</li>
- *
- * <li><b>cite</b>
- *
- * The URL of the citation.</li>
- *
- * <li><b>post</b>
- *
- * Any text that follows the citation.</li>
- *
- * </ul>
- *
- * @param $args An @c array specifying the attributes for formatting
- * the citation.
- *
- * @return A @c string containing the formatted citation.
- *
- * @private
- */
- function format_cite($args) {
- $pre = (isset($args['pre']) ? $args['pre'] : '');
- $text = (isset($args['text']) ? $args['text'] : '');
- $cite = $args['cite'];
- $post = (isset($args['post']) ? $args['post'] : '');
- $this->_strip_borders($pre, $post);
- $tag = $pre . '<cite';
- if (preg_match('/^xhtml2/', $this->flavor()) && $cite) {
- $cite = $this->format_url(array('url' => $cite));
- $tag .= " cite=\"$cite\"";
- } else {
- $post .= ':';
- }
- $tag .= '>';
- return $tag . $this->format_inline(array('text' => $text)) . '</cite>' . $post;
- } // function format_cite
-
- /**
- * Processes '@...@' type blocks (code snippets). The following
- * attributes are allowed:
- *
- * <ul>
- *
- * <li><b>text</b>
- *
- * The text of the code itself.</li>
- *
- * <li><b>lang</b>
- *
- * The language (programming language) for the code.</li>
- *
- * </ul>
- *
- * @param $args An @c array specifying the attributes for formatting
- * the code.
- *
- * @return A @c string containing the formatted code.
- *
- * @private
- */
- function format_code($args) {
- $code = (isset($args['text']) ? $args['text'] : '');
- $lang = $args['lang'];
- $code = $this->encode_html($code, 1);
- $code = preg_replace('/<textile#(\d+)>/', '<textile#$1>', $code);
- $tag = '<code';
- if ($lang) { $tag .= " language=\"$lang\""; }
- return $tag . '>' . $code . '</code>';
- } // function format_code
-
- /**
- * Returns a string of tag attributes to accomodate the class,
- * style and symbols present in @c $clsty.
- *
- * @c $clsty is checked for:
- *
- * <ul>
- *
- * <li><b><code>{...}</code></b>
- *
- * style rules. If present, they are appended to <code>$style</code>.</li>
- *
- * <li><b><code>(...#...)</code></b>
- *
- * class and/or ID name declaration</li>
- *
- * <li><b><code>(</code> (one or more)</b>
- *
- * pad left characters</li>
- *
- * <li><b><code>)</code> (one or more)</b>
- *
- * pad right characters</li>
- *
- * <li><b><code>[ll]</code></b>
- *
- * language declaration</li>
- *
- * </ul>
- *
- * The attribute string returned will contain any combination
- * of class, id, style and/or lang attributes.
- *
- * @param $clsty A @c string specifying the class/style to process.
- * @param $class A @c string specifying the predetermined class.
- * @param $style A @c string specifying the predetermined style.
- *
- * @return A @c string containing the formatted class, ID, style,
- * and/or language.
- *
- * @private
- */
- function format_classstyle($clsty = NULL, $class = NULL, $style = NULL) {
- $class = preg_replace('/^ /', '', $class, 1);
-
- unset($lang, $padleft, $padright, $id);
- if ($clsty && preg_match('/{([^}]+)}/', $clsty, $matches)) {
- $_style = $matches[1];
- $_style = preg_replace('/\n/', ' ', $_style);
- $style .= ';' . $_style;
- $clsty = preg_replace('/{[^}]+}/', '', $clsty);
- }
- if ($clsty && (preg_match('/\(([A-Za-z0-9_\- ]+?)(?:#(.+?))?\)/', $clsty, $matches) ||
- preg_match('/\(([A-Za-z0-9_\- ]+?)?(?:#(.+?))\)/', $clsty, $matches))) {
- if ($matches[1] || $matches[2]) {
- if ($class) {
- $class = $matches[1] . ' ' . $class;
- } else {
- $class = $matches[1];
- }
- $id = $matches[2];
- if ($class) {
- $clsty = preg_replace('/\([A-Za-z0-9_\- ]+?(#.*?)?\)/', '', $clsty);
- }
- if ($id) {
- $clsty = preg_replace('/\(#.+?\)/', '', $clsty);
- }
- }
- }
- if ($clsty && preg_match('/(\(+)/', $clsty, $matches)) {
- $padleft = strlen($matches[1]);
- $clsty = preg_replace('/\(+/', '', $clsty, 1);
- }
- if ($clsty && preg_match('/(\)+)/', $clsty, $matches)) {
- $padright = strlen($matches[1]);
- $clsty = preg_replace('/\)+/', '', $clsty, 1);
- }
- if ($clsty && preg_match('/\[(.+?)\]/', $clsty, $matches)) {
- $lang = $matches[1];
- $clsty = preg_replace('/\[.+?\]/', '', $clsty);
- }
- $attrs = '';
- if ($padleft) { $style .= ";padding-left:${padleft}em"; }
- if ($padright) { $style .= ";padding-right:${padright}em"; }
- $style = preg_replace('/^;/', '', $style, 1);
- $class = preg_replace('/^ /', '', $class, 1);
- $class = preg_replace('/ $/', '', $class, 1);
- if ($class) { $attrs .= " class=\"$class\""; }
- if ($id) { $attrs .= " id=\"$id\""; }
- if ($style) { $attrs .= " style=\"$style\""; }
- if ($lang) { $attrs .= " lang=\"$lang\""; }
- $attrs = preg_replace('/^ /', '', $attrs, 1);
- return $attrs;
- } // function format_classstyle
-
- /**
- * Constructs an HTML tag. Accepted arguments:
- *
- * <ul>
- *
- * <li><b>tag</b>
- *
- * the tag to produce</li>
- *
- * <li><b>text</b>
- *
- * the text to output inside the tag</li>
- *
- * <li><b>pre</b>
- *
- * text to produce before the tag</li>
- *
- * <li><b>post</b>
- *
- * text to produce following the tag</li>
- *
- * <li><b>clsty</b>
- *
- * class and/or style attributes that should be assigned to the tag.</li>
- *
- * </ul>
- *
- * @param $args @c array specifying the attributes for formatting
- * the tag.
- *
- * @return A @c string containing the formatted tag.
- *
- * @private
- */
- function format_tag($args) {
- $tagname = $args['tag'];
- $text = (isset($args['text']) ? $args['text'] : '');
- $pre = (isset($args['pre']) ? $args['pre'] : '');
- $post = (isset($args['post']) ? $args['post'] : '');
- $clsty = (isset($args['clsty']) ? $args['clsty'] : '');
- $this->_strip_borders($pre, $post);
- $tag = "<$tagname";
- $attr = $this->format_classstyle($clsty);
- if ($attr) { $tag .= " $attr"; }
- $tag .= ">$text</$tagname>";
- return $pre . $tag . $post;
- } // function format_tag
-
- /**
- * Takes a Textile formatted definition list and
- * returns the markup for it. Arguments accepted:
- *
- * <ul>
- *
- * <li><b>text</b>
- *
- * The text to be processed.</li>
- *
- * </ul>
- *
- * @param $args An @c array specifying the attributes for formatting
- * the definition list.
- *
- * @return A @c string containing the formatted definition list.
- *
- * @private
- */
- function format_deflist($args) {
- $str = (isset($args['text']) ? $args['text'] : '');
- unset($clsty);
- $lines = preg_split('/\n/', $str);
- if (preg_match('{^(dl(' . $this->clstyre . '*?)\.\.?(?:\ +|$))}x', $lines[0], $matches)) {
- $clsty = $matches[2];
- $lines[0] = substr($lines[0], strlen($matches[1]));
- }
-
- unset($dt, $dd);
- $out = '';
- foreach ($lines as $line) {
- if (preg_match('{^((?:' . $this->clstyre . '*)(?:[^\ ].*?)(?<!["\'\ ])):([^\ \/].*)$}x', $line, $matches)) {
- if ($dt && $dd) { $out .= $this->add_term($dt, $dd); }
- $dt = $matches[1];
- $dd = $matches[2];
- } else {
- $dd .= "\n" . $line;
- }
- }
- if ($dt && $dd) { $out .= $this->add_term($dt, $dd); }
-
- $tag = '<dl';
- if ($clsty) { $attr = $this->format_classstyle($clsty); }
- if ($attr) { $tag .= " $attr"; }
- $tag .= '>' . "\n";
-
- return $tag . $out . "</dl>\n";
- } // function format_deflist
-
- /**
- * Processes a single definition list item from the provided term
- * and definition.
- *
- * @param $dt A @c string specifying the term to be defined.
- * @param $dd A @c string specifying the definition for the term.
- *
- * @return A @c string containing the formatted definition list
- * item.
- *
- * @private
- */
- function add_term($dt, $dd) {
- unset($dtattr, $ddattr);
- unset($dtlang);
- if (preg_match('{^(' . $this->clstyre . '*)}x', $dt, $matches)) {
- $param = $matches[1];
- $dtattr = $this->format_classstyle($param);
- if (preg_match('/\[([A-Za-z]+?)\]/', $param, $matches)) {
- $dtlang = $matches[1];
- }
- $dt = substr($dt, strlen($param));
- }
- if (preg_match('{^(' . $this->clstyre . '*)}x', $dd, $matches)) {
- $param = $matches[1];
- // if the language was specified for the term,
- // then apply it to the definition as well (unless
- // already specified of course)
- if ($dtlang && preg_match('/\[([A-Za-z]+?)\]/', $param)) {
- unset($dtlang);
- }
- $ddattr = $this->format_classstyle(($dtlang ? "[$dtlang]" : '') . $param);
- $dd = substr($dd, strlen($param));
- }
- $out = '<dt';
- if ($dtattr) { $out .= " $dtattr"; }
- $out .= '>' . $this->format_inline(array('text' => $dt)) . '</dt>' . "\n";
- if (preg_match('/\n\n/', $dd)) {
- if (preg_match('/\n\n/', $dd)) { $dd = $this->process($dd); }
- } else {
- $dd = $this->format_paragraph(array('text' => $dd));
- }
- $out .= '<dd';
- if ($ddattr) { $out .= " $ddattr"; }
- $out .= '>' . $dd . '</dd>' . "\n";
- return $out;
- } // function add_term
-
- /**
- * Takes a Textile formatted list (numeric or bulleted) and
- * returns the markup for it. Text that is passed in requires
- * substantial parsing, so the @c format_list method is a little
- * involved. But it should always produce a proper ordered
- * or unordered list. If it cannot (due to misbalanced input),
- * it will return the original text. Arguments accepted:
- *
- * <ul>
- *
- * <li><b>text</b>
- *
- * The text to be processed.</li>
- *
- * </ul>
- *
- * @param $args An @c array specifying the attributes for formatting
- * the list.
- *
- * @return A @c string containing the formatted list.
- *
- * @private
- */
- function format_list($args) {
- $str = (isset($args['text']) ? $args['text'] : '');
-
- $list_tags = array('*' => 'ul', '#' => 'ol');
-
- $lines = preg_split('/\n/', $str);
-
- unset($stack);
- $last_depth = 0;
- $item = '';
- $out = '';
- foreach ($lines as $line) {
- if (preg_match('{^((?:' . $this->clstypadre . '*|' . $this->halignre . ')*)
- ([\#\*]+)
- ((?:' . $this->halignre . '|' . $this->clstypadre . '*)*)
- \ (.+)$}x', $line, $matches)) {
- if ($item != '') {
- if (preg_match('/\n/', $item)) {
- if ($this->options['_line_open']) {
- $item = preg_replace('/(<li[^>]*>|^)/m', '$1' . $this->options['_line_open'], $item);
- $item = preg_replace('/(\n|$)/s', $this->options['_line_close'] . '$1', $item);
- } else {
- $item = preg_replace('/(\n)/s', $this->options['_line_close'] . '$1', $item);
- }
- }
- $out .= $item;
- $item = '';
- }
- $type = substr($matches[2], 0, 1);
- $depth = strlen($matches[2]);
- $blockparam = $matches[1];
- $itemparam = $matches[3];
- $line = $matches[4];
- unset ($blockclsty, $blockalign, $blockattr, $itemattr, $itemclsty,
- $itemalign);
- if (preg_match('{(' . $this->clstypadre . '+)}x', $blockparam, $matches)) {
- $blockclsty = $matches[1];
- }
- if (preg_match('{(' . $this->halignre . '+)}', $blockparam, $matches)) {
- $blockalign = $matches[1];
- }
- if (preg_match('{(' . $this->clstypadre . '+)}x', $itemparam, $matches)) {
- $itemclsty = $matches[1];
- }
- if (preg_match('{(' . $this->halignre . '+)}', $itemparam, $matches)) {
- $itemalign = $matches[1];
- }
- if ($itemclsty) { $itemattr = $this->format_classstyle($itemclsty); }
- if ($depth > $last_depth) {
- for ($j = $last_depth; $j < $depth; $j++) {
- $out .= "\n<$list_tags[$type]";
- $stack[] = $type;
- if ($blockclsty) {
- $blockattr = $this->format_classstyle($blockclsty);
- if ($blockattr) { $out .= ' ' . $blockattr; }
- }
- $out .= ">\n<li";
- if ($itemattr) { $out .= " $itemattr"; }
- $out .= ">";
- }
- } elseif ($depth < $last_depth) {
- for ($j = $depth; $j < $last_depth; $j++) {
- if ($j == $depth) { $out .= "</li>\n"; }
- $type = array_pop($stack);
- $out .= "</$list_tags[$type]>\n</li>\n";
- }
- if ($depth) {
- $out .= '<li';
- if ($itemattr) { $out .= " $itemattr"; }
- $out .= '>';
- }
- } else {
- $out .= "</li>\n<li";
- if ($itemattr) { $out .= " $itemattr"; }
- $out .= '>';
- }
- $last_depth = $depth;
- }
- if ($item != '') { $item .= "\n"; }
- $item .= $this->format_paragraph(array('text' => $line));
- }
-
- if (preg_match('/\n/', $item, $matches)) {
- if ($this->options['_line_open']) {
- $item = preg_replace('/(<li[^>]*>|^)/m', '$1' . $this->options['_line_open'], $item);
- $item = preg_replace('/(\n|$)/s', $this->options['_line_close'] . '$1', $item);
- } else {
- $item = preg_replace('/(\n)/s', $this->options['_line_close'] . '$1', $item);
- }
- }
- $out .= $item;
-
- for ($j = 1; $j <= $last_depth; $j++) {
- if ($j == 1) { $out .= '</li>'; }
- $type = array_pop($stack);
- $out .= "\n" . '</' . $list_tags[$type] . '>' . "\n";
- if ($j != $last_depth) { $out .= '</li>'; }
- }
-
- return $out . "\n";
- } // function format_list
-
- /**
- * Processes '==xxxxx==' type blocks for filters. A filter
- * would follow the open '==' sequence and is specified within
- * pipe characters, like so:
- * <pre>
- * ==|filter|text to be filtered==
- * </pre>
- * You may specify multiple filters in the filter portion of
- * the string. Simply comma delimit the filters you desire
- * to execute. Filters are defined using the filters method.
- *
- * @param $args An @c array specifying the attributes for formatting
- * the block.
- *
- * @return A @c string containing the formatted block.
- *
- * @private
- */
- function format_block($args) {
- $str = (isset($args['text']) ? $args['text'] : '');
- $inline = $args['inline'];
- $pre = (isset($args['pre']) ? $args['pre'] : '');
- $post = (isset($args['post']) ? $args['post'] : '');
- $this->_strip_borders($pre, $post);
- $filters = (preg_match('/^(\|(?:(?:[a-z0-9_\-]+)\|)+)/', $str, $matches) ? $matches[1] : '');
- if ($filters) {
- $filtreg = preg_replace('/[^A-Za-z0-9]/', '\\\\$1', $filters);
- $str = preg_replace('/^' . $filtreg . '/', '', $str, 1);
- $filters = preg_replace('/^\|/', '', $filters, 1);
- $filters = preg_replace('/\|$/', '', $filter, 1);
- $filters = preg_split('/\|/', $filters);
- $str = $this->apply_filters(array('text' => $str, 'filters' => $filters));
- $count = count($filters);
- if ($str = preg_replace('!(<p>){' . $count . '}!se', '(++$i ? "$1" : "$1")', $str) && $i) {
- $str = preg_replace('!(</p>){' . $count . '}!s', '$1', $str);
- $str = preg_replace('!(<br( /)?>){' . $count . '}!s', '$1', $str);
- }
- }
- if ($inline) {
- // strip off opening para, closing para, since we're
- // operating within an inline block
- $str = preg_replace('/^\s*<p[^>]*>/', '', $str, 1);
- $str = preg_replace('/<\/p>\s*$/', '', $str, 1);
- }
- return $pre . $str . $post;
- } // function format_block
-
- /**
- * Takes the Textile link attributes and transforms them into
- * a hyperlink.
- *
- * @param $args An @c array specifying the attributes for formatting
- * the link.
- *
- * @return A @c string containing the formatted link.
- *
- * @private
- */
- function format_link($args) {
- $text = (isset($args['text']) ? $args['text'] : '');
- $linktext = (isset($args['linktext']) ? $args['linktext'] : '');
- $title = $args['title'];
- $url = $args['url'];
- $clsty = $args['clsty'];
-
- if (!$url || ($url == '')) {
- return $text;
- }
- if (isset($this->links) && isset($this->links[$url])) {
- $title = ($title ? $title : $this->links[$url]['title']);
- $url = $this->links[$url]['url'];
- }
- $linktext = preg_replace('/ +$/', '', $linktext, 1);
- $linktext = $this->format_paragraph(array('text' => $linktext));
- $url = $this->format_url(array('linktext' => $linktext, 'url' => $url));
- $tag = "<a href=\"$url\"";
- $attr = $this->format_classstyle($clsty);
- if ($attr) { $tag .= " $attr"; }
- if ($title) {
- $title = preg_replace('/^\s+/', '', $title, 1);
- if (strlen($title)) { $tag .= " title=\"$title\""; }
- }
- $tag .= ">$linktext</a>";
- return $tag;
- } // function format_link
-
- /**
- * Takes the given @c $url and transforms it appropriately.
- *
- * @param $args An @c array specifying the attributes for formatting
- * the url.
- *
- * @return A @c string containing the formatted url.
- *
- * @private
- */
- function format_url($args) {
- $url = ($args['url'] ? $args['url'] : '');
- if (preg_match('/^(mailto:)?([-\+\w]+@[-\w]+(\.\w[-\w]*)+)$/', $url, $matches)) {
- $url = 'mailto:' . $this->mail_encode($matches[2]);
- }
- if (!preg_match('!^(/|\./|\.\./|#)!', $url)) {
- if (!preg_match('!^(https?|ftp|mailto|nntp|telnet)!', $url)) { $url = "http://$url"; }
- }
- $url = preg_replace('/&(?!amp;)/', '&', $url);
- $url = preg_replace('/\ /', '+', $url);
- $url = preg_replace_callback('/^((?:.+?)\?)(.+)$/', $this->_cb('$m[1] . $me->encode_url($m[2])'), $url);
- return $url;
- } // function format_url
-
- /**
- * Takes a Textile formatted span and returns the markup for it.
- *
- * @return A @c string containing the formatted span.
- *
- * @private
- */
- function format_span($args) {
- $text = (isset($args['text']) ? $args['text'] : '');
- $pre = (isset($args['pre']) ? $args['pre'] : '');
- $post = (isset($args['post']) ? $args['post'] : '');
- $align = $args['align'];
- $cite = (isset($args['cite']) ? $args['cite'] : '');
- $clsty = $args['clsty'];
- $this->_strip_borders($pre, $post);
- unset($class, $style);
- $tag = "<span";
- $style = '';
- if ($align) {
- if ($self->options['css_mode']) {
- $alignment = $this->_halign($align);
- if ($alignment) { $style .= ";float:$alignment"; }
- if ($alignment) { $class .= ' ' . $this->options['css']["class_align_$alignment"]; }
- } else {
- $alignment = ($this->_halign($align) ? $this->_halign($align) : $this->_valign($align));
- if ($alignment) { $tag .= " align=\"$alignment\""; }
- }
- }
- $attr = $this->format_classstyle($clsty, $class, $style);
- if ($attr) { $tag .= " $attr"; }
- if ($cite) {
- $cite = preg_replace('/^:/', '', $cite, 1);
- $cite = $this->format_url(array('url' => $cite));
- $tag .= " cite=\"$cite\"";
- }
- return $pre . $tag . '>' . $this->format_paragraph(array('text' => $text)) . '</span>' . $post;
- } // function format_span
-
- /**
- * Returns markup for the given image. @c $src is the location of
- * the image, @c $extra contains the optional height/width and/or
- * alt text. @c $url is an optional hyperlink for the image. @c $class
- * holds the optional CSS class attribute.
- *
- * Arguments you may pass:
- *
- * <ul>
- *
- * <li><b>src</b>
- *
- * The 'src' (URL) for the image. This may be a local path,
- * ideally starting with a '/'. Images can be located within
- * the file system if the docroot method is used to specify
- * where the docroot resides. If the image can be found, the
- * image_size method is used to determine the dimensions of
- * the image.</li>
- *
- * <li><b>extra</b>
- *
- * Additional parameters for the image. This would include
- * alt text, height/width specification or scaling instructions.</li>
- *
- * <li><b>align</b>
- *
- * Alignment attribute.</li>
- *
- * <li><b>pre</b>
- *
- * Text to produce prior to the tag.</li>
- *
- * <li><b>post</b>
- *
- * Text to produce following the tag.</li>
- *
- * <li><b>link</b>
- *
- * Optional URL to connect with the image tag.</li>
- *
- * <li><b>clsty</b>
- *
- * Class and/or style attributes.</li>
- *
- * </ul>
- *
- * @param $args An @c array specifying the attributes for formatting
- * the image.
- *
- * @return A @c string containing the formatted image.
- *
- * @private
- */
- function format_image($args) {
- $src = (isset($args['src']) ? $args['src'] : '');
- $extra = $args['extra'];
- $align = $args['align'];
- $pre = (isset($args['pre']) ? $args['pre'] : '');
- $post = (isset($args['post']) ? $args['post'] : '');
- $link = $args['url'];
- $clsty = $args['clsty'];
- $this->_strip_borders($pre, $post);
- if (strlen($src) == 0) { return $pre . '!!' . $post; }
- unset($tag);
- if (preg_match('/^xhtml2/', $this->options['flavor'])) {
- unset($type); // poor man's mime typing. need to extend this externally
- if (preg_match('/(?:\.jpeg|\.jpg)$/i', $src)) {
- $type = 'image/jpeg';
- } elseif (preg_match('/\.gif$/i', $src)) {
- $type = 'image/gif';
- } elseif (preg_match('/\.png$/i', $src)) {
- $type = 'image/png';
- } elseif (preg_match('/\.tiff$/i', $src)) {
- $type = 'image/tiff';
- }
- $tag = "<object";
- if ($type) { $tag .= " type=\"$type\""; }
- $tag .= " data=\"$src\"";
- } else {
- $tag = "<img src=\"$src\"";
- }
- unset($class, $style);
- if ($align) {
- if ($this->options['css_mode']) {
- $alignment = $this->_halign($align);
- if ($alignment) { $style .= ";float:$alignment"; }
- if ($alignment) { $class .= ' ' . $alignment; }
- $alignment = $this->_valign($align);
- if ($alignment) {
- $imgvalign = (preg_match('/(top|bottom)/', $alignment) ? 'text-' . $alignment : $alignment);
- if ($imgvalign) { $style .= ";vertical-align:$imgvalign"; }
- if ($alignment) { $class .= ' ' . $this->options['css']["class_align_$alignment"]; }
- }
- } else {
- $alignment = ($this->_halign($align) ? $this->_halign($align) : $this->_valign($align));
- if ($alignment) { $tag .= " align=\"$alignment\""; }
- }
- }
- unset($pctw, $pcth, $w, $h, $alt);
- if ($extra) {
- $alt = (preg_match('/\(([^\)]+)\)/', $extra, $matches) ? $matches[1] : '');
- $extra = preg_replace('/\([^\)]+\)/', '', $extra, 1);
- $pct = (preg_match('/(^|\s)(\d+)%(\s|$)/', $extra, $matches) ? $matches[2] : '');
- if (!$pct) {
- list($pctw, $pcth) = (preg_match('/(^|\s)(\d+)%x(\d+)%(\s|$)/', $extra, $matches) ? array($matches[2], $matches[3]) : NULL);
- } else {
- $pctw = $pcth = $pct;
- }
- if (!$pctw && !$pcth) {
- list($w,$h) = (preg_match('/(^|\s)(\d+|\*)x(\d+|\*)(\s|$)/', $extra, $matches) ? array($matches[2], $matches[3]) : NULL);
- if ($w == '*') { $w = ''; }
- if ($h == '*') { $h = ''; }
- if (!$w) {
- $w = (preg_match('/(^|[,\s])(\d+)w([\s,]|$)/', $extra, $matches) ? $matches[2] : '');
- }
- if (!$h) {
- $h = (preg_match('/(^|[,\s])(\d+)h([\s,]|$)/', $extra, $matches) ? $matches[2] : '');
- }
- }
- }
- $alt = ($alt ? $alt : '');
- if (!preg_match('/^xhtml2/', $this->options['flavor'])) {
- $tag .= ' alt="' . $this->encode_html_basic($alt) . '"';
- }
- if ($w && $h) {
- if (!preg_match('/^xhtml2/', $this->options['flavor'])) {
- $tag .= " height=\"$h\" width=\"$w\"";
- } else {
- $style .= ";height:${h}px;width:${w}px";
- }
- } else {
- list($image_w, $image_h) = $this->image_size($src);
- if (($image_w && $image_h) && ($w || $h)) {
- // image size determined, but only width or height specified
- if ($w && !$h) {
- // width defined, scale down height proportionately
- $h = intval($image_h * ($w / $image_w));
- } elseif ($h && !$w) {
- $w = intval($image_w * ($h / $image_h));
- }
- } else {
- $w = $image_w;
- $h = $image_h;
- }
- if ($w && $h) {
- if ($pctw || $pcth) {
- $w = intval($w * $pctw / 100);
- $h = intval($h * $pcth / 100);
- }
- if (!preg_match('/^xhtml2/', $this->options['flavor'])) {
- $tag .= " height=\"$h\" width=\"$w\"";
- } else {
- $style .= ";height:{$h}px;width:{$w}px";
- }
- }
- }
- $attr = $this->format_classstyle($clsty, $class, $style);
- if ($attr) { $tag .= " $attr"; }
- if (preg_match('/^xhtml2/', $this->options['flavor'])) {
- $tag .= '><p>' . $this->encode_html_basic($alt) . '</p></object>';
- } elseif (preg_match('/^xhtml/', $this->options['flavor'])) {
- $tag .= ' />';
- } else {
- $tag .= '>';
- }
- if ($link) {
- $link = preg_replace('/^:/', '', $link, 1);
- $link = $this->format_url(array('url' => $link));
- $tag = '<a href="' . $link . '">' . $tag . '</a>';
- }
- return $pre . $tag . $post;
- } // function format_image
-
- /**
- * Takes a Wiki-ish string of data and transforms it into a full
- * table.
- *
- * @param $args An @c array specifying the attributes for formatting
- * the table.
- *
- * @return A @c string containing the formatted table.
- *
- * @private
- */
- function format_table($args) {
- $str = (isset($args['text']) ? $args['text'] : '');
-
- $lines = preg_split('/\n/', $str);
- unset($rows);
- $line_count = count($lines);
- for ($i = 0; $i < $line_count; $i++) {
- if (!preg_match('/\|\s*$/', $lines[$i])) {
- if ($i + 1 < $line_count) {
- if ($i + 1 <= count($lines) - 1) { $lines[$i + 1] = $lines[$i] . "\n" . $lines[$i + 1]; }
- } else {
- $rows[] = $lines[$i];
- }
- } else {
- $rows[] = $lines[$i];
- }
- }
- unset($tid, $tpadl, $tpadr, $tlang);
- $tclass = '';
- $tstyle = '';
- $talign = '';
- if (preg_match('/^table[^\.]/', $rows[0])) {
- $row = $rows[0];
- $row = preg_replace('/^table/', '', $row, 1);
- $params = 1;
- // process row parameters until none are left
- while ($params) {
- if (preg_match('{^(' . $this->tblalignre . ')}', $row, $matches)) {
- // found row alignment
- $talign .= $matches[1];
- if ($matches[1]) { $row = substr($row, strlen($matches[1])); }
- if ($matches[1]) { continue; }
- }
- if (preg_match('{^(' . $this->clstypadre . ')}x', $row, $matches)) {
- // found a class/id/style/padding indicator
- $clsty = $matches[1];
- if ($clsty) { $row = substr($row, strlen($clsty)); }
- if (preg_match('/{([^}]+)}/', $clsty, $matches)) {
- $tstyle = $matches[1];
- $clsty = preg_replace('/{([^}]+)}/', '', $clsty, 1);
- if ($tstyle) { continue; }
- }
- if (preg_match('/\(([A-Za-z0-9_\- ]+?)(?:#(.+?))?\)/', $clsty, $matches) ||
- preg_match('/\(([A-Za-z0-9_\- ]+?)?(?:#(.+?))\)/', $clsty, $matches)) {
- if ($matches[1] || $matches[2]) {
- $tclass = $matches[1];
- $tid = $matches[2];
- continue;
- }
- }
- if (preg_match('/(\(+)/', $clsty, $matches)) { $tpadl = strlen($matches[1]); }
- if (preg_match('/(\)+)/', $clsty, $matches)) { $tpadr = strlen($matches[1]); }
- if (preg_match('/\[(.+?)\]/', $clsty, $matches)) { $tlang = $matches[1]; }
- if ($clsty) { continue; }
- }
- $params = 0;
- }
- $row = preg_replace('/\.\s+/', '', $row, 1);
- $rows[0] = $row;
- }
- $out = '';
- $cols = preg_split('/\|/', $rows[0] . ' ');
- unset($colaligns, $rowspans);
- foreach ($rows as $row) {
- $cols = preg_split('/\|/', $row . ' ');
- $colcount = count($cols) - 1;
- array_pop($cols);
- $colspan = 0;
- $row_out = '';
- unset($rowclass, $rowid, $rowalign, $rowstyle, $rowheader);
- if (!$cols[0]) { $cols[0] = ''; }
- if (preg_match('/_/', $cols[0])) {
- $cols[0] = preg_replace('/_/', '', $cols[0]);
- $rowheader = 1;
- }
- if (preg_match('/{([^}]+)}/', $cols[0], $matches)) {
- $rowstyle = $matches[1];
- $cols[0] = preg_replace('/{[^}]+}/', '', $cols[0]);
- }
- if (preg_match('/\(([^\#]+?)?(#(.+))?\)/', $cols[0], $matches)) {
- $rowclass = $matches[1];
- $rowid = $matches[3];
- $cols[0] = preg_replace('/\([^\)]+\)/', '', $cols[0]);
- }
- if (preg_match('{(' . $this->alignre . ')}', $cols[0], $matches)) { $rowalign = $matches[1]; }
- for ($c = $colcount - 1; $c > 0; $c--) {
- if ($rowspans[$c]) {
- $rowspans[$c]--;
- if ($rowspans[$c] > 1) { continue; }
- }
- unset($colclass, $colid, $header, $colparams, $colpadl, $colpadr, $collang);
- $colstyle = '';
- $colalign = $colaligns[$c];
- $col = array_pop($cols);
- $col = ($col ? $col : '');
- $attrs = '';
- if (preg_match('{^(((_|[/\\\\]\d+|' . $this->alignre . '|' . $this->clstypadre . ')+)\.\ )}x', $col, $matches)) {
- $colparams = $matches[2];
- $col = substr($col, strlen($matches[1]));
- $params = 1;
- // keep processing column parameters until there
- // are none left...
- while ($params) {
- if (preg_match('{^(_|' . $this->alignre . ')(.*)$}', $colparams, $matches)) {
- // found alignment or heading indicator
- $attrs .= $matches[1];
- if ($matches[1]) { $colparams = $matches[2]; }
- if ($matches[1]) { continue; }
- }
- if (preg_match('{^(' . $this->clstypadre . ')(.*)$}x', $colparams, $matches)) {
- // found a class/id/style/padding marker
- $clsty = $matches[1];
- if ($clsty) { $colparams = $matches[2]; }
- if (preg_match('/{([^}]+)}/', $clsty, $matches)) {
- $colstyle = $matches[1];
- $clsty = preg_replace('/{([^}]+)}/', '', $clsty, 1);
- }
- if (preg_match('/\(([A-Za-z0-9_\- ]+?)(?:#(.+?))?\)/', $clsty, $matches) ||
- preg_match('/\(([A-Za-z0-9_\- ]+?)?(?:#(.+?))\)/', $clsty, $matches)) {
- if ($matches[1] || $matches[2]) {
- $colclass = $matches[1];
- $colid = $matches[2];
- if ($colclass) {
- $clsty = preg_replace('/\([A-Za-z0-9_\- ]+?(#.*?)?\)/', '', $clsty);
- } elseif ($colid) {
- $clsty = preg_replace('/\(#.+?\)/', '', $clsty);
- }
- }
- }
- if (preg_match('/(\(+)/', $clsty, $matches)) {
- $colpadl = strlen($matches[1]);
- $clsty = preg_replace('/\(+/', '', $clsty, 1);
- }
- if (preg_match('/(\)+)/', $clsty, $matches)) {
- $colpadr = strlen($matches[1]);
- $clsty = preg_replace('/\)+/', '', $clsty, 1);
- }
- if (preg_match('/\[(.+?)\]/', $clsty, $matches)) {
- $collang = $matches[1];
- $clsty = preg_replace('/\[.+?\]/', '', $clsty, 1);
- }
- if ($clsty) { continue; }
- }
- if (preg_match('/^\\\\(\d+)/', $colparams, $matches)) {
- $colspan = $matches[1];
- $colparams = substr($colparams, strlen($matches[1]) + 1);
- if ($matches[1]) { continue; }
- }
- if (preg_match('/\/(\d+)/', $colparams, $matches)) {
- if ($matches[1]) { $rowspans[$c] = $matches[1]; }
- $colparams = substr($colparams, strlen($matches[1]) + 1);
- if ($matches[1]) { continue; }
- }
- $params = 0;
- }
- }
- if (strlen($attrs)) {
- if (preg_match('/_/', $attrs)) { $header = 1; }
- if (preg_match('{(' . $this->alignre . ')}', $attrs, $matches) && strlen($matches[1])) { $colalign = ''; }
- // determine column alignment
- if (preg_match('/<>/', $attrs)) {
- $colalign .= '<>';
- } elseif (preg_match('/</', $attrs)) {
- $colalign .= '<';
- } elseif (preg_match('/=/', $attrs)) {
- $colalign = '=';
- } elseif (preg_match('/>/', $attrs)) {
- $colalign = '>';
- }
- if (preg_match('/\^/', $attrs)) {
- $colalign .= '^';
- } elseif (preg_match('/~/', $attrs)) {
- $colalign .= '~';
- } elseif (preg_match('/-/', $attrs)) {
- $colalign .= '-';
- }
- }
- if ($rowheader) { $header = 1; }
- if ($header) { $colaligns[$c] = $colalign; }
- $col = preg_replace('/^ +/', '', $col, 1); $col = preg_replace('/ +$/', '', $col, 1);
- if (strlen($col)) {
- // create one cell tag
- $rowspan = ($rowspans[$c] ? $rowspans[$c] : 0);
- $col_out = '<' . ($header ? 'th' : 'td');
- if ($colalign) {
- // horizontal, vertical alignment
- $halign = $this->_halign($colalign);
- if ($halign) { $col_out .= " align=\"$halign\""; }
- $valign = $this->_valign($colalign);
- if ($valign) { $col_out .= " valign=\"$valign\""; }
- }
- // apply css attributes, row, column spans
- if ($colpadl) { $colstyle .= ";padding-left:${colpadl}em"; }
- if ($colpadr) { $colstyle .= ";padding-right:${colpadr}em"; }
- if ($colclass) { $col_out .= " class=\"$colclass\""; }
- if ($colid) { $col_out .= " id=\"$colid\""; }
- if ($colstyle) { $colstyle = preg_replace('/^;/', '', $colstyle, 1); }
- if ($colstyle) { $col_out .= " style=\"$colstyle\""; }
- if ($collang) { $col_out .= " lang=\"$collang\""; }
- if ($colspan > 1) { $col_out .= " colspan=\"$colspan\""; }
- if ($rowspan > 1) { $col_out .= " rowspan=\"$rowspan\""; }
- $col_out .= '>';
- // if the content of this cell has newlines OR matches
- // our paragraph block signature, process it as a full-blown
- // textile document
- if (preg_match('/\n\n/', $col) ||
- preg_match('{^(?:' . $this->halignre . '|' . $this->clstypadre . '*)*
- [\*\#]
- (?:' . $this->clstypadre . '*|' . $this->halignre . ')*\ }x', $col)) {
- $col_out .= $this->process($col);
- } else {
- $col_out .= $this->format_paragraph(array('text' => $col));
- }
- $col_out .= '</' . ($header ? 'th' : 'td') . '>';
- $row_out = $col_out . $row_out;
- if ($colspan) { $colspan = 0; }
- } else {
- if ($colspan == 0) { $colspan = 1; }
- $colspan++;
- }
- }
- if ($colspan > 1) {
- // handle the spanned column if we came up short
- $colspan--;
- $row_out = "<td"
- . ($colspan > 1 ? " colspan=\"$colspan\"" : '')
- . "></td>$row_out";
- }
-
- // build one table row
- $out .= "<tr";
- if ($rowalign) {
- $valign = $this->_valign($rowalign);
- if ($valign) { $out .= " valign=\"$valign\""; }
- }
- if ($rowclass) { $out .= " class=\"$rowclass\""; }
- if ($rowid) { $out .= " id=\"$rowid\""; }
- if ($rowstyle) { $out .= " style=\"$rowstyle\""; }
- $out .= ">$row_out</tr>";
- }
-
- // now, form the table tag itself
- $table = '';
- $table .= "<table";
- if ($talign) {
- if ($this->options['css_mode']) {
- // horizontal alignment
- $alignment = $this->_halign($talign);
- if ($talign == '=') {
- $tstyle .= ';margin-left:auto;margin-right:auto';
- } else {
- if ($alignment) { $tstyle .= ';float:' . $alignment; }
- }
- if ($alignment) { $tclass .= ' ' . $alignment; }
- } else {
- $alignment = $this->_halign($talign);
- if ($alignment) { $table .= " align=\"$alignment\""; }
- }
- }
- if ($tpadl) { $tstyle .= ";padding-left:${tpadl}em"; }
- if ($tpadr) { $tstyle .= ";padding-right:${tpadr}em"; }
- if ($tclass) { $tclass = preg_replace('/^ /', '', $tclass, 1); }
- if ($tclass) { $table .= " class=\"$tclass\""; }
- if ($tid) { $table .= " id=\"$tid\""; }
- if ($tstyle) { $tstyle = preg_replace('/^;/', '', $tstyle, 1); }
- if ($tstyle) { $table .= " style=\"$tstyle\""; }
- if ($tlang) { $table .= " lang=\"$tlang\""; }
- if ($tclass || $tid || $tstyle) { $table .= " cellspacing=\"0\""; }
- $table .= ">$out</table>";
-
- if (preg_match('|<tr></tr>|', $table)) {
- // exception -- something isn't right so return fail case
- return NULL;
- }
-
- return $table;
- } // function format_table
-
- /**
- * The following attributes are allowed:
- *
- * <ul>
- *
- * <li><b>text</b>
- *
- * The text to be processed.</li>
- *
- * <li><b>filters</b>
- *
- * An array reference of filter names to run for the given text.</li>
- *
- * </ul>
- *
- * @param $args An @c array specifying the text and filters to
- * apply.
- *
- * @return A @c string containing the filtered text.
- *
- * @private
- */
- function apply_filters($args) {
- $text = $args['text'];
- if (!$text) { return ''; }
- $list = $args['filters'];
- $filters = $this->options['filters'];
- if (!is_array($filters)) { return $text; }
-
- $param = $this->filter_param();
- foreach ($list as $filter) {
- if (!isset($filters[$filter])) { continue; }
- if (is_string($filters[$filter])) {
- $text = (($f = create_function('$text, $param', $filters[$filter])) ? $f($text, $param) : $text);
- }
- }
- return $text;
- } // function apply_filters
-
- // minor utility / formatting routines
-
- var $Have_Entities = 1;
-
- /**
- * Encodes input @c $html string, escaping characters as needed
- * to HTML entities. This relies on the @c htmlentities function
- * for full effect. If unavailable, @c encode_html_basic is used
- * as a fallback technique. If the "char_encoding" flag is
- * set to false, @c encode_html_basic is used exclusively.
- *
- * @param $html A @c string specifying the HTML to be encoded.
- * @param $can_double_encode If provided, a @c bool indicating
- * whether or not ampersand characters should be
- * unconditionally encoded.
- *
- * @return A @c string containing the encoded HTML.
- *
- * @private
- */
- function encode_html($html, $can_double_encode = FALSE) {
- if (!$html) { return ''; }
- if ($this->Have_Entities && $this->options['char_encoding']) {
- $html = htmlentities($html);
- } else {
- $html = $this->encode_html_basic($html, $can_double_encode);
- }
- return $html;
- } // function encode_html
-
- /**
- * Decodes HTML entities in @c $html to their natural character
- * equivalents.
- *
- * @param $html A @c string specifying the HTML to be decoded.
- *
- * @return A @c string containing the decode HTML
- *
- * @private
- */
- function decode_html($html) {
- $html = preg_replace('!"!', '"', $html);
- $html = preg_replace('!&!', '&', $html);
- $html = preg_replace('!<!', '<', $html);
- $html = preg_replace('!>!', '>', $html);
- return $html;
- } // function decode_html
-
- /**
- * Encodes the input @c $html string for the following characters:
- * \<, \>, & and ". If @c $can_double_encode is true, all
- * ampersand characters are escaped even if they already were.
- * If @c $can_double_encode is false, ampersands are only escaped
- * when they aren't part of a HTML entity already.
- *
- * @param $html A @c string specifying the HTML to be encoded.
- * @param $can_double_encode If provided, a @c bool indicating
- * whether or not ampersand characters should be
- * unconditionally encoded.
- *
- * @return A @c string containing the encoded HTML.
- *
- * @private
- */
- function encode_html_basic($html, $can_double_encode = FALSE) {
- if (!$html) { return ''; }
- if (!preg_match('/[^\w\s]/', $html)) { return $html; }
- if ($can_double_encode) {
- $html = preg_replace('!&!', '&', $html);
- } else {
- // Encode any & not followed by something that looks like
- // an entity, numeric or otherwise.
- $html = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w{1,8});)/', '&', $html);
- }
- $html = preg_replace('!"!', '"', $html);
- $html = preg_replace('!<!', '<', $html);
- $html = preg_replace('!>!', '>', $html);
- return $html;
- } // function encode_html_basic
-
- /**
- * Returns the size for the image identified in @c $file. This
- * method relies upon the @c getimagesize function. If unavailable,
- * @c image_size will return @c NULL. Otherwise, the expected return
- * value is an array of the width and height (in that order), in
- * pixels.
- *
- * @param $file A @c string specifying the path or URL for the image
- * file.
- *
- * @return An @c array containing the width and height
- * (respectively) of the image.
- *
- * @private
- */
- function image_size($file) {
- $Have_ImageSize = function_exists('getimagesize');
-
- if ($Have_ImageSize) {
- if (file_exists($file)) {
- return @getimagesize($file);
- } else {
- if ($docroot = ($this->docroot() ? $this->docroot() : $_SERVER['DOCUMENT_ROOT'])) {
- $fullpath = $docroot . preg_replace('|^/*(.*)$|', '/$1', $file);
- if (file_exists($fullpath)) {
- return @getimagesize($fullpath);
- }
- }
- }
- }
- return @getimagesize($file);
- } // function image_size
-
- /**
- * Encodes the query portion of a URL, escaping characters
- * as necessary.
- *
- * @param $str A @c string specifying the URL to be encoded.
- *
- * @return A @c string containing the encoded URL.
- *
- * @private
- */
- function encode_url($str) {
- $str = preg_replace_callback('!([^A-Za-z0-9_\.\-\+\&=%;])!x',
- $this->_cb('ord($m[1]) > 255 ? \'%u\' . sprintf("%04X", ord($m[1]))
- : \'%\' . sprintf("%02X", ord($m[1]))'), $str);
- return $str;
- } // function encode_url
-
- /**
- * Encodes the email address in @c $addr for 'mailto:' links.
- *
- * @param $addr A @c string specifying the email address to encode.
- *
- * @return A @c string containing the encoded email address.
- *
- * @private
- */
- function mail_encode($addr) {
- // granted, this is simple, but it gives off warm fuzzies
- $addr = preg_replace_callback('!([^\$])!x',
- $this->_cb('ord($m[1]) > 255 ? \'%u\' . sprintf("%04X", ord($m[1]))
- : \'%\' . sprintf("%02X", ord($m[1]))'), $addr);
- return $addr;
- } // function mail_encode
-
- /**
- * Processes string, formatting plain quotes into curly quotes.
- *
- * @param $str A @c string specifying the text to process.
- *
- * @return A @c string containing the processed text.
- *
- * @private
- */
- function process_quotes($str) {
- // stub routine for now. subclass and implement.
- return $str;
- } // function process_quotes
-
- // a default set of macros for the {...} macro syntax
- // just a handy way to write a lot of the international characters
- // and some commonly used symbols
-
- /**
- * Returns an associative @c array of macros that are assigned to be processed by
- * default within the @c format_inline method.
- *
- * @return An @c array containing the default macros.
- *
- * @private
- */
- function default_macros() {
- // <, >, " must be html entities in the macro text since
- // those values are escaped by the time they are processed
- // for macros.
- return array(
- 'c|' => '¢', // CENT SIGN
- '|c' => '¢', // CENT SIGN
- 'L-' => '£', // POUND SIGN
- '-L' => '£', // POUND SIGN
- 'Y=' => '¥', // YEN SIGN
- '=Y' => '¥', // YEN SIGN
- '(c)' => '©', // COPYRIGHT SIGN
- '<<' => '«', // LEFT-POINTING DOUBLE ANGLE QUOTATION
- '(r)' => '®', // REGISTERED SIGN
- '+_' => '±', // PLUS-MINUS SIGN
- '_+' => '±', // PLUS-MINUS SIGN
- '>>' => '»', // RIGHT-POINTING DOUBLE ANGLE QUOTATION
- '1/4' => '¼', // VULGAR FRACTION ONE QUARTER
- '1/2' => '½', // VULGAR FRACTION ONE HALF
- '3/4' => '¾', // VULGAR FRACTION THREE QUARTERS
- 'A`' => 'À', // LATIN CAPITAL LETTER A WITH GRAVE
- '`A' => 'À', // LATIN CAPITAL LETTER A WITH GRAVE
- 'A\'' => 'Á', // LATIN CAPITAL LETTER A WITH ACUTE
- '\'A' => 'Á', // LATIN CAPITAL LETTER A WITH ACUTE
- 'A^' => 'Â', // LATIN CAPITAL LETTER A WITH CIRCUMFLEX
- '^A' => 'Â', // LATIN CAPITAL LETTER A WITH CIRCUMFLEX
- 'A~' => 'Ã', // LATIN CAPITAL LETTER A WITH TILDE
- '~A' => 'Ã', // LATIN CAPITAL LETTER A WITH TILDE
- 'A"' => 'Ä', // LATIN CAPITAL LETTER A WITH DIAERESIS
- '"A' => 'Ä', // LATIN CAPITAL LETTER A WITH DIAERESIS
- 'Ao' => 'Å', // LATIN CAPITAL LETTER A WITH RING ABOVE
- 'oA' => 'Å', // LATIN CAPITAL LETTER A WITH RING ABOVE
- 'AE' => 'Æ', // LATIN CAPITAL LETTER AE
- 'C,' => 'Ç', // LATIN CAPITAL LETTER C WITH CEDILLA
- ',C' => 'Ç', // LATIN CAPITAL LETTER C WITH CEDILLA
- 'E`' => 'È', // LATIN CAPITAL LETTER E WITH GRAVE
- '`E' => 'È', // LATIN CAPITAL LETTER E WITH GRAVE
- 'E\'' => 'É', // LATIN CAPITAL LETTER E WITH ACUTE
- '\'E' => 'É', // LATIN CAPITAL LETTER E WITH ACUTE
- 'E^' => 'Ê', // LATIN CAPITAL LETTER E WITH CIRCUMFLEX
- '^E' => 'Ê', // LATIN CAPITAL LETTER E WITH CIRCUMFLEX
- 'E"' => 'Ë', // LATIN CAPITAL LETTER E WITH DIAERESIS
- '"E' => 'Ë', // LATIN CAPITAL LETTER E WITH DIAERESIS
- 'I`' => 'Ì', // LATIN CAPITAL LETTER I WITH GRAVE
- '`I' => 'Ì', // LATIN CAPITAL LETTER I WITH GRAVE
- 'I\'' => 'Í', // LATIN CAPITAL LETTER I WITH ACUTE
- '\'I' => 'Í', // LATIN CAPITAL LETTER I WITH ACUTE
- 'I^' => 'Î', // LATIN CAPITAL LETTER I WITH CIRCUMFLEX
- '^I' => 'Î', // LATIN CAPITAL LETTER I WITH CIRCUMFLEX
- 'I"' => 'Ï', // LATIN CAPITAL LETTER I WITH DIAERESIS
- '"I' => 'Ï', // LATIN CAPITAL LETTER I WITH DIAERESIS
- 'D-' => 'Ð', // LATIN CAPITAL LETTER ETH
- '-D' => 'Ð', // LATIN CAPITAL LETTER ETH
- 'N~' => 'Ñ', // LATIN CAPITAL LETTER N WITH TILDE
- '~N' => 'Ñ', // LATIN CAPITAL LETTER N WITH TILDE
- 'O`' => 'Ò', // LATIN CAPITAL LETTER O WITH GRAVE
- '`O' => 'Ò', // LATIN CAPITAL LETTER O WITH GRAVE
- 'O\'' => 'Ó', // LATIN CAPITAL LETTER O WITH ACUTE
- '\'O' => 'Ó', // LATIN CAPITAL LETTER O WITH ACUTE
- 'O^' => 'Ô', // LATIN CAPITAL LETTER O WITH CIRCUMFLEX
- '^O' => 'Ô', // LATIN CAPITAL LETTER O WITH CIRCUMFLEX
- 'O~' => 'Õ', // LATIN CAPITAL LETTER O WITH TILDE
- '~O' => 'Õ', // LATIN CAPITAL LETTER O WITH TILDE
- 'O"' => 'Ö', // LATIN CAPITAL LETTER O WITH DIAERESIS
- '"O' => 'Ö', // LATIN CAPITAL LETTER O WITH DIAERESIS
- 'O/' => 'Ø', // LATIN CAPITAL LETTER O WITH STROKE
- '/O' => 'Ø', // LATIN CAPITAL LETTER O WITH STROKE
- 'U`' => 'Ù', // LATIN CAPITAL LETTER U WITH GRAVE
- '`U' => 'Ù', // LATIN CAPITAL LETTER U WITH GRAVE
- 'U\'' => 'Ú', // LATIN CAPITAL LETTER U WITH ACUTE
- '\'U' => 'Ú', // LATIN CAPITAL LETTER U WITH ACUTE
- 'U^' => 'Û', // LATIN CAPITAL LETTER U WITH CIRCUMFLEX
- '^U' => 'Û', // LATIN CAPITAL LETTER U WITH CIRCUMFLEX
- 'U"' => 'Ü', // LATIN CAPITAL LETTER U WITH DIAERESIS
- '"U' => 'Ü', // LATIN CAPITAL LETTER U WITH DIAERESIS
- 'Y\'' => 'Ý', // LATIN CAPITAL LETTER Y WITH ACUTE
- '\'Y' => 'Ý', // LATIN CAPITAL LETTER Y WITH ACUTE
- 'a`' => 'à', // LATIN SMALL LETTER A WITH GRAVE
- '`a' => 'à', // LATIN SMALL LETTER A WITH GRAVE
- 'a\'' => 'á', // LATIN SMALL LETTER A WITH ACUTE
- '\'a' => 'á', // LATIN SMALL LETTER A WITH ACUTE
- 'a^' => 'â', // LATIN SMALL LETTER A WITH CIRCUMFLEX
- '^a' => 'â', // LATIN SMALL LETTER A WITH CIRCUMFLEX
- 'a~' => 'ã', // LATIN SMALL LETTER A WITH TILDE
- '~a' => 'ã', // LATIN SMALL LETTER A WITH TILDE
- 'a"' => 'ä', // LATIN SMALL LETTER A WITH DIAERESIS
- '"a' => 'ä', // LATIN SMALL LETTER A WITH DIAERESIS
- 'ao' => 'å', // LATIN SMALL LETTER A WITH RING ABOVE
- 'oa' => 'å', // LATIN SMALL LETTER A WITH RING ABOVE
- 'ae' => 'æ', // LATIN SMALL LETTER AE
- 'c,' => 'ç', // LATIN SMALL LETTER C WITH CEDILLA
- ',c' => 'ç', // LATIN SMALL LETTER C WITH CEDILLA
- 'e`' => 'è', // LATIN SMALL LETTER E WITH GRAVE
- '`e' => 'è', // LATIN SMALL LETTER E WITH GRAVE
- 'e\'' => 'é', // LATIN SMALL LETTER E WITH ACUTE
- '\'e' => 'é', // LATIN SMALL LETTER E WITH ACUTE
- 'e^' => 'ê', // LATIN SMALL LETTER E WITH CIRCUMFLEX
- '^e' => 'ê', // LATIN SMALL LETTER E WITH CIRCUMFLEX
- 'e"' => 'ë', // LATIN SMALL LETTER E WITH DIAERESIS
- '"e' => 'ë', // LATIN SMALL LETTER E WITH DIAERESIS
- 'i`' => 'ì', // LATIN SMALL LETTER I WITH GRAVE
- '`i' => 'ì', // LATIN SMALL LETTER I WITH GRAVE
- 'i\'' => 'í', // LATIN SMALL LETTER I WITH ACUTE
- '\'i' => 'í', // LATIN SMALL LETTER I WITH ACUTE
- 'i^' => 'î', // LATIN SMALL LETTER I WITH CIRCUMFLEX
- '^i' => 'î', // LATIN SMALL LETTER I WITH CIRCUMFLEX
- 'i"' => 'ï', // LATIN SMALL LETTER I WITH DIAERESIS
- '"i' => 'ï', // LATIN SMALL LETTER I WITH DIAERESIS
- 'n~' => 'ñ', // LATIN SMALL LETTER N WITH TILDE
- '~n' => 'ñ', // LATIN SMALL LETTER N WITH TILDE
- 'o`' => 'ò', // LATIN SMALL LETTER O WITH GRAVE
- '`o' => 'ò', // LATIN SMALL LETTER O WITH GRAVE
- 'o\'' => 'ó', // LATIN SMALL LETTER O WITH ACUTE
- '\'o' => 'ó', // LATIN SMALL LETTER O WITH ACUTE
- 'o^' => 'ô', // LATIN SMALL LETTER O WITH CIRCUMFLEX
- '^o' => 'ô', // LATIN SMALL LETTER O WITH CIRCUMFLEX
- 'o~' => 'õ', // LATIN SMALL LETTER O WITH TILDE
- '~o' => 'õ', // LATIN SMALL LETTER O WITH TILDE
- 'o"' => 'ö', // LATIN SMALL LETTER O WITH DIAERESIS
- '"o' => 'ö', // LATIN SMALL LETTER O WITH DIAERESIS
- ':-' => '÷', // DIVISION SIGN
- '-:' => '÷', // DIVISION SIGN
- 'o/' => 'ø', // LATIN SMALL LETTER O WITH STROKE
- '/o' => 'ø', // LATIN SMALL LETTER O WITH STROKE
- 'u`' => 'ù', // LATIN SMALL LETTER U WITH GRAVE
- '`u' => 'ù', // LATIN SMALL LETTER U WITH GRAVE
- 'u\'' => 'ú', // LATIN SMALL LETTER U WITH ACUTE
- '\'u' => 'ú', // LATIN SMALL LETTER U WITH ACUTE
- 'u^' => 'û', // LATIN SMALL LETTER U WITH CIRCUMFLEX
- '^u' => 'û', // LATIN SMALL LETTER U WITH CIRCUMFLEX
- 'u"' => 'ü', // LATIN SMALL LETTER U WITH DIAERESIS
- '"u' => 'ü', // LATIN SMALL LETTER U WITH DIAERESIS
- 'y\'' => 'ý', // LATIN SMALL LETTER Y WITH ACUTE
- '\'y' => 'ý', // LATIN SMALL LETTER Y WITH ACUTE
- 'y"' => 'ÿ', // LATIN SMALL LETTER Y WITH DIAERESIS
- '"y' => 'ÿ', // LATIN SMALL LETTER Y WITH DIAERESIS
- 'OE' => 'Œ', // LATIN CAPITAL LIGATURE OE
- 'oe' => 'œ', // LATIN SMALL LIGATURE OE
- '*' => '•', // BULLET
- 'Fr' => '₣', // FRENCH FRANC SIGN
- 'L=' => '₤', // LIRA SIGN
- '=L' => '₤', // LIRA SIGN
- 'Rs' => '₨', // RUPEE SIGN
- 'C=' => '€', // EURO SIGN
- '=C' => '€', // EURO SIGN
- 'tm' => '™', // TRADE MARK SIGN
- '<-' => '←', // LEFTWARDS ARROW
- '->' => '→', // RIGHTWARDS ARROW
- '<=' => '⇐', // LEFTWARDS DOUBLE ARROW
- '=>' => '⇒', // RIGHTWARDS DOUBLE ARROW
- '=/' => '≠', // NOT EQUAL TO
- '/=' => '≠', // NOT EQUAL TO
- '<_' => '≤', // LESS-THAN OR EQUAL TO
- '_<' => '≤', // LESS-THAN OR EQUAL TO
- '>_' => '≥', // GREATER-THAN OR EQUAL TO
- '_>' => '≥', // GREATER-THAN OR EQUAL TO
- ':(' => '☹', // WHITE FROWNING FACE
- ':)' => '☺', // WHITE SMILING FACE
- 'spade' => '♠', // BLACK SPADE SUIT
- 'club' => '♣', // BLACK CLUB SUIT
- 'heart' => '♥', // BLACK HEART SUIT
- 'diamond' => '♦', // BLACK DIAMOND SUIT
- );
- } // function default_macros
-
- // "private", internal routines
-
- /**
- * Sets the default CSS names for CSS controlled markup. This
- * is an internal function that should not be called directly.
- *
- * @private
- */
- function _css_defaults() {
- $css_defaults = array(
- 'class_align_right' => 'right',
- 'class_align_left' => 'left',
- 'class_align_center' => 'center',
- 'class_align_top' => 'top',
- 'class_align_bottom' => 'bottom',
- 'class_align_middle' => 'middle',
- 'class_align_justify' => 'justify',
- 'class_caps' => 'caps',
- 'class_footnote' => 'footnote',
- 'id_footnote_prefix' => 'fn',
- );
- $this->css($css_defaults);
- } // function _css_defaults
-
- /**
- * Returns the alignment keyword depending on the symbol passed.
- *
- * <ul>
- *
- * <li><b><code>\<\></code></b>
- *
- * becomes 'justify'</li>
- *
- * <li><b><code>\<</code></b>
- *
- * becomes 'left'</li>
- *
- * <li><b><code>\></code></b>
- *
- * becomes 'right'</li>
- *
- * <li><b><code>=</code></b>
- *
- * becomes 'center'</li>
- *
- * </ul>
- *
- * @param $align A @c string specifying the alignment code.
- *
- * @return A @c string containing the alignment text.
- *
- * @private
- */
- function _halign($align) {
- if (preg_match('/<>/', $align)) {
- return 'justify';
- } elseif (preg_match('/</', $align)) {
- return 'left';
- } elseif (preg_match('/>/', $align)) {
- return 'right';
- } elseif (preg_match('/=/', $align)) {
- return 'center';
- }
- return '';
- } // function _halign
-
- /**
- * Returns the alignment keyword depending on the symbol passed.
- *
- * <ul>
- *
- * <li><b><code>^</code></b>
- *
- * becomes 'top'</li>
- *
- * <li><b><code>~</code></b>
- *
- * becomes 'bottom'</li>
- *
- * <li><b><code>-</code></b>
- *
- * becomes 'middle'</li>
- *
- * </ul>
- *
- * @param $align A @c string specifying the alignment code.
- *
- * @return A @c string containing the alignment text.
- *
- * @private
- */
- function _valign($align) {
- if (preg_match('/\^/', $align)) {
- return 'top';
- } elseif (preg_match('/~/', $align)) {
- return 'bottom';
- } elseif (preg_match('/-/', $align)) {
- return 'middle';
- }
- return '';
- } // function _valign
-
- /**
- * Returns the alignment keyword depending on the symbol passed.
- * The following alignment symbols are recognized, and given
- * preference in the order listed:
- *
- * <ul>
- *
- * <li><b><code>^</code></b>
- *
- * becomes 'top'</li>
- *
- * <li><b><code>~</code></b>
- *
- * becomes 'bottom'</li>
- *
- * <li><b><code>-</code></b>
- *
- * becomes 'middle'</li>
- *
- * <li><b><code>\<</code></b>
- *
- * becomes 'left'</li>
- *
- * <li><b><code>\></code></b>
- *
- * becomes 'right'</li>
- *
- * </ul>
- *
- * @param $align A @c string containing the alignment code.
- *
- * @return A @c string containing the alignment text.
- *
- * @private
- */
- function _imgalign($align) {
- $align = preg_replace('/(<>|=)/', '', $align);
- return ($this->_valign($align) ? $this->_valign($align) : $this->_halign($align));
- } // function _imgalign
-
- /**
- * This utility routine will take 'border' characters off of
- * the given @c $pre and @c $post strings if they match one of these
- * conditions:
- * <pre>
- * $pre starts with '[', $post ends with ']'
- * $pre starts with '{', $post ends with '}'
- * </pre>
- * If neither condition is met, then the @c $pre and @c $post
- * values are left untouched.
- *
- * @param $pre A @c string specifying the prefix.
- * @param $post A @c string specifying the postfix.
- *
- * @private
- */
- function _strip_borders(&$pre, &$post) {
- if ($post && $pre && preg_match('/[{[]/', ($open = substr($pre, 0, 1)))) {
- $close = substr($post, 0, 1);
- if ((($open == '{') && ($close == '}')) ||
- (($open == '[') && ($close == ']'))) {
- $pre = substr($pre, 1);
- $post = substr($post, 1);
- } else {
- if (!preg_match('/[}\]]/', $close)) { $close = substr($post, -1, 1); }
- if ((($open == '{') && ($close == '}')) ||
- (($open == '[') && ($close == ']'))) {
- $pre = substr($pre, 1);
- $post = substr($post, 0, strlen($post) - 1);
- }
- }
- }
- } // function _strip_borders
-
- /**
- * An internal routine that takes a string and appends it to an array.
- * It returns a marker that is used later to restore the preserved
- * string.
- *
- * @param $array The @c array in which to store the replacement
- * text.
- * @param $str A @c string specifying the replacement text.
- *
- * @return A @c string containing a temporary marker for the
- * replacement.
- *
- * @private
- */
- function _repl(&$array, $str) {
- $array[] = $str;
- return '<textile#' . count($array) . '>';
- } // function _repl
-
- /**
- * An internal routine responsible for breaking up a string into
- * individual tag and plaintext elements.
- *
- * @param $str A @c string specifying the text to tokenize.
- *
- * @return An @c array containing the tag and text tokens.
- *
- * @private
- */
- function _tokenize($str) {
- $pos = 0;
- $len = strlen($str);
- unset($tokens);
-
- $depth = 6;
- $nested_tags = substr(str_repeat('(?:</?[A-Za-z0-9:]+ \s? (?:[^<>]|', $depth), 0, -1)
- . str_repeat(')*>)', $depth);
- $match = '(?s: <! ( -- .*? -- \s* )+ > )| # comment
- (?s: <\? .*? \?> )| # processing instruction
- (?s: <% .*? %> )| # ASP-like
- (?:' . $nested_tags . ')|
- (?:' . $this->codere . ')'; // nested tags
-
- while (preg_match('{(' . $match . ')}x', substr($str, $pos), $matches, PREG_OFFSET_CAPTURE)) {
- $whole_tag = $matches[1][0];
- $sec_start = $pos + $matches[1][1] + strlen($whole_tag);
- $tag_start = $sec_start - strlen($whole_tag);
- if ($pos < $tag_start) {
- $tokens[] = array('text', substr($str, $pos, $tag_start - $pos));
- }
- if (preg_match('/^[[{]?@/', $whole_tag)) {
- $tokens[] = array('text', $whole_tag);
- } else {
- // this clever hack allows us to preserve \n within tags.
- // this is restored at the end of the format_paragraph method
- //$whole_tag = preg_replace('/\n/', "\r", $whole_tag);
- $whole_tag = preg_replace('/\n/', "\001", $whole_tag);
- $tokens[] = array('tag', $whole_tag);
- }
- $pos = $sec_start;
- }
- if ($pos < $len) { $tokens[] = array('text', substr($str, $pos, $len - $pos)); }
- return $tokens;
- } // function _tokenize
-
- /**
- * Returns the version of this release of Textile.php. *JHR*
- *
- * @return An @c array with keys 'text' and 'build' containing the
- * text version and build ID of this release, respectively.
- *
- * @static
- */
- function version() {
- /* Why text and an ID? Well, the text is easier for the user to
- * read and understand while the build ID, being a number (a date
- * with a serial, specifically), is easier for the developer to
- * use to determine newer/older versions for upgrade and
- * installation purposes.
- */
- return array("text" => "2.0.8", "build" => 2005032100);
- } // function version
-
- /**
- * Creates a custom callback function from the provided PHP
- * code. The result is used as the callback in
- * @c preg_replace_callback calls. *JHR*
- *
- * @param $function A @c string specifying the PHP code for the
- * function body.
- *
- * @return A @c function to be used for the callback.
- *
- * @private
- */
- function _cb($function) {
- $current =& Textile::_current_store($this);
- return create_function('$m', '$me =& Textile::_current(); return ' . $function . ';');
- } // function _cb
-
- /**
- * Stores a static variable for the Textile class. This helper
- * function is used by @c _current to simulate a static
- * class variable in PHP. *JHR*
- *
- * @param $new If a non-@c NULL object reference, the Textile object
- * to be set as the current object.
- *
- * @return The @c array containing a reference to the current
- * Textile object at index 0. An array is used because PHP
- * does not allow static variables to be references.
- *
- * @static
- * @private
- */
- /* static */ function &_current_store(&$new) {
- static $current = array();
-
- if ($new != NULL) {
- $current = array(&$new);
- }
-
- return $current;
- } // function _current_store
-
- /**
- * Returns the "current" Textile object. This is used within
- * anonymous callback functions which cannot have the scope of a
- * specific object. *JHR*
- *
- * @return An @c object reference to the current Textile object.
- *
- * @static
- * @private
- */
- /* static */ function &_current() {
- $current =& Textile::_current_store($null = NULL);
- return $current[0];
- } // function _current
- } // class Textile
-
- /**
- * Brad Choate's mttextile Movable Type plugin adds some additional
- * functionality to the Textile.pm Perl module. This includes optional
- * "SmartyPants" processing of text to produce smart quotes, dashes,
- * etc., code colorizing using Beautifier, and some special lookup
- * links (imdb, google, dict, and amazon). The @c MTLikeTextile class
- * is a subclass of @c Textile that provides an MT-like implementation
- * of Textile to produce results similar to that of the mttextile
- * plugin. Currently only the SmartyPants and special lookup links are
- * implemented.
- *
- * Using the @c MTLikeTextile class is exactly the same as using @c
- * Textile. Simply use <code>$textile = new MTLikeTextile;</code>
- * instead of <code>$textile = new Textile;</code> to create a Textile
- * object. This will enable the special lookup links. To enable
- * SmartyPants processing, you must install the SmartyPants-PHP
- * implementation available at
- * <a
- * href="http://monauraljerk.org/smartypants-php/">http://monauraljerk.org/smartypants-php/</a>
- * and include the
- * SmartyPants-PHP.inc file.
- *
- * <pre><code>
- * include_once("Textile.php");
- * include_once("SmartyPants-PHP.inc");
- * $text = \<\<\<EOT
- * h1. Heading
- *
- * A _simple_ demonstration of Textile markup.
- *
- * * One
- * * Two
- * * Three
- *
- * "More information":http://www.textism.com/tools/textile is available.
- * EOT;
- *
- * $textile = new MTLikeTextile;
- * $html = $textile->process($text);
- * print $html;
- * </code></pre>
- *
- * @brief A Textile implementation providing additional
- * Movable-Type-like formatting to produce results similar to
- * the mttextile plugin.
- *
- * @author Jim Riggs \<textile at jimandlisa dot com\>
- */
- class MTLikeTextile extends Textile {
- /**
- * Instantiates a new MTLikeTextile object. Optional options
- * can be passed to initialize the object. Attributes for the
- * options key are the same as the get/set method names
- * documented here.
- *
- * @param $options The @c array specifying the options to use for
- * this object.
- *
- * @public
- */
- function MTLikeTextile($options = array()) {
- parent::Textile($options);
- } // function MTLikeTextile
-
- /**
- * @private
- */
- function process_quotes($str) {
- if (!$this->options['do_quotes'] || !function_exists('SmartyPants')) {
- return $str;
- }
-
- return SmartyPants($str, $this->options['smarty_mode']);
- } // function process_quotes
-
- /**
- * @private
- */
- function format_url($args) {
- $url = ($args['url'] ? $args['url'] : '');
-
- if (preg_match('/^(imdb|google|dict|amazon)(:(.+))?$/x', $url, $matches)) {
- $term = $matches[3];
- $term = ($term ? $term : strip_tags($args['linktext']));
-
- switch ($matches[1]) {
- case 'imdb':
- $args['url'] = 'http://www.imdb.com/Find?for=' . $term;
- break;
-
- case 'google':
- $args['url'] = 'http://www.google.com/search?q=' . $term;
- break;
-
- case 'dict':
- $args['url'] = 'http://www.dictionary.com/search?q=' . $term;
- break;
-
- case 'amazon':
- $args['url'] = 'http://www.amazon.com/exec/obidos/external-search?index=blended&keyword=' . $term;
- break;
- }
- }
-
- return parent::format_url($args);
- } // function format_url
- } // class MTLikeTextile
-
- /**
- * @mainpage
- * Textile - A Humane Web Text Generator.
- *
- * @section synopsis SYNOPSIS
- *
- * <pre><code>
- * include_once("Textile.php");
- * $text = \<\<\<EOT
- * h1. Heading
- *
- * A _simple_ demonstration of Textile markup.
- *
- * * One
- * * Two
- * * Three
- *
- * "More information":http://www.textism.com/tools/textile is available.
- * EOT;
- *
- * $textile = new Textile;
- * $html = $textile->process($text);
- * print $html;
- * </code></pre>
- *
- * @section abstract ABSTRACT
- *
- * Textile.php is a PHP-based implementation of Dean Allen's Textile
- * syntax. Textile is shorthand for doing common formatting tasks.
- *
- * @section syntax SYNTAX
- *
- * Textile processes text in units of blocks and lines.
- * A block might also be considered a paragraph, since blocks
- * are separated from one another by a blank line. Blocks
- * can begin with a signature that helps identify the rest
- * of the block content. Block signatures include:
- *
- * <ul>
- *
- * <li><b>p</b>
- *
- * A paragraph block. This is the default signature if no
- * signature is explicitly given. Paragraphs are formatted
- * with all the inline rules (see inline formatting) and
- * each line receives the appropriate markup rules for
- * the flavor of HTML in use. For example, newlines for XHTML
- * content receive a \<br /\> tag at the end of the line
- * (with the exception of the last line in the paragraph).
- * Paragraph blocks are enclosed in a \<p\> tag.</li>
- *
- * <li><b>pre</b>
- *
- * A pre-formatted block of text. Textile will not add any
- * HTML tags for individual lines. Whitespace is also preserved.
- *
- * Note that within a "pre" block, \< and \> are
- * translated into HTML entities automatically.</li>
- *
- * <li><b>bc</b>
- *
- * A "bc" signature is short for "block code", which implies
- * a preformatted section like the 'pre' block, but it also
- * gets a \<code\> tag (or for XHTML 2, a \<blockcode\>
- * tag is used instead).
- *
- * Note that within a "bc" block, \< and \> are
- * translated into HTML entities automatically.</li>
- *
- * <li><b>table</b>
- *
- * For composing HTML tables. See the "TABLES" section for more
- * information.</li>
- *
- * <li><b>bq</b>
- *
- * A "bq" signature is short for "block quote". Paragraph text
- * formatting is applied to these blocks and they are enclosed
- * in a \<blockquote\> tag as well as \<p\> tags
- * within.</li>
- *
- * <li><b>h1, h2, h3, h4, h5, h6</b>
- *
- * Headline signatures that produce \<h1\>, etc. tags.
- * You can adjust the relative output of these using the
- * head_offset attribute.</li>
- *
- * <li><b>clear</b>
- *
- * A 'clear' signature is simply used to indicate that the next
- * block should emit a CSS style attribute that clears any
- * floating elements. The default behavior is to clear "both",
- * but you can use the left (\< or right \>) alignment
- * characters to indicate which side to clear.</li>
- *
- * <li><b>dl</b>
- *
- * A "dl" signature is short for "definition list". See the
- * "LISTS" section for more information.</li>
- *
- * <li><b>fn</b>
- *
- * A "fn" signature is short for "footnote". You add a number
- * following the "fn" keyword to number the footnote. Footnotes
- * are output as paragraph tags but are given a special CSS
- * class name which can be used to style them as you see fit.</li>
- *
- * </ul>
- *
- * All signatures should end with a period and be followed
- * with a space. Inbetween the signature and the period, you
- * may use several parameters to further customize the block.
- * These include:
- *
- * <ul>
- *
- * <li><b><code>{style rule}</code></b>
- *
- * A CSS style rule. Style rules can span multiple lines.</li>
- *
- * <li><b><code>[ll]</code></b>
- *
- * A language identifier (for a "lang" attribute).</li>
- *
- * <li><b><code>(class)</code> or <code>(#id)</code> or <code>(class#id)</code></b>
- *
- * For CSS class and id attributes.</li>
- *
- * <li><b><code>\></code>, <code>\<</code>, <code>=</code>, <code>\<\></code></b>
- *
- * Modifier characters for alignment. Right-justification, left-justification,
- * centered, and full-justification.</li>
- *
- * <li><b><code>(</code> (one or more)</b>
- *
- * Adds padding on the left. 1em per "(" character is applied.
- * When combined with the align-left or align-right modifier,
- * it makes the block float.</li>
- *
- * <li><b><code>)</code> (one or more)</b>
- *
- * Adds padding on the right. 1em per ")" character is applied.
- * When combined with the align-left or align-right modifier,
- * it makes the block float.</li>
- *
- * <li><b><code>|filter|</code> or <code>|filter|filter|filter|</code></b>
- *
- * A filter may be invoked to further format the text for this
- * signature. If one or more filters are identified, the text
- * will be processed first using the filters and then by
- * Textile's own block formatting rules.</li>
- *
- * </ul>
- *
- * @subsection extendedblocks Extended Blocks
- *
- * Normally, a block ends with the first blank line encountered.
- * However, there are situations where you may want a block to continue
- * for multiple paragraphs of text. To cause a given block signature
- * to stay active, use two periods in your signature instead of one.
- * This will tell Textile to keep processing using that signature
- * until it hits the next signature is found.
- *
- * For example:
- * <pre>
- * bq.. This is paragraph one of a block quote.
- *
- * This is paragraph two of a block quote.
- *
- * p. Now we're back to a regular paragraph.
- * </pre>
- * You can apply this technique to any signature (although for
- * some it doesn't make sense, like "h1" for example). This is
- * especially useful for "bc" blocks where your code may
- * have many blank lines scattered through it.
- *
- * @subsection escaping Escaping
- *
- * Sometimes you want Textile to just get out of the way and
- * let you put some regular HTML markup in your document. You
- * can disable Textile formatting for a given block using the '=='
- * escape mechanism:
- * <pre>
- * p. Regular paragraph
- *
- * ==
- * Escaped portion -- will not be formatted
- * by Textile at all
- * ==
- *
- * p. Back to normal.
- * </pre>
- * You can also use this technique within a Textile block,
- * temporarily disabling the inline formatting functions:
- * <pre>
- * p. This is ==*a test*== of escaping.
- * </pre>
- * @subsection inlineformatting Inline Formatting
- *
- * Formatting within a block of text is covered by the "inline"
- * formatting rules. These operators must be placed up against
- * text/punctuation to be recognized. These include:
- *
- * <ul>
- *
- * <li><b><code>*strong*</code></b>
- *
- * Translates into \<strong\>strong\</strong\>.</li>
- *
- * <li><b>_emphasis_</b>
- *
- * Translates into \<em\>emphasis\</em\>.</li>
- *
- * <li><b><code>**bold**</code></b>
- *
- * Translates into \<b\>bold\</b\>.</li>
- *
- * <li><b><code>__italics__</code></b>
- *
- * Translates into \<i\>italics\</i\>.</li>
- *
- * <li><b><code>++bigger++</code></b>
- *
- * Translates into \<big\>bigger\</big\>.</li>
- *
- * <li><b><code>--smaller--</code></b>
- *
- * Translates into: \<small\>smaller\</small\>.</li>
- *
- * <li><b><code>-deleted text-</code></b>
- *
- * Translates into \<del\>deleted text\</del\>.</li>
- *
- * <li><b><code>+inserted text+</code></b>
- *
- * Translates into \<ins\>inserted text\</ins\>.</li>
- *
- * <li><b><code>^superscript^</code></b>
- *
- * Translates into \<sup\>superscript\</sup\>.</li>
- *
- * <li><b><code>~subscript~</code></b>
- *
- * Translates into \<sub\>subscript\</sub\>.</li>
- *
- * <li><b><code>\%span\%</code></b>
- *
- * Translates into \<span\>span\</span\>.</li>
- *
- * <li><b><code>\@code\@</code></b>
- *
- * Translates into \<code\>code\</code\>. Note
- * that within a '\@...\@' section, \< and \> are
- * translated into HTML entities automatically.</li>
- *
- * </ul>
- *
- * Inline formatting operators accept the following modifiers:
- *
- * <ul>
- *
- * <li><b><code>{style rule}</code></b>
- *
- * A CSS style rule.</li>
- *
- * <li><b><code>[ll]</code></b>
- *
- * A language identifier (for a "lang" attribute).</li>
- *
- * <li><b><code>(class)</code> or <code>(#id)</code> or <code>(class#id)</code></b>
- *
- * For CSS class and id attributes.</li>
- *
- * </ul>
- *
- * @subsubsection examples Examples
- * <pre>
- * Textile is *way* cool.
- *
- * Textile is *_way_* cool.
- * </pre>
- * Now this won't work, because the formatting
- * characters need whitespace before and after
- * to be properly recognized.
- * <pre>
- * Textile is way c*oo*l.
- * </pre>
- * However, you can supply braces or brackets to
- * further clarify that you want to format, so
- * this would work:
- * <pre>
- * Textile is way c[*oo*]l.
- * </pre>
- * @subsection footnotes Footnotes
- *
- * You can create footnotes like this:
- * <pre>
- * And then he went on a long trip[1].
- * </pre>
- * By specifying the brackets with a number inside, Textile will
- * recognize that as a footnote marker. It will replace that with
- * a construct like this:
- * <pre>
- * And then he went on a long
- * trip<sup class="footnote"><a href="#fn1">1</a></sup>
- * </pre>
- * To supply the content of the footnote, place it at the end of your
- * document using a "fn" block signature:
- * <pre>
- * fn1. And there was much rejoicing.
- * </pre>
- * Which creates a paragraph that looks like this:
- * <pre>
- * <p class="footnote" id="fn1"><sup>1</sup> And there was
- * much rejoicing.</p>
- * </pre>
- * @subsection links Links
- *
- * Textile defines a shorthand for formatting hyperlinks.
- * The format looks like this:
- * <pre>
- * "Text to display":http://example.com
- * </pre>
- * In addition to this, you can add 'title' text to your link:
- * <pre>
- * "Text to display (Title text)":http://example.com
- * </pre>
- * The URL portion of the link supports relative paths as well
- * as other protocols like ftp, mailto, news, telnet, etc.
- * <pre>
- * "E-mail me please":mailto:someone\@example.com
- * </pre>
- * You can also use single quotes instead of double-quotes if
- * you prefer. As with the inline formatting rules, a hyperlink
- * must be surrounded by whitespace to be recognized (an
- * exception to this is common punctuation which can reside
- * at the end of the URL). If you have to place a URL next to
- * some other text, use the bracket or brace trick to do that:
- * <pre>
- * You["gotta":http://example.com]seethis!
- * </pre>
- * Textile supports an alternate way to compose links. You can
- * optionally create a lookup list of links and refer to them
- * separately. To do this, place one or more links in a block
- * of it's own (it can be anywhere within your document):
- * <pre>
- * [excom]http://example.com
- * [exorg]http://example.org
- * </pre>
- * For a list like this, the text in the square brackets is
- * used to uniquely identify the link given. To refer to that
- * link, you would specify it like this:
- * <pre>
- * "Text to display":excom
- * </pre>
- * Once you've defined your link lookup table, you can use
- * the identifiers any number of times.
- *
- * @subsection images Images
- *
- * Images are identified by the following pattern:
- * <pre>
- * !/path/to/image!
- * </pre>
- * Image attributes may also be specified:
- * <pre>
- * !/path/to/image 10x20!
- * </pre>
- * Which will render an image 10 pixels wide and 20 pixels high.
- * Another way to indicate width and height:
- * <pre>
- * !/path/to/image 10w 20h!
- * </pre>
- * You may also redimension the image using a percentage.
- * <pre>
- * !/path/to/image 20%x40%!
- * </pre>
- * Which will render the image at 20% of it's regular width
- * and 40% of it's regular height.
- *
- * Or specify one percentage to resize proprotionately:
- * <pre>
- * !/path/to/image 20%!
- * </pre>
- * Alt text can be given as well:
- * <pre>
- * !/path/to/image (Alt text)!
- * </pre>
- * The path of the image may refer to a locally hosted image or
- * can be a full URL.
- *
- * You can also use the following modifiers after the opening '!'
- * character:
- *
- * <ul>
- *
- * <li><b><code>\<</code></b>
- *
- * Align the image to the left (causes the image to float if
- * CSS options are enabled).</li>
- *
- * <li><b><code>\></code></b>
- *
- * Align the image to the right (causes the image to float if
- * CSS options are enabled).</li>
- *
- * <li><b><code>-</code> (dash)</b>
- *
- * Aligns the image to the middle.</li>
- *
- * <li><b><code>^</code></b>
- *
- * Aligns the image to the top.</li>
- *
- * <li><b><code>~</code> (tilde)</b>
- *
- * Aligns the image to the bottom.</li>
- *
- * <li><b><code>{style rule}</code></b>
- *
- * Applies a CSS style rule to the image.</li>
- *
- * <li><b><code>(class)</code> or <code>(#id)</code> or <code>(class#id)</code></b>
- *
- * Applies a CSS class and/or id to the image.</li>
- *
- * <li><b><code>(</code> (one or more)</b>
- *
- * Pads 1em on the left for each '(' character.</li>
- *
- * <li><b><code>)</code> (one or more)</b>
- *
- * Pads 1em on the right for each ')' character.</li>
- *
- * </ul>
- *
- * @subsection characterreplacements Character Replacements
- *
- * A few simple, common symbols are automatically replaced:
- * <pre>
- * (c)
- * (r)
- * (tm)
- * </pre>
- * In addition to these, there are a whole set of character
- * macros that are defined by default. All macros are enclosed
- * in curly braces. These include:
- * <pre>
- * {c|} or {|c} cent sign
- * {L-} or {-L} pound sign
- * {Y=} or {=Y} yen sign
- * </pre>
- * Many of these macros can be guessed. For example:
- * <pre>
- * {A'} or {'A}
- * {a"} or {"a}
- * {1/4}
- * {*}
- * {:)}
- * {:(}
- * </pre>
- * @subsection lists Lists
- *
- * Textile also supports ordered and unordered lists.
- * You simply place an asterisk or pound sign, followed
- * with a space at the start of your lines.
- *
- * Simple lists:
- * <pre>
- * * one
- * * two
- * * three
- * </pre>
- * Multi-level lists:
- * <pre>
- * * one
- * ** one A
- * ** one B
- * *** one B1
- * * two
- * ** two A
- * ** two B
- * * three
- * </pre>
- * Ordered lists:
- * <pre>
- * # one
- * # two
- * # three
- * </pre>
- * Styling lists:
- * <pre>
- * (class#id)* one
- * * two
- * * three
- * </pre>
- * The above sets the class and id attributes for the \<ul\>
- * tag.
- * <pre>
- * *(class#id) one
- * * two
- * * three
- * </pre>
- * The above sets the class and id attributes for the first \<li\>
- * tag.
- *
- * Definition lists:
- * <pre>
- * dl. textile:a cloth, especially one manufactured by weaving
- * or knitting; a fabric
- * format:the arrangement of data for storage or display.
- * </pre>
- * Note that there is no space between the term and definition. The
- * term must be at the start of the line (or following the "dl"
- * signature as shown above).
- *
- * @subsection tables Tables
- *
- * Textile supports tables. Tables must be in their own block and
- * must have pipe characters delimiting the columns. An optional
- * block signature of "table" may be used, usually for applying
- * style, class, id or other options to the table element itself.
- *
- * From the simple:
- * <pre>
- * |a|b|c|
- * |1|2|3|
- * </pre>
- * To the complex:
- * <pre>
- * table(fig). {color:red}_|Top|Row|
- * {color:blue}|/2. Second|Row|
- * |_{color:green}. Last|
- * </pre>
- * Modifiers can be specified for the table signature itself,
- * for a table row (prior to the first '|' character) and
- * for any cell (following the '|' for that cell). Note that for
- * cells, a period followed with a space must be placed after
- * any modifiers to distinguish the modifier from the cell content.
- *
- * Modifiers allowed are:
- *
- * <ul>
- *
- * <li><b><code>{style rule}</code></b>
- *
- * A CSS style rule.</li>
- *
- * <li><b><code>(class)</code> or <code>(#id)</code> or <code>(class#id)</code></b>
- *
- * A CSS class and/or id attribute.</li>
- *
- * <li><b><code>(</code> (one or more)</b>
- *
- * Adds 1em of padding to the left for each '(' character.</li>
- *
- * <li><b><code>)</code> (one or more)</b>
- *
- * Adds 1em of padding to the right for each ')' character.</li>
- *
- * <li><b><code>\<</code></b>
- *
- * Aligns to the left (floats to left for tables if combined with the
- * ')' modifier).</li>
- *
- * <li><b><code>\></code></b>
- *
- * Aligns to the right (floats to right for tables if combined with
- * the '(' modifier).</li>
- *
- * <li><b><code>=</code></b>
- *
- * Aligns to center (sets left, right margins to 'auto' for tables).</li>
- *
- * <li><b><code>\<\></code></b>
- *
- * For cells only. Justifies text.</li>
- *
- * <li><b><code>^</code></b>
- *
- * For rows and cells only. Aligns to the top.</li>
- *
- * <li><b><code>~</code> (tilde)</b>
- *
- * For rows and cells only. Aligns to the bottom.</li>
- *
- * <li><b><code>_</code> (underscore)</b>
- *
- * Can be applied to a table row or cell to indicate a header
- * row or cell.</li>
- *
- * <li><b><code>\\2</code> or <code>\\3</code> or <code>\\4</code>, etc.</b>
- *
- * Used within cells to indicate a colspan of 2, 3, 4, etc. columns.
- * When you see "\\", think "push forward".</li>
- *
- * <li><b><code>/2</code> or <code>/3</code> or <code>/4</code>, etc.</b>
- *
- * Used within cells to indicate a rowspan of 2, 3, 4, etc. rows.
- * When you see "/", think "push downward".</li>
- *
- * </ul>
- *
- * When a cell is identified as a header cell and an alignment
- * is specified, that becomes the default alignment for
- * cells below it. You can always override this behavior by
- * specifying an alignment for one of the lower cells.
- *
- * @subsection cssnotes CSS Notes
- *
- * When CSS is enabled (and it is by default), CSS class names
- * are automatically applied in certain situations.
- *
- * <ul>
- *
- * <li>Aligning a block or span or other element to
- * left, right, etc.
- *
- * "left" for left justified, "right" for right justified,
- * "center" for centered text, "justify" for full-justified
- * text.</li>
- *
- * <li>Aligning an image to the top or bottom
- *
- * "top" for top alignment, "bottom" for bottom alignment,
- * "middle" for middle alignment.</li>
- *
- * <li>Footnotes
- *
- * "footnote" is applied to the paragraph tag for the
- * footnote text itself. An id of "fn" plus the footnote
- * number is placed on the paragraph for the footnote as
- * well. For the footnote superscript tag, a class of
- * "footnote" is used.</li>
- *
- * <li>Capped text
- *
- * For a series of characters that are uppercased, a
- * span is placed around them with a class of "caps".</li>
- *
- * </ul>
- *
- * @subsection miscellaneous Miscellaneous
- *
- * Textile tries to do it's very best to ensure proper XHTML
- * syntax. It will even attempt to fix errors you may introduce
- * writing in HTML yourself. Unescaped '&' characters within
- * URLs will be properly escaped. Singlet tags such as br, img
- * and hr are checked for the '/' terminator (and it's added
- * if necessary). The best way to make sure you produce valid
- * XHTML with Textile is to not use any HTML markup at all--
- * use the Textile syntax and let it produce the markup for you.
- *
- * @section license LICENSE
- *
- * Text::Textile is licensed under the same terms as Perl
- * itself. Textile.php is licensed under the terms of the GNU General
- * Public License.
- *
- * @section authorandcopyright AUTHOR & COPYRIGHT
- *
- * Text::Textile was written by Brad Choate, \<brad at bradchoate dot com\>.
- * It is an adaptation of Textile, developed by Dean Allen of Textism.com.
- *
- * Textile.php is a PHP port of Brad Choate's Text::Textile
- * (Textile.pm) Perl module.
- *
- * Textile.php was ported by Jim Riggs \<textile at jimandlissa dot
- * com\>. Great care has been taken to leave the Perl code in much the
- * same form as Textile.pm. While changes were required due to
- * syntactical differences between Perl and PHP, much of the code was
- * left intact (even if alternative syntax or code optimizations could
- * have been made in PHP), even to the point where one can compare
- * functions/subroutines side by side between the two implementations.
- * This has been done to ensure compatibility, reduce the possibility
- * of introducing errors, and simplify maintainance as one version or
- * the other is updated.
- *
- * @author Jim Riggs \<textile at jimandlissa dot com\>
- * @author Brad Choate \<brad at bradchoate dot com\>
- * @copyright Copyright © 2004 Jim Riggs and Brad Choate
- * @version @(#) $Id: Textile.php,v 1.13 2005/03/21 15:26:55 jhriggs Exp $
- */
- ?>
|