Skip to content

Instantly share code, notes, and snippets.

@pagelab
Last active August 20, 2022 04:10
Show Gist options
  • Save pagelab/50b9b3f3f972a72636eb6f757d588068 to your computer and use it in GitHub Desktop.
Save pagelab/50b9b3f3f972a72636eb6f757d588068 to your computer and use it in GitHub Desktop.
Adding a class to external links in content blocks.
<?php
namespace MyPlugin;
// Adds a class to external links in content blocks.
add_filter( 'render_block', __NAMESPACE__ . '\\add_class_external_links', 10, 2 );
/**
* Adds a CSS class to external links in content blocks.
*
* @link https://developer.wordpress.org/reference/hooks/render_block/
* @param $block_content string The block content about to be appended.
* @param $block array The full block, including name and attributes.
* @return string
*/
function add_class_external_links( $block_content, $block ) {
// List of content blocks.
$blocks = [
'core/heading',
'core/paragraph',
'core/quote',
'core/pullquote',
'core/preformatted',
'core/list',
'core/table',
];
// Cancel early if necessary.
if ( ! in_array( $block['blockName'], $blocks ) ) return $block_content;
// Get this domain.
$url = parse_url( site_url() );
$domain = $url['host'];
// Let's start the content parser.
$dom = new \DOMDocument('5.0', 'utf-8');
// Enable libxml errors.
$internal_errors = libxml_use_internal_errors( true );
// Need to force conversion to specific encoding standard to prevent errors.
$dom->loadHTML( mb_convert_encoding( $block_content, 'HTML-ENTITIES', 'UTF-8' ) );
libxml_use_internal_errors( $internal_errors );
$xpath = new \DOMXPath( $dom );
// Find all links that does not include this site's domain.
$links = $xpath->query( "//a[not(contains(@href, '$domain'))]" );
// If there are links to an external domain.
if ( ! is_null( $xpath->query( "//a[not(contains(@href, $domain))]" ) ) ) {
// Add the class to the link.
foreach( $links as $link ) {
$link->setAttribute( 'class','epc-external-link' );
}
// Save the block content.
$block_content = $dom->saveHTML($dom->documentElement);
}
// Return the original block content.
return $block_content;
}
@pagelab
Copy link
Author

pagelab commented Aug 20, 2022

/**
 *
 * Style external links
 *
 */
.epc-external-link::after {
	padding: 0px;
	content: '';
	width: 16px;
	height: 16px;
	display: inline-block;
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='16' height='16'%3E%3Cpath d='M10 6v2H5v11h11v-5h2v6a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h6zm11-3v8h-2V6.413l-7.793 7.794-1.414-1.414L17.585 5H13V3h8z' fill='rgba(50,152,219,1)'/%3E%3C/svg%3E");
	mask-position: center;
	mask-repeat: no-repeat;
	background-color: currentColor;
    margin-left: 0.2rem;
}

.entry-content .epc-external-link {
	position: relative;
}

.entry-content .epc-external-link::before {
	text-transform: none;
	letter-spacing: 0;
	font-weight: normal;
	font-family: var(--wp--preset--font-family--system);
	font-size: var(--wp--preset--font-size--small);
	line-height: var(--wp--custom--typography--line-height--small);
    content:  '↪ ' attr(href);
    position: absolute;
    top: -2rem;
    background-color: transparent;
    color: transparent;
    border: thin solid transparent;
    border-radius: .3rem;
    padding: .3rem .7rem .3rem .5rem;
    font-size: .9rem;
    pointer-events: none;
    user-select: none;
    max-width: 15rem;
 	white-space: nowrap;
  	overflow: hidden;
  	text-overflow: ellipsis;
  	transition: background-color 200ms, color 200ms, border-color 200ms;
}

.entry-content .epc-external-link:hover::before {
    background-color: var(--wp--preset--color--background);
    color: var(--wp--preset--color--foreground);
    border-color: var(--wp--preset--color--foreground);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment