Skip to content

Instantly share code, notes, and snippets.

@Nosgoroth
Created April 24, 2024 14:48
Curl quotes (transform straight quotes into curly ones) (PHP5)
<?php
function curl_quotes($str) {
// Adapted from: https://github.com/kellym/smartquotes.js/blob/master/lib/replacements.js
// Single quotes
$sx = "'"; // straight (\u0027)
$s1 = ""; // Opening (\u2018)
$s2 = ""; // Closing (\u2019)
// Double quotes
$dx = '"'; // straight (\u0022)
$d1 = ""; // Opening (\u201C)
$d2 = ""; // Closing (\u201D)
// Primes
$prime1 = ''; // Single prime, also for ft (\u2032)
$prime2 = ''; // Double prime (\u2033)
$prime3 = ''; // Triple prime (\u2034)
$prime4 = ''; // Quadruple prime (\u2057)
// word character range
$wcr = 'a-zA-ZáàâäãåçéèêëíìîïñóòôöõúùûüýÿæœÁÀÂÄÃÅÇÉÈÊËÍÌÎÏÑÓÒÔÖÕÚÙÛÜÝŸÆŒ';
// word groups
$word = "[${wcr}_0-9]";
$nonword = "[^${wcr}_0-9]";
// quadruple prime
$str = preg_replace(
"/${sx}${sx}${sx}${sx}/i",
"${prime4}",
$str
);
// triple prime
// [/'''/g, retainLength => '\u2034' + (retainLength ? '\u2063\u2063' : '')],
$str = preg_replace(
"/${sx}${sx}${sx}/i",
"${prime3}",
$str
);
// beginning "
// [new RegExp(`(${nonWord}|^)"(${word})`, 'g'), '$1\u201c$2'],
// Using preg_replace_callback to support multiple straight quotes in a row
$str = preg_replace_callback(
"/(${nonword}|^)(${dx}+)(${word})/",
function ($match) use ($d1) {
return $match[1].str_repeat($d1, strlen($match[2])).$match[3];
},
$str
);
// ending "
// [/(\u201c[^"]*)"([^"]*$|[^\u201c"]*\u201c)/g, '$1\u201d$2'],
// Using preg_replace_callback to support multiple straight quotes in a row
$str = preg_replace_callback(
"/(${d1}[^${dx}]*)(${dx}+)([^${dx}]*$|[^${d1}${dx}]*${d1})/",
function ($match) use ($d2) {
return $match[1].str_repeat($d2, strlen($match[2])).$match[3];
},
$str
);
// remaining " at end of word
// [/([^0-9])"/g, '$1\u201d'],
// Using preg_replace_callback to support multiple straight quotes in a row
$str = preg_replace_callback(
"/([^0-9])(${dx}+)/",
function ($match) use ($d2) {
return $match[1].str_repeat($d2, strlen($match[2]));
},
$str
);
// double prime as two single quotes
// [/''/g, retainLength => '\u2033' + (retainLength ? '\u2063' : '')],
$str = preg_replace(
"/${sx}${sx}/i",
"${prime2}",
$str
);
// beginning '
// [new RegExp(`(${nonWord}|^)'(\\S)`, 'g'), '$1\u2018$2'],
$str = preg_replace(
"/(${nonword}|^)${sx}([^\s])/",
"$1${s1}$2",
$str
);
// conjunction's possession
// [new RegExp(`(${word})'([${pL}])`, 'ig'), '$1\u2019$2'],
$str = preg_replace(
"/(${word})${sx}(${wcr})/i",
"$1${s2}$2",
$str
);
// abbrev. years like '93
// [new RegExp(`(\\u2018)([0-9]{2}[^\\u2019]*)(\\u2018([^0-9]|$)|$|\\u2019[${pL}])`, 'ig'), '\u2019$2$3'],
$str = preg_replace(
"/(${s1})([0-9]{2}[^${s2}]*)(${s1}([^0-9]|$)|$|${s2}[${wcr}])/i",
"${s2}$2$3",
$str
);
// ending '
// [new RegExp(`((\\u2018[^']*)|[${pL}])'([^0-9]|$)`, 'ig'), '$1\u2019$3'],
$str = preg_replace(
"/((${s1}[^']*)|[${wcr}])'([^0-9]|$)/",
"$1${s2}$3",
$str
);
// backwards apostrophe
// [new RegExp(`(\\B|^)\\u2018(?=([^\\u2018\\u2019]*\\u2019\\b)*([^\\u2018\\u2019]*\\B${nonWord}[\\u2018\\u2019]\\b|[^\\u2018\\u2019]*$))`, 'ig'), '$1\u2019'],
// AAAAAAHHHHHH I HAVE NO IDEA WHAT THIS DOES
$str = preg_replace(
"/(\\B|^)${s1}(?=([^${s1}${s2}]*${s2}\\b)*([^${s1}${s2}]*\\B${nonword}[${s1}${s2}]\\b|[^${s1}${s2}]*$))/i",
"$1${s2}$3",
$str
);
// double prime
// [/"/g, '\u2033'],
$str = preg_replace(
"/${dx}/i",
"${prime2}",
$str
);
// prime
//[/'/g, '\u2032']
$str = preg_replace(
"/${sx}/i",
"${prime1}",
$str
);
return $str;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment