You are here

function EducateQuotes in Typogrify 7

Same name and namespace in other branches
  1. 5 smartypants.php \EducateQuotes()
  2. 6 smartypants.php \EducateQuotes()

EducatedQuotes. Example input: "Isn't this fun?" Example output: [0]Isn’t this fun?[1];

Parameters

string $_: Input text.

Return value

string The string, with "educated" curly quote HTML entities.

2 calls to EducateQuotes()
SmartQuotes in ./smartypants.php
SmartQuotes
SmartyPants in ./smartypants.php
SmartyPants.

File

./smartypants.php, line 831
SmartyPants - Smart punctuation for web sites

Code

function EducateQuotes($_, $quotes) {

  // Make our own "punctuation" character class, because the POSIX-style
  // [:PUNCT:] is only available in Perl 5.6 or later:
  $punct_class = "[!\"#\\\$\\%'()*+,-.\\/:;<=>?\\@\\[\\\\\\]\\^_`{|}~]";

  // Special case if the very first character is a quote
  // followed by punctuation at a non-word-break.
  // Close the quotes by brute force:
  $_ = preg_replace(array(
    "/^'(?={$punct_class}\\B)/",
    "/^\"(?={$punct_class}\\B)/",
  ), array(
    $quotes[3],
    $quotes[1],
  ), $_);

  // Special case for double sets of quotes, e.g.:
  // <p>He said, "'Quoted' words in a larger quote."</p>.
  $spacer = '&#8201;';
  $_ = preg_replace(array(
    "/\"'(?=\\p{L})/u",
    "/'\"(?=\\p{L})/u",
    "/(\\p{L})\"'/u",
    "/(\\p{L})'\"/u",
  ), array(
    $quotes[0] . $spacer . $quotes[2],
    $quotes[2] . $spacer . $quotes[0],
    '\\1' . $quotes[1] . $spacer . $quotes[3],
    '\\1' . $quotes[3] . $spacer . $quotes[1],
  ), $_);

  // Special case for decade abbreviations (the '80s):
  $_ = preg_replace("/'(?=\\d{2}s)/", '&#8217;', $_);

  // Special case for apostroph.
  $_ = preg_replace("/(\\p{L})(')(?=\\p{L}|\$)/u", '\\1&#8217;', $_);
  $close_class = '[^\\ \\t\\r\\n\\[\\{\\(\\-]';
  $dec_dashes = '&\\#8211;|&\\#8212;';

  // Get most opening single quotes:
  $_ = preg_replace("{\n    (\n      \\s         |   # a whitespace char, or\n      &nbsp;      |   # a non-breaking space entity, or\n      --          |   # dashes, or\n      &[mn]dash;  |   # named dash entities\n      {$dec_dashes} |   # or decimal entities\n      &\\#x201[34];   # or hex\n    )\n    '                 # the quote\n    (?=\\p{L})           # followed by a word character\n    }x", '\\1' . $quotes[2], $_);

  // Single closing quotes:
  $_ = preg_replace("{\n    ({$close_class})?\n    '\n    (?(1)|            # If \$1 captured, then do nothing;\n      (?=\\s | s\\b)  # otherwise, positive lookahead for a whitespace\n    )                 # char or an 's' at a word ending position. This\n                      # is a special case to handle something like:\n                      # \"<i>Custer</i>'s Last Stand.\"\n    }xi", '\\1' . $quotes[3], $_);

  // Any remaining single quotes should be opening ones:
  $_ = str_replace("'", $quotes[2], $_);

  // Get most opening double quotes:
  $_ = preg_replace("{\n    (\n      \\s         |   # a whitespace char, or\n      &nbsp;      |   # a non-breaking space entity, or\n      --          |   # dashes, or\n      &[mn]dash;  |   # named dash entities\n      {$dec_dashes} |   # or decimal entities\n      &\\#x201[34];   # or hex\n    )\n    \"                # the quote\n    (?=\\p{L})           # followed by a word character\n    }x", '\\1' . $quotes[0], $_);

  // Double closing quotes:
  $_ = preg_replace("{\n    ({$close_class})?\n    \"\n    (?(1)|(?=\\s))   # If \$1 captured, then do nothing;\n                     # if not, then make sure the next char is whitespace.\n    }x", '\\1' . $quotes[1], $_);

  // Any remaining quotes should be opening ones.
  $_ = str_replace('"', $quotes[0], $_);
  return $_;
}