(file) Return to Render.pm CVS log (file) (dir) Up to [RizwankCVS] / geekymedia_web / twiki / lib / TWiki

   1 rizwank 1.1 # Module of TWiki Collaboration Platform, http://TWiki.org/
   2             #
   3             # Copyright (C) 2001-2004 Peter Thoeny, peter@thoeny.com
   4             #
   5             # For licensing info read license.txt file in the TWiki root.
   6             # This program is free software; you can redistribute it and/or
   7             # modify it under the terms of the GNU General Public License
   8             # as published by the Free Software Foundation; either version 2
   9             # of the License, or (at your option) any later version.
  10             #
  11             # This program is distributed in the hope that it will be useful,
  12             # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14             # GNU General Public License for more details, published at 
  15             # http://www.gnu.org/copyleft/gpl.html
  16             #
  17             # Notes:
  18             # - Latest version at http://twiki.org/
  19             # - Installation instructions in $dataDir/Main/TWikiDocumentation.txt
  20             # - Customize variables in TWiki.cfg when installing TWiki.
  21             # - Optionally change TWiki.pm for custom extensions of rendering rules.
  22 rizwank 1.1 # - Upgrading TWiki is easy as long as you do not customize TWiki.pm.
  23             # - Check web server error logs for errors, i.e. % tail /var/log/httpd/error_log
  24             #
  25             # Jun 2001 - written by John Talintyre, jet@cheerful.com
  26             
  27             =begin twiki
  28             
  29             ---+ TWiki::Render Module
  30             
  31             This module provides most of the actual HTML rendering code in TWiki.
  32             
  33             =cut
  34             
  35             package TWiki::Render;
  36             
  37             use strict;
  38             
  39             use TWiki qw(:renderflags %regex $TranslationToken);
  40             
  41             # ===========================
  42             # Read the configuration file at compile time in order to set locale
  43 rizwank 1.1 BEGIN {
  44                 # Do a dynamic 'use locale' for this module
  45                 if( $TWiki::useLocale ) {
  46                     require locale;
  47                     import locale ();
  48                 }
  49             }
  50             
  51             # Globals used in rendering
  52             use vars qw(
  53             	$isList @listTypes @listElements
  54                     $newTopicFontColor $newTopicBgColor $linkToolTipInfo $noAutoLink
  55                     $newLinkSymbol %ffCache
  56                     
  57                 );
  58                 
  59             
  60             $noAutoLink = 0;
  61             
  62             =pod
  63             
  64 rizwank 1.1 ---++ sub initialize ()
  65             
  66             Initializes global render module state from preference values (NEWTOPICBGCOLOR, NEWTOPICFONTCOLOR NEWTOPICLINKSYMBOL LINKTOOLTIPINFO NOAUTOLINK)
  67             
  68             Clears the FORMFIELD metadata cache preparatory to expanding %FORMFIELD
  69             tags.
  70             
  71             =cut
  72             
  73             sub initialize
  74             {
  75                 # Add background color and font color (AlWilliams - 18 Sep 2000)
  76                 # PTh: Moved from internalLink to initialize ('cause of performance)
  77                 $newTopicBgColor   = TWiki::Prefs::getPreferencesValue("NEWTOPICBGCOLOR")   || "#FFFFCE";
  78                 $newTopicFontColor = TWiki::Prefs::getPreferencesValue("NEWTOPICFONTCOLOR") || "#0000FF";
  79                 $newLinkSymbol     = TWiki::Prefs::getPreferencesValue("NEWTOPICLINKSYMBOL") || "<sup>?</sup>";
  80                 # tooltip init
  81                 $linkToolTipInfo   = TWiki::Prefs::getPreferencesValue("LINKTOOLTIPINFO")   || "";
  82                 $linkToolTipInfo = '$username - $date - r$rev: $summary' if( $linkToolTipInfo =~ /^on$/ );
  83                 # Prevent autolink of WikiWords
  84                 $noAutoLink        = TWiki::Prefs::getPreferencesValue("NOAUTOLINK") || 0;
  85 rizwank 1.1 
  86               undef %ffCache;
  87             }
  88             
  89             =pod
  90             
  91             ---++ sub renderParent (  $web, $topic, $meta, $args  )
  92             
  93             Not yet documented.
  94             
  95             =cut
  96             
  97             sub renderParent
  98             {
  99                 my( $web, $topic, $meta, $args ) = @_;
 100                 
 101                 my $text = "";
 102             
 103                 my $dontRecurse = 0;
 104                 my $noWebHome = 0;
 105                 my $prefix = "";
 106 rizwank 1.1     my $suffix = "";
 107                 my $usesep = "";
 108             
 109                 if( $args ) {
 110                    $dontRecurse = TWiki::extractNameValuePair( $args, "dontrecurse" );
 111                    $noWebHome =   TWiki::extractNameValuePair( $args, "nowebhome" );
 112                    $prefix =      TWiki::extractNameValuePair( $args, "prefix" );
 113                    $suffix =      TWiki::extractNameValuePair( $args, "suffix" );
 114                    $usesep =      TWiki::extractNameValuePair( $args, "separator" );
 115                 }
 116             
 117                 if( ! $usesep ) {
 118                    $usesep = " &gt; ";
 119                 }
 120             
 121                 my %visited = ();
 122                 $visited{"$web.$topic"} = 1;
 123             
 124                 my $sep = "";
 125                 my $cWeb = $web;
 126             
 127 rizwank 1.1     while( 1 ) {
 128                     my %parent = $meta->findOne( "TOPICPARENT" );
 129                     if( %parent ) {
 130                         my $name = $parent{"name"};
 131                         my $pWeb = $cWeb;
 132                         my $pTopic = $name;
 133                         if( $name =~ /^(.*)\.(.*)$/ ) {
 134                            $pWeb = $1;
 135                            $pTopic = $2;
 136                         }
 137                         if( $noWebHome && ( $pTopic eq $mainTopicname ) ) {
 138                            last;  # exclude "WebHome"
 139                         }
 140                         $text = "[[$pWeb.$pTopic][$pTopic]]$sep$text";
 141                         $sep = $usesep;
 142                         if( $dontRecurse || ! $name ) {
 143                            last;
 144                         } else {
 145                            my $dummy;
 146                            if( $visited{"$pWeb.$pTopic"} ) {
 147                               last;
 148 rizwank 1.1                } else {
 149                               $visited{"$pWeb.$pTopic"} = 1;
 150                            }
 151                            if( TWiki::Store::topicExists( $pWeb, $pTopic ) ) {
 152                                ( $meta, $dummy ) = TWiki::Store::readTopMeta( $pWeb, $pTopic );
 153                            } else {
 154                                last;
 155                            }
 156                            $cWeb = $pWeb;
 157                         }
 158                     } else {
 159                         last;
 160                     }
 161                 }
 162             
 163                 if( $text && $prefix ) {
 164                    $text = "$prefix$text";
 165                 }
 166             
 167                 if( $text && $suffix ) {
 168                    $text .= $suffix;
 169 rizwank 1.1     }
 170             
 171                 return $text;
 172             }
 173             
 174             # ========================
 175             =pod
 176             
 177             ---++ sub renderMoved (  $web, $topic, $meta  )
 178             
 179             Not yet documented.
 180             
 181             =cut
 182             
 183             sub renderMoved
 184             {
 185                 my( $web, $topic, $meta ) = @_;
 186                 
 187                 my $text = "";
 188                 
 189                 my %moved = $meta->findOne( "TOPICMOVED" );
 190 rizwank 1.1     
 191                 if( %moved ) {
 192                     my $from = $moved{"from"};
 193                     $from =~ /(.*)\.(.*)/;
 194                     my $fromWeb = $1;
 195                     my $fromTopic = $2;
 196                     my $to   = $moved{"to"};
 197                     $to =~ /(.*)\.(.*)/;
 198                     my $toWeb = $1;
 199                     my $toTopic = $2;
 200                     my $by   = $moved{"by"};
 201                     $by = TWiki::userToWikiName( $by );
 202                     my $date = $moved{"date"};
 203                     $date = TWiki::formatTime( $date, "", "gmtime" );
 204                     
 205                     # Only allow put back if current web and topic match stored information
 206                     my $putBack = "";
 207                     if( $web eq $toWeb && $topic eq $toTopic ) {
 208                         $putBack  = " - <a title=\"Click to move topic back to previous location, with option to change references.\"";
 209                         $putBack .= " href=\"$dispScriptUrlPath/rename$scriptSuffix/$web/$topic?newweb=$fromWeb&newtopic=$fromTopic&";
 210                         $putBack .= "confirm=on\">put it back</a>";
 211 rizwank 1.1         }
 212                     $text = "<i><nop>$to moved from <nop>$from on $date by $by </i>$putBack";
 213                 }
 214                 
 215                 return $text;
 216             }
 217             
 218             
 219             # ========================
 220             =pod
 221             
 222             ---++ sub renderFormField (  $meta, $args  )
 223             
 224             Not yet documented.
 225             
 226             =cut
 227             
 228             sub renderFormField
 229             {
 230                 my( $meta, $args ) = @_;
 231                 my $text = "";
 232 rizwank 1.1     if( $args ) {
 233                     my $name = TWiki::extractNameValuePair( $args, "name" );
 234                     $text = TWiki::Search::getMetaFormField( $meta, $name ) if( $name );
 235                 }
 236                 return $text;
 237             }
 238             
 239             # =========================
 240             =pod
 241             
 242             ---++ sub renderFormData (  $web, $topic, $meta  )
 243             
 244             Not yet documented.
 245             
 246             =cut
 247             
 248             sub renderFormData
 249             {
 250                 my( $web, $topic, $meta ) = @_;
 251             
 252                 my $metaText = "";
 253 rizwank 1.1     
 254                 my %form = $meta->findOne( "FORM" );
 255                 if( %form ) {
 256                     my $name = $form{"name"};
 257                     $metaText = "<div class=\"twikiForm\">\n";
 258                     $metaText .= "<p></p>\n"; # prefix empty line
 259                     $metaText .= "|*[[$name]]*||\n"; # table header
 260                     my @fields = $meta->find( "FIELD" );
 261                     foreach my $field ( @fields ) {
 262                         my $title = $field->{"title"};
 263                         my $value = $field->{"value"};
 264                         $value =~ s/\n/<br \/>/g;      # undo expansion
 265                         $metaText .= "|  $title:|$value  |\n";
 266                     }
 267                     $metaText .= "\n</div>";
 268                 }
 269             
 270                 return $metaText;
 271             }
 272             
 273             # Before including topic text in a hidden field in web form, encode
 274 rizwank 1.1 # characters that would break the field
 275             =pod
 276             
 277             ---++ sub encodeSpecialChars (  $text  )
 278             
 279             Not yet documented.
 280             
 281             =cut
 282             
 283             sub encodeSpecialChars
 284             {
 285                 my( $text ) = @_;
 286                 
 287                 $text =~ s/&/%_A_%/g;
 288                 $text =~ s/\"/%_Q_%/g;
 289                 $text =~ s/>/%_G_%/g;
 290                 $text =~ s/</%_L_%/g;
 291                 # PTh, JoachimDurchholz 22 Nov 2001: Fix for Codev.OperaBrowserDoublesEndOfLines
 292                 $text =~ s/(\r*\n|\r)/%_N_%/g;
 293             
 294                 return $text;
 295 rizwank 1.1 }
 296             
 297             =pod
 298             
 299             ---++ sub decodeSpecialChars (  $text  )
 300             
 301             Not yet documented.
 302             
 303             =cut
 304             
 305             sub decodeSpecialChars
 306             {
 307                 my( $text ) = @_;
 308                 
 309                 $text =~ s/%_N_%/\r\n/g;
 310                 $text =~ s/%_L_%/</g;
 311                 $text =~ s/%_G_%/>/g;
 312                 $text =~ s/%_Q_%/\"/g;
 313                 $text =~ s/%_A_%/&/g;
 314             
 315                 return $text;
 316 rizwank 1.1 }
 317             
 318             
 319             # =========================
 320             # Render bulleted and numbered lists, including nesting.
 321             # Called from several places.  Accumulates @listTypes and @listElements
 322             # to track nested lists.
 323             =pod
 324             
 325             ---++ sub emitList (  $theType, $theElement, $theDepth, $theOlType  )
 326             
 327             Not yet documented.
 328             
 329             =cut
 330             
 331             sub emitList {
 332                 my( $theType, $theElement, $theDepth, $theOlType ) = @_;
 333             
 334                 my $result = "";
 335                 $isList = 1;
 336             
 337 rizwank 1.1     # Ordered list type
 338                 $theOlType = "" unless( $theOlType );
 339                 $theOlType =~ s/^(.).*/$1/;
 340                 $theOlType = "" if( $theOlType eq "1" );
 341             
 342                 if( @listTypes < $theDepth ) {
 343                     my $firstTime = 1;
 344                     while( @listTypes < $theDepth ) {
 345                         push( @listTypes, $theType );
 346                         push( @listElements, $theElement );
 347                         $result .= "<$theElement>\n" unless( $firstTime );
 348                         if( $theOlType ) {
 349                             $result .= "<$theType type=\"$theOlType\">\n";
 350                         } else {
 351                             $result .= "<$theType>\n";
 352                         }
 353                         $firstTime = 0;
 354                     }
 355             
 356                 } elsif( @listTypes > $theDepth ) {
 357                     while( @listTypes > $theDepth ) {
 358 rizwank 1.1             local($_) = pop @listElements;
 359                         $result .= "</$_>\n";
 360                         local($_) = pop @listTypes;
 361                         $result .= "</$_>\n";
 362                     }
 363                     $result .= "</$listElements[$#listElements]>\n" if( @listElements );
 364             
 365                 } elsif( @listElements ) {
 366                     $result = "</$listElements[$#listElements]>\n";
 367                 }
 368             
 369                 if( ( @listTypes ) && ( $listTypes[$#listTypes] ne $theType ) ) {
 370                     $result .= "</$listTypes[$#listTypes]>\n<$theType>\n";
 371                     $listTypes[$#listTypes] = $theType;
 372                     $listElements[$#listElements] = $theElement;
 373                 }
 374             
 375                 return $result;
 376             }
 377             
 378             # ========================
 379 rizwank 1.1 =pod
 380             
 381             ---++ sub emitTR (  $thePre, $theRow, $insideTABLE  )
 382             
 383             Not yet documented.
 384             
 385             =cut
 386             
 387             sub emitTR {
 388                 my ( $thePre, $theRow, $insideTABLE ) = @_;
 389             
 390                 my $text = "";
 391                 my $attr = "";
 392                 my $l1 = 0;
 393                 my $l2 = 0;
 394                 if( $insideTABLE ) {
 395                     $text = "$thePre<tr>";
 396                 } else {
 397                     $text = "$thePre<table border=\"1\" cellspacing=\"0\" cellpadding=\"1\"> <tr>";
 398                 }
 399                 $theRow =~ s/\t/   /g;  # change tabs to space
 400 rizwank 1.1     $theRow =~ s/\s*$//;    # remove trailing spaces
 401                 $theRow =~ s/(\|\|+)/$TranslationToken . length($1) . "\|"/ge;  # calc COLSPAN
 402             
 403                 foreach( split( /\|/, $theRow ) ) {
 404                     $attr = "";
 405                     #AS 25-5-01 Fix to avoid matching also single columns
 406                     if ( s/$TranslationToken([0-9]+)//o ) { 
 407                         $attr = " colspan=\"$1\"" ;
 408                     }
 409                     s/^\s+$/ &nbsp; /;
 410                     /^(\s*).*?(\s*)$/;
 411                     $l1 = length( $1 || "" );
 412                     $l2 = length( $2 || "" );
 413                     if( $l1 >= 2 ) {
 414                         if( $l2 <= 1 ) {
 415                             $attr .= ' align="right"';
 416                         } else {
 417                             $attr .= ' align="center"';
 418                         }
 419                     }
 420                     if( /^\s*(\*.*\*)\s*$/ ) {
 421 rizwank 1.1             $text .= "<th$attr bgcolor=\"#99CCCC\"> $1 </th>";
 422                     } else {
 423                         $text .= "<td$attr> $_ </td>";
 424                     }
 425                 }
 426                 $text .= "</tr>";
 427                 return $text;
 428             }
 429             
 430             # =========================
 431             =pod
 432             
 433             ---++ sub fixedFontText (  $theText, $theDoBold  )
 434             
 435             Not yet documented.
 436             
 437             =cut
 438             
 439             sub fixedFontText
 440             {
 441                 my( $theText, $theDoBold ) = @_;
 442 rizwank 1.1     # preserve white space, so replace it by "&nbsp; " patterns
 443                 $theText =~ s/\t/   /g;
 444                 $theText =~ s|((?:[\s]{2})+)([^\s])|'&nbsp; ' x (length($1) / 2) . "$2"|eg;
 445                 if( $theDoBold ) {
 446                     return "<code><b>$theText</b></code>";
 447                 } else {
 448                     return "<code>$theText</code>";
 449                 }
 450             }
 451             
 452             # =========================
 453             # Build an HTML &lt;Hn> element with suitable anchor for linking from %<nop>TOC%
 454             =pod
 455             
 456             ---++ sub makeAnchorHeading (  $theText, $theLevel  )
 457             
 458             Not yet documented.
 459             
 460             =cut
 461             
 462             sub makeAnchorHeading
 463 rizwank 1.1 {
 464                 my( $theHeading, $theLevel ) = @_;
 465             
 466                 # - Build '<nop><h1><a name="atext"></a> heading </h1>' markup
 467                 # - Initial '<nop>' is needed to prevent subsequent matches.
 468                 # - filter out $regex{headerPatternNoTOC} ( '!!' and '%NOTOC%' )
 469                 # CODE_SMELL: Empty anchor tags seem not to be allowed, but validators and browsers tolerate them
 470             
 471                 my $anchorName =       makeAnchorName( $theHeading, 0 );
 472                 my $compatAnchorName = makeAnchorName( $theHeading, 1 );
 473                 $theHeading =~ s/$regex{headerPatternNoTOC}//o; # filter '!!', '%NOTOC%'
 474                 my $text = "<nop><h$theLevel>";
 475                 $text .= "<a name=\"$anchorName\"> </a>";
 476                 $text .= "<a name=\"$compatAnchorName\"> </a>" if( $compatAnchorName ne $anchorName );
 477                 $text .= " $theHeading </h$theLevel>";
 478             
 479                 return $text;
 480             }
 481             
 482             # =========================
 483             # Build a valid HTML anchor name
 484 rizwank 1.1 =pod
 485             
 486             ---++ sub makeAnchorName (  $anchorName, $compatibilityMode  )
 487             
 488             Not yet documented.
 489             
 490             =cut
 491             
 492             sub makeAnchorName
 493             {
 494                 my( $anchorName, $compatibilityMode ) = @_;
 495             
 496                 if ( ! $compatibilityMode && $anchorName =~ /^$regex{anchorRegex}$/ ) {
 497             	# accept, already valid -- just remove leading #
 498             	return substr($anchorName, 1);
 499                 }
 500             
 501                 if ( $compatibilityMode ) {
 502             	# remove leading/trailing underscores first, allowing them to be
 503             	# reintroduced
 504             	$anchorName =~ s/^[\s\#\_]*//;
 505 rizwank 1.1         $anchorName =~ s/[\s\_]*$//;
 506                 }
 507                 $anchorName =~ s/<\w[^>]*>//gi;         # remove HTML tags
 508                 $anchorName =~ s/\&\#?[a-zA-Z0-9]*;//g; # remove HTML entities
 509                 $anchorName =~ s/\&//g;                 # remove &
 510                 $anchorName =~ s/^(.+?)\s*$regex{headerPatternNoTOC}.*/$1/o; # filter TOC excludes if not at beginning
 511                 $anchorName =~ s/$regex{headerPatternNoTOC}//o; # filter '!!', '%NOTOC%'
 512                 # FIXME: More efficient to match with '+' on next line:
 513                 $anchorName =~ s/$regex{singleMixedNonAlphaNumRegex}/_/g;      # only allowed chars
 514                 $anchorName =~ s/__+/_/g;               # remove excessive '_'
 515                 if ( !$compatibilityMode ) {
 516                     $anchorName =~ s/^[\s\#\_]*//;      # no leading space nor '#', '_'
 517                 }
 518                 $anchorName =~ s/^(.{32})(.*)$/$1/;     # limit to 32 chars - FIXME: Use Unicode chars before truncate
 519                 if ( !$compatibilityMode ) {
 520                     $anchorName =~ s/[\s\_]*$//;        # no trailing space, nor '_'
 521                 }
 522             
 523                 # No need to encode 8-bit characters in anchor due to UTF-8 URL support
 524             
 525                 return $anchorName;
 526 rizwank 1.1 }
 527             
 528             # =========================
 529             =pod
 530             
 531             ---++ sub linkToolTipInfo ( $theWeb, $theTopic )
 532             
 533             Returns =title="..."= tooltip info in case LINKTOOLTIPINFO perferences variable is set. 
 534             Warning: Slower performance if enabled.
 535             
 536             =cut
 537             
 538             sub linkToolTipInfo
 539             {
 540                 my( $theWeb, $theTopic ) = @_;
 541                 return "" unless( $linkToolTipInfo );
 542                 return "" if( $linkToolTipInfo =~ /^off$/i );
 543             
 544                 # FIXME: This is slow, it can be improved by caching topic rev info and summary
 545                 my( $date, $user, $rev ) = TWiki::Store::getRevisionInfo( $theWeb, $theTopic );
 546                 my $text = $linkToolTipInfo;
 547 rizwank 1.1     $text =~ s/\$web/<nop>$theWeb/g;
 548                 $text =~ s/\$topic/<nop>$theTopic/g;
 549                 $text =~ s/\$rev/1.$rev/g;
 550                 $text =~ s/\$date/&TWiki::formatTime( $date )/ge;
 551                 $text =~ s/\$username/<nop>$user/g;                                     # "jsmith"
 552                 $text =~ s/\$wikiname/"<nop>" . &TWiki::userToWikiName( $user, 1 )/ge;  # "JohnSmith"
 553                 $text =~ s/\$wikiusername/"<nop>" . &TWiki::userToWikiName( $user )/ge; # "Main.JohnSmith"
 554                 if( $text =~ /\$summary/ ) {
 555                     my $summary = &TWiki::Store::readFileHead( "$TWiki::dataDir/$theWeb/$theTopic.txt", 16 );
 556                     $summary = &TWiki::makeTopicSummary( $summary, $theTopic, $theWeb );
 557                     $summary =~ s/[\"\']/<nop>/g;       # remove quotes (not allowed in title attribute)
 558                     $text =~ s/\$summary/$summary/g;
 559                 }
 560                 return " title=\"$text\"";
 561             }
 562             
 563             # =========================
 564             =pod
 565             
 566             ---++ sub internalLink (  $thePreamble, $theWeb, $theTopic, $theLinkText, $theAnchor, $doLink, $doKeepWeb )
 567             
 568 rizwank 1.1 Not yet documented.
 569             
 570             =cut
 571             
 572             sub internalLink {
 573                 my( $thePreamble, $theWeb, $theTopic, $theLinkText, $theAnchor, $doLink, $doKeepWeb ) = @_;
 574                 # $thePreamble is text used before the TWiki link syntax
 575                 # $doLink is boolean: false means suppress link for non-existing pages
 576                 # $doKeepWeb is boolean: true to keep web prefix (for non existing Web.TOPIC)
 577             
 578                 # Get rid of leading/trailing spaces in topic name
 579                 $theTopic =~ s/^\s*//;
 580                 $theTopic =~ s/\s*$//;
 581             
 582                 # Turn spaced-out names into WikiWords - upper case first letter of
 583                 # whole link, and first of each word. TODO: Try to turn this off,
 584                 # avoiding spaces being stripped elsewhere - e.g. $doPreserveSpacedOutWords 
 585                 $theTopic =~ s/^(.)/\U$1/;
 586                 $theTopic =~ s/\s($regex{singleMixedAlphaNumRegex})/\U$1/go;	
 587             
 588                 # Add <nop> before WikiWord inside link text to prevent double links
 589 rizwank 1.1     $theLinkText =~ s/([\s\(])($regex{singleUpperAlphaRegex})/$1<nop>$2/go;
 590              
 591                  # Allow spacing out, etc
 592                  if (TWiki::isWikiName($theLinkText)) {
 593                     $theLinkText = TWiki::Plugins::renderWikiWordHandler( $theLinkText ) || $theLinkText;
 594                  }
 595             
 596                 my $exist = &TWiki::Store::topicExists( $theWeb, $theTopic );
 597                 # I18N - Only apply plural processing if site language is English, or
 598                 # if a built-in English-language web (Main, TWiki or Plugins).  Plurals
 599                 # apply to names ending in 's', where topic doesn't exist with plural
 600                 # name.
 601                 if(  ( $doPluralToSingular ) and ( $siteLang eq 'en' 
 602             					or $theWeb eq $mainWebname
 603             					or $theWeb eq $twikiWebname
 604             					or $theWeb eq 'Plugins' 
 605             				     ) 
 606             	    and ( $theTopic =~ /s$/ ) and not ( $exist ) ) {
 607                     # Topic name is plural in form and doesn't exist as written
 608                     my $tmp = $theTopic;
 609                     $tmp =~ s/ies$/y/;       # plurals like policy / policies
 610 rizwank 1.1         $tmp =~ s/sses$/ss/;     # plurals like address / addresses
 611                     $tmp =~ s/([Xx])es$/$1/; # plurals like box / boxes
 612                     $tmp =~ s/([A-Za-rt-z])s$/$1/; # others, excluding ending ss like address(es)
 613                     if( &TWiki::Store::topicExists( $theWeb, $tmp ) ) {
 614                         $theTopic = $tmp;
 615                         $exist = 1;
 616                     }
 617                 }
 618             
 619                 my $text = $thePreamble;
 620                 if( $exist) {
 621                     if( $theAnchor ) {
 622                         my $anchor = makeAnchorName( $theAnchor );
 623                         $text .= "<a class=\"twikiAnchorLink\" href=\"$dispScriptUrlPath$dispViewPath"
 624             		  .  "$scriptSuffix/$theWeb/$theTopic\#$anchor\""
 625                               .  &linkToolTipInfo( $theWeb, $theTopic )
 626                               .  ">$theLinkText</a>";
 627                         return $text;
 628                     } else {
 629                         $text .= "<a class=\"twikiLink\" href=\"$dispScriptUrlPath$dispViewPath"
 630             		  .  "$scriptSuffix/$theWeb/$theTopic\""
 631 rizwank 1.1                   .  &linkToolTipInfo( $theWeb, $theTopic )
 632                               .  ">$theLinkText</a>";
 633                         return $text;
 634                     }
 635             
 636                 } elsif( $doLink ) {
 637                     $text .= "<span class=\"twikiNewLink\" style='background : $newTopicBgColor;'>"
 638                           .  "<font color=\"$newTopicFontColor\">$theLinkText</font>"
 639                           .  "<a href=\"$dispScriptUrlPath/edit$scriptSuffix/$theWeb/$theTopic?topicparent=$TWiki::webName.$TWiki::topicName\">$newLinkSymbol</a></span>";
 640                     return $text;
 641             
 642                 } elsif( $doKeepWeb ) {
 643                     $text .= "$theWeb.$theLinkText";
 644                     return $text;
 645             
 646                 } else {
 647                     $text .= $theLinkText;
 648                     return $text;
 649                 }
 650             }
 651             
 652 rizwank 1.1 # =========================
 653             =pod
 654             
 655             ---++ sub internalCrosswebLink (  $thePreamble, $theWeb, $theTopic, $theLinkText, $theAnchor, $doLink  )
 656             
 657             Not yet documented.
 658             
 659             =cut
 660             
 661             sub internalCrosswebLink
 662             {
 663                 my( $thePreamble, $theWeb, $theTopic, $theLinkText, $theAnchor, $doLink ) = @_;
 664                 if ( $theTopic eq $TWiki::mainTopicname && $theWeb ne $TWiki::webName ) {
 665                     return internalLink( $thePreamble, $theWeb, $theTopic, $theWeb, $theAnchor, $doLink );
 666                 } else {
 667                     return internalLink( $thePreamble, $theWeb, $theTopic, $theLinkText, $theAnchor, $doLink );
 668                 }
 669             }
 670             
 671             # =========================
 672             # Handle most internal and external links
 673 rizwank 1.1 =pod
 674             
 675             ---++ sub specificLink (  $thePreamble, $theWeb, $theTopic, $theText, $theLink  )
 676             
 677             Not yet documented.
 678             
 679             =cut
 680             
 681             sub specificLink
 682             {
 683                 my( $thePreamble, $theWeb, $theTopic, $theText, $theLink ) = @_;
 684             
 685                 # format: $thePreamble[[$theText]]
 686                 # format: $thePreamble[[$theLink][$theText]]
 687                 #
 688                 # Current page's $theWeb and $theTopic are also used
 689             
 690                 # Strip leading/trailing spaces
 691                 $theLink =~ s/^\s*//;
 692                 $theLink =~ s/\s*$//;
 693             
 694 rizwank 1.1     if( $theLink =~ /^$regex{linkProtocolPattern}\:/ ) {
 695             
 696                     # External link: add <nop> before WikiWord and ABBREV 
 697             	# inside link text, to prevent double links
 698             	$theText =~ s/([\s\(])($regex{singleUpperAlphaRegex})/$1<nop>$2/go;
 699                     return "$thePreamble<a href=\"$theLink\" target=\"_top\">$theText</a>";
 700             
 701                 } else {
 702             
 703             	# Internal link: get any 'Web.' prefix, or use current web
 704             	$theLink =~ s/^($regex{webNameRegex}|$regex{defaultWebNameRegex})\.//;
 705             	my $web = $1 || $theWeb;
 706             	(my $baz = "foo") =~ s/foo//;       # reset $1, defensive coding
 707             
 708             	# Extract '#anchor'
 709             	# FIXME and NOTE: Had '-' as valid anchor character, removed
 710             	# $theLink =~ s/(\#[a-zA-Z_0-9\-]*$)//;
 711             	$theLink =~ s/($regex{anchorRegex}$)//;
 712             	my $anchor = $1 || "";
 713             
 714             	# Get the topic name
 715 rizwank 1.1 	my $topic = $theLink || $theTopic;  # remaining is topic
 716             	$topic =~ s/\&[a-z]+\;//gi;        # filter out &any; entities
 717             	$topic =~ s/\&\#[0-9]+\;//g;       # filter out &#123; entities
 718             	$topic =~ s/[\\\/\#\&\(\)\{\}\[\]\<\>\!\=\:\,\.]//g;
 719             	$topic =~ s/$securityFilter//go;    # filter out suspicious chars
 720             	if( ! $topic ) {
 721             	    return "$thePreamble$theText"; # no link if no topic
 722             	}
 723             
 724             	return internalLink( $thePreamble, $web, $topic, $theText, $anchor, 1 );
 725                 }
 726             
 727             }
 728             
 729             # =========================
 730             =pod
 731             
 732             ---++ sub externalLink (  $pre, $url  )
 733             
 734             Not yet documented.
 735             
 736 rizwank 1.1 =cut
 737             
 738             sub externalLink
 739             {
 740                 my( $pre, $url ) = @_;
 741                 if( $url =~ /\.(gif|jpg|jpeg|png)$/i ) {
 742                     my $filename = $url;
 743                     $filename =~ s@.*/([^/]*)@$1@go;
 744                     return "$pre<img src=\"$url\" alt=\"$filename\" />";
 745                 }
 746             
 747                 return "$pre<a href=\"$url\" target=\"_top\">$url</a>";
 748             }
 749             
 750             # =========================
 751             =pod
 752             
 753             ---++ sub mailtoLink (  $theAccount, $theSubDomain, $theTopDomain  )
 754             
 755             Not yet documented.
 756             
 757 rizwank 1.1 =cut
 758             
 759             sub mailtoLink
 760             {
 761                 my( $theAccount, $theSubDomain, $theTopDomain ) = @_;
 762             
 763                 my $addr = "$theAccount\@$theSubDomain$TWiki::noSpamPadding\.$theTopDomain";
 764                 return "<a href=\"mailto\:$addr\">$addr</a>";
 765             }
 766             
 767             # =========================
 768             =pod
 769             
 770             ---++ sub mailtoLinkFull (  $theAccount, $theSubDomain, $theTopDomain, $theLinkText  )
 771             
 772             Not yet documented.
 773             
 774             =cut
 775             
 776             sub mailtoLinkFull
 777             {
 778 rizwank 1.1     my( $theAccount, $theSubDomain, $theTopDomain, $theLinkText ) = @_;
 779             
 780                 my $addr = "$theAccount\@$theSubDomain$TWiki::noSpamPadding\.$theTopDomain";
 781                 return "<a href=\"mailto\:$addr\">$theLinkText</a>";
 782             }
 783             
 784             # =========================
 785             =pod
 786             
 787             ---++ sub mailtoLinkSimple (  $theMailtoString, $theLinkText  )
 788             
 789             Not yet documented.
 790             
 791             =cut
 792             
 793             sub mailtoLinkSimple
 794             {
 795                 # Does not do any anti-spam padding, because address will not include '@'
 796                 my( $theMailtoString, $theLinkText ) = @_;	
 797             
 798                 # Defensive coding
 799 rizwank 1.1     if ($theMailtoString =~ s/@//g ) {
 800                 	writeWarning("mailtoLinkSimple called with an '\@' in string - internal TWiki error");
 801                 }
 802                 return "<a href=\"mailto\:$theMailtoString\">$theLinkText</a>";
 803             }
 804             
 805             =pod
 806             
 807             ---++ sub getFormField ( $web, $topic, $args )
 808             
 809             +Returns the expansion of a %FORMFIELD{}% tag.
 810             
 811             =cut
 812             
 813             sub getFormField
 814             {
 815                my( $web, $topic, $args ) = @_;
 816             
 817               my $formField = TWiki::extractNameValuePair( $args );
 818               my $formTopic = TWiki::extractNameValuePair( $args, "topic" );
 819               my $altText   = TWiki::extractNameValuePair( $args, "alttext" );
 820 rizwank 1.1   my $default   = TWiki::extractNameValuePair( $args, "default" ) || undef;
 821               my $format    = TWiki::extractNameValuePair( $args, "format" );
 822             
 823               unless ( $format ) {
 824                    # if null format explicitly set, return empty
 825                    return "" if ( $args =~ m/format\s*=/o);
 826                    # Otherwise default to value
 827                    $format = "\$value";
 828               }
 829             
 830               my $formWeb;
 831               if ( $formTopic ) {
 832                    if ($topic =~ /^([^.]+)\.([^.]+)/o) {
 833                      ( $formWeb, $topic ) = ( $1, $2 );
 834             	   } else {
 835                      # SMELL: Undocumented feature, "web" parameter
 836                      $formWeb = TWiki::extractNameValuePair( $args, "web" );
 837             	   }
 838                    $formWeb = $web unless $formWeb;
 839               } else {
 840                    $formWeb = $web;
 841 rizwank 1.1        $formTopic = $topic;
 842               }
 843             
 844               my $meta = $ffCache{"$formWeb.$formTopic"};
 845               unless ( $meta ) {
 846                    my $dummyText;
 847                    ( $meta, $dummyText ) =
 848                      TWiki::Store::readTopic( $formWeb, $formTopic );
 849                    $ffCache{"$formWeb.$formTopic"} = $meta;
 850               }
 851             
 852               my $text = "";
 853               my $found = 0;
 854               if ( $meta ) {
 855                    my @fields = $meta->find( "FIELD" );
 856                    foreach my $field ( @fields ) {
 857                      my $title = $field->{"title"};
 858                      my $name = $field->{"name"};
 859                      if( $title eq $formField || $name eq $formField ) {
 860                            $found = 1;
 861                            my $value = $field->{"value"};
 862 rizwank 1.1                if (length $value) {
 863                              $text = $format;
 864                              $text =~ s/\$value/$value/go;
 865                            } elsif ( defined $default ) {
 866                              $text = $default;
 867                            }
 868                            last; #one hit suffices
 869                      }
 870                    }
 871               }
 872             
 873               unless ( $found ) {
 874                    $text = $altText;
 875               }
 876             
 877               return "" unless $text;
 878             
 879               return getRenderedVersion( $text, $web );
 880             }
 881             
 882             =pod
 883 rizwank 1.1 
 884             ---++ sub getRenderedVersion (  $text, $theWeb, $meta  )
 885             
 886             Not yet documented.
 887             
 888             =cut
 889             
 890             sub getRenderedVersion
 891             {
 892                 my( $text, $theWeb, $meta ) = @_;
 893                 my( $head, $result, $extraLines, $insidePRE, $insideTABLE, $insideNoAutoLink );
 894             
 895                 return "" unless $text;  # nothing to do
 896             
 897                 # FIXME: Get $theTopic from parameter to handle [[#anchor]] correctly
 898                 # (fails in %INCLUDE%, %SEARCH%)
 899                 my $theTopic = $TWiki::topicName;
 900             
 901                 # PTh 22 Jul 2000: added $theWeb for correct handling of %INCLUDE%, %SEARCH%
 902                 if( !$theWeb ) {
 903                     $theWeb = $TWiki::webName;
 904 rizwank 1.1     }
 905             
 906                 $head = "";
 907                 $result = "";
 908                 $insidePRE = 0;
 909                 $insideTABLE = 0;
 910                 $insideNoAutoLink = 0;      # PTh 02 Feb 2001: Added Codev.DisableWikiWordLinks
 911                 $isList = 0;
 912                 @listTypes = ();
 913                 @listElements = ();
 914             
 915                 # Initial cleanup
 916                 $text =~ s/\r//g;
 917                 $text =~ s/(\n?)$/\n<nop>\n/s; # clutch to enforce correct rendering at end of doc
 918                 # Convert any occurrences of token (very unlikely - details in
 919                 # Codev.NationalCharTokenClash)
 920                 $text =~ s/$TranslationToken/!/go;	
 921             
 922                 my @verbatim = ();
 923                 $text = TWiki::takeOutVerbatim( $text, \@verbatim );
 924                 $text =~ s/\\\n//g;  # Join lines ending in "\"
 925 rizwank 1.1 
 926                 # do not render HTML head, style sheets and scripts
 927                 if( $text =~ m/<body[\s\>]/i ) {
 928                     my $bodyTag = "";
 929                     my $bodyText = "";
 930                     ( $head, $bodyTag, $bodyText ) = split( /(<body)/i, $text, 3 );
 931                     $text = $bodyTag . $bodyText;
 932                 }
 933                 
 934                 # Wiki Plugin Hook
 935                 &TWiki::Plugins::startRenderingHandler( $text, $theWeb, $meta );
 936             
 937                 # $isList is tested and set by this loop and 'emitList' function
 938                 $isList = 0;		# True when within a list
 939             
 940                 foreach( split( /\n/, $text ) ) {
 941             
 942                     # change state:
 943                     m|<pre>|i  && ( $insidePRE = 1 );
 944                     m|</pre>|i && ( $insidePRE = 0 );
 945                     m|<noautolink>|i   && ( $insideNoAutoLink = 1 );
 946 rizwank 1.1         m|</noautolink>|i  && ( $insideNoAutoLink = 0 );
 947             
 948                     if( $insidePRE ) {
 949                         # inside <PRE>
 950             
 951                         # close list tags if any
 952                         if( @listTypes ) {
 953                             $result .= &emitList( "", "", 0 );
 954                             $isList = 0;
 955                         }
 956             
 957             # Wiki Plugin Hook
 958                         &TWiki::Plugins::insidePREHandler( $_ );
 959             
 960                         s/(.*)/$1\n/;
 961                         s/\t/   /g;		# Three spaces
 962                         $result .= $_;
 963             
 964                     } else {
 965                       # normal state, do Wiki rendering
 966             
 967 rizwank 1.1 # Wiki Plugin Hook
 968                       &TWiki::Plugins::outsidePREHandler( $_ );
 969                       $extraLines = undef;   # Plugins might introduce extra lines
 970                       do {                   # Loop over extra lines added by plugins
 971                         $_ = $extraLines if( defined $extraLines );
 972                         s/^(.*?)\n(.*)$/$1/s;
 973                         $extraLines = $2;    # Save extra lines, need to parse each separately
 974             
 975             # Escape rendering: Change " !AnyWord" to " <nop>AnyWord", for final " AnyWord" output
 976                         s/(^|[\s\(])\!(?=[\w\*\=])/$1<nop>/g;
 977             
 978             # Blockquoted email (indented with '> ')
 979                         s/^>(.*?)$/> <cite> $1 <\/cite><br \/>/g;
 980             
 981             # Embedded HTML
 982                         s/\<(\!\-\-)/$TranslationToken$1/g;  # Allow standalone "<!--"
 983                         s/(\-\-)\>/$1$TranslationToken/g;    # Allow standalone "-->"
 984             	    # FIXME: next 2 lines are redundant since s///g's below do same
 985             	    # thing
 986                         s/(\<\<+)/"&lt\;" x length($1)/ge;
 987                         s/(\>\>+)/"&gt\;" x length($1)/ge;
 988 rizwank 1.1             s/\<nop\>/nopTOKEN/g;  # defuse <nop> inside HTML tags
 989                         s/\<(\S.*?)\>/$TranslationToken$1$TranslationToken/g;
 990                         s/</&lt\;/g;
 991                         s/>/&gt\;/g;
 992                         s/$TranslationToken(\S.*?)$TranslationToken/\<$1\>/go;
 993                         s/nopTOKEN/\<nop\>/g;
 994                         s/(\-\-)$TranslationToken/$1\>/go;
 995                         s/$TranslationToken(\!\-\-)/\<$1/go;
 996             
 997             # Handle embedded URLs
 998                         s!(^|[\-\*\s\(])($regex{linkProtocolPattern}\:([^\s\<\>\"]+[^\s\.\,\!\?\;\:\)\<]))!&externalLink($1,$2)!geo;
 999             
1000             # Entities
1001                         s/&(\w+?)\;/$TranslationToken$1\;/g;      # "&abc;"
1002                         s/&(\#[0-9]+)\;/$TranslationToken$1\;/g;  # "&#123;"
1003                         s/&/&amp;/g;                              # escape standalone "&"
1004                         s/$TranslationToken/&/go;
1005             
1006             # Headings
1007                         # '<h6>...</h6>' HTML rule
1008                         s/$regex{headerPatternHt}/&makeAnchorHeading($2,$1)/geoi;
1009 rizwank 1.1             # '\t+++++++' rule
1010                         s/$regex{headerPatternSp}/&makeAnchorHeading($2,(length($1)))/geo;
1011                         # '----+++++++' rule
1012                         s/$regex{headerPatternDa}/&makeAnchorHeading($2,(length($1)))/geo;
1013             
1014             # Horizontal rule
1015                         s/^---+/<hr \/>/;
1016                         s!^([a-zA-Z0-9]+)----*!<table width=\"100%\"><tr><td valign=\"bottom\"><h2>$1</h2></td><td width=\"98%\" valign=\"middle\"><hr /></td></tr></table>!o;
1017             
1018             # Table of format: | cell | cell |
1019                         # PTh 25 Jan 2001: Forgiving syntax, allow trailing white space
1020                         if( $_ =~ /^(\s*)\|.*\|\s*$/ ) {
1021                             s/^(\s*)\|(.*)/&emitTR($1,$2,$insideTABLE)/e;
1022                             $insideTABLE = 1;
1023                         } elsif( $insideTABLE ) {
1024                             $result .= "</table>\n";
1025                             $insideTABLE = 0;
1026                         }
1027             
1028             # Lists and paragraphs
1029                         s/^\s*$/<p \/>/o                 && ( $isList = 0 );
1030 rizwank 1.1             m/^(\S+?)/o                      && ( $isList = 0 );
1031             	    # Definition list
1032                         s/^(\t+)\$\s(([^:]+|:[^\s]+)+?):\s/<dt> $2 <\/dt><dd> /o && ( $result .= &emitList( "dl", "dd", length $1 ) );
1033                         s/^(\t+)(\S+?):\s/<dt> $2<\/dt><dd> /o && ( $result .= &emitList( "dl", "dd", length $1 ) );
1034             	    # Unnumbered list
1035                         s/^(\t+)\* /<li> /o              && ( $result .= &emitList( "ul", "li", length $1 ) );
1036             	    # Numbered list
1037                         s/^(\t+)([1AaIi]\.|\d+\.?) ?/<li> /o && ( $result .= &emitList( "ol", "li", length $1, $2 ) );
1038             	    # Finish the list
1039                         if( ! $isList ) {
1040                             $result .= &emitList( "", "", 0 );
1041                             $isList = 0;
1042                         }
1043             
1044             # '#WikiName' anchors
1045                         s/^(\#)($regex{wikiWordRegex})/ '<a name="' . &makeAnchorName( $2 ) . '"><\/a>'/ge;
1046             
1047             # enclose in white space for the regex that follow
1048                          s/(.*)/\n$1\n/;
1049             
1050             # Emphasizing
1051 rizwank 1.1             # PTh 25 Sep 2000: More relaxed rules, allow leading '(' and trailing ',.;:!?)'
1052                         s/([\s\(])==([^\s]+?|[^\s].*?[^\s])==([\s\,\.\;\:\!\?\)])/$1 . &fixedFontText( $2, 1 ) . $3/ge;
1053                         s/([\s\(])__([^\s]+?|[^\s].*?[^\s])__([\s\,\.\;\:\!\?\)])/$1<strong><em>$2<\/em><\/strong>$3/g;
1054                         s/([\s\(])\*([^\s]+?|[^\s].*?[^\s])\*([\s\,\.\;\:\!\?\)])/$1<strong>$2<\/strong>$3/g;
1055                         s/([\s\(])_([^\s]+?|[^\s].*?[^\s])_([\s\,\.\;\:\!\?\)])/$1<em>$2<\/em>$3/g;
1056                         s/([\s\(])=([^\s]+?|[^\s].*?[^\s])=([\s\,\.\;\:\!\?\)])/$1 . &fixedFontText( $2, 0 ) . $3/ge;
1057             
1058             # Mailto
1059             	    # Email addresses must always be 7-bit, even within I18N sites
1060             
1061             	    # RD 27 Mar 02: Mailto improvements - FIXME: check security...
1062             	    # Explicit [[mailto:... ]] link without an '@' - hence no 
1063             	    # anti-spam padding needed.
1064                         # '[[mailto:string display text]]' link (no '@' in 'string'):
1065                         s/\[\[mailto\:([^\s\@]+)\s+(.+?)\]\]/&mailtoLinkSimple( $1, $2 )/ge;
1066             
1067             	    # Explicit [[mailto:... ]] link including '@', with anti-spam 
1068             	    # padding, so match name@subdom.dom.
1069                         # '[[mailto:string display text]]' link
1070                         s/\[\[mailto\:([a-zA-Z0-9\-\_\.\+]+)\@([a-zA-Z0-9\-\_\.]+)\.(.+?)(\s+|\]\[)(.*?)\]\]/&mailtoLinkFull( $1, $2, $3, $5 )/ge;
1071             
1072 rizwank 1.1 	    # Normal mailto:foo@example.com ('mailto:' part optional)
1073             	    # FIXME: Should be '?' after the 'mailto:'...
1074                         s/([\s\(])(?:mailto\:)*([a-zA-Z0-9\-\_\.\+]+)\@([a-zA-Z0-9\-\_\.]+)\.([a-zA-Z0-9\-\_]+)(?=[\s\.\,\;\:\!\?\)])/$1 . &mailtoLink( $2, $3, $4 )/ge;
1075             
1076             # Make internal links
1077                         # Escape rendering: Change " ![[..." to " [<nop>[...", for final unrendered " [[..." output
1078                         s/(\s)\!\[\[/$1\[<nop>\[/g;
1079             	    # Spaced-out Wiki words with alternative link text
1080                         # '[[Web.odd wiki word#anchor][display text]]' link:
1081                         s/\[\[([^\]]+)\]\[([^\]]+)\]\]/&specificLink("",$theWeb,$theTopic,$2,$1)/ge;
1082                         # RD 25 Mar 02: Codev.EasierExternalLinking
1083                         # '[[URL#anchor display text]]' link:
1084                         s/\[\[([a-z]+\:\S+)\s+(.*?)\]\]/&specificLink("",$theWeb,$theTopic,$2,$1)/ge;
1085             	    # Spaced-out Wiki words
1086                         # '[[Web.odd wiki word#anchor]]' link:
1087                         s/\[\[([^\]]+)\]\]/&specificLink("",$theWeb,$theTopic,$1,$1)/ge;
1088             
1089                         # do normal WikiWord link if not disabled by <noautolink> or NOAUTOLINK preferences variable
1090                         unless( $noAutoLink || $insideNoAutoLink ) {
1091             
1092                             # 'Web.TopicName#anchor' link:
1093 rizwank 1.1                 s/([\s\(])($regex{webNameRegex})\.($regex{wikiWordRegex})($regex{anchorRegex})/&internalLink($1,$2,$3,"$TranslationToken$3$4$TranslationToken",$4,1)/geo;
1094                             # 'Web.TopicName' link:
1095                             s/([\s\(])($regex{webNameRegex})\.($regex{wikiWordRegex})/&internalCrosswebLink($1,$2,$3,"$TranslationToken$3$TranslationToken","",1)/geo;
1096             
1097                             # 'TopicName#anchor' link:
1098                             s/([\s\(])($regex{wikiWordRegex})($regex{anchorRegex})/&internalLink($1,$theWeb,$2,"$TranslationToken$2$3$TranslationToken",$3,1)/geo;
1099             
1100                             # 'TopicName' link:
1101             		s/([\s\(])($regex{wikiWordRegex})/&internalLink($1,$theWeb,$2,$2,"",1)/geo;
1102             
1103             		# Handle acronyms/abbreviations of three or more letters
1104                             # 'Web.ABBREV' link:
1105                             s/([\s\(])($regex{webNameRegex})\.($regex{abbrevRegex})/&internalLink($1,$2,$3,$3,"",0,1)/geo;
1106                             # 'ABBREV' link:
1107             		s/([\s\(])($regex{abbrevRegex})/&internalLink($1,$theWeb,$2,$2,"",0)/geo;
1108                             # (deprecated <link> moved to DefaultPlugin)
1109             
1110                             s/$TranslationToken(\S.*?)$TranslationToken/$1/go;
1111                         }
1112             
1113                         s/^\n//;
1114 rizwank 1.1             s/\t/   /g;
1115                         $result .= $_;
1116             
1117                       } while( defined( $extraLines ) );  # extra lines produced by plugins
1118                     }
1119                 }
1120                 if( $insideTABLE ) {
1121                     $result .= "</table>\n";
1122                 }
1123                 $result .= &emitList( "", "", 0 );
1124                 if( $insidePRE ) {
1125                     $result .= "</pre>\n";
1126                 }
1127             
1128                 # Wiki Plugin Hook
1129                 &TWiki::Plugins::endRenderingHandler( $result );
1130             
1131                 $result = TWiki::putBackVerbatim( $result, "pre", @verbatim );
1132             
1133                 $result =~ s|\n?<nop>\n$||o; # clean up clutch
1134                 return "$head$result";
1135 rizwank 1.1 }
1136             
1137             =end twiki
1138             
1139             =cut
1140             
1141             1;

Rizwan Kassim
Powered by
ViewCVS 0.9.2