a|img|iframe|video|audio|source' . '|embed)\b[^>]*>#i'; private const MARKED_PATTERN = '#<[a-z]+ ' . self::ATTRIBUTE . '=#i'; private const ANCHOR = ''; private const FIRST_ONLY = 1; public function __construct( private AddressMatch $address_match ) { } public function mark( string $content, string $link_url, string $label ): string { return (string) preg_replace_callback( self::TAG_PATTERN, fn( array $tag ): string => $this->marked_tag( $tag[0], $tag['name'], $link_url, $label ), $content ); } public function with_anchor( string $marked_content ): string { return (string) preg_replace( self::MARKED_PATTERN, self::ANCHOR . '$0', $marked_content, self::FIRST_ONLY ); } private function marked_tag( string $tag, string $tag_name, string $link_url, string $label ): string { if ( ! $this->address_match->tag_points_to( $tag, $link_url ) ) { return $tag; } $name_end = strlen( $tag_name ) + 1; return substr( $tag, 0, $name_end ) . ' ' . self::ATTRIBUTE . '="' . esc_attr( $label ) . '"' . substr( $tag, $name_end ); } }