wptexturize

Replaces common plain text characters into formatted entities.

Description

(string) wptexturize( (string) $text, (bool) $reset = false ); 

As an example,

Becomes:

Code within certain html blocks are skipped.

Do not use this function before the action hook; everything will break.

Returns (string)

The string replaced with html entities

Parameters (2)

0. $text (string)
The text to be formatted
1. $reset — Optional. (bool) => false
Set to true for unit testing. Translated patterns will reset.

Usage

  1. if ( !function_exists( 'wptexturize' ) ) { 
  2. require_once ABSPATH . WPINC . '/formatting.php'; 
  3.  
  4. // The text to be formatted 
  5. $text = ''; 
  6.  
  7. // Set to true for unit testing. Translated patterns will reset. 
  8. $reset = false; 
  9.  
  10. // NOTICE! Understand what this does before running. 
  11. $result = wptexturize($text, $reset); 
  12.  

Defined (1)

The function is defined in the following location(s).

/wp-includes/formatting.php  
  1. function wptexturize( $text, $reset = false ) { 
  2. global $wp_cockneyreplace, $shortcode_tags; 
  3. static $static_characters = null,  
  4. $static_replacements = null,  
  5. $dynamic_characters = null,  
  6. $dynamic_replacements = null,  
  7. $default_no_texturize_tags = null,  
  8. $default_no_texturize_shortcodes = null,  
  9. $run_texturize = true,  
  10. $apos = null,  
  11. $prime = null,  
  12. $double_prime = null,  
  13. $opening_quote = null,  
  14. $closing_quote = null,  
  15. $opening_single_quote = null,  
  16. $closing_single_quote = null,  
  17. $open_q_flag = '<!--oq-->',  
  18. $open_sq_flag = '<!--osq-->',  
  19. $apos_flag = '<!--apos-->'; 
  20.  
  21. // If there's nothing to do, just stop. 
  22. if ( empty( $text ) || false === $run_texturize ) { 
  23. return $text; 
  24.  
  25. // Set up static variables. Run once only. 
  26. if ( $reset || ! isset( $static_characters ) ) { 
  27. /** 
  28. * Filters whether to skip running wptexturize(). 
  29. * Passing false to the filter will effectively short-circuit wptexturize(). 
  30. * returning the original text passed to the function instead. 
  31. * The filter runs only once, the first time wptexturize() is called. 
  32. * @since 4.0.0 
  33. * @see wptexturize() 
  34. * @param bool $run_texturize Whether to short-circuit wptexturize(). 
  35. */ 
  36. $run_texturize = apply_filters( 'run_wptexturize', $run_texturize ); 
  37. if ( false === $run_texturize ) { 
  38. return $text; 
  39.  
  40. /** translators: opening curly double quote */ 
  41. $opening_quote = _x( '“', 'opening curly double quote' ); 
  42. /** translators: closing curly double quote */ 
  43. $closing_quote = _x( '”', 'closing curly double quote' ); 
  44.  
  45. /** translators: apostrophe, for example in 'cause or can't */ 
  46. $apos = _x( '’', 'apostrophe' ); 
  47.  
  48. /** translators: prime, for example in 9' (nine feet) */ 
  49. $prime = _x( '′', 'prime' ); 
  50. /** translators: double prime, for example in 9" (nine inches) */ 
  51. $double_prime = _x( '″', 'double prime' ); 
  52.  
  53. /** translators: opening curly single quote */ 
  54. $opening_single_quote = _x( '‘', 'opening curly single quote' ); 
  55. /** translators: closing curly single quote */ 
  56. $closing_single_quote = _x( '’', 'closing curly single quote' ); 
  57.  
  58. /** translators: en dash */ 
  59. $en_dash = _x( '–', 'en dash' ); 
  60. /** translators: em dash */ 
  61. $em_dash = _x( '—', 'em dash' ); 
  62.  
  63. $default_no_texturize_tags = array('pre', 'code', 'kbd', 'style', 'script', 'tt'); 
  64. $default_no_texturize_shortcodes = array('code'); 
  65.  
  66. // if a plugin has provided an autocorrect array, use it 
  67. if ( isset($wp_cockneyreplace) ) { 
  68. $cockney = array_keys( $wp_cockneyreplace ); 
  69. $cockneyreplace = array_values( $wp_cockneyreplace ); 
  70. } else { 
  71. /** translators: This is a comma-separated list of words that defy the syntax of quotations in normal use,  
  72. * for example... 'We do not have enough words yet' ... is a typical quoted phrase. But when we write 
  73. * lines of code 'til we have enough of 'em, then we need to insert apostrophes instead of quotes. 
  74. */ 
  75. $cockney = explode( ', ', _x( "'tain't, 'twere, 'twas, 'tis, 'twill, 'til, 'bout, 'nuff, 'round, 'cause, 'em",  
  76. 'Comma-separated list of words to texturize in your language' ) ); 
  77.  
  78. $cockneyreplace = explode( ', ', _x( '’tain’t, ’twere, ’twas, ’tis, ’twill, ’til, ’bout, ’nuff, ’round, ’cause, ’em',  
  79. 'Comma-separated list of replacement words in your language' ) ); 
  80.  
  81. $static_characters = array_merge( array( '...', '``', '\'\'', ' (tm)' ), $cockney ); 
  82. $static_replacements = array_merge( array( '…', $opening_quote, $closing_quote, ' ™' ), $cockneyreplace ); 
  83.  
  84.  
  85. // Pattern-based replacements of characters. 
  86. // Sort the remaining patterns into several arrays for performance tuning. 
  87. $dynamic_characters = array( 'apos' => array(), 'quote' => array(), 'dash' => array() ); 
  88. $dynamic_replacements = array( 'apos' => array(), 'quote' => array(), 'dash' => array() ); 
  89. $dynamic = array(); 
  90. $spaces = wp_spaces_regexp(); 
  91.  
  92. // '99' and '99" are ambiguous among other patterns; assume it's an abbreviated year at the end of a quotation. 
  93. if ( "'" !== $apos || "'" !== $closing_single_quote ) { 
  94. $dynamic[ '/\'(\d\d)\'(?=\Z|[., :;!?)}\-\]]|>|' . $spaces . ')/' ] = $apos_flag . '$1' . $closing_single_quote; 
  95. if ( "'" !== $apos || '"' !== $closing_quote ) { 
  96. $dynamic[ '/\'(\d\d)"(?=\Z|[., :;!?)}\-\]]|>|' . $spaces . ')/' ] = $apos_flag . '$1' . $closing_quote; 
  97.  
  98. // '99 '99s '99's (apostrophe) But never '9 or '99% or '999 or '99.0. 
  99. if ( "'" !== $apos ) { 
  100. $dynamic[ '/\'(?=\d\d(?:\Z|(?![%\d]|[., ]\d)))/' ] = $apos_flag; 
  101.  
  102. // Quoted Numbers like '0.42' 
  103. if ( "'" !== $opening_single_quote && "'" !== $closing_single_quote ) { 
  104. $dynamic[ '/(?<=\A|' . $spaces . ')\'(\d[., \d]*)\'/' ] = $open_sq_flag . '$1' . $closing_single_quote; 
  105.  
  106. // Single quote at start, or preceded by (, {, <, [, ", -, or spaces. 
  107. if ( "'" !== $opening_single_quote ) { 
  108. $dynamic[ '/(?<=\A|[([{"\-]|<|' . $spaces . ')\'/' ] = $open_sq_flag; 
  109.  
  110. // Apostrophe in a word. No spaces, double apostrophes, or other punctuation. 
  111. if ( "'" !== $apos ) { 
  112. $dynamic[ '/(?<!' . $spaces . ')\'(?!\Z|[., :;!?"\'() {}[\]\-]|&[lg]t;|' . $spaces . ')/' ] = $apos_flag; 
  113.  
  114. $dynamic_characters['apos'] = array_keys( $dynamic ); 
  115. $dynamic_replacements['apos'] = array_values( $dynamic ); 
  116. $dynamic = array(); 
  117.  
  118. // Quoted Numbers like "42" 
  119. if ( '"' !== $opening_quote && '"' !== $closing_quote ) { 
  120. $dynamic[ '/(?<=\A|' . $spaces . ')"(\d[., \d]*)"/' ] = $open_q_flag . '$1' . $closing_quote; 
  121.  
  122. // Double quote at start, or preceded by (, {, <, [, -, or spaces, and not followed by spaces. 
  123. if ( '"' !== $opening_quote ) { 
  124. $dynamic[ '/(?<=\A|[([{\-]|<|' . $spaces . ')"(?!' . $spaces . ')/' ] = $open_q_flag; 
  125.  
  126. $dynamic_characters['quote'] = array_keys( $dynamic ); 
  127. $dynamic_replacements['quote'] = array_values( $dynamic ); 
  128. $dynamic = array(); 
  129.  
  130. // Dashes and spaces 
  131. $dynamic[ '/---/' ] = $em_dash; 
  132. $dynamic[ '/(?<=^|' . $spaces . ')--(?=$|' . $spaces . ')/' ] = $em_dash; 
  133. $dynamic[ '/(?<!xn)--/' ] = $en_dash; 
  134. $dynamic[ '/(?<=^|' . $spaces . ')-(?=$|' . $spaces . ')/' ] = $en_dash; 
  135.  
  136. $dynamic_characters['dash'] = array_keys( $dynamic ); 
  137. $dynamic_replacements['dash'] = array_values( $dynamic ); 
  138.  
  139. // Must do this every time in case plugins use these filters in a context sensitive manner 
  140. /** 
  141. * Filters the list of HTML elements not to texturize. 
  142. * @since 2.8.0 
  143. * @param array $default_no_texturize_tags An array of HTML element names. 
  144. */ 
  145. $no_texturize_tags = apply_filters( 'no_texturize_tags', $default_no_texturize_tags ); 
  146. /** 
  147. * Filters the list of shortcodes not to texturize. 
  148. * @since 2.8.0 
  149. * @param array $default_no_texturize_shortcodes An array of shortcode names. 
  150. */ 
  151. $no_texturize_shortcodes = apply_filters( 'no_texturize_shortcodes', $default_no_texturize_shortcodes ); 
  152.  
  153. $no_texturize_tags_stack = array(); 
  154. $no_texturize_shortcodes_stack = array(); 
  155.  
  156. // Look for shortcodes and HTML elements. 
  157.  
  158. preg_match_all( '@\[/?([^<>&/\[\]\x00-\x20=]++)@', $text, $matches ); 
  159. $tagnames = array_intersect( array_keys( $shortcode_tags ), $matches[1] ); 
  160. $found_shortcodes = ! empty( $tagnames ); 
  161. $shortcode_regex = $found_shortcodes ? _get_wptexturize_shortcode_regex( $tagnames ) : ''; 
  162. $regex = _get_wptexturize_split_regex( $shortcode_regex ); 
  163.  
  164. $textarr = preg_split( $regex, $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY ); 
  165.  
  166. foreach ( $textarr as &$curl ) { 
  167. // Only call _wptexturize_pushpop_element if $curl is a delimiter. 
  168. $first = $curl[0]; 
  169. if ( '<' === $first ) { 
  170. if ( '<!--' === substr( $curl, 0, 4 ) ) { 
  171. // This is an HTML comment delimiter. 
  172. continue; 
  173. } else { 
  174. // This is an HTML element delimiter. 
  175.  
  176. // Replace each & with & unless it already looks like an entity. 
  177. $curl = preg_replace( '/&(?!#(?:\d+|x[a-f0-9]+);|[a-z1-4]{1, 8};)/i', '&', $curl ); 
  178.  
  179. _wptexturize_pushpop_element( $curl, $no_texturize_tags_stack, $no_texturize_tags ); 
  180.  
  181. } elseif ( '' === trim( $curl ) ) { 
  182. // This is a newline between delimiters. Performance improves when we check this. 
  183. continue; 
  184.  
  185. } elseif ( '[' === $first && $found_shortcodes && 1 === preg_match( '/^' . $shortcode_regex . '$/', $curl ) ) { 
  186. // This is a shortcode delimiter. 
  187.  
  188. if ( '[[' !== substr( $curl, 0, 2 ) && ']]' !== substr( $curl, -2 ) ) { 
  189. // Looks like a normal shortcode. 
  190. _wptexturize_pushpop_element( $curl, $no_texturize_shortcodes_stack, $no_texturize_shortcodes ); 
  191. } else { 
  192. // Looks like an escaped shortcode. 
  193. continue; 
  194.  
  195. } elseif ( empty( $no_texturize_shortcodes_stack ) && empty( $no_texturize_tags_stack ) ) { 
  196. // This is neither a delimiter, nor is this content inside of no_texturize pairs. Do texturize. 
  197.  
  198. $curl = str_replace( $static_characters, $static_replacements, $curl ); 
  199.  
  200. if ( false !== strpos( $curl, "'" ) ) { 
  201. $curl = preg_replace( $dynamic_characters['apos'], $dynamic_replacements['apos'], $curl ); 
  202. $curl = wptexturize_primes( $curl, "'", $prime, $open_sq_flag, $closing_single_quote ); 
  203. $curl = str_replace( $apos_flag, $apos, $curl ); 
  204. $curl = str_replace( $open_sq_flag, $opening_single_quote, $curl ); 
  205. if ( false !== strpos( $curl, '"' ) ) { 
  206. $curl = preg_replace( $dynamic_characters['quote'], $dynamic_replacements['quote'], $curl ); 
  207. $curl = wptexturize_primes( $curl, '"', $double_prime, $open_q_flag, $closing_quote ); 
  208. $curl = str_replace( $open_q_flag, $opening_quote, $curl ); 
  209. if ( false !== strpos( $curl, '-' ) ) { 
  210. $curl = preg_replace( $dynamic_characters['dash'], $dynamic_replacements['dash'], $curl ); 
  211.  
  212. // 9x9 (times), but never 0x9999 
  213. if ( 1 === preg_match( '/(?<=\d)x\d/', $curl ) ) { 
  214. // Searching for a digit is 10 times more expensive than for the x, so we avoid doing this one! 
  215. $curl = preg_replace( '/\b(\d(?(?<=0)[\d\., ]+|[\d\., ]*))x(\d[\d\., ]*)\b/', '$1×$2', $curl ); 
  216.  
  217. // Replace each & with & unless it already looks like an entity. 
  218. $curl = preg_replace( '/&(?!#(?:\d+|x[a-f0-9]+);|[a-z1-4]{1, 8};)/i', '&', $curl ); 
  219.  
  220. return implode( '', $textarr );