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
titleelement, awidthandheight, 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 atinit; useeasy_svg_registrable_iconsfor that. - To add a CSS class or ARIA attributes. Pass
classandlabeltoeasy_svg_icon(); the function adds those after this filter ran.
Parameters
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.
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.
The part before the first slash, or easy-svg when the name had none.
Return value
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$markupon every path. - Accepted args. Register with
10, 3, or$slugand$collectionnever arrive. - Adding
classhere.easy_svg_icon()inserts its ownclassattribute in front of yours when the caller passes one, and browsers keep the first of twoclassattributes. Let callers pass the class. - Filling an empty
easy-svgicon. Returning markup for a missingeasy-svgslug 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.