You are here

function EducateQuotes in Typogrify 5

Same name and namespace in other branches
  1. 6 smartypants.php \EducateQuotes()
  2. 7 smartypants.php \EducateQuotes()
2 calls to EducateQuotes()
SmartQuotes in ./smartypants.php
SmartyPants in ./smartypants.php

File

./smartypants.php, line 403

Code

function EducateQuotes($_) {

  #

  #   Parameter:  String.

  #

  #   Returns:    The string, with "educated" curly quote HTML entities.

  #

  #   Example input:  "Isn't this fun?"

  #   Example output: “Isn’t this fun?”

  #

  # 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(
    '&#8217;',
    '&#8221;',
  ), $_);

  # Special case for double sets of quotes, e.g.:

  #   <p>He said, "'Quoted' words in a larger quote."</p>
  $_ = preg_replace(array(
    "/\"'(?=\\w)/",
    "/'\"(?=\\w)/",
  ), array(
    '&#8220;&#8216;',
    '&#8216;&#8220;',
  ), $_);

  # Special case for decade abbreviations (the '80s):
  $_ = preg_replace("/'(?=\\d{2}s)/", '&#8217;', $_);
  $close_class = '[^\\ \\t\\r\\n\\[\\{\\(\\-]';
  $dec_dashes = '&\\#8211;|&\\#8212;';

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

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

  # Any remaining single quotes should be opening ones:
  $_ = str_replace("'", '&#8216;', $_);

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

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

  # Any remaining quotes should be opening ones.
  $_ = str_replace('"', '&#8220;', $_);
  return $_;
}