You have to watch editor changes, you can hook the js to ‘enqueue_block_editor_assets’.
your-child-theme/js/default-open-in-new-tab.js
wp.domReady(() => {
//console.log("Custom script loaded");
const { subscribe } = wp.data; //we want to subscribe to changes of the editor
// Helper function to determine if a URL is external
const isExternalLink = (url) => {
try {
const domain = (new URL(url)).hostname;
return domain !== window.location.hostname;
} catch (e) {
return false;
}
};
const updateLinksToOpenInNewTab = () => {
const blocks = wp.data.select('core/block-editor').getBlocks();
blocks.forEach((block) => {
if (block.attributes && block.attributes.content) {
const parser = new DOMParser();
const doc = parser.parseFromString(block.attributes.content, 'text/html');
const links = doc.querySelectorAll('a');
links.forEach((link) => {
const href = link.getAttribute('href');
if (href && isExternalLink(href)) {
link.setAttribute('target', '_blank');
link.setAttribute('rel', 'noreferrer noopener');
}
});
const updatedContent = doc.body.innerHTML;
if (updatedContent !== block.attributes.content) {
wp.data.dispatch('core/block-editor').updateBlockAttributes(block.clientId, {
content: updatedContent
});
}
}
});
};
subscribe(() => {
updateLinksToOpenInNewTab(); // when editor's state changes, this happens
});
// console.log("Subscription added to update links to open in new tab.");
});
functions.php
function enqueue_custom_editor_script() {
wp_enqueue_script(
'default-open-in-new-tab',
get_stylesheet_directory_uri() . '/js/default-open-in-new-tab.js',
array( 'wp-hooks', 'wp-element', 'wp-dom-ready', 'wp-edit-post' ),
filemtime( get_stylesheet_directory() . '/js/default-open-in-new-tab.js' ),
true
);
}
add_action( 'enqueue_block_editor_assets', 'enqueue_custom_editor_script' );
Got this together thanks to ChatGPT4. It would be probably a more native way to write it in JSX and have it compiled by Babel.