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