WordPress Version: 5.3
/**
* Callback to add rel="noreferrer noopener" string to HTML A element.
*
* Will not duplicate existing noreferrer and noopener values
* to prevent from invalidating the HTML.
*
* @since 5.1.0
*
* @param array $matches Single Match
* @return string HTML A Element with rel noreferrer noopener in addition to any existing values
*/
function wp_targeted_link_rel_callback($matches)
{
$link_html = $matches[1];
$rel_match = array();
/**
* Filters the rel values that are added to links with `target` attribute.
*
* @since 5.1.0
*
* @param string $rel The rel values.
* @param string $link_html The matched content of the link tag including all HTML attributes.
*/
$rel = apply_filters('wp_targeted_link_rel', 'noopener noreferrer', $link_html);
// Avoid additional regex if the filter removes rel values.
if (!$rel) {
return "<a {$link_html}>";
}
// Value with delimiters, spaces around are optional.
$attr_regex = '|rel\s*=\s*?(\\\\{0,1}["\'])(.*?)\1|i';
preg_match($attr_regex, $link_html, $rel_match);
if (empty($rel_match[0])) {
// No delimiters, try with a single value and spaces, because `rel = va"lue` is totally fine...
$attr_regex = '|rel\s*=(\s*)([^\s]*)|i';
preg_match($attr_regex, $link_html, $rel_match);
}
if (!empty($rel_match[0])) {
$parts = preg_split('|\s+|', strtolower($rel_match[2]));
$parts = array_map('esc_attr', $parts);
$needed = explode(' ', $rel);
$parts = array_unique(array_merge($parts, $needed));
$delimiter = trim($rel_match[1]) ? $rel_match[1] : '"';
$rel = 'rel=' . $delimiter . trim(implode(' ', $parts)) . $delimiter;
$link_html = str_replace($rel_match[0], $rel, $link_html);
} elseif (preg_match('|target\s*=\s*?\\\\"|', $link_html)) {
$link_html .= " rel=\\\"{$rel}\\\"";
} elseif (preg_match('#(target|href)\s*=\s*?\'#', $link_html)) {
$link_html .= " rel='{$rel}'";
} else {
$link_html .= " rel=\"{$rel}\"";
}
return "<a {$link_html}>";
}