Skip to content

Instantly share code, notes, and snippets.

@pagelab
Last active March 28, 2024 19:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save pagelab/9087ecbdc49023a7a0f5f3718205b0cd to your computer and use it in GitHub Desktop.
Save pagelab/9087ecbdc49023a7a0f5f3718205b0cd to your computer and use it in GitHub Desktop.
Add clickable anchor icons with links in all core/paragraph blocks.
<?php
namespace MyPlugin;
add_filter( 'render_block_core/heading', __NAMESPACE__ . '\\add_anchor_icon', 10, 2 );
/**
* Add clickable anchor icons to all core/paragragh blocks.
*
* @param string $block_content The block content about to be appended.
* @param array $block The full block, including name and attributes.
* @return string Modified block content.
*/
function add_anchor_icon( $block_content, $block ) {
// Let's start the content parser.
$dom = new \DOMDocument('5.0', 'utf-8');
// Need to force conversion to specific encoding standard to prevent errors.
$internal_errors = libxml_use_internal_errors( true );
@$dom->loadHTML( mb_convert_encoding( $block_content, 'HTML-ENTITIES', 'UTF-8' ) );
libxml_use_internal_errors( $internal_errors );
// Let's use XPath to find headings.
$xpath = new \DOMXPath( $dom );
// Find heading elements.
$headings = $xpath->query( "//h1|//h2|//h3|//h4|//h5|//h6" );
// Iterate.
foreach ( $headings as $heading ) {
// Get the heading ID.
$id = $heading->getAttribute('id');
// Create the link element.
$link = $dom->createElement( 'a' );
// Set link attributes (class and href).
$link->setAttribute( 'class', 'epc-anchor-link' );
$link->setAttribute( 'href', '#' . esc_attr( $id ) );
// Define the HTML fragment with the icon.
$fragment = '<span aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" class="epc-anchor-icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2.5" stroke="var(--wp--preset--color--links)" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><line x1="5" y1="9" x2="19" y2="9"></line><line x1="5" y1="15" x2="19" y2="15"></line><line x1="11" y1="4" x2="7" y2="20"></line><line x1="17" y1="4" x2="13" y2="20"></line></svg></span><span class="epc-visually-hidden">(permalink)</span>';
// Append the fragment to the link element.
$append = $dom->createDocumentFragment();
$append->appendXML( $fragment );
$link->appendChild( $append );
// Append the link to the heading.
$heading->appendChild( $link );
// Save the document.
$block_content = $dom->saveHTML($dom->documentElement);
}
// Return the changed block content.
return $block_content;
}
@pagelab
Copy link
Author

pagelab commented Aug 20, 2022

.epc-visually-hidden {
    position: absolute;
    width: 1px;
    clip: rect(0 0 0 0);
    overflow: hidden;
    white-space: nowrap;
}

.epc-anchor-link {
	position: relative;
    top: 0.2rem;
}

.epc-anchor-link:hover {
	text-decoration: none;
}

@pagelab
Copy link
Author

pagelab commented Aug 22, 2022

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