Iconseasy_svg_icon_markup

easy_svg_icon_markup

Filter the SVG markup of one icon before easy_svg_icon() and the shortcode print it, or serve a whole icon collection of your own through them.

Filter · Easy SVG · Status: Stable

easy_svg_icon_markup lets you change the SVG of one icon right before easy_svg_icon() or the [easy_svg_icon] shortcode prints it. You can tweak the plugin's own icons, or answer for a collection Easy SVG does not know, so easy_svg_icon( 'acme/logo' ) prints your add-on's icon.

Usage

add_filter( 'easy_svg_icon_markup', 'myplugin_icon_markup', 10, 3 );

function myplugin_icon_markup( string $markup, string $slug, string $collection ): string {
	return $markup;
}

When to use it

  • Add a title element, a width and height, or a data attribute to icons on their way into templates.
  • Serve your own collection (an add-on, a theme folder of SVG files) through the one template tag and shortcode the site already uses.
  • Swap one icon for another on a specific site without touching templates.

When not to use it:

  • To change what the core Icon block or wp_get_icon() draws. Those read the markup handed to the WordPress icon registry at init; use easy_svg_registrable_icons for that.
  • To add a CSS class or ARIA attributes. Pass class and label to easy_svg_icon(); the function adds those after this filter ran.

Parameters

body
$markupstring
Required

For the easy-svg collection: the stored post_content of the esw_icon post with that slug, which is sanitized and hardened markup, or an empty string when no such icon exists. For every other collection: always an empty string, so your callback supplies the icon.

body
$slugstring
Required

The part of the name after the first slash, as the caller wrote it, unvalidated. easy_svg_icon( 'acme/logo' ) passes logo; easy_svg_icon( 'heart' ) passes heart. Treat it as untrusted input: in a shortcode it comes from whoever wrote the post.

body
$collectionstring
Required

The part before the first slash, or easy-svg when the name had none.

Return value

returnstring

The markup to use. It is cast to string. An empty string means "no icon": easy_svg_icon() then returns an empty string and adds no attributes. Anything else is printed as it is, after easy_svg_icon() inserted its class and ARIA attributes into the first svg tag.

Default

The stored markup for easy-svg icons, an empty string for anything else.

Examples

Give one icon a fixed size

add_filter( 'easy_svg_icon_markup', 'mytheme_size_logo_icon', 10, 3 );

function mytheme_size_logo_icon( $markup, $slug, $collection ) {
	if ( 'easy-svg' !== $collection || 'logo' !== $slug || '' === $markup ) {
		return $markup;
	}

	return preg_replace( '/^(\s*<svg)\b/i', '$1 width="120" height="32"', $markup, 1 );
}

Only touch the markup you recognise, and always return the original otherwise.

Serve a collection from your theme

Files live in wp-content/themes/mytheme/icons/*.svg. easy_svg_icon( 'mytheme/arrow' ) and [easy_svg_icon name="mytheme/arrow"] then print icons/arrow.svg, cleaned the same way the plugin cleans its own icons.

add_filter( 'easy_svg_icon_markup', 'mytheme_icon_collection', 10, 3 );

function mytheme_icon_collection( $markup, $slug, $collection ) {
	if ( 'mytheme' !== $collection || '' !== $markup ) {
		return $markup;
	}

	// The slug is user input: only names Easy SVG itself would accept.
	if ( ! defined( 'EASY_SVG_ICON_NAME_PATTERN' ) || 1 !== preg_match( EASY_SVG_ICON_NAME_PATTERN, $slug ) ) {
		return '';
	}

	$cache_key = 'mytheme_icon_' . $slug;
	$cached    = wp_cache_get( $cache_key, 'mytheme' );
	if ( false !== $cached ) {
		return $cached;
	}

	$file = get_theme_file_path( 'icons/' . $slug . '.svg' );
	if ( ! is_readable( $file ) ) {
		return '';
	}

	$sanitizer = function_exists( 'easy_svg_sanitizer' ) ? easy_svg_sanitizer() : null;
	if ( null === $sanitizer || ! function_exists( 'easy_svg_harden_icon_markup' ) ) {
		return '';
	}

	$clean = $sanitizer->sanitize( (string) file_get_contents( $file ) );
	$clean = is_string( $clean ) ? easy_svg_harden_icon_markup( $clean ) : '';

	wp_cache_set( $cache_key, $clean, 'mytheme', HOUR_IN_SECONDS );

	return $clean;
}

Add a title for tooltips

A title child shows as a tooltip on hover. Keep it in addition to label, not instead of it.

add_filter( 'easy_svg_icon_markup', 'myplugin_icon_title', 10, 3 );

function myplugin_icon_title( $markup, $slug, $collection ) {
	if ( 'easy-svg' !== $collection || 'info' !== $slug || '' === $markup ) {
		return $markup;
	}

	$title = '<title>' . esc_html__( 'More information', 'myplugin' ) . '</title>';

	return preg_replace( '/(<svg\b[^>]*>)/i', '$1' . $title, $markup, 1 );
}

Defensive: only on a plugin that has the filter

add_action( 'plugins_loaded', 'myplugin_hook_icons' );

function myplugin_hook_icons() {
	if ( ! function_exists( 'easy_svg_icon' ) ) {
		return; // Easy SVG is not active.
	}
	add_filter( 'easy_svg_icon_markup', 'myplugin_icon_title', 10, 3 );
}

Whatever your callback returns is printed without escaping, into every page that uses the icon. Never return markup from a request, a user field or a remote URL without cleaning it. Run your own SVG through easy_svg_sanitizer() and then easy_svg_harden_icon_markup(), as the theme collection example does; the hardener removes script, style, foreignObject, animation elements, every on attribute and every href that does not point inside the drawing. And validate $slug before you build a file path from it: ../ in a shortcode attribute is a path traversal.

How it works

The filter runs inside easy_svg_icon_markup(), which every render path calls:

  • It fires once per call to easy_svg_icon(), so once per rendered icon. Nothing caches the filtered result; cache expensive work yourself, as the theme collection example does.
  • It fires whether or not the icon library switch is on, and on every WordPress version, because the template tag needs no core icon registry.
  • The core Icon block and wp_get_icon() never run it.
  • Easy SVG Pro uses this same filter to serve its own collections through easy_svg_icon().

Pitfalls

  • Forgetting the default return. A callback that returns nothing (or null) for icons it does not handle turns every icon on the site into an empty string. Return $markup on every path.
  • Accepted args. Register with 10, 3, or $slug and $collection never arrive.
  • Adding class here. easy_svg_icon() inserts its own class attribute in front of yours when the caller passes one, and browsers keep the first of two class attributes. Let callers pass the class.
  • Filling an empty easy-svg icon. Returning markup for a missing easy-svg slug works for the template tag but not for the Icon block, so editors and themes see different things.
  • Expensive callbacks. A page with 40 icons calls you 40 times.