Changeset 2814 for sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/inc/formatting.php
- Timestamp:
- 03/25/2016 06:22:12 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/inc/formatting.php
r2452 r2814 27 27 add_filter( 'the_excerpt', array( __CLASS__, 'remove_inline_internal' ) ); 28 28 add_filter( 'the_content', array( __CLASS__, 'remove_inline_internal' ) ); 29 30 add_filter( 'the_excerpt', array( __CLASS__, 'autolink_references' ), 11 ); 31 add_filter( 'the_content', array( __CLASS__, 'autolink_references' ), 11 ); 29 32 30 33 add_action( 'the_content', array( __CLASS__, 'fix_unintended_markdown' ) ); … … 237 240 } 238 241 242 /** 243 * Automatically detects inline references to parsed resources and links to them. 244 * 245 * Examples: 246 * - Functions: get_the_ID() 247 * - Classes: WP_Query 248 * - Methods: WP_Query::is_single() 249 * 250 * Note: currently there is not a reliable way to infer references to hooks. Recommend 251 * using the {@}see 'hook_name'} notation as used in the inline docs. 252 * 253 * @param string $text The text. 254 * @return string 255 */ 256 public function autolink_references( $text ) { 257 $r = ''; 258 $textarr = preg_split( '/(<[^<>]+>)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // split out HTML tags 259 $nested_code_pre = 0; // Keep track of how many levels link is nested inside <pre> or <code> 260 foreach ( $textarr as $piece ) { 261 262 if ( preg_match( '|^<code[\s>]|i', $piece ) || preg_match( '|^<pre[\s>]|i', $piece ) || preg_match( '|^<script[\s>]|i', $piece ) || preg_match( '|^<style[\s>]|i', $piece ) ) 263 $nested_code_pre++; 264 elseif ( $nested_code_pre && ( '</code>' === strtolower( $piece ) || '</pre>' === strtolower( $piece ) || '</script>' === strtolower( $piece ) || '</style>' === strtolower( $piece ) ) ) 265 $nested_code_pre--; 266 267 if ( $nested_code_pre || empty( $piece ) || ( $piece[0] === '<' && ! preg_match( '|^<\s*[\w]{1,20}+://|', $piece ) ) ) { 268 $r .= $piece; 269 continue; 270 } 271 272 // Long strings might contain expensive edge cases ... 273 if ( 10000 < strlen( $piece ) ) { 274 // ... break it up 275 foreach ( _split_str_by_whitespace( $piece, 2100 ) as $chunk ) { // 2100: Extra room for scheme and leading and trailing paretheses 276 if ( 2101 < strlen( $chunk ) ) { 277 $r .= $chunk; // Too big, no whitespace: bail. 278 } else { 279 $r .= make_clickable( $chunk ); 280 } 281 } 282 } else { 283 /* 284 * Everthing outside of this conditional block was copied from core's 285 *`make_clickable()`. 286 */ 287 288 $content = " $piece "; // Pad with whitespace to simplify the regexes 289 290 // Only if the text contains something that might be a function. 291 if ( false !== strpos( $content, '()' ) ) { 292 293 // Detect references to class methods, e.g. WP_Query::query() 294 // or functions, e.g. register_post_type(). 295 $content = preg_replace_callback( 296 '~ 297 (?!<.*?) # Non-capturing check to ensure not matching what looks like the inside of an HTML tag. 298 ( # 1: The full method or function name. 299 ((\w+)::)? # 2: The class prefix, if a method reference. 300 (\w+) # 3: The method or function name. 301 ) 302 \(\) # The () that signifies either a method or function. 303 (?![^<>]*?>) # Non-capturing check to ensure not matching what looks like the inside of an HTML tag. 304 ~x', 305 function ( $matches ) { 306 // Reference to a class method. 307 if ( $matches[2] ) { 308 // Only link actually parsed methods. 309 if ( $post = get_page_by_title( $matches[1], OBJECT, 'wp-parser-method' ) ) { 310 return sprintf( 311 '<a href="%s">%s</a>', 312 get_permalink( $post->ID ), 313 $matches[0] 314 ); 315 } 316 317 // Reference to a function. 318 } else { 319 // Only link actually parsed functions. 320 if ( $post = get_page_by_title( $matches[1], OBJECT, 'wp-parser-function' ) ) { 321 return sprintf( 322 '<a href="%s">%s</a>', 323 get_permalink( $post->ID ), 324 $matches[0] 325 ); 326 } 327 } 328 329 // It's not a reference to an actual thing, so restore original text. 330 return $matches[0]; 331 }, 332 $content 333 ); 334 335 } 336 337 // Detect references to classes, e.g. WP_Query 338 $content = preg_replace_callback( 339 // Most class names start with an uppercase letter and have an underscore. 340 // The exceptions are explicitly listed since future classes likely won't violate previous statement. 341 '~' 342 . '(?<!/)' 343 . '\b' // Word boundary 344 . '(' // Primary match grouping 345 . 'wpdb|wp_atom_server|wp_xmlrpc_server extends IXR_Server' // Exceptions that start with lowercase letter 346 . '|AtomFeed|AtomEntry|AtomParser|MagpieRSS|RSSCache|Translations|Walker' // Exceptions that lack an underscore 347 . '|[A-Z][a-zA-Z]+_\w+' // Most start with uppercase, has underscore 348 . ')' // End primary match grouping 349 . '\b' // Word boundary 350 . '(?!([<:]|"|\'>))' // Does not appear within a tag 351 . '~', 352 function ( $matches ) { 353 // If match is all caps, it's not a possible class name. 354 // We'll chalk the sole exception, WP, as merely being an abbreviation (the regex won't match it anyhow). 355 if ( strtoupper( $matches[0] ) === $matches[0] ) { 356 return $matches[0]; 357 } 358 359 // Only link actually parsed classes. 360 if ( $post = get_page_by_title( $matches[0], OBJECT, 'wp-parser-class' ) ) { 361 return sprintf( 362 '<a href="%s">%s</a>', 363 get_permalink( $post->ID ), 364 $matches[0] 365 ); 366 } 367 368 // Not a class reference, so put the original reference back in. 369 return $matches[0]; 370 }, 371 $content 372 ); 373 374 // Maybelater: Detect references to hooks, Currently not deemed reliably possible. 375 376 $content = substr( $content, 1, -1 ); // Remove our whitespace padding. 377 $r .= $content; 378 379 } // end else 380 381 } // end foreach 382 383 // Cleanup of accidental links within links 384 return preg_replace( '#(<a([ \r\n\t]+[^>]+?>|>))<a [^>]+?>([^>]+?)</a></a>#i', "$1$3</a>", $r ); 385 } 386 239 387 } // DevHub_Formatting 240 388
Note: See TracChangeset
for help on using the changeset viewer.