Overview

Namespaces

  • None
  • PHP

Classes

  • Breadcrumb
  • Breadcrumbs
  • CacheFile
  • Comment
  • CommentArray
  • CommentFilter
  • CommentForm
  • CommentList
  • Config
  • Database
  • DatabaseQuery
  • DatabaseQuerySelect
  • DatabaseQuerySelectFulltext
  • DatabaseStopwords
  • Debug
  • Field
  • Fieldgroup
  • Fieldgroups
  • FieldgroupsArray
  • Fields
  • FieldsArray
  • Fieldtype
  • FieldtypeMulti
  • Fieldtypes
  • FileLog
  • FilenameArray
  • Fuel
  • HookEvent
  • ImageSizer
  • Inputfield
  • InputfieldsArray
  • InputfieldWrapper
  • Language
  • LanguageParser
  • Languages
  • LanguagesPageFieldValue
  • LanguageSupportInstall
  • LanguageTranslator
  • Markdown_Parser
  • MarkdownExtra_Parser
  • ModuleJS
  • ModulePlaceholder
  • Modules
  • Notice
  • NoticeError
  • NoticeMessage
  • Notices
  • NullPage
  • Page
  • PageArray
  • Pagefile
  • Pagefiles
  • PagefilesManager
  • PageFinder
  • Pageimage
  • Pageimages
  • PagerNav
  • PagerNavItem
  • Pages
  • PagesAccess
  • PagesSortfields
  • PagesType
  • Paths
  • Permission
  • Permissions
  • Process
  • ProcessController
  • ProcessWire
  • Role
  • Roles
  • Sanitizer
  • Selector
  • SelectorBitwiseAnd
  • SelectorContains
  • SelectorContainsLike
  • SelectorContainsWords
  • SelectorEnds
  • SelectorEqual
  • SelectorGreaterThan
  • SelectorGreaterThanEqual
  • SelectorLessThan
  • SelectorLessThanEqual
  • SelectorNotEqual
  • Selectors
  • SelectorStarts
  • Session
  • SessionCSRF
  • SmartyPants_Parser
  • SmartyPantsTypographer_Parser
  • SystemUpdate1
  • Template
  • TemplateFile
  • Templates
  • TemplatesArray
  • Textformatter
  • Textile
  • User
  • Users
  • Wire
  • WireArray
  • WireData
  • WireInput
  • WireInputData
  • WireSaveableItems
  • WireSaveableItemsLookup
  • WireUpload

Interfaces

  • CommentFormInterface
  • CommentListInterface
  • ConfigurableModule
  • FieldtypeLanguageInterface
  • FieldtypePageTitleCompatible
  • HasLookupItems
  • HasRoles
  • InputfieldHasArrayValue
  • Module
  • Saveable
  • TrackChanges

Exceptions

  • ProcessController404Exception
  • ProcessControllerPermissionException
  • Wire404Exception
  • WireDatabaseException
  • WireException
  • WirePermissionException

Functions

  • __
  • _n
  • _x
  • fuel
  • identify_modifier_markdown
  • Markdown
  • mdwp_add_p
  • mdwp_hide_tags
  • mdwp_show_tags
  • mdwp_strip_p
  • ProcessWireClassLoader
  • ProcessWireHostSiteConfig
  • ProcessWireShutdown
  • removeNewlines
  • SmartDashes
  • SmartEllipsis
  • SmartQuotes
  • smarty_modifier_markdown
  • smarty_modifier_smartypants
  • SmartyPants
  • tabIndent
  • unregisterGLOBALS
  • wire
  • wireDecodeJSON
  • wireEncodeJSON
  • wireMkdir
  • Overview
  • Namespace
  • Class
  • Tree
  • Download
   1: <?php
   2: #
   3: # SmartyPants Typographer  -  Smart typography for web sites
   4: #
   5: # PHP SmartyPants & Typographer  
   6: # Copyright (c) 2004-2006 Michel Fortin
   7: # <http://www.michelf.com/>
   8: #
   9: # Original SmartyPants
  10: # Copyright (c) 2003-2004 John Gruber
  11: # <http://daringfireball.net/>
  12: #
  13: 
  14: 
  15: define( 'SMARTYPANTS_VERSION',            "1.5.1oo2" ); # Unreleased
  16: define( 'SMARTYPANTSTYPOGRAPHER_VERSION', "1.0"      ); # Wed 28 Jun 2006
  17: 
  18: 
  19: #
  20: # Default configuration:
  21: #
  22: #  1  ->  "--" for em-dashes; no en-dash support  
  23: #  2  ->  "---" for em-dashes; "--" for en-dashes  
  24: #  3  ->  "--" for em-dashes; "---" for en-dashes  
  25: #  See docs for more configuration options.
  26: #
  27: define( 'SMARTYPANTS_ATTR',    1 );
  28: 
  29: # Openning and closing smart double-quotes.
  30: define( 'SMARTYPANTS_SMART_DOUBLEQUOTE_OPEN',  "&#8220;" );
  31: define( 'SMARTYPANTS_SMART_DOUBLEQUOTE_CLOSE', "&#8221;" );
  32: 
  33: # Space around em-dashes.  "He_—_or she_—_should change that."
  34: define( 'SMARTYPANTS_SPACE_EMDASH',      " " );
  35: 
  36: # Space around en-dashes.  "He_–_or she_–_should change that."
  37: define( 'SMARTYPANTS_SPACE_ENDASH',      " " );
  38: 
  39: # Space before a colon. "He said_: here it is."
  40: define( 'SMARTYPANTS_SPACE_COLON',       "&#160;" );
  41: 
  42: # Space before a semicolon. "That's what I said_; that's what he said."
  43: define( 'SMARTYPANTS_SPACE_SEMICOLON',   "&#160;" );
  44: 
  45: # Space before a question mark and an exclamation mark: "¡_Holà_! What_?"
  46: define( 'SMARTYPANTS_SPACE_MARKS',       "&#160;" );
  47: 
  48: # Space inside french quotes. "Voici la «_chose_» qui m'a attaqué."
  49: define( 'SMARTYPANTS_SPACE_FRENCHQUOTE', "&#160;" );
  50: 
  51: # Space as thousand separator. "On compte 10_000 maisons sur cette liste."
  52: define( 'SMARTYPANTS_SPACE_THOUSAND',    "&#160;" );
  53: 
  54: # Space before a unit abreviation. "This 12_kg of matter costs 10_$."
  55: define( 'SMARTYPANTS_SPACE_UNIT',        "&#160;" );
  56: 
  57: # SmartyPants will not alter the content of these tags:
  58: define( 'SMARTYPANTS_TAGS_TO_SKIP', 'pre|code|kbd|script|math');
  59: 
  60: 
  61: 
  62: ### Standard Function Interface ###
  63: 
  64: define( 'SMARTYPANTS_PARSER_CLASS', 'SmartyPantsTypographer_Parser' );
  65: 
  66: function SmartyPants($text, $attr = SMARTYPANTS_ATTR) {
  67: #
  68: # Initialize the parser and return the result of its transform method.
  69: #
  70:     # Setup static parser array.
  71:     static $parser = array();
  72:     if (!isset($parser[$attr])) {
  73:         $parser_class = SMARTYPANTS_PARSER_CLASS;
  74:         $parser[$attr] = new $parser_class($attr);
  75:     }
  76: 
  77:     # Transform text using parser.
  78:     return $parser[$attr]->transform($text);
  79: }
  80: 
  81: function SmartQuotes($text, $attr = 1) {
  82:     switch ($attr) {
  83:         case 0:  return $text;
  84:         case 2:  $attr = 'qb'; break;
  85:         default: $attr = 'q'; break;
  86:     }
  87:     return SmartyPants($text, $attr);
  88: }
  89: 
  90: function SmartDashes($text, $attr = 1) {
  91:     switch ($attr) {
  92:         case 0:  return $text;
  93:         case 2:  $attr = 'D'; break;
  94:         case 3:  $attr = 'i'; break;
  95:         default: $attr = 'd'; break;
  96:     }
  97:     return SmartyPants($text, $attr);
  98: }
  99: 
 100: function SmartEllipsis($text, $attr = 1) {
 101:     switch ($attr) {
 102:         case 0:  return $text;
 103:         default: $attr = 'e'; break;
 104:     }
 105:     return SmartyPants($text, $attr);
 106: }
 107: 
 108: 
 109: ### WordPress Plugin Interface ###
 110: 
 111: /*
 112: Plugin Name: SmartyPants Typographer
 113: Plugin URI: http://www.michelf.com/projects/php-smartypants/
 114: Description: SmartyPants is a web publishing utility that translates plain ASCII punctuation characters into &#8220;smart&#8221; typographic punctuation HTML entities. The Typographer extension will also replace normal spaces with unbrekable ones where appropriate to silently remove unwanted line breaks around punctuation and at some other places. This plugin <strong>replace the default WordPress Texturize algorithm</strong> for the content and the title of your posts, the comments body and author name, and everywhere else Texturize normally apply.
 115: Version: 1.0
 116: Author: Michel Fortin
 117: Author URI: http://www.michelf.com/
 118: */
 119: 
 120: if (isset($wp_version)) {
 121:     # Remove default Texturize filter that would conflict with SmartyPants.
 122:     remove_filter('category_description', 'wptexturize');
 123:     remove_filter('list_cats', 'wptexturize');
 124:     remove_filter('comment_author', 'wptexturize');
 125:     remove_filter('comment_text', 'wptexturize');
 126:     remove_filter('single_post_title', 'wptexturize');
 127:     remove_filter('the_title', 'wptexturize');
 128:     remove_filter('the_content', 'wptexturize');
 129:     remove_filter('the_excerpt', 'wptexturize');
 130:     # Add SmartyPants filter with priority 10 (same as Texturize).
 131:     add_filter('category_description', 'SmartyPants', 10);
 132:     add_filter('list_cats', 'SmartyPants', 10);
 133:     add_filter('comment_author', 'SmartyPants', 10);
 134:     add_filter('comment_text', 'SmartyPants', 10);
 135:     add_filter('single_post_title', 'SmartyPants', 10);
 136:     add_filter('the_title', 'SmartyPants', 10);
 137:     add_filter('the_content', 'SmartyPants', 10);
 138:     add_filter('the_excerpt', 'SmartyPants', 10);
 139: }
 140: 
 141: 
 142: ### Smarty Modifier Interface ###
 143: 
 144: function smarty_modifier_smartypants($text, $attr = NULL) {
 145:     return SmartyPants($text, $attr);
 146: }
 147: 
 148: 
 149: 
 150: #
 151: # SmartyPants Parser Class
 152: #
 153: 
 154: class SmartyPants_Parser {
 155: 
 156:     # Options to specify which transformations to make:
 157:     var $do_nothing   = 0;
 158:     var $do_quotes    = 0;
 159:     var $do_backticks = 0;
 160:     var $do_dashes    = 0;
 161:     var $do_ellipses  = 0;
 162:     var $do_stupefy   = 0;
 163:     var $convert_quot = 0; # should we translate &quot; entities into normal quotes?
 164: 
 165:     function SmartyPants_Parser($attr = SMARTYPANTS_ATTR) {
 166:     #
 167:     # Initialize a SmartyPants_Parser with certain attributes.
 168:     #
 169:     # Parser attributes:
 170:     # 0 : do nothing
 171:     # 1 : set all
 172:     # 2 : set all, using old school en- and em- dash shortcuts
 173:     # 3 : set all, using inverted old school en and em- dash shortcuts
 174:     # 
 175:     # q : quotes
 176:     # b : backtick quotes (``double'' only)
 177:     # B : backtick quotes (``double'' and `single')
 178:     # d : dashes
 179:     # D : old school dashes
 180:     # i : inverted old school dashes
 181:     # e : ellipses
 182:     # w : convert &quot; entities to " for Dreamweaver users
 183:     #
 184:         if ($attr == "0") {
 185:             $this->do_nothing   = 1;
 186:         }
 187:         else if ($attr == "1") {
 188:             # Do everything, turn all options on.
 189:             $this->do_quotes    = 1;
 190:             $this->do_backticks = 1;
 191:             $this->do_dashes    = 1;
 192:             $this->do_ellipses  = 1;
 193:         }
 194:         else if ($attr == "2") {
 195:             # Do everything, turn all options on, use old school dash shorthand.
 196:             $this->do_quotes    = 1;
 197:             $this->do_backticks = 1;
 198:             $this->do_dashes    = 2;
 199:             $this->do_ellipses  = 1;
 200:         }
 201:         else if ($attr == "3") {
 202:             # Do everything, turn all options on, use inverted old school dash shorthand.
 203:             $this->do_quotes    = 1;
 204:             $this->do_backticks = 1;
 205:             $this->do_dashes    = 3;
 206:             $this->do_ellipses  = 1;
 207:         }
 208:         else if ($attr == "-1") {
 209:             # Special "stupefy" mode.
 210:             $this->do_stupefy   = 1;
 211:         }
 212:         else {
 213:             $chars = preg_split('//', $attr);
 214:             foreach ($chars as $c){
 215:                 if      ($c == "q") { $this->do_quotes    = 1; }
 216:                 else if ($c == "b") { $this->do_backticks = 1; }
 217:                 else if ($c == "B") { $this->do_backticks = 2; }
 218:                 else if ($c == "d") { $this->do_dashes    = 1; }
 219:                 else if ($c == "D") { $this->do_dashes    = 2; }
 220:                 else if ($c == "i") { $this->do_dashes    = 3; }
 221:                 else if ($c == "e") { $this->do_ellipses  = 1; }
 222:                 else if ($c == "w") { $this->convert_quot = 1; }
 223:                 else {
 224:                     # Unknown attribute option, ignore.
 225:                 }
 226:             }
 227:         }
 228:     }
 229: 
 230:     function transform($text) {
 231: 
 232:         if ($this->do_nothing) {
 233:             return $text;
 234:         }
 235: 
 236:         $tokens = $this->tokenizeHTML($text);
 237:         $result = '';
 238:         $in_pre = 0;  # Keep track of when we're inside <pre> or <code> tags.
 239: 
 240:         $prev_token_last_char = ""; # This is a cheat, used to get some context
 241:                                     # for one-character tokens that consist of 
 242:                                     # just a quote char. What we do is remember
 243:                                     # the last character of the previous text
 244:                                     # token, to use as context to curl single-
 245:                                     # character quote tokens correctly.
 246: 
 247:         foreach ($tokens as $cur_token) {
 248:             if ($cur_token[0] == "tag") {
 249:                 # Don't mess with quotes inside tags.
 250:                 $result .= $cur_token[1];
 251:                 if (preg_match('@<(/?)(?:'.SMARTYPANTS_TAGS_TO_SKIP.')[\s>]@', $cur_token[1], $matches)) {
 252:                     $in_pre = isset($matches[1]) && $matches[1] == '/' ? 0 : 1;
 253:                 }
 254:             } else {
 255:                 $t = $cur_token[1];
 256:                 $last_char = substr($t, -1); # Remember last char of this token before processing.
 257:                 if (! $in_pre) {
 258:                     $t = $this->educate($t, $prev_token_last_char);
 259:                 }
 260:                 $prev_token_last_char = $last_char;
 261:                 $result .= $t;
 262:             }
 263:         }
 264: 
 265:         return $result;
 266:     }
 267: 
 268: 
 269:     function educate($t, $prev_token_last_char) {
 270:         $t = $this->processEscapes($t);
 271: 
 272:         if ($this->convert_quot) {
 273:             $t = preg_replace('/&quot;/', '"', $t);
 274:         }
 275: 
 276:         if ($this->do_dashes) {
 277:             if ($this->do_dashes == 1) $t = $this->educateDashes($t);
 278:             if ($this->do_dashes == 2) $t = $this->educateDashesOldSchool($t);
 279:             if ($this->do_dashes == 3) $t = $this->educateDashesOldSchoolInverted($t);
 280:         }
 281: 
 282:         if ($this->do_ellipses) $t = $this->educateEllipses($t);
 283: 
 284:         # Note: backticks need to be processed before quotes.
 285:         if ($this->do_backticks) {
 286:             $t = $this->educateBackticks($t);
 287:             if ($this->do_backticks == 2) $t = $this->educateSingleBackticks($t);
 288:         }
 289: 
 290:         if ($this->do_quotes) {
 291:             if ($t == "'") {
 292:                 # Special case: single-character ' token
 293:                 if (preg_match('/\S/', $prev_token_last_char)) {
 294:                     $t = "&#8217;";
 295:                 }
 296:                 else {
 297:                     $t = "&#8216;";
 298:                 }
 299:             }
 300:             else if ($t == '"') {
 301:                 # Special case: single-character " token
 302:                 if (preg_match('/\S/', $prev_token_last_char)) {
 303:                     $t = "&#8221;";
 304:                 }
 305:                 else {
 306:                     $t = "&#8220;";
 307:                 }
 308:             }
 309:             else {
 310:                 # Normal case:
 311:                 $t = $this->educateQuotes($t);
 312:             }
 313:         }
 314: 
 315:         if ($this->do_stupefy) $t = $this->stupefyEntities($t);
 316:         
 317:         return $t;
 318:     }
 319: 
 320: 
 321:     function educateQuotes($_) {
 322:     #
 323:     #   Parameter:  String.
 324:     #
 325:     #   Returns:    The string, with "educated" curly quote HTML entities.
 326:     #
 327:     #   Example input:  "Isn't this fun?"
 328:     #   Example output: &#8220;Isn&#8217;t this fun?&#8221;
 329:     #
 330:         # Make our own "punctuation" character class, because the POSIX-style
 331:         # [:PUNCT:] is only available in Perl 5.6 or later:
 332:         $punct_class = "[!\"#\\$\\%'()*+,-.\\/:;<=>?\\@\\[\\\\\]\\^_`{|}~]";
 333: 
 334:         # Special case if the very first character is a quote
 335:         # followed by punctuation at a non-word-break. Close the quotes by brute force:
 336:         $_ = preg_replace(
 337:             array("/^'(?=$punct_class\\B)/", "/^\"(?=$punct_class\\B)/"),
 338:             array('&#8217;',                 '&#8221;'), $_);
 339: 
 340: 
 341:         # Special case for double sets of quotes, e.g.:
 342:         #   <p>He said, "'Quoted' words in a larger quote."</p>
 343:         $_ = preg_replace(
 344:             array("/\"'(?=\w)/",    "/'\"(?=\w)/"),
 345:             array('&#8220;&#8216;', '&#8216;&#8220;'), $_);
 346: 
 347:         # Special case for decade abbreviations (the '80s):
 348:         $_ = preg_replace("/'(?=\\d{2}s)/", '&#8217;', $_);
 349: 
 350:         $close_class = '[^\ \t\r\n\[\{\(\-]';
 351:         $dec_dashes = '&\#8211;|&\#8212;';
 352: 
 353:         # Get most opening single quotes:
 354:         $_ = preg_replace("{
 355:             (
 356:                 \\s          |   # a whitespace char, or
 357:                 &nbsp;      |   # a non-breaking space entity, or
 358:                 --          |   # dashes, or
 359:                 &[mn]dash;  |   # named dash entities
 360:                 $dec_dashes |   # or decimal entities
 361:                 &\\#x201[34];    # or hex
 362:             )
 363:             '                   # the quote
 364:             (?=\\w)              # followed by a word character
 365:             }x", '\1&#8216;', $_);
 366:         # Single closing quotes:
 367:         $_ = preg_replace("{
 368:             ($close_class)?
 369:             '
 370:             (?(1)|          # If $1 captured, then do nothing;
 371:               (?=\\s | s\\b)  # otherwise, positive lookahead for a whitespace
 372:             )               # char or an 's' at a word ending position. This
 373:                             # is a special case to handle something like:
 374:                             # \"<i>Custer</i>'s Last Stand.\"
 375:             }xi", '\1&#8217;', $_);
 376: 
 377:         # Any remaining single quotes should be opening ones:
 378:         $_ = str_replace("'", '&#8216;', $_);
 379: 
 380: 
 381:         # Get most opening double quotes:
 382:         $_ = preg_replace("{
 383:             (
 384:                 \\s          |   # a whitespace char, or
 385:                 &nbsp;      |   # a non-breaking space entity, or
 386:                 --          |   # dashes, or
 387:                 &[mn]dash;  |   # named dash entities
 388:                 $dec_dashes |   # or decimal entities
 389:                 &\\#x201[34];    # or hex
 390:             )
 391:             \"                   # the quote
 392:             (?=\\w)              # followed by a word character
 393:             }x", '\1&#8220;', $_);
 394: 
 395:         # Double closing quotes:
 396:         $_ = preg_replace("{
 397:             ($close_class)?
 398:             \"
 399:             (?(1)|(?=\\s))   # If $1 captured, then do nothing;
 400:                                # if not, then make sure the next char is whitespace.
 401:             }x", '\1&#8221;', $_);
 402: 
 403:         # Any remaining quotes should be opening ones.
 404:         $_ = str_replace('"', '&#8220;', $_);
 405: 
 406:         return $_;
 407:     }
 408: 
 409: 
 410:     function educateBackticks($_) {
 411:     #
 412:     #   Parameter:  String.
 413:     #   Returns:    The string, with ``backticks'' -style double quotes
 414:     #               translated into HTML curly quote entities.
 415:     #
 416:     #   Example input:  ``Isn't this fun?''
 417:     #   Example output: &#8220;Isn't this fun?&#8221;
 418:     #
 419: 
 420:         $_ = str_replace(array("``",       "''",),
 421:                          array('&#8220;', '&#8221;'), $_);
 422:         return $_;
 423:     }
 424: 
 425: 
 426:     function educateSingleBackticks($_) {
 427:     #
 428:     #   Parameter:  String.
 429:     #   Returns:    The string, with `backticks' -style single quotes
 430:     #               translated into HTML curly quote entities.
 431:     #
 432:     #   Example input:  `Isn't this fun?'
 433:     #   Example output: &#8216;Isn&#8217;t this fun?&#8217;
 434:     #
 435: 
 436:         $_ = str_replace(array("`",       "'",),
 437:                          array('&#8216;', '&#8217;'), $_);
 438:         return $_;
 439:     }
 440: 
 441: 
 442:     function educateDashes($_) {
 443:     #
 444:     #   Parameter:  String.
 445:     #
 446:     #   Returns:    The string, with each instance of "--" translated to
 447:     #               an em-dash HTML entity.
 448:     #
 449: 
 450:         $_ = str_replace('--', '&#8212;', $_);
 451:         return $_;
 452:     }
 453: 
 454: 
 455:     function educateDashesOldSchool($_) {
 456:     #
 457:     #   Parameter:  String.
 458:     #
 459:     #   Returns:    The string, with each instance of "--" translated to
 460:     #               an en-dash HTML entity, and each "---" translated to
 461:     #               an em-dash HTML entity.
 462:     #
 463: 
 464:         #                      em         en
 465:         $_ = str_replace(array("---",     "--",),
 466:                          array('&#8212;', '&#8211;'), $_);
 467:         return $_;
 468:     }
 469: 
 470: 
 471:     function educateDashesOldSchoolInverted($_) {
 472:     #
 473:     #   Parameter:  String.
 474:     #
 475:     #   Returns:    The string, with each instance of "--" translated to
 476:     #               an em-dash HTML entity, and each "---" translated to
 477:     #               an en-dash HTML entity. Two reasons why: First, unlike the
 478:     #               en- and em-dash syntax supported by
 479:     #               EducateDashesOldSchool(), it's compatible with existing
 480:     #               entries written before SmartyPants 1.1, back when "--" was
 481:     #               only used for em-dashes.  Second, em-dashes are more
 482:     #               common than en-dashes, and so it sort of makes sense that
 483:     #               the shortcut should be shorter to type. (Thanks to Aaron
 484:     #               Swartz for the idea.)
 485:     #
 486: 
 487:         #                      en         em
 488:         $_ = str_replace(array("---",     "--",),
 489:                          array('&#8211;', '&#8212;'), $_);
 490:         return $_;
 491:     }
 492: 
 493: 
 494:     function educateEllipses($_) {
 495:     #
 496:     #   Parameter:  String.
 497:     #   Returns:    The string, with each instance of "..." translated to
 498:     #               an ellipsis HTML entity. Also converts the case where
 499:     #               there are spaces between the dots.
 500:     #
 501:     #   Example input:  Huh...?
 502:     #   Example output: Huh&#8230;?
 503:     #
 504: 
 505:         $_ = str_replace(array("...",     ". . .",), '&#8230;', $_);
 506:         return $_;
 507:     }
 508: 
 509: 
 510:     function stupefyEntities($_) {
 511:     #
 512:     #   Parameter:  String.
 513:     #   Returns:    The string, with each SmartyPants HTML entity translated to
 514:     #               its ASCII counterpart.
 515:     #
 516:     #   Example input:  &#8220;Hello &#8212; world.&#8221;
 517:     #   Example output: "Hello -- world."
 518:     #
 519: 
 520:                             #  en-dash    em-dash
 521:         $_ = str_replace(array('&#8211;', '&#8212;'),
 522:                          array('-',       '--'), $_);
 523: 
 524:         # single quote         open       close
 525:         $_ = str_replace(array('&#8216;', '&#8217;'), "'", $_);
 526: 
 527:         # double quote         open       close
 528:         $_ = str_replace(array('&#8220;', '&#8221;'), '"', $_);
 529: 
 530:         $_ = str_replace('&#8230;', '...', $_); # ellipsis
 531: 
 532:         return $_;
 533:     }
 534: 
 535: 
 536:     function processEscapes($_) {
 537:     #
 538:     #   Parameter:  String.
 539:     #   Returns:    The string, with after processing the following backslash
 540:     #               escape sequences. This is useful if you want to force a "dumb"
 541:     #               quote or other character to appear.
 542:     #
 543:     #               Escape  Value
 544:     #               ------  -----
 545:     #               \\      &#92;
 546:     #               \"      &#34;
 547:     #               \'      &#39;
 548:     #               \.      &#46;
 549:     #               \-      &#45;
 550:     #               \`      &#96;
 551:     #
 552:         $_ = str_replace(
 553:             array('\\\\',  '\"',    "\'",    '\.',    '\-',    '\`'),
 554:             array('&#92;', '&#34;', '&#39;', '&#46;', '&#45;', '&#96;'), $_);
 555: 
 556:         return $_;
 557:     }
 558: 
 559: 
 560:     function tokenizeHTML($str) {
 561:     #
 562:     #   Parameter:  String containing HTML markup.
 563:     #   Returns:    An array of the tokens comprising the input
 564:     #               string. Each token is either a tag (possibly with nested,
 565:     #               tags contained therein, such as <a href="<MTFoo>">, or a
 566:     #               run of text between tags. Each element of the array is a
 567:     #               two-element array; the first is either 'tag' or 'text';
 568:     #               the second is the actual value.
 569:     #
 570:     #
 571:     #   Regular expression derived from the _tokenize() subroutine in 
 572:     #   Brad Choate's MTRegex plugin.
 573:     #   <http://www.bradchoate.com/past/mtregex.php>
 574:     #
 575:         $index = 0;
 576:         $tokens = array();
 577: 
 578:         $match = '(?s:<!(?:--.*?--\s*)+>)|'.    # comment
 579:                  '(?s:<\?.*?\?>)|'.             # processing instruction
 580:                                                 # regular tags
 581:                  '(?:<[/!$]?[-a-zA-Z0-9:]+\b(?>[^"\'>]+|"[^"]*"|\'[^\']*\')*>)'; 
 582: 
 583:         $parts = preg_split("{($match)}", $str, -1, PREG_SPLIT_DELIM_CAPTURE);
 584: 
 585:         foreach ($parts as $part) {
 586:             if (++$index % 2 && $part != '') 
 587:                 $tokens[] = array('text', $part);
 588:             else
 589:                 $tokens[] = array('tag', $part);
 590:         }
 591:         return $tokens;
 592:     }
 593: 
 594: }
 595: 
 596: 
 597: #
 598: # SmartyPants Typographer Parser Class
 599: #
 600: class SmartyPantsTypographer_Parser extends SmartyPants_Parser {
 601: 
 602:     # Options to specify which transformations to make:
 603:     var $do_comma_quotes      = 0;
 604:     var $do_guillemets        = 0;
 605:     var $do_space_emdash      = 0;
 606:     var $do_space_endash      = 0;
 607:     var $do_space_colon       = 0;
 608:     var $do_space_semicolon   = 0;
 609:     var $do_space_marks       = 0;
 610:     var $do_space_frenchquote = 0;
 611:     var $do_space_thousand    = 0;
 612:     var $do_space_unit        = 0;
 613:     
 614:     # Smart quote characters:
 615:     var $smart_doublequote_open  = SMARTYPANTS_SMART_DOUBLEQUOTE_OPEN;
 616:     var $smart_doublequote_close = SMARTYPANTS_SMART_DOUBLEQUOTE_CLOSE;
 617:     var $smart_singlequote_open  = '&#8216;';
 618:     var $smart_singlequote_close = '&#8217;'; # Also apostrophe.
 619: 
 620:     # Space characters for different places:
 621:     var $space_emdash      = SMARTYPANTS_SPACE_EMDASH;
 622:     var $space_endash      = SMARTYPANTS_SPACE_ENDASH;
 623:     var $space_colon       = SMARTYPANTS_SPACE_COLON;
 624:     var $space_semicolon   = SMARTYPANTS_SPACE_SEMICOLON;
 625:     var $space_marks       = SMARTYPANTS_SPACE_MARKS;
 626:     var $space_frenchquote = SMARTYPANTS_SPACE_FRENCHQUOTE;
 627:     var $space_thousand    = SMARTYPANTS_SPACE_THOUSAND;
 628:     var $space_unit        = SMARTYPANTS_SPACE_UNIT;
 629:     
 630:     # Expression of a space (breakable or not):
 631:     var $space = '(?: | |&nbsp;|&#0*160;|&#x0*[aA]0;)';
 632: 
 633:     
 634: 
 635:     function SmartyPantsTypographer_Parser($attr = SMARTYPANTS_ATTR) {
 636:     #
 637:     # Initialize a SmartyPantsTypographer_Parser with certain attributes.
 638:     #
 639:     # Parser attributes:
 640:     # 0 : do nothing
 641:     # 1 : set all, except dash spacing
 642:     # 2 : set all, except dash spacing, using old school en- and em- dash shortcuts
 643:     # 3 : set all, except dash spacing, using inverted old school en and em- dash shortcuts
 644:     # 
 645:     # Punctuation:
 646:     # q -> quotes
 647:     # b -> backtick quotes (``double'' only)
 648:     # B -> backtick quotes (``double'' and `single')
 649:     # c -> comma quotes (,,double`` only)
 650:     # g -> guillemets (<<double>> only)
 651:     # d -> dashes
 652:     # D -> old school dashes
 653:     # i -> inverted old school dashes
 654:     # e -> ellipses
 655:     # w -> convert &quot; entities to " for Dreamweaver users
 656:     #
 657:     # Spacing:
 658:     # : -> colon spacing +-
 659:     # ; -> semicolon spacing +-
 660:     # m -> question and exclamation marks spacing +-
 661:     # h -> em-dash spacing +-
 662:     # H -> en-dash spacing +-
 663:     # f -> french quote spacing +-
 664:     # t -> thousand separator spacing -
 665:     # u -> unit spacing +-
 666:     #   (you can add a plus sign after some of these options denoted by + to 
 667:     #    add the space when it is not already present, or you can add a minus 
 668:     #    sign to completly remove any space present)
 669:     #
 670:         # Initialize inherited SmartyPants parser.
 671:         parent::SmartyPants_Parser($attr);
 672:                 
 673:         if ($attr == "1" || $attr == "2" || $attr == "3") {
 674:             # Do everything, turn all options on.
 675:             $this->do_comma_quotes      = 1;
 676:             $this->do_guillemets  = 1;
 677:             $this->do_space_emdash      = 1;
 678:             $this->do_space_endash      = 1;
 679:             $this->do_space_colon       = 1;
 680:             $this->do_space_semicolon   = 1;
 681:             $this->do_space_marks       = 1;
 682:             $this->do_space_frenchquote = 1;
 683:             $this->do_space_thousand    = 1;
 684:             $this->do_space_unit        = 1;
 685:         }
 686:         else if ($attr == "-1") {
 687:             # Special "stupefy" mode.
 688:             $this->do_stupefy   = 1;
 689:         }
 690:         else {
 691:             $chars = preg_split('//', $attr);
 692:             foreach ($chars as $c){
 693:                 if      ($c == "c") { $current =& $this->do_comma_quotes; }
 694:                 else if ($c == "g") { $current =& $this->do_guillemets; }
 695:                 else if ($c == ":") { $current =& $this->do_space_colon; }
 696:                 else if ($c == ";") { $current =& $this->do_space_semicolon; }
 697:                 else if ($c == "m") { $current =& $this->do_space_marks; }
 698:                 else if ($c == "h") { $current =& $this->do_space_emdash; }
 699:                 else if ($c == "H") { $current =& $this->do_space_endash; }
 700:                 else if ($c == "f") { $current =& $this->do_space_frenchquote; }
 701:                 else if ($c == "t") { $current =& $this->do_space_thousand; }
 702:                 else if ($c == "u") { $current =& $this->do_space_unit; }
 703:                 else if ($c == "+") {
 704:                     $current = 2;
 705:                     unset($current);
 706:                 }
 707:                 else if ($c == "-") {
 708:                     $current = -1;
 709:                     unset($current);
 710:                 }
 711:                 else {
 712:                     # Unknown attribute option, ignore.
 713:                 }
 714:                 $current = 1;
 715:             }
 716:         }
 717:     }
 718: 
 719: 
 720:     function educate($t, $prev_token_last_char) {
 721:         $t = parent::educate($t, $prev_token_last_char);
 722:         
 723:         if ($this->do_comma_quotes)      $t = $this->educateCommaQuotes($t);
 724:         if ($this->do_guillemets)        $t = $this->educateGuillemets($t);
 725:         
 726:         if ($this->do_space_emdash)      $t = $this->spaceEmDash($t);
 727:         if ($this->do_space_endash)      $t = $this->spaceEnDash($t);
 728:         if ($this->do_space_colon)       $t = $this->spaceColon($t);
 729:         if ($this->do_space_semicolon)   $t = $this->spaceSemicolon($t);
 730:         if ($this->do_space_marks)       $t = $this->spaceMarks($t);
 731:         if ($this->do_space_frenchquote) $t = $this->spaceFrenchQuotes($t);
 732:         if ($this->do_space_thousand)    $t = $this->spaceThousandSeparator($t);
 733:         if ($this->do_space_unit)        $t = $this->spaceUnit($t);
 734:         
 735:         return $t;
 736:     }
 737: 
 738: 
 739:     function educateQuotes($_) {
 740:     #
 741:     #   Parameter:  String.
 742:     #
 743:     #   Returns:    The string, with "educated" curly quote HTML entities.
 744:     #
 745:     #   Example input:  "Isn't this fun?"
 746:     #   Example output: &#8220;Isn&#8217;t this fun?&#8221;
 747:     #
 748:         $dq_open  = $this->smart_doublequote_open;
 749:         $dq_close = $this->smart_doublequote_close;
 750:         $sq_open  = $this->smart_singlequote_open;
 751:         $sq_close = $this->smart_singlequote_close;
 752:     
 753:         # Make our own "punctuation" character class, because the POSIX-style
 754:         # [:PUNCT:] is only available in Perl 5.6 or later:
 755:         $punct_class = "[!\"#\\$\\%'()*+,-.\\/:;<=>?\\@\\[\\\\\]\\^_`{|}~]";
 756: 
 757:         # Special case if the very first character is a quote
 758:         # followed by punctuation at a non-word-break. Close the quotes by brute force:
 759:         $_ = preg_replace(
 760:             array("/^'(?=$punct_class\\B)/", "/^\"(?=$punct_class\\B)/"),
 761:             array($sq_close,                 $dq_close), $_);
 762: 
 763:         # Special case for double sets of quotes, e.g.:
 764:         #   <p>He said, "'Quoted' words in a larger quote."</p>
 765:         $_ = preg_replace(
 766:             array("/\"'(?=\w)/",     "/'\"(?=\w)/"),
 767:             array($dq_open.$sq_open, $sq_open.$dq_open), $_);
 768: 
 769:         # Special case for decade abbreviations (the '80s):
 770:         $_ = preg_replace("/'(?=\\d{2}s)/", $sq_close, $_);
 771: 
 772:         $close_class = '[^\ \t\r\n\[\{\(\-]';
 773:         $dec_dashes = '&\#8211;|&\#8212;';
 774: 
 775:         # Get most opening single quotes:
 776:         $_ = preg_replace("{
 777:             (
 778:                 \\s          |   # a whitespace char, or
 779:                 &nbsp;      |   # a non-breaking space entity, or
 780:                 --          |   # dashes, or
 781:                 &[mn]dash;  |   # named dash entities
 782:                 $dec_dashes |   # or decimal entities
 783:                 &\\#x201[34];    # or hex
 784:             )
 785:             '                   # the quote
 786:             (?=\\w)              # followed by a word character
 787:             }x", '\1'.$sq_open, $_);
 788:         # Single closing quotes:
 789:         $_ = preg_replace("{
 790:             ($close_class)?
 791:             '
 792:             (?(1)|          # If $1 captured, then do nothing;
 793:               (?=\\s | s\\b)  # otherwise, positive lookahead for a whitespace
 794:             )               # char or an 's' at a word ending position. This
 795:                             # is a special case to handle something like:
 796:                             # \"<i>Custer</i>'s Last Stand.\"
 797:             }xi", '\1'.$sq_close, $_);
 798: 
 799:         # Any remaining single quotes should be opening ones:
 800:         $_ = str_replace("'", $sq_open, $_);
 801: 
 802: 
 803:         # Get most opening double quotes:
 804:         $_ = preg_replace("{
 805:             (
 806:                 \\s          |   # a whitespace char, or
 807:                 &nbsp;      |   # a non-breaking space entity, or
 808:                 --          |   # dashes, or
 809:                 &[mn]dash;  |   # named dash entities
 810:                 $dec_dashes |   # or decimal entities
 811:                 &\\#x201[34];    # or hex
 812:             )
 813:             \"                   # the quote
 814:             (?=\\w)              # followed by a word character
 815:             }x", '\1'.$dq_open, $_);
 816: 
 817:         # Double closing quotes:
 818:         $_ = preg_replace("{
 819:             ($close_class)?
 820:             \"
 821:             (?(1)|(?=\\s))   # If $1 captured, then do nothing;
 822:                                # if not, then make sure the next char is whitespace.
 823:             }x", '\1'.$dq_close, $_);
 824: 
 825:         # Any remaining quotes should be opening ones.
 826:         $_ = str_replace('"', $dq_open, $_);
 827: 
 828:         return $_;
 829:     }
 830: 
 831: 
 832:     function educateCommaQuotes($_) {
 833:     #
 834:     #   Parameter:  String.
 835:     #   Returns:    The string, with ,,comma,, -style double quotes
 836:     #               translated into HTML curly quote entities.
 837:     #
 838:     #   Example input:  ,,Isn't this fun?,,
 839:     #   Example output: &#8222;Isn't this fun?&#8222;
 840:     #
 841:     # Note: this is meant to be used alongside with backtick quotes; there is 
 842:     # no language that use only lower quotations alone mark like in the example.
 843:     #
 844:         $_ = str_replace(",,", '&#8222;', $_);
 845:         return $_;
 846:     }
 847: 
 848: 
 849:     function educateGuillemets($_) {
 850:     #
 851:     #   Parameter:  String.
 852:     #   Returns:    The string, with << guillemets >> -style quotes
 853:     #               translated into HTML guillemets entities.
 854:     #
 855:     #   Example input:  << Isn't this fun? >>
 856:     #   Example output: &#8222; Isn't this fun? &#8222;
 857:     #
 858:         $_ = preg_replace("/(?:<|&lt;){2}/", '&#171;', $_);
 859:         $_ = preg_replace("/(?:>|&gt;){2}/", '&#187;', $_);
 860:         return $_;
 861:     }
 862: 
 863: 
 864:     function spaceFrenchQuotes($_) {
 865:     #
 866:     #   Parameters: String, replacement character, and forcing flag.
 867:     #   Returns:    The string, with appropriates spaces replaced 
 868:     #               inside french-style quotes, only french quotes.
 869:     #
 870:     #   Example input:  Quotes in « French », »German« and »Finnish» style.
 871:     #   Example output: Quotes in «_French_», »German« and »Finnish» style.
 872:     #
 873:         $opt = ( $this->do_space_frenchquote ==  2 ? '?' : '' );
 874:         $chr = ( $this->do_space_frenchquote != -1 ? $this->space_frenchquote : '' );
 875:         
 876:         # Characters allowed immediatly outside quotes.
 877:         $outside_char = $this->space . '|\s|[.,:;!?\[\](){}|@*~=+-]|¡|¿';
 878:         
 879:         $_ = preg_replace(
 880:             "/(^|$outside_char)(&#171;|«|&#8250;|‹)$this->space$opt/",
 881:             "\\1\\2$chr", $_);
 882:         $_ = preg_replace(
 883:             "/$this->space$opt(&#187;|»|&#8249;|›)($outside_char|$)/", 
 884:             "$chr\\1\\2", $_);
 885:         return $_;
 886:     }
 887: 
 888: 
 889:     function spaceColon($_) {
 890:     #
 891:     #   Parameters: String, replacement character, and forcing flag.
 892:     #   Returns:    The string, with appropriates spaces replaced 
 893:     #               before colons.
 894:     #
 895:     #   Example input:  Ingredients : fun.
 896:     #   Example output: Ingredients_: fun.
 897:     #
 898:         $opt = ( $this->do_space_colon ==  2 ? '?' : '' );
 899:         $chr = ( $this->do_space_colon != -1 ? $this->space_colon : '' );
 900:         
 901:         $_ = preg_replace("/$this->space$opt(:)(\\s|$)/m",
 902:                           "$chr\\1\\2", $_);
 903:         return $_;
 904:     }
 905: 
 906: 
 907:     function spaceSemicolon($_) {
 908:     #
 909:     #   Parameters: String, replacement character, and forcing flag.
 910:     #   Returns:    The string, with appropriates spaces replaced 
 911:     #               before semicolons.
 912:     #
 913:     #   Example input:  There he goes ; there she goes.
 914:     #   Example output: There he goes_; there she goes.
 915:     #
 916:         $opt = ( $this->do_space_semicolon ==  2 ? '?' : '' );
 917:         $chr = ( $this->do_space_semicolon != -1 ? $this->space_semicolon : '' );
 918:         
 919:         $_ = preg_replace("/$this->space(;)(?=\\s|$)/m", 
 920:                           " \\1", $_);
 921:         $_ = preg_replace("/((?:^|\\s)(?>[^&;\\s]+|&#?[a-zA-Z0-9]+;)*)".
 922:                           " $opt(;)(?=\\s|$)/m", 
 923:                           "\\1$chr\\2", $_);
 924:         return $_;
 925:     }
 926: 
 927: 
 928:     function spaceMarks($_) {
 929:     #
 930:     #   Parameters: String, replacement character, and forcing flag.
 931:     #   Returns:    The string, with appropriates spaces replaced 
 932:     #               around question and exclamation marks.
 933:     #
 934:     #   Example input:  ¡ Holà ! What ?
 935:     #   Example output: ¡_Holà_! What_?
 936:     #
 937:         $opt = ( $this->do_space_marks ==  2 ? '?' : '' );
 938:         $chr = ( $this->do_space_marks != -1 ? $this->space_marks : '' );
 939: 
 940:         // Regular marks.
 941:         $_ = preg_replace("/$this->space$opt([?!]+)/", "$chr\\1", $_);
 942: 
 943:         // Inverted marks.
 944:         $imarks = "(?:¡|&iexcl;|&#161;|&#x[Aa]1;|¿|&iquest;|&#191;|&#x[Bb][Ff];)";
 945:         $_ = preg_replace("/($imarks+)$this->space$opt/", "\\1$chr", $_);
 946:     
 947:         return $_;
 948:     }
 949: 
 950: 
 951:     function spaceEmDash($_) {
 952:     #
 953:     #   Parameters: String, two replacement characters separated by a hyphen (`-`),
 954:     #               and forcing flag.
 955:     #
 956:     #   Returns:    The string, with appropriates spaces replaced 
 957:     #               around dashes.
 958:     #
 959:     #   Example input:  Then — without any plan — the fun happend.
 960:     #   Example output: Then_—_without any plan_—_the fun happend.
 961:     #
 962:         $opt = ( $this->do_space_emdash ==  2 ? '?' : '' );
 963:         $chr = ( $this->do_space_emdash != -1 ? $this->space_emdash : '' );
 964:         $_ = preg_replace("/$this->space$opt(&#8212;|—)$this->space$opt/", 
 965:             "$chr\\1$chr", $_);
 966:         return $_;
 967:     }
 968:     
 969:     
 970:     function spaceEnDash($_) {
 971:     #
 972:     #   Parameters: String, two replacement characters separated by a hyphen (`-`),
 973:     #               and forcing flag.
 974:     #
 975:     #   Returns:    The string, with appropriates spaces replaced 
 976:     #               around dashes.
 977:     #
 978:     #   Example input:  Then — without any plan — the fun happend.
 979:     #   Example output: Then_—_without any plan_—_the fun happend.
 980:     #
 981:         $opt = ( $this->do_space_endash ==  2 ? '?' : '' );
 982:         $chr = ( $this->do_space_endash != -1 ? $this->space_endash : '' );
 983:         $_ = preg_replace("/$this->space$opt(&#8211;|–)$this->space$opt/", 
 984:             "$chr\\1$chr", $_);
 985:         return $_;
 986:     }
 987: 
 988: 
 989:     function spaceThousandSeparator($_) {
 990:     #
 991:     #   Parameters: String, replacement character, and forcing flag.
 992:     #   Returns:    The string, with appropriates spaces replaced 
 993:     #               inside numbers (thousand separator in french).
 994:     #
 995:     #   Example input:  Il y a 10 000 insectes amusants dans ton jardin.
 996:     #   Example output: Il y a 10_000 insectes amusants dans ton jardin.
 997:     #
 998:         $chr = ( $this->do_space_thousand != -1 ? $this->space_thousand : '' );
 999:         $_ = preg_replace('/([0-9]) ([0-9])/', "\\1$chr\\2", $_);
1000:         return $_;
1001:     }
1002: 
1003: 
1004:     var $units = '
1005:         ### Metric units (with prefixes)
1006:         (?:
1007:             p |
1008:             µ | &micro; | &\#0*181; | &\#[xX]0*[Bb]5; |
1009:             [mcdhkMGT]
1010:         )?
1011:         (?:
1012:             [mgstAKNJWCVFSTHBL]|mol|cd|rad|Hz|Pa|Wb|lm|lx|Bq|Gy|Sv|kat|
1013:             Ω | Ohm | &Omega; | &\#0*937; | &\#[xX]0*3[Aa]9;
1014:         )|
1015:         ### Computers units (KB, Kb, TB, Kbps)
1016:         [kKMGT]?(?:[oBb]|[oBb]ps|flops)|
1017:         ### Money
1018:         ¢ | &cent; | &\#0*162; | &\#[xX]0*[Aa]2; |
1019:         M?(?:
1020:             £ | &pound; | &\#0*163; | &\#[xX]0*[Aa]3; |
1021:             ¥ | &yen;   | &\#0*165; | &\#[xX]0*[Aa]5; |
1022:             € | &euro;  | &\#0*8364; | &\#[xX]0*20[Aa][Cc]; |
1023:             $
1024:         )|
1025:         ### Other units
1026:         (?: ° | &deg; | &\#0*176; | &\#[xX]0*[Bb]0; ) [CF]? | 
1027:         %|pt|pi|M?px|em|en|gal|lb|[NSEOW]|[NS][EOW]|ha|mbar
1028:         '; //x
1029: 
1030:     function spaceUnit($_) {
1031:     #
1032:     #   Parameters: String, replacement character, and forcing flag.
1033:     #   Returns:    The string, with appropriates spaces replaced
1034:     #               before unit symbols.
1035:     #
1036:     #   Example input:  Get 3 mol of fun for 3 $.
1037:     #   Example output: Get 3_mol of fun for 3_$.
1038:     #
1039:         $opt = ( $this->do_space_unit ==  2 ? '?' : '' );
1040:         $chr = ( $this->do_space_unit != -1 ? $this->space_unit : '' );
1041: 
1042:         $_ = preg_replace('/
1043:             (?:([0-9])[ ]'.$opt.') # Number followed by space.
1044:             ('.$this->units.')     # Unit.
1045:             (?![a-zA-Z0-9])  # Negative lookahead for other unit characters.
1046:             /x',
1047:             "\\1$chr\\2", $_);
1048: 
1049:         return $_;
1050:     }
1051: 
1052: 
1053:     function spaceAbbr($_) {
1054:     #
1055:     #   Parameters: String, replacement character, and forcing flag.
1056:     #   Returns:    The string, with appropriates spaces replaced
1057:     #               around abbreviations.
1058:     #
1059:     #   Example input:  Fun i.e. something pleasant.
1060:     #   Example output: Fun i.e._something pleasant.
1061:     #
1062:         $opt = ( $this->do_space_abbr ==  2 ? '?' : '' );
1063:         
1064:         $_ = preg_replace("/(^|\s)($this->abbr_after) $opt/m",
1065:             "\\1\\2$this->space_abbr", $_);
1066:         $_ = preg_replace("/( )$opt($this->abbr_sp_before)(?![a-zA-Z'])/m", 
1067:             "\\1$this->space_abbr\\2", $_);
1068:         return $_;
1069:     }
1070: 
1071: 
1072:     function stupefyEntities($_) {
1073:     #
1074:     #   Adding angle quotes and lower quotes to SmartyPants's stupefy mode.
1075:     #
1076:         $_ = parent::stupefyEntities($_);
1077: 
1078:         $_ = str_replace(array('&#8222;', '&#171;', '&#187'), '"', $_);
1079: 
1080:         return $_;
1081:     }
1082: 
1083: 
1084:     function processEscapes($_) {
1085:     #
1086:     #   Adding a few more escapes to SmartyPants's escapes:
1087:     #
1088:     #               Escape  Value
1089:     #               ------  -----
1090:     #               \,      &#44;
1091:     #               \<      &#60;
1092:     #               \>      &#62;
1093:     #
1094:         $_ = parent::processEscapes($_);
1095: 
1096:         $_ = str_replace(
1097:             array('\,',    '\<',    '\>',    '\&lt;', '\&gt;'),
1098:             array('&#44;', '&#60;', '&#62;', '&#60;', '&#62;'), $_);
1099: 
1100:         return $_;
1101:     }
1102: }
1103: 
1104: 
1105: /*
1106: 
1107: PHP SmartyPants Typographer
1108: ===========================
1109: 
1110: Version History
1111: ---------------
1112: 
1113: 1.0 (28 Jun 2006)
1114: 
1115: *   First public release of PHP SmartyPants Typographer.
1116: 
1117: 
1118: Bugs
1119: ----
1120: 
1121: To file bug reports or feature requests (other than topics listed in the
1122: Caveats section above) please send email to:
1123: 
1124: <michel.fortin@michelf.com>
1125: 
1126: If the bug involves quotes being curled the wrong way, please send example
1127: text to illustrate.
1128: 
1129: 
1130: ### Algorithmic Shortcomings ###
1131: 
1132: One situation in which quotes will get curled the wrong way is when
1133: apostrophes are used at the start of leading contractions. For example:
1134: 
1135:     'Twas the night before Christmas.
1136: 
1137: In the case above, SmartyPants will turn the apostrophe into an opening
1138: single-quote, when in fact it should be a closing one. I don't think
1139: this problem can be solved in the general case -- every word processor
1140: I've tried gets this wrong as well. In such cases, it's best to use the
1141: proper HTML entity for closing single-quotes (`&#8217;`) by hand.
1142: 
1143: 
1144: Copyright and License
1145: ---------------------
1146: 
1147: PHP SmartyPants & Typographer  
1148: Copyright (c) 2004-2006 Michel Fortin  
1149: <http://www.michelf.com>  
1150: All rights reserved.
1151: 
1152: Original SmartyPants  
1153: Copyright (c) 2003-2004 John Gruber  
1154: <http://daringfireball.net/>  
1155: All rights reserved.
1156: 
1157: Redistribution and use in source and binary forms, with or without
1158: modification, are permitted provided that the following conditions are met:
1159: 
1160: *   Redistributions of source code must retain the above copyright
1161:     notice, this list of conditions and the following disclaimer.
1162: 
1163: *   Redistributions in binary form must reproduce the above copyright
1164:     notice, this list of conditions and the following disclaimer in the
1165:     documentation and/or other materials provided with the distribution.
1166: 
1167: *   Neither the name "SmartyPants" nor the names of its contributors may
1168:     be used to endorse or promote products derived from this software
1169:     without specific prior written permission.
1170: 
1171: This software is provided by the copyright holders and contributors "as is"
1172: and any express or implied warranties, including, but not limited to, the 
1173: implied warranties of merchantability and fitness for a particular purpose 
1174: are disclaimed. In no event shall the copyright owner or contributors be 
1175: liable for any direct, indirect, incidental, special, exemplary, or 
1176: consequential damages (including, but not limited to, procurement of 
1177: substitute goods or services; loss of use, data, or profits; or business 
1178: interruption) however caused and on any theory of liability, whether in 
1179: contract, strict liability, or tort (including negligence or otherwise) 
1180: arising in any way out of the use of this software, even if advised of the
1181: possibility of such damage.
1182: 
1183: */
1184: ?>
ProcessWire API documentation generated by ApiGen 2.6.0