00001 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 class CI_Typography {
00028
00029
00030 var $block_elements = 'address|blockquote|div|dl|fieldset|form|h\d|hr|noscript|object|ol|p|pre|script|table|ul';
00031
00032
00033 var $skip_elements = 'p|pre|ol|ul|dl|object|table';
00034
00035
00036 var $inline_elements = 'a|abbr|acronym|b|bdo|br|button|cite|code|del|dfn|em|i|img|ins|input|label|map|kbd|samp|select|span|strong|sub|sup|textarea|var';
00037
00038
00039 var $protect_braced_quotes = FALSE;
00040
00041
00042
00043
00044
00045 function CI_Typography()
00046 {
00047 }
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 function auto_typography($str, $strip_js_event_handlers = TRUE, $reduce_linebreaks = FALSE)
00067 {
00068 if ($str == '')
00069 {
00070 return '';
00071 }
00072
00073
00074 if (strpos($str, "\r") !== FALSE)
00075 {
00076 $str = str_replace(array("\r\n", "\r"), "\n", $str);
00077 }
00078
00079
00080
00081 if ($reduce_linebreaks === TRUE)
00082 {
00083 $str = preg_replace("/\n\n+/", "\n\n", $str);
00084 }
00085
00086
00087 if ($strip_js_event_handlers === TRUE)
00088 {
00089 $str = preg_replace("#<([^><]+?)([^a-z_\-]on\w*|xmlns)(\s*=\s*[^><]*)([><]*)#i", "<\\1\\4", $str);
00090 }
00091
00092
00093
00094 if (preg_match_all("#<.+?>#si", $str, $matches))
00095 {
00096 for ($i = 0; $i < count($matches['0']); $i++)
00097 {
00098 $str = str_replace($matches['0'][$i],
00099 str_replace(array("'",'"'), array('{@SQ}', '{@DQ}'), $matches['0'][$i]),
00100 $str);
00101 }
00102 }
00103
00104 if ($this->protect_braced_quotes === TRUE)
00105 {
00106 if (preg_match_all("#\{.+?}#si", $str, $matches))
00107 {
00108 for ($i = 0; $i < count($matches['0']); $i++)
00109 {
00110 $str = str_replace($matches['0'][$i],
00111 str_replace(array("'",'"'), array('{@SQ}', '{@DQ}'), $matches['0'][$i]),
00112 $str);
00113 }
00114 }
00115 }
00116
00117
00118
00119
00120 $str = preg_replace("#<(/*)(".$this->inline_elements.")([ >])#i", "{@TAG}\\1\\2\\3", $str);
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 $chunks = preg_split('/(<(?:[^<>]+(?:"[^"]*"|\'[^\']*\')?)+>)/', $str, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
00132
00133
00134 $str = '';
00135 $process = TRUE;
00136 $paragraph = FALSE;
00137 foreach ($chunks as $chunk)
00138 {
00139
00140
00141 if (preg_match("#<(/*)(".$this->block_elements.").*?>#", $chunk, $match))
00142 {
00143 if (preg_match("#".$this->skip_elements."#", $match[2]))
00144 {
00145 $process = ($match[1] == '/') ? TRUE : FALSE;
00146 }
00147
00148 $str .= $chunk;
00149 continue;
00150 }
00151
00152 if ($process == FALSE)
00153 {
00154 $str .= $chunk;
00155 continue;
00156 }
00157
00158
00159 $str .= $this->_format_newlines($chunk);
00160 }
00161
00162
00163 if ( ! preg_match("/^<(?:".$this->block_elements.")/i", $str, $match))
00164 {
00165 $str = "<p>{$str}</p>";
00166 }
00167
00168
00169 $str = $this->format_characters($str);
00170
00171
00172 $table = array(
00173
00174
00175
00176 '/(<p.*?>)<p>/' => '$1',
00177
00178
00179 '#(</p>)+#' => '</p>',
00180 '/(<p><p>)+/' => '<p>',
00181
00182
00183 '#<p></p><('.$this->block_elements.')#' => '<$1',
00184
00185
00186 '/\{@TAG\}/' => '<',
00187 '/\{@DQ\}/' => '"',
00188 '/\{@SQ\}/' => "'"
00189
00190 );
00191
00192
00193 if ($reduce_linebreaks === TRUE)
00194 {
00195 $table['#<p>\n*</p>#'] = '';
00196 }
00197 else
00198 {
00199
00200
00201 $table['#<p></p>#'] = '<p> </p>';
00202 }
00203
00204 return preg_replace(array_keys($table), $table, $str);
00205
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 function format_characters($str)
00222 {
00223 static $table;
00224
00225 if ( ! isset($table))
00226 {
00227 $table = array(
00228
00229
00230
00231
00232 '/(^|\W|\s)\'"/' => '$1‘“',
00233 '/\'"(\s|\W|$)/' => '’”$1',
00234 '/(^|\W|\s)"\'/' => '$1“‘',
00235 '/"\'(\s|\W|$)/' => '”’$1',
00236
00237
00238 '/\'(\s|\W|$)/' => '’$1',
00239 '/(^|\W|\s)\'/' => '$1‘',
00240
00241
00242 '/"(\s|\W|$)/' => '”$1',
00243 '/(^|\W|\s)"/' => '$1“',
00244
00245
00246 "/(\w)'(\w)/" => '$1’$2',
00247
00248
00249 '/\s?\-\-\s?/' => '—',
00250 '/(\w)\.{3}/' => '$1…',
00251
00252
00253 '/(\W) /' => '$1 ',
00254
00255
00256 '/&(?!#?[a-zA-Z0-9]{2,};)/' => '&'
00257 );
00258 }
00259
00260 return preg_replace(array_keys($table), $table, $str);
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 function _format_newlines($str)
00275 {
00276 if ($str == '')
00277 {
00278 return $str;
00279 }
00280
00281 if (strpos($str, "\n") === FALSE)
00282 {
00283 return $str;
00284 }
00285
00286
00287 $str = str_replace("\n\n", "</p>\n\n<p>", $str);
00288
00289
00290 $str = preg_replace("/([^\n])(\n)([^\n])/", "\\1<br />\\2\\3", $str);
00291
00292
00293 if ($str != "\n")
00294 {
00295 $str = '<p>'.$str.'</p>';
00296 }
00297
00298
00299
00300 $str = preg_replace("/<p><\/p>(.*)/", "\\1", $str, 1);
00301
00302 return $str;
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 function nl2br_except_pre($str)
00315 {
00316 $ex = explode("pre>",$str);
00317 $ct = count($ex);
00318
00319 $newstr = "";
00320 for ($i = 0; $i < $ct; $i++)
00321 {
00322 if (($i % 2) == 0)
00323 {
00324 $newstr .= nl2br($ex[$i]);
00325 }
00326 else
00327 {
00328 $newstr .= $ex[$i];
00329 }
00330
00331 if ($ct - 1 != $i)
00332 $newstr .= "pre>";
00333 }
00334
00335 return $newstr;
00336 }
00337
00338 }
00339
00340
00341
00342