00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00017 final class RussianTypograph extends BaseFilter
00018 {
00019 const MAGIC_DELIMITER = '<>';
00020
00021 private static $symbols =
00022 array(
00023 ' ' => ' ',
00024 ' < ' => ' < ',
00025 ' > ' => ' > ',
00026 '…' => '…',
00027 '...' => '…',
00028 '™' => '™',
00029 '(tm)' => '™',
00030 '(TM)' => '™',
00031 '©' => '©',
00032 '(c)' => '©',
00033 '(C)' => '©',
00034 '№' => '№',
00035 '—' => '—',
00036 '–' => '—',
00037 '«' => '«',
00038 '»' => '»',
00039 '„' => '„',
00040 '“' => '“',
00041 '•' => '•',
00042 '®' => '®',
00043 '¼' => '¼',
00044 '½' => '½',
00045 '¾' => '¾',
00046 '±' => '±',
00047 '+/-' => '±',
00048 '!=' => '≠',
00049 '<>' => '≠',
00050
00051
00052 ' 1/4' => ' ¼',
00053 ' 1/2' => ' ½',
00054 ' 3/4' => ' ¾',
00055 '1/4 ' => '¼ ',
00056 '1/2 ' => '½ ',
00057 '3/4 ' => '¾ '
00058 );
00059
00060 private static $from = array(
00061 '~\-{2,}~',
00062 '~([\w\pL\pP]+)\s+\-\s+~u',
00063 '~(\s)\s*~u',
00064 '~([\s\pP]|^)([\w\pL]{1,2})\s~Uu',
00065 '~( |\s)\s+~u',
00066 '~\"(.*)\"~e',
00067 '~\"([^\s]*)\"~',
00068 '~\"([^\s]*)\s+([^\s\.]*)\"~',
00069 '~([\w\pL\']+)~eu'
00070 );
00071
00072 private static $to = array(
00073 '-',
00074 '$1 — ',
00075 '$1$1',
00076 '$1$2 ',
00077 '$1',
00078 '\'«\'.$this->innerQuotes(\'$1\').\'»\'',
00079 '«$1»',
00080 '«$1 $2»',
00081 'str_replace("\'", \'’\', \'$1\')'
00082 );
00083
00087 public static function me()
00088 {
00089 return Singleton::getInstance(__CLASS__);
00090 }
00091
00092 public function apply($value)
00093 {
00094 if (!$value = trim(strtr($value, self::$symbols)))
00095 return null;
00096
00097 $list =
00098 preg_split(
00099 '~([^<>]*)(?![^<]*?>)~',
00100 $value,
00101 null,
00102 PREG_SPLIT_DELIM_CAPTURE
00103 | PREG_SPLIT_NO_EMPTY
00104 | PREG_SPLIT_OFFSET_CAPTURE
00105 );
00106
00107 $tags = array();
00108 $text = null;
00109
00110 foreach ($list as $row) {
00111 $string = $row[0];
00112 if (
00113 (strpos($string, '<') === false)
00114 && (strpos($string, '>') === false)
00115 ) {
00116 $text .= $string;
00117 } else {
00118 $tags[] = $string;
00119 $text .= self::MAGIC_DELIMITER;
00120 }
00121 }
00122
00123 $text = $this->typographize($text);
00124
00125 if ($tags) {
00126 $i = 0;
00127 $out = null;
00128
00129 foreach (explode(self::MAGIC_DELIMITER, $text) as $chunk) {
00130 $out .= $chunk;
00131
00132 if (isset($tags[$i]))
00133 $out .= $tags[$i++];
00134 }
00135
00136 return $out;
00137 }
00138
00139 return CompressWhitespaceFilter::me()->apply($text);
00140 }
00141
00142 private function typographize($text)
00143 {
00144 if (mb_strlen($text) < 2)
00145 return $text;
00146
00147 return
00148 preg_replace(
00149 self::$from,
00150 self::$to,
00151 stripslashes($text)
00152 );
00153 }
00154
00155 private function innerQuotes($text)
00156 {
00157 return
00158 preg_replace(
00159 array(
00160 '~«(.*)»~U',
00161 '~\"(.*)\"~U',
00162 ),
00163 '„$1“',
00164 stripslashes($text)
00165 );
00166 }
00167 }
00168 ?>