<?php namespace Converter;
// Author: Taufik Nurrohman <https://github.com/tovic>
// <https://github.com/tovic/typography-plugin-for-mecha-cms/blob/master/typography/workers/converter.typography.php>
/**
* ====================================================================
* TYPOGRAPHY CONVERTER
* ====================================================================
*
* -- CODE: -----------------------------------------------------------
*
* $parser = new Converter\Typography();
*
* echo $parser->run('He said, "Yes, you\'re gross!"');
*
* --------------------------------------------------------------------
*
*/
class Typography {
// single quote [o, c]
public $q = array('‘', '’');
// double quote [o, c]
public $Q = array('“', '”');
// dash [n, m]
public $d = array('–', '—');
// ellipsis [h]
public $e = array('…');
// white-space(s) ...
public $s = array(' ', ' ');
// Skip parsing process if we are in these HTML tag(s)
public $ignore = 'code|kbd|math|pre|script|style';
// Run converter ...
public function run($text) {
if( ! trim($text)) return $text;
$_ = '#(<\/?[-:\w]+(?:>|\s[^<>]*?>))#';
$parts = preg_split($_, $text, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
$text = "";
$x = 0;
foreach($parts as $v) {
if( ! trim($v)) {
$text .= $v;
continue;
}
if($v[0] === '<' && substr($v, -1) === '>') {
if(preg_match('#^<(\/)?(?:' . $this->ignore . ')(?:>|\s[^<>]*?>)$#', $v, $m)) {
$x = isset($m[1]) && $m[1] === '/' ? 0 : 1;
}
$text .= $v; // this is a HTML tag ...
} else {
$text .= ! $x ? $this->replace($v) : $v; // process or skip ...
}
}
return $text;
}
// Replace character(s) ...
protected function replace($text) {
// Convert some HTML entiti(y|es) back
// to their plain text version ...
$text = str_replace(
array('"', ''', '"', '''),
array('"', "'", '"', "'"),
$text);
$text = $this->escape($text);
$text = $this->nbsp($text);
$text = $this->dot($text);
$text = $this->dash($text);
$text = $this->quote($text);
return $text;
}
// From `'foo'` to `‘foo’` and `"bar"` to `“bar”`
protected function quote($text) {
$text = preg_replace(
array(
// single quote
'#(?<=^|\W)\'(?!$)#',
'#(?<!^)\'(?=\W|$)#',
// double quote
'#(?<=^|\W)"(?!$)#',
'#(?<!^)"(?=\W|$)#'
),
array(
// single quote
$this->q[0],
$this->q[1],
// double quote
$this->Q[0],
$this->Q[1]
),
$text);
// Fix for `foo”‘` and `foo’“`
$text = str_replace(
array(
$this->Q[1] . $this->q[0],
$this->q[1] . $this->Q[0]
),
array(
$this->Q[1] . $this->q[1],
$this->q[1] . $this->Q[1]
),
$text);
// The rest of the quote(s) should be a closing quote(s)
return str_replace(array("'", '"'), array($this->q[1], $this->Q[1]), $text);
}
// From `--` to `–` and `---` to `—`
protected function dash($text) {
return str_replace(
array(
'---',
'--'
),
array(
$this->d[1],
$this->d[0]
),
$text);
}
// From `...` to `…`
protected function dot($text) {
return str_replace(
array(
'...',
'. . .'
),
$this->e[0],
$text);
}
// ...
protected function nbsp($text) {
return preg_replace('#(?<=\S)\s+(?=[:;?!])#', $this->s[1], $text);
}
// Ignore parser with `\"foo\"`
protected function escape($text) {
return str_replace(
array(
'\\\\',
'\"',
"\'",
'\.',
'\-',
'\`'
),
array(
'\',
'"',
''',
'.',
'-',
'`'
),
$text);
}
// Reverse conversion, e.g. from `“foo”` to `"foo"`
public function destroy($text) {
return str_replace(
array(
$this->d[0],
$this->d[1],
$this->q[0],
$this->q[1],
$this->Q[0],
$this->Q[1],
$this->e[0],
$this->s[0],
$this->s[1]
),
array(
'--',
'---',
"'",
"'",
'"',
'"',
'...',
' ',
' '
),
$text);
}
}
Smaller than **SmartyPants** and `wptexturize` function.
Be the first to comment
You can use [html][/html], [css][/css], [php][/php] and more to embed the code. Urls are automatically hyperlinked. Line breaks and paragraphs are automatically generated.