190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber<?php
290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber# SmartyPants  -  Smart punctuation for web sites
590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber# by John Gruber
790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber# <http://daringfireball.net>
890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber# PHP port by Michel Fortin
1090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber# <http://www.michelf.com/>
1190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
1290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber# Copyright (c) 2003-2004 John Gruber
1390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber# Copyright (c) 2004-2005 Michel Fortin
1490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
1590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
1690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
1790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberglobal  $SmartyPantsPHPVersion, $SmartyPantsSyntaxVersion,
1890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $smartypants_attr, $sp_tags_to_skip;
1990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
2090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber$SmartyPantsPHPVersion    = '1.5.1e'; # Fru 9 Dec 2005
2190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber$SmartyPantsSyntaxVersion = '1.5.1';  # Fri 12 Mar 2004
2290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
2390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
2490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber# Configurable variables:
2590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber$smartypants_attr = "1";  # Change this to configure.
2690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                          #  1 =>  "--" for em-dashes; no en-dash support
2790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                          #  2 =>  "---" for em-dashes; "--" for en-dashes
2890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                          #  3 =>  "--" for em-dashes; "---" for en-dashes
2990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                          #  See docs for more configuration options.
3090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
3190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber# Globals:
3290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber$sp_tags_to_skip = '<(/?)(?:pre|code|kbd|script|math)[\s>]';
3390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
3490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
3590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber# -- WordPress plugin interface -----------------------------------------------
3690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber/*
3790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberPlugin Name: SmartyPants
3890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberPlugin URI: http://www.michelf.com/projects/php-smartypants/
3990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberDescription: SmartyPants is a web publishing utility that translates plain ASCII punctuation characters into &#8220;smart&#8221; typographic punctuation HTML entities. 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. Based on the original Perl version by <a href="http://daringfireball.net/">John Gruber</a>.
4090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberVersion: 1.5.1e
4190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberAuthor: Michel Fortin
4290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberAuthor URI: http://www.michelf.com/
4390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber*/
4490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberif (isset($wp_version)) {
4590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # Remove default Texturize filter that would conflict with SmartyPants.
4690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    remove_filter('category_description', 'wptexturize');
4790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    remove_filter('list_cats', 'wptexturize');
4890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    remove_filter('comment_author', 'wptexturize');
4990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    remove_filter('comment_text', 'wptexturize');
5090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    remove_filter('single_post_title', 'wptexturize');
5190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    remove_filter('the_title', 'wptexturize');
5290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    remove_filter('the_content', 'wptexturize');
5390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    remove_filter('the_excerpt', 'wptexturize');
5490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # Add SmartyPants filter with priority 10 (same as Texturize).
5590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    add_filter('category_description', 'SmartyPants', 10);
5690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    add_filter('list_cats', 'SmartyPants', 10);
5790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    add_filter('comment_author', 'SmartyPants', 10);
5890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    add_filter('comment_text', 'SmartyPants', 10);
5990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    add_filter('single_post_title', 'SmartyPants', 10);
6090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    add_filter('the_title', 'SmartyPants', 10);
6190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    add_filter('the_content', 'SmartyPants', 10);
6290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    add_filter('the_excerpt', 'SmartyPants', 10);
6390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
6490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
6590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber# -- Smarty Modifier Interface ------------------------------------------------
6690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfunction smarty_modifier_smartypants($text, $attr = NULL) {
6790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return SmartyPants($text, $attr);
6890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
6990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
7090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
7190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
7290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfunction SmartyPants($text, $attr = NULL, $ctx = NULL) {
7390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    global $smartypants_attr, $sp_tags_to_skip;
7490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # Paramaters:
7590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $text;   # text to be parsed
7690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $attr;   # value of the smart_quotes="" attribute
7790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $ctx;    # MT context object (unused)
7890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if ($attr == NULL) $attr = $smartypants_attr;
7990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
8090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # Options to specify which transformations to make:
8190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $do_stupefy = FALSE;
8290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $convert_quot = 0;  # should we translate &quot; entities into normal quotes?
8390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
8490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # Parse attributes:
8590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # 0 : do nothing
8690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # 1 : set all
8790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # 2 : set all, using old school en- and em- dash shortcuts
8890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # 3 : set all, using inverted old school en and em- dash shortcuts
8990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    #
9090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # q : quotes
9190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # b : backtick quotes (``double'' only)
9290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # B : backtick quotes (``double'' and `single')
9390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # d : dashes
9490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # D : old school dashes
9590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # i : inverted old school dashes
9690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # e : ellipses
9790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # w : convert &quot; entities to " for Dreamweaver users
9890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
9990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if ($attr == "0") {
10090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        # Do nothing.
10190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        return $text;
10290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
10390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    else if ($attr == "1") {
10490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        # Do everything, turn all options on.
10590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $do_quotes    = 1;
10690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $do_backticks = 1;
10790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $do_dashes    = 1;
10890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $do_ellipses  = 1;
10990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
11090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    else if ($attr == "2") {
11190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        # Do everything, turn all options on, use old school dash shorthand.
11290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $do_quotes    = 1;
11390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $do_backticks = 1;
11490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $do_dashes    = 2;
11590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $do_ellipses  = 1;
11690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
11790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    else if ($attr == "3") {
11890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        # Do everything, turn all options on, use inverted old school dash shorthand.
11990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $do_quotes    = 1;
12090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $do_backticks = 1;
12190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $do_dashes    = 3;
12290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $do_ellipses  = 1;
12390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
12490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    else if ($attr == "-1") {
12590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        # Special "stupefy" mode.
12690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $do_stupefy   = 1;
12790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
12890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    else {
12990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $chars = preg_split('//', $attr);
13090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        foreach ($chars as $c){
13190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            if      ($c == "q") { $do_quotes    = 1; }
13290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            else if ($c == "b") { $do_backticks = 1; }
13390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            else if ($c == "B") { $do_backticks = 2; }
13490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            else if ($c == "d") { $do_dashes    = 1; }
13590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            else if ($c == "D") { $do_dashes    = 2; }
13690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            else if ($c == "i") { $do_dashes    = 3; }
13790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            else if ($c == "e") { $do_ellipses  = 1; }
13890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            else if ($c == "w") { $convert_quot = 1; }
13990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            else {
14090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                # Unknown attribute option, ignore.
14190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            }
14290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        }
14390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
14490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
14590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $tokens = _TokenizeHTML($text);
14690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $result = '';
14790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $in_pre = 0;  # Keep track of when we're inside <pre> or <code> tags.
14890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
14990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $prev_token_last_char = "";     # This is a cheat, used to get some context
15090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                                    # for one-character tokens that consist of
15190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                                    # just a quote char. What we do is remember
15290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                                    # the last character of the previous text
15390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                                    # token, to use as context to curl single-
15490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                                    # character quote tokens correctly.
15590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
15690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    foreach ($tokens as $cur_token) {
15790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        if ($cur_token[0] == "tag") {
15890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            # Don't mess with quotes inside tags.
15990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $result .= $cur_token[1];
16090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            if (preg_match("@$sp_tags_to_skip@", $cur_token[1], $matches)) {
16190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                $in_pre = isset($matches[1]) && $matches[1] == '/' ? 0 : 1;
16290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            }
16390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        } else {
16490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $t = $cur_token[1];
16590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $last_char = substr($t, -1); # Remember last char of this token before processing.
16690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            if (! $in_pre) {
16790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                $t = ProcessEscapes($t);
16890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
16990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                if ($convert_quot) {
17090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    $t = preg_replace('/&quot;/', '"', $t);
17190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                }
17290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
17390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                if ($do_dashes) {
17490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    if ($do_dashes == 1) $t = EducateDashes($t);
17590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    if ($do_dashes == 2) $t = EducateDashesOldSchool($t);
17690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    if ($do_dashes == 3) $t = EducateDashesOldSchoolInverted($t);
17790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                }
17890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
17990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                if ($do_ellipses) $t = EducateEllipses($t);
18090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
18190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                # Note: backticks need to be processed before quotes.
18290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                if ($do_backticks) {
18390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    $t = EducateBackticks($t);
18490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    if ($do_backticks == 2) $t = EducateSingleBackticks($t);
18590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                }
18690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
18790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                if ($do_quotes) {
18890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    if ($t == "'") {
18990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                        # Special case: single-character ' token
19090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                        if (preg_match('/\S/', $prev_token_last_char)) {
19190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                            $t = "&#8217;";
19290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                        }
19390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                        else {
19490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                            $t = "&#8216;";
19590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                        }
19690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    }
19790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    else if ($t == '"') {
19890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                        # Special case: single-character " token
19990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                        if (preg_match('/\S/', $prev_token_last_char)) {
20090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                            $t = "&#8221;";
20190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                        }
20290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                        else {
20390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                            $t = "&#8220;";
20490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                        }
20590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    }
20690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    else {
20790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                        # Normal case:
20890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                        $t = EducateQuotes($t);
20990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    }
21090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                }
21190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
21290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                if ($do_stupefy) $t = StupefyEntities($t);
21390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            }
21490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $prev_token_last_char = $last_char;
21590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $result .= $t;
21690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        }
21790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
21890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
21990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return $result;
22090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
22190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
22290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
22390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfunction SmartQuotes($text, $attr = NULL, $ctx = NULL) {
22490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    global $smartypants_attr, $sp_tags_to_skip;
22590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # Paramaters:
22690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $text;   # text to be parsed
22790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $attr;   # value of the smart_quotes="" attribute
22890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $ctx;    # MT context object (unused)
22990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if ($attr == NULL) $attr = $smartypants_attr;
23090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
23190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $do_backticks;   # should we educate ``backticks'' -style quotes?
23290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
23390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if ($attr == 0) {
23490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        # do nothing;
23590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        return $text;
23690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
23790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    else if ($attr == 2) {
23890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        # smarten ``backticks'' -style quotes
23990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $do_backticks = 1;
24090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
24190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    else {
24290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $do_backticks = 0;
24390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
24490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
24590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # Special case to handle quotes at the very end of $text when preceded by
24690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # an HTML tag. Add a space to give the quote education algorithm a bit of
24790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # context, so that it can guess correctly that it's a closing quote:
24890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $add_extra_space = 0;
24990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if (preg_match("/>['\"]\\z/", $text)) {
25090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $add_extra_space = 1; # Remember, so we can trim the extra space later.
25190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $text .= " ";
25290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
25390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
25490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $tokens = _TokenizeHTML($text);
25590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $result = '';
25690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $in_pre = 0;  # Keep track of when we're inside <pre> or <code> tags
25790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
25890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $prev_token_last_char = "";     # This is a cheat, used to get some context
25990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                                    # for one-character tokens that consist of
26090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                                    # just a quote char. What we do is remember
26190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                                    # the last character of the previous text
26290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                                    # token, to use as context to curl single-
26390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                                    # character quote tokens correctly.
26490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
26590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    foreach ($tokens as $cur_token) {
26690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        if ($cur_token[0] == "tag") {
26790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            # Don't mess with quotes inside tags
26890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $result .= $cur_token[1];
26990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            if (preg_match("@$sp_tags_to_skip@", $cur_token[1], $matches)) {
27090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                $in_pre = isset($matches[1]) && $matches[1] == '/' ? 0 : 1;
27190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            }
27290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        } else {
27390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $t = $cur_token[1];
27490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $last_char = substr($t, -1); # Remember last char of this token before processing.
27590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            if (! $in_pre) {
27690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                $t = ProcessEscapes($t);
27790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                if ($do_backticks) {
27890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    $t = EducateBackticks($t);
27990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                }
28090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
28190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                if ($t == "'") {
28290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    # Special case: single-character ' token
28390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    if (preg_match('/\S/', $prev_token_last_char)) {
28490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                        $t = "&#8217;";
28590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    }
28690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    else {
28790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                        $t = "&#8216;";
28890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    }
28990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                }
29090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                else if ($t == '"') {
29190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    # Special case: single-character " token
29290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    if (preg_match('/\S/', $prev_token_last_char)) {
29390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                        $t = "&#8221;";
29490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    }
29590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    else {
29690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                        $t = "&#8220;";
29790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    }
29890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                }
29990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                else {
30090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    # Normal case:
30190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                    $t = EducateQuotes($t);
30290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                }
30390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
30490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            }
30590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $prev_token_last_char = $last_char;
30690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $result .= $t;
30790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        }
30890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
30990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
31090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if ($add_extra_space) {
31190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        preg_replace('/ \z/', '', $result);  # Trim trailing space if we added one earlier.
31290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
31390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return $result;
31490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
31590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
31690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
31790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfunction SmartDashes($text, $attr = NULL, $ctx = NULL) {
31890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    global $smartypants_attr, $sp_tags_to_skip;
31990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # Paramaters:
32090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $text;   # text to be parsed
32190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $attr;   # value of the smart_dashes="" attribute
32290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $ctx;    # MT context object (unused)
32390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if ($attr == NULL) $attr = $smartypants_attr;
32490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
32590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # reference to the subroutine to use for dash education, default to EducateDashes:
32690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $dash_sub_ref = 'EducateDashes';
32790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
32890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if ($attr == 0) {
32990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        # do nothing;
33090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        return $text;
33190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
33290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    else if ($attr == 2) {
33390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        # use old smart dash shortcuts, "--" for en, "---" for em
33490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $dash_sub_ref = 'EducateDashesOldSchool';
33590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
33690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    else if ($attr == 3) {
33790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        # inverse of 2, "--" for em, "---" for en
33890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        $dash_sub_ref = 'EducateDashesOldSchoolInverted';
33990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
34090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
34190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $tokens;
34290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $tokens = _TokenizeHTML($text);
34390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
34490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $result = '';
34590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $in_pre = 0;  # Keep track of when we're inside <pre> or <code> tags
34690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    foreach ($tokens as $cur_token) {
34790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        if ($cur_token[0] == "tag") {
34890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            # Don't mess with quotes inside tags
34990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $result .= $cur_token[1];
35090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            if (preg_match("@$sp_tags_to_skip@", $cur_token[1], $matches)) {
35190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                $in_pre = isset($matches[1]) && $matches[1] == '/' ? 0 : 1;
35290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            }
35390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        } else {
35490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $t = $cur_token[1];
35590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            if (! $in_pre) {
35690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                $t = ProcessEscapes($t);
35790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                $t = $dash_sub_ref($t);
35890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            }
35990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $result .= $t;
36090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        }
36190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
36290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return $result;
36390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
36490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
36590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
36690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfunction SmartEllipses($text, $attr = NULL, $ctx = NULL) {
36790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # Paramaters:
36890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $text;   # text to be parsed
36990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $attr;   # value of the smart_ellipses="" attribute
37090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $ctx;    # MT context object (unused)
37190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if ($attr == NULL) $attr = $smartypants_attr;
37290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
37390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if ($attr == 0) {
37490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        # do nothing;
37590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        return $text;
37690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
37790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
37890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $tokens;
37990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $tokens = _TokenizeHTML($text);
38090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
38190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $result = '';
38290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $in_pre = 0;  # Keep track of when we're inside <pre> or <code> tags
38390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    foreach ($tokens as $cur_token) {
38490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        if ($cur_token[0] == "tag") {
38590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            # Don't mess with quotes inside tags
38690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $result .= $cur_token[1];
38790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            if (preg_match("@$sp_tags_to_skip@", $cur_token[1], $matches)) {
38890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                $in_pre = isset($matches[1]) && $matches[1] == '/' ? 0 : 1;
38990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            }
39090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        } else {
39190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $t = $cur_token[1];
39290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            if (! $in_pre) {
39390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                $t = ProcessEscapes($t);
39490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                $t = EducateEllipses($t);
39590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            }
39690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $result .= $t;
39790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        }
39890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
39990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return $result;
40090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
40190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
40290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
40390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfunction EducateQuotes($_) {
40490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
40590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Parameter:  String.
40690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
40790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Returns:    The string, with "educated" curly quote HTML entities.
40890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
40990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Example input:  "Isn't this fun?"
41090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Example output: &#8220;Isn&#8217;t this fun?&#8221;
41190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
41290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # Make our own "punctuation" character class, because the POSIX-style
41390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # [:PUNCT:] is only available in Perl 5.6 or later:
41490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $punct_class = "[!\"#\\$\\%'()*+,-.\\/:;<=>?\\@\\[\\\\\]\\^_`{|}~]";
41590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
41690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # Special case if the very first character is a quote
41790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # followed by punctuation at a non-word-break. Close the quotes by brute force:
41890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = preg_replace(
41990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        array("/^'(?=$punct_class\\B)/", "/^\"(?=$punct_class\\B)/"),
42090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        array('&#8217;',                 '&#8221;'), $_);
42190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
42290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
42390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # Special case for double sets of quotes, e.g.:
42490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    #   <p>He said, "'Quoted' words in a larger quote."</p>
42590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = preg_replace(
42690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        array("/\"'(?=\w)/",    "/'\"(?=\w)/"),
42790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        array('&#8220;&#8216;', '&#8216;&#8220;'), $_);
42890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
42990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # Special case for decade abbreviations (the '80s):
43090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = preg_replace("/'(?=\\d{2}s)/", '&#8217;', $_);
43190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
43290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $close_class = '[^\ \t\r\n\[\{\(\-]';
43390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $dec_dashes = '&\#8211;|&\#8212;';
43490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
43590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # Get most opening single quotes:
43690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = preg_replace("{
43790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        (
43890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            \\s          |   # a whitespace char, or
43990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            &nbsp;      |   # a non-breaking space entity, or
44090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            --          |   # dashes, or
44190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            &[mn]dash;  |   # named dash entities
44290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $dec_dashes |   # or decimal entities
44390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            &\\#x201[34];    # or hex
44490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        )
44590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        '                   # the quote
44690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        (?=\\w)              # followed by a word character
44790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        }x", '\1&#8216;', $_);
44890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # Single closing quotes:
44990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = preg_replace("{
45090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        ($close_class)?
45190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        '
45290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        (?(1)|          # If $1 captured, then do nothing;
45390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber          (?=\\s | s\\b)  # otherwise, positive lookahead for a whitespace
45490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        )               # char or an 's' at a word ending position. This
45590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                        # is a special case to handle something like:
45690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                        # \"<i>Custer</i>'s Last Stand.\"
45790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        }xi", '\1&#8217;', $_);
45890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
45990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # Any remaining single quotes should be opening ones:
46090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = str_replace("'", '&#8216;', $_);
46190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
46290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
46390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # Get most opening double quotes:
46490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = preg_replace("{
46590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        (
46690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            \\s          |   # a whitespace char, or
46790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            &nbsp;      |   # a non-breaking space entity, or
46890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            --          |   # dashes, or
46990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            &[mn]dash;  |   # named dash entities
47090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $dec_dashes |   # or decimal entities
47190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            &\\#x201[34];    # or hex
47290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        )
47390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        \"                   # the quote
47490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        (?=\\w)              # followed by a word character
47590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        }x", '\1&#8220;', $_);
47690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
47790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # Double closing quotes:
47890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = preg_replace("{
47990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        ($close_class)?
48090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        \"
48190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        (?(1)|(?=\\s))   # If $1 captured, then do nothing;
48290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                           # if not, then make sure the next char is whitespace.
48390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        }x", '\1&#8221;', $_);
48490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
48590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # Any remaining quotes should be opening ones.
48690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = str_replace('"', '&#8220;', $_);
48790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
48890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return $_;
48990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
49090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
49190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
49290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfunction EducateBackticks($_) {
49390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
49490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Parameter:  String.
49590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Returns:    The string, with ``backticks'' -style double quotes
49690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               translated into HTML curly quote entities.
49790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
49890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Example input:  ``Isn't this fun?''
49990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Example output: &#8220;Isn't this fun?&#8221;
50090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
50190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
50290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = str_replace(array("``",       "''",),
50390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                     array('&#8220;', '&#8221;'), $_);
50490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return $_;
50590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
50690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
50790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
50890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfunction EducateSingleBackticks($_) {
50990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
51090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Parameter:  String.
51190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Returns:    The string, with `backticks' -style single quotes
51290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               translated into HTML curly quote entities.
51390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
51490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Example input:  `Isn't this fun?'
51590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Example output: &#8216;Isn&#8217;t this fun?&#8217;
51690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
51790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
51890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = str_replace(array("`",       "'",),
51990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                     array('&#8216;', '&#8217;'), $_);
52090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return $_;
52190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
52290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
52390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
52490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfunction EducateDashes($_) {
52590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
52690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Parameter:  String.
52790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
52890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Returns:    The string, with each instance of "--" translated to
52990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               an em-dash HTML entity.
53090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
53190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
53290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = str_replace('--', '&#8212;', $_);
53390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return $_;
53490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
53590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
53690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
53790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfunction EducateDashesOldSchool($_) {
53890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
53990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Parameter:  String.
54090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
54190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Returns:    The string, with each instance of "--" translated to
54290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               an en-dash HTML entity, and each "---" translated to
54390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               an em-dash HTML entity.
54490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
54590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
54690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    #                      em         en
54790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = str_replace(array("---",     "--",),
54890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                     array('&#8212;', '&#8211;'), $_);
54990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return $_;
55090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
55190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
55290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
55390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfunction EducateDashesOldSchoolInverted($_) {
55490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
55590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Parameter:  String.
55690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
55790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Returns:    The string, with each instance of "--" translated to
55890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               an em-dash HTML entity, and each "---" translated to
55990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               an en-dash HTML entity. Two reasons why: First, unlike the
56090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               en- and em-dash syntax supported by
56190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               EducateDashesOldSchool(), it's compatible with existing
56290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               entries written before SmartyPants 1.1, back when "--" was
56390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               only used for em-dashes.  Second, em-dashes are more
56490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               common than en-dashes, and so it sort of makes sense that
56590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               the shortcut should be shorter to type. (Thanks to Aaron
56690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               Swartz for the idea.)
56790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
56890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
56990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    #                      en         em
57090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = str_replace(array("---",     "--",),
57190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                     array('&#8211;', '&#8212;'), $_);
57290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return $_;
57390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
57490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
57590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
57690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfunction EducateEllipses($_) {
57790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
57890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Parameter:  String.
57990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Returns:    The string, with each instance of "..." translated to
58090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               an ellipsis HTML entity. Also converts the case where
58190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               there are spaces between the dots.
58290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
58390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Example input:  Huh...?
58490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Example output: Huh&#8230;?
58590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
58690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
58790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = str_replace(array("...",     ". . .",), '&#8230;', $_);
58890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return $_;
58990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
59090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
59190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
59290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfunction StupefyEntities($_) {
59390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
59490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Parameter:  String.
59590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Returns:    The string, with each SmartyPants HTML entity translated to
59690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               its ASCII counterpart.
59790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
59890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Example input:  &#8220;Hello &#8212; world.&#8221;
59990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Example output: "Hello -- world."
60090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
60190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
60290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                        #  en-dash    em-dash
60390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = str_replace(array('&#8211;', '&#8212;'),
60490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                     array('-',       '--'), $_);
60590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
60690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # single quote         open       close
60790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = str_replace(array('&#8216;', '&#8217;'), "'", $_);
60890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
60990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    # double quote         open       close
61090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = str_replace(array('&#8220;', '&#8221;'), '"', $_);
61190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
61290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = str_replace('&#8230;', '...', $_); # ellipsis
61390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
61490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return $_;
61590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
61690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
61790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
61890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfunction ProcessEscapes($_) {
61990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
62090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Parameter:  String.
62190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Returns:    The string, with after processing the following backslash
62290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               escape sequences. This is useful if you want to force a "dumb"
62390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               quote or other character to appear.
62490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
62590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               Escape  Value
62690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               ------  -----
62790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               \\      &#92;
62890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               \"      &#34;
62990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               \'      &#39;
63090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               \.      &#46;
63190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               \-      &#45;
63290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               \`      &#96;
63390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
63490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $_ = str_replace(
63590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        array('\\\\',  '\"',    "\'",    '\.',    '\-',    '\`'),
63690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        array('&#92;', '&#34;', '&#39;', '&#46;', '&#45;', '&#96;'), $_);
63790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
63890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return $_;
63990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
64090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
64190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
64290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber# _TokenizeHTML is shared between PHP SmartyPants and PHP Markdown.
64390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber# We only define it if it is not already defined.
64490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberif (!function_exists('_TokenizeHTML')) :
64590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfunction _TokenizeHTML($str) {
64690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
64790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Parameter:  String containing HTML markup.
64890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Returns:    An array of the tokens comprising the input
64990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               string. Each token is either a tag (possibly with nested,
65090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               tags contained therein, such as <a href="<MTFoo>">, or a
65190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               run of text between tags. Each element of the array is a
65290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               two-element array; the first is either 'tag' or 'text';
65390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#               the second is the actual value.
65490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
65590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
65690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Regular expression derived from the _tokenize() subroutine in
65790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   Brad Choate's MTRegex plugin.
65890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#   <http://www.bradchoate.com/past/mtregex.php>
65990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#
66090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $index = 0;
66190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $tokens = array();
66290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
66390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $match = '(?s:<!(?:--.*?--\s*)+>)|'.    # comment
66490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber             '(?s:<\?.*?\?>)|'.             # processing instruction
66590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                                            # regular tags
66690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber             '(?:<[/!$]?[-a-zA-Z0-9:]+\b(?>[^"\'>]+|"[^"]*"|\'[^\']*\')*>)';
66790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
66890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    $parts = preg_split("{($match)}", $str, -1, PREG_SPLIT_DELIM_CAPTURE);
66990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
67090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    foreach ($parts as $part) {
67190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        if (++$index % 2 && $part != '')
67290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $tokens[] = array('text', $part);
67390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        else
67490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber            $tokens[] = array('tag', $part);
67590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    }
67690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return $tokens;
67790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
67890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberendif;
67990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
68090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
68190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber/*
68290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
68390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberPHP SmartyPants
68490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber===============
68590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
68690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberDescription
68790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber-----------
68890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
68990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberThis is a PHP translation of the original SmartyPants quote educator written in
69090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberPerl by John Gruber.
69190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
69290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberSmartyPants is a web publishing utility that translates plain ASCII
69390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberpunctuation characters into "smart" typographic punctuation HTML
69490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberentities. SmartyPants can perform the following transformations:
69590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
69690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber*   Straight quotes (`"` and `'`) into "curly" quote HTML entities
69790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber*   Backticks-style quotes (` ``like this'' `) into "curly" quote HTML
69890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    entities
69990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber*   Dashes (`--` and `---`) into en- and em-dash entities
70090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber*   Three consecutive dots (`...`) into an ellipsis entity
70190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
70290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberSmartyPants does not modify characters within `<pre>`, `<code>`, `<kbd>`,
70390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber`<script>`, or `<math>` tag blocks. Typically, these tags are used to
70490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberdisplay text where smart quotes and other "smart punctuation" would not
70590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberbe appropriate, such as source code or example markup.
70690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
70790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
70890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber### Backslash Escapes ###
70990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
71090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberIf you need to use literal straight quotes (or plain hyphens and
71190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberperiods), SmartyPants accepts the following backslash escape sequences
71290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberto force non-smart punctuation. It does so by transforming the escape
71390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Hubersequence into a decimal-encoded HTML entity:
71490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
71590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    Escape  Value  Character
71690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    ------  -----  ---------
71790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber      \\    &#92;    \
71890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber      \"    &#34;    "
71990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber      \'    &#39;    '
72090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber      \.    &#46;    .
72190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber      \-    &#45;    -
72290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber      \`    &#96;    `
72390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
72490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberThis is useful, for example, when you want to use straight quotes as
72590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfoot and inch marks: 6'2" tall; a 17" iMac.
72690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
72790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
72890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberBugs
72990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber----
73090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
73190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberTo file bug reports or feature requests (other than topics listed in the
73290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberCaveats section above) please send email to:
73390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
73490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber<michel.fortin@michelf.com>
73590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
73690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberIf the bug involves quotes being curled the wrong way, please send example
73790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Hubertext to illustrate.
73890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
73990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
74090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber### Algorithmic Shortcomings ###
74190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
74290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberOne situation in which quotes will get curled the wrong way is when
74390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberapostrophes are used at the start of leading contractions. For example:
74490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
74590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    'Twas the night before Christmas.
74690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
74790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberIn the case above, SmartyPants will turn the apostrophe into an opening
74890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Hubersingle-quote, when in fact it should be a closing one. I don't think
74990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberthis problem can be solved in the general case -- every word processor
75090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberI've tried gets this wrong as well. In such cases, it's best to use the
75190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberproper HTML entity for closing single-quotes (`&#8217;`) by hand.
75290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
75390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
75490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberVersion History
75590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber---------------
75690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
75790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber1.5.1e (9 Dec 2005)
75890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
75990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber*   Corrected a bug that prevented special characters from being
76090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    escaped.
76190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
76290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
76390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber1.5.1d (25 May 2005)
76490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
76590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber*   Corrected a small bug in `_TokenizeHTML` where a Doctype declaration
76690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    was not seen as HTML (smart quotes where applied inside).
76790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
76890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
76990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber1.5.1c (13 Dec 2004)
77090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
77190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber*   Changed a regular expression in `_TokenizeHTML` that could lead to
77290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    a segmentation fault with PHP 4.3.8 on Linux.
77390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
77490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
77590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber1.5.1b (6 Sep 2004)
77690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
77790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber*   Corrected a problem with quotes immediately following a dash
77890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    with no space between: `Text--"quoted text"--text.`
77990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
78090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber*   PHP SmartyPants can now be used as a modifier by the Smarty
78190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    template engine. Rename the file to "modifier.smartypants.php"
78290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    and put it in your smarty plugins folder.
78390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
78490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber*   Replaced a lot of space characters by tabs, saving about 4 KB.
78590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
78690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
78790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber1.5.1a (30 Jun 2004)
78890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
78990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber*   PHP Markdown and PHP Smartypants now share the same `_TokenizeHTML`
79090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    function when loaded simultanously.
79190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
79290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber*   Changed the internals of `_TokenizeHTML` to lower the PHP version
79390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    requirement to PHP 4.0.5.
79490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
79590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
79690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber1.5.1 (6 Jun 2004)
79790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
79890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber*   Initial release of PHP SmartyPants, based on version 1.5.1 of the
79990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    original SmartyPants written in Perl.
80090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
80190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
80290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberAuthor
80390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber------
80490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
80590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberJohn Gruber
80690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber<http://daringfireball.net/>
80790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
80890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberPorted to PHP by Michel Fortin
80990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber<http://www.michelf.com/>
81090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
81190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
81290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberAdditional Credits
81390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber------------------
81490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
81590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberPortions of this plug-in are based on Brad Choate's nifty MTRegex plug-in.
81690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberBrad Choate also contributed a few bits of source code to this plug-in.
81790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberBrad Choate is a fine hacker indeed. (<http://bradchoate.com/>)
81890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
81990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberJeremy Hedley (<http://antipixel.com/>) and Charles Wiltgen
82090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber(<http://playbacktime.com/>) deserve mention for exemplary beta testing.
82190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
82290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
82390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberCopyright and License
82490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber---------------------
82590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
82690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberCopyright (c) 2003 John Gruber
82790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber<http://daringfireball.net/>
82890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberAll rights reserved.
82990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
83090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberCopyright (c) 2004-2005 Michel Fortin
83190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber<http://www.michelf.com>
83290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
83390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberRedistribution and use in source and binary forms, with or without
83490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Hubermodification, are permitted provided that the following conditions are met:
83590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
83690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber*   Redistributions of source code must retain the above copyright
83790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    notice, this list of conditions and the following disclaimer.
83890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
83990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber*   Redistributions in binary form must reproduce the above copyright
84090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    notice, this list of conditions and the following disclaimer in the
84190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    documentation and/or other materials provided with the distribution.
84290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
84390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber*   Neither the name "SmartyPants" nor the names of its contributors may
84490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    be used to endorse or promote products derived from this software
84590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    without specific prior written permission.
84690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
84790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberThis software is provided by the copyright holders and contributors "as is"
84890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberand any express or implied warranties, including, but not limited to, the
84990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberimplied warranties of merchantability and fitness for a particular purpose
85090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberare disclaimed. In no event shall the copyright owner or contributors be
85190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberliable for any direct, indirect, incidental, special, exemplary, or
85290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberconsequential damages (including, but not limited to, procurement of
85390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Hubersubstitute goods or services; loss of use, data, or profits; or business
85490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberinterruption) however caused and on any theory of liability, whether in
85590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Hubercontract, strict liability, or tort (including negligence or otherwise)
85690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberarising in any way out of the use of this software, even if advised of the
85790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberpossibility of such damage.
85890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
85990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber*/
86090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber?>