The only easy way I can think of without hacking the parser code would be a plugin. I think you could attach the plugin to OnWebPagePrerender.
Something like this:
if (strpos($modx->resource->_output, '_blank') !== false) {
$modx->resource->_output = str_replace('target="_blank"', 'target="_blank" rel="noopener noreferrer" ', $modx->resource_output);
}
return;
(The noreferrer is to make it work in Firefox.)
This will slow down your page loads a little. A better method would be to search the site and modify all the resources, templates, and chunks, although that wouldn't fix any hrefs created dynamically in code.
A snippet to make the modifications would look like this (tested):
/* FixHref snippet */
$objectTypes = array(
'modResource' => 'pagetitle',
'modChunk' => 'name',
'modTemplate' => 'name',
);
$count = 0;
$nl = (php_sapi_name() == 'cli')? "\n" : "<br>";
$output = '';
$typeCounts = array();
foreach ($objectTypes as $type => $nameAlias) {
$typeCounts[$type] = 0;
$objs = $modx->getCollection($type);
foreach ($objs as $obj) {
if ($obj->get('class_key') === 'Article') {
$content = $obj->get('content');
} else {
$content = $obj->getContent();
}
if (empty($content)) {
// $modx->log(modX::LOG_LEVEL_ERROR, 'Could not get content for ' . $type . ' ' . $obj->get('id'));
continue;
}
if ((strpos($content, '_blank') !== false) && (strpos($content, 'noopener') === false)) {
$pattern = '/target\s*=\s*[\'"]_blank[\'"]/i';
$newContent = preg_replace($pattern, 'target="_blank" rel="noopener noreferrer" ', $content);
$obj->setContent($newContent);
if ($obj->save()) {
if ($content !== $newContent) {
$output .= $nl . 'Modified ' . $type . ' ' . $obj->get($nameAlias);
} else {
$output .= $nl . 'Failed to modify ' . $type . ' ' . $obj->get($nameAlias);
}
}
$typeCounts[$type]++;
$count++;
}
}
}
$output .= $nl . "Finished -- found " . $count . " total objects with _blank and not noopener" . $nl;
$output .= "Changed: " . $nl . print_r($typeCounts, true);
if (php_sapi_name() == 'cli') {
echo $output;
} else {
return $output;
}
I would back up the DB before running this, just in case.
[ed. note: BobRay last edited this post 6 years, 1 month ago.]