X-Git-Url: https://scripts.mit.edu/gitweb/autoinstalls/wordpress.git/blobdiff_plain/8f374b7233bc2815ccc387e448d208c5434eb961..784f914b1e4b1c62d6657e86397c2e83bcee4295:/wp-includes/formatting.php
diff --git a/wp-includes/formatting.php b/wp-includes/formatting.php
index f69c9382..14f3852b 100644
--- a/wp-includes/formatting.php
+++ b/wp-includes/formatting.php
@@ -5,34 +5,85 @@
* Handles many functions for formatting output.
*
* @package WordPress
- **/
+ */
/**
* Replaces common plain text characters into formatted entities
*
* As an example,
- *
- * 'cause today's effort makes it worth tomorrow's "holiday"...
- *
+ *
+ * 'cause today's effort makes it worth tomorrow's "holiday" ...
+ *
* Becomes:
- *
- * ’cause today’s effort makes it worth tomorrow’s “holiday”…
- *
+ *
+ * ’cause today’s effort makes it worth tomorrow’s “holiday” …
+ *
* Code within certain html blocks are skipped.
*
+ * Do not use this function before the 'init' action hook; everything will break.
+ *
* @since 0.71
- * @uses $wp_cockneyreplace Array of formatted entities for certain common phrases
+ *
+ * @global array $wp_cockneyreplace Array of formatted entities for certain common phrases
+ * @global array $shortcode_tags
+ * @staticvar array $static_characters
+ * @staticvar array $static_replacements
+ * @staticvar array $dynamic_characters
+ * @staticvar array $dynamic_replacements
+ * @staticvar array $default_no_texturize_tags
+ * @staticvar array $default_no_texturize_shortcodes
+ * @staticvar bool $run_texturize
*
* @param string $text The text to be formatted
+ * @param bool $reset Set to true for unit testing. Translated patterns will reset.
* @return string The string replaced with html entities
*/
-function wptexturize($text) {
- global $wp_cockneyreplace;
- static $static_characters, $static_replacements, $dynamic_characters, $dynamic_replacements,
- $default_no_texturize_tags, $default_no_texturize_shortcodes;
+function wptexturize( $text, $reset = false ) {
+ global $wp_cockneyreplace, $shortcode_tags;
+ static $static_characters = null,
+ $static_replacements = null,
+ $dynamic_characters = null,
+ $dynamic_replacements = null,
+ $default_no_texturize_tags = null,
+ $default_no_texturize_shortcodes = null,
+ $run_texturize = true,
+ $apos = null,
+ $prime = null,
+ $double_prime = null,
+ $opening_quote = null,
+ $closing_quote = null,
+ $opening_single_quote = null,
+ $closing_single_quote = null,
+ $open_q_flag = '',
+ $open_sq_flag = '',
+ $apos_flag = '';
+
+ // If there's nothing to do, just stop.
+ if ( empty( $text ) || false === $run_texturize ) {
+ return $text;
+ }
+
+ // Set up static variables. Run once only.
+ if ( $reset || ! isset( $static_characters ) ) {
+ /**
+ * Filter whether to skip running wptexturize().
+ *
+ * Passing false to the filter will effectively short-circuit wptexturize().
+ * returning the original text passed to the function instead.
+ *
+ * The filter runs only once, the first time wptexturize() is called.
+ *
+ * @since 4.0.0
+ *
+ * @see wptexturize()
+ *
+ * @param bool $run_texturize Whether to short-circuit wptexturize().
+ */
+ $run_texturize = apply_filters( 'run_wptexturize', $run_texturize );
+ if ( false === $run_texturize ) {
+ return $text;
+ }
- // No need to set up these static variables more than once
- if ( ! isset( $static_characters ) ) {
/* translators: opening curly double quote */
$opening_quote = _x( '“', 'opening curly double quote' );
/* translators: closing curly double quote */
@@ -61,94 +112,291 @@ function wptexturize($text) {
// if a plugin has provided an autocorrect array, use it
if ( isset($wp_cockneyreplace) ) {
- $cockney = array_keys($wp_cockneyreplace);
- $cockneyreplace = array_values($wp_cockneyreplace);
- } elseif ( "'" != $apos ) { // Only bother if we're doing a replacement.
- $cockney = array( "'tain't", "'twere", "'twas", "'tis", "'twill", "'til", "'bout", "'nuff", "'round", "'cause" );
- $cockneyreplace = array( $apos . "tain" . $apos . "t", $apos . "twere", $apos . "twas", $apos . "tis", $apos . "twill", $apos . "til", $apos . "bout", $apos . "nuff", $apos . "round", $apos . "cause" );
+ $cockney = array_keys( $wp_cockneyreplace );
+ $cockneyreplace = array_values( $wp_cockneyreplace );
} else {
- $cockney = $cockneyreplace = array();
+ /* translators: This is a comma-separated list of words that defy the syntax of quotations in normal use,
+ * for example... 'We do not have enough words yet' ... is a typical quoted phrase. But when we write
+ * lines of code 'til we have enough of 'em, then we need to insert apostrophes instead of quotes.
+ */
+ $cockney = explode( ',', _x( "'tain't,'twere,'twas,'tis,'twill,'til,'bout,'nuff,'round,'cause,'em",
+ 'Comma-separated list of words to texturize in your language' ) );
+
+ $cockneyreplace = explode( ',', _x( '’tain’t,’twere,’twas,’tis,’twill,’til,’bout,’nuff,’round,’cause,’em',
+ 'Comma-separated list of replacement words in your language' ) );
+ }
+
+ $static_characters = array_merge( array( '...', '``', '\'\'', ' (tm)' ), $cockney );
+ $static_replacements = array_merge( array( '…', $opening_quote, $closing_quote, ' ™' ), $cockneyreplace );
+
+
+ // Pattern-based replacements of characters.
+ // Sort the remaining patterns into several arrays for performance tuning.
+ $dynamic_characters = array( 'apos' => array(), 'quote' => array(), 'dash' => array() );
+ $dynamic_replacements = array( 'apos' => array(), 'quote' => array(), 'dash' => array() );
+ $dynamic = array();
+ $spaces = wp_spaces_regexp();
+
+ // '99' and '99" are ambiguous among other patterns; assume it's an abbreviated year at the end of a quotation.
+ if ( "'" !== $apos || "'" !== $closing_single_quote ) {
+ $dynamic[ '/\'(\d\d)\'(?=\Z|[.,:;!?)}\-\]]|>|' . $spaces . ')/' ] = $apos_flag . '$1' . $closing_single_quote;
+ }
+ if ( "'" !== $apos || '"' !== $closing_quote ) {
+ $dynamic[ '/\'(\d\d)"(?=\Z|[.,:;!?)}\-\]]|>|' . $spaces . ')/' ] = $apos_flag . '$1' . $closing_quote;
+ }
+
+ // '99 '99s '99's (apostrophe) But never '9 or '99% or '999 or '99.0.
+ if ( "'" !== $apos ) {
+ $dynamic[ '/\'(?=\d\d(?:\Z|(?![%\d]|[.,]\d)))/' ] = $apos_flag;
+ }
+
+ // Quoted Numbers like '0.42'
+ if ( "'" !== $opening_single_quote && "'" !== $closing_single_quote ) {
+ $dynamic[ '/(?<=\A|' . $spaces . ')\'(\d[.,\d]*)\'/' ] = $open_sq_flag . '$1' . $closing_single_quote;
}
- $static_characters = array_merge( array( '---', ' -- ', '--', ' - ', 'xn–', '...', '``', '\'\'', ' (tm)' ), $cockney );
- $static_replacements = array_merge( array( $em_dash, ' ' . $em_dash . ' ', $en_dash, ' ' . $en_dash . ' ', 'xn--', '…', $opening_quote, $closing_quote, ' ™' ), $cockneyreplace );
+ // Single quote at start, or preceded by (, {, <, [, ", -, or spaces.
+ if ( "'" !== $opening_single_quote ) {
+ $dynamic[ '/(?<=\A|[([{"\-]|<|' . $spaces . ')\'/' ] = $open_sq_flag;
+ }
+
+ // Apostrophe in a word. No spaces, double apostrophes, or other punctuation.
+ if ( "'" !== $apos ) {
+ $dynamic[ '/(?|\[.*\])/Us', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
+ // Look for shortcodes and HTML elements.
- foreach ( $textarr as &$curl ) {
- if ( empty( $curl ) )
- continue;
+ preg_match_all( '@\[/?([^<>&/\[\]\x00-\x20=]++)@', $text, $matches );
+ $tagnames = array_intersect( array_keys( $shortcode_tags ), $matches[1] );
+ $found_shortcodes = ! empty( $tagnames );
+ $shortcode_regex = $found_shortcodes ? _get_wptexturize_shortcode_regex( $tagnames ) : '';
+ $regex = _get_wptexturize_split_regex( $shortcode_regex );
- // Only call _wptexturize_pushpop_element if first char is correct tag opening
+ $textarr = preg_split( $regex, $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
+
+ foreach ( $textarr as &$curl ) {
+ // Only call _wptexturize_pushpop_element if $curl is a delimiter.
$first = $curl[0];
if ( '<' === $first ) {
- _wptexturize_pushpop_element($curl, $no_texturize_tags_stack, $no_texturize_tags, '<', '>');
- } elseif ( '[' === $first ) {
- _wptexturize_pushpop_element($curl, $no_texturize_shortcodes_stack, $no_texturize_shortcodes, '[', ']');
- } elseif ( empty($no_texturize_shortcodes_stack) && empty($no_texturize_tags_stack) ) {
- // This is not a tag, nor is the texturization disabled static strings
- $curl = str_replace($static_characters, $static_replacements, $curl);
- // regular expressions
- $curl = preg_replace($dynamic_characters, $dynamic_replacements, $curl);
+ if ( '';
+ $quote_pattern = "/$needle(?=\\Z|[.,:;!?)}\\-\\]]|>|" . $spaces . ")/";
+ $prime_pattern = "/(?<=\\d)$needle/";
+ $flag_after_digit = "/(?<=\\d)$flag/";
+ $flag_no_digit = "/(? &$sentence ) {
+ if ( false === strpos( $sentence, $needle ) ) {
+ continue;
+ } elseif ( 0 !== $key && 0 === substr_count( $sentence, $close_quote ) ) {
+ $sentence = preg_replace( $quote_pattern, $flag, $sentence, -1, $count );
+ if ( $count > 1 ) {
+ // This sentence appears to have multiple closing quotes. Attempt Vulcan logic.
+ $sentence = preg_replace( $flag_no_digit, $close_quote, $sentence, -1, $count2 );
+ if ( 0 === $count2 ) {
+ // Try looking for a quote followed by a period.
+ $count2 = substr_count( $sentence, "$flag." );
+ if ( $count2 > 0 ) {
+ // Assume the rightmost quote-period match is the end of quotation.
+ $pos = strrpos( $sentence, "$flag." );
+ } else {
+ // When all else fails, make the rightmost candidate a closing quote.
+ // This is most likely to be problematic in the context of bug #18549.
+ $pos = strrpos( $sentence, $flag );
+ }
+ $sentence = substr_replace( $sentence, $close_quote, $pos, strlen( $flag ) );
+ }
+ // Use conventional replacement on any remaining primes and quotes.
+ $sentence = preg_replace( $prime_pattern, $prime, $sentence );
+ $sentence = preg_replace( $flag_after_digit, $prime, $sentence );
+ $sentence = str_replace( $flag, $close_quote, $sentence );
+ } elseif ( 1 == $count ) {
+ // Found only one closing quote candidate, so give it priority over primes.
+ $sentence = str_replace( $flag, $close_quote, $sentence );
+ $sentence = preg_replace( $prime_pattern, $prime, $sentence );
+ } else {
+ // No closing quotes found. Just run primes pattern.
+ $sentence = preg_replace( $prime_pattern, $prime, $sentence );
+ }
+ } else {
+ $sentence = preg_replace( $prime_pattern, $prime, $sentence );
+ $sentence = preg_replace( $quote_pattern, $close_quote, $sentence );
+ }
+ if ( '"' == $needle && false !== strpos( $sentence, '"' ) ) {
+ $sentence = str_replace( '"', $close_quote, $sentence );
+ }
+ }
+
+ return implode( $open_quote, $sentences );
+}
+
/**
* Search for disabled element tags. Push element to stack on tag open and pop
- * on tag close. Assumes first character of $text is tag opening.
+ * on tag close.
+ *
+ * Assumes first char of $text is tag opening and last char is tag closing.
+ * Assumes second char of $text is optionally '/' to indicate closing as in