wp-includes/html-api/class-wp-html-decoder.php:258Attempt to read a character reference at the given location in a given string, depending on the context in which it's found.
…
null === WP_HTML_Decoder::read_character_reference( 'attribute', '&notin', 0 );
'∉' === WP_HTML_Decoder::read_character_reference( 'attribute', '∉', 0, $token_length );
7 === $token_length; // ∉
'¬' === WP_HTML_Decoder::read_character_reference( 'data', '&notin', 0, $token_length );
4 === $token_length; // &not
'∉' === WP_HTML_Decoder::read_character_reference( 'data', '∉', 0, $token_length );
7 === $token_length; // &notin;$contextstring$textstring$atintoptional0$match_byte_lengthoptionalnull?string public static function read_character_reference( $context, $text, $at = 0, &$match_byte_length = null ) { /** * Mappings for HTML5 named character references. * * @var WP_Token_Map $html5_named_character_references */ global $html5_named_character_references; $length = strlen( $text ); if ( $at + 1 >= $length ) { return null; } if ( '&' !== $text[ $at ] ) { return null; } /* * Numeric character references. * * When truncated, these will encode the code point found by parsing the * digits that are available. For example, when `🅰` is truncated * to `DZ` it will encode `DZ`. It does not: * - know how to parse the original `🅰`. * - fail to parse and return plaintext `DZ`. * - fail to parse and return the replacement character `�` */ if ( '#' === $text[ $at + 1 ] ) { if ( $at + 2 >= $length ) { return null; } /** Tracks inner parsing within the numeric character reference. */ $digits_at = $at + 2; if ( 'x' === $text[ $digits_at ] || 'X' === $text[ $digits_at ] ) { $numeric_base = 16; $numeric_digits = '0123456789abcdefABCDEF'; $max_digits = 6; //  ++$digits_at; } else { $numeric_base = 10; $numeric_digits = '0123456789'; $max_digits = 7; //  } // Cannot encode invalid Unicode code points. Max is to U+10FFFF. $zero_count = strspn( $text, '0', $digits_at ); $digit_count = strspn( $text, $numeric_digits, $digits_at + $zero_count ); $after_digits = $digits_at + $zero_count + $digit_count; $has_semicolon = $after_digits < $length && ';' === $text[ $after_digits ]; $end_of_span = $has_semicolon ? $after_digits + 1 : $after_digits; // `&#` or `&#x` without digits returns into plaintext. if ( 0 === $digit_count && 0 === $zero_count ) { return null; } // Whereas `&#` and only zeros is invalid. if ( 0 === $digit_count ) { $match_byte_length = $end_of_span - $at; return '�'; } // If there are too many digits then it's not worth parsing. It's invalid. if ( $digit_count > $max_digits ) { $match_byte_length = $end_of_span - $at; return '�'; } $digits = substr( $text, $digits_at + $zero_count, $digit_count ); $code_point = intval( $digits, $numeric_base ); /* * Noncharacters, 0x0D, and non-ASCII-whitespace control characters. * * > A noncharacter is a code point that is in the range U+FDD0 to U+FDEF, * > inclusive, or U+FFFE, U+FFFF, U+1FFFE, U+1FFFF, U+2FFFE, U+2FFFF, * > U+3FFFE, U+3FFFF, U+4FFFE, U+4FFFF, U+5FFFE, U+5FFFF, U+6FFFE, * > U+6FFFF, U+7FFFE, U+7FFFF, U+8FFFE, U+8FFFF, U+9FFFE, U+9FFFF,Introduced in 6.6.0. One change between 6.7.7 and 7.1.0.
Signature, return type and hooks compared across 5 parsed releases.
string|false to ?string.verified against sourcesrc/wp-includes/html-api/class-wp-html-decoder.php, and regenerated for each WordPress release so it tracks the code rather than a snapshot of it.