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