esw_svg_allowed_attributes
Filter the attribute names Easy SVG keeps on SVG elements: allow a presentation attribute your exports need, or remove ones your site never wants.
Filter · Easy SVG · Status: Stable
When Easy SVG cleans an SVG, every attribute whose name is not on an allow-list is removed from its element. This filter gives you that list. Add an attribute a design tool writes and your files keep it, take one out and it is stripped from every SVG the site stores from then on.
Usage
apply_filters( 'esw_svg_allowed_attributes', array $attributes )
add_filter( 'esw_svg_allowed_attributes', 'myplugin_svg_attributes' );
When to use it
- An exporter writes a presentation attribute the library does not know yet, such as
transform-originormask-type, and the drawing looks different after upload. - You need an accessibility attribute that is not covered by the built-in
aria-*rule, for examplefocusable. - Your policy is stricter than the default and you want HTML-only attributes such as
srcorsrcsetgone from every SVG.
Do not use it:
- For event handlers. Nothing that starts with
onbelongs on this list. - To keep or remove
aria-*ordata-*attributes. The library keeps those on its own, whatever the list says. - To keep editor metadata such as
inkscape:label. It is safe to lose and only makes files bigger.
Parameters
A flat, numerically indexed array of attribute names, for example array( 'about', 'accept', 'action', ... ). Without other callbacks it is the default list of the bundled enshrined/svg-sanitize library: 328 entries in version 1.0.0, covering HTML, SVG, MathML and a few XML names such as xlink:href and xml:space. Names are matched case-insensitively against the attribute name as written, prefix included (xlink:href, inkscape:label).
Return value
The attribute names the sanitizer may keep. It must be an array. Returning anything else makes the library throw a TypeError while the sanitizer is built, and the upload ends with a fatal error.
Default
The AllowedAttributes list of enshrined/svg-sanitize 1.0.0, unchanged. Useful to know:
- Already on it:
id,class,style,role,tabindex,href,xlink:href,viewbox,preserveaspectratio,transform, every common presentation attribute (fill,stroke,stroke-width,opacity,clip-path,mask,filter, font attributes) and the animation timing attributes (attributename,values,begin,dur). - Not on it, so removed: every
on*handler,focusable,transform-origin,mask-type,from,to,xml:lang, and editor namespaces such asinkscape:*andsodipodi:*. - Always kept, independent of the list: every name that starts with
aria-ordata-.
Examples
Keep focusable for older screen readers
This is the example from the plugin readme.
/**
* Keep focusable="false" on inline SVG icons.
*
* @param string[] $attributes Allowed attribute names.
* @return string[]
*/
function myplugin_allow_focusable( $attributes ) {
$attributes[] = 'focusable';
return $attributes;
}
add_filter( 'esw_svg_allowed_attributes', 'myplugin_allow_focusable' );
Keep newer presentation attributes from your exporter
/**
* Keep presentation attributes that newer design tools write.
*
* @param string[] $attributes Allowed attribute names.
* @return string[]
*/
function myplugin_allow_svg2_presentation( $attributes ) {
return array_merge( $attributes, array( 'transform-origin', 'mask-type' ) );
}
add_filter( 'esw_svg_allowed_attributes', 'myplugin_allow_svg2_presentation' );
Without this, mask-type="alpha" is dropped and a mask falls back to luminance, so the shape can come out lighter or invisible.
Strip HTML attributes that carry URLs
/**
* Remove HTML-only URL attributes from every stored SVG.
*
* @param string[] $attributes Allowed attribute names.
* @return string[]
*/
function myplugin_strict_svg_attributes( $attributes ) {
if ( ! is_array( $attributes ) ) {
return array();
}
$blocked = array( 'src', 'srcset', 'poster', 'background', 'action' );
return array_values(
array_filter(
$attributes,
static function ( $name ) use ( $blocked ) {
return ! in_array( strtolower( $name ), $blocked, true );
}
)
);
}
add_filter( 'esw_svg_allowed_attributes', 'myplugin_strict_svg_attributes' );
The is_array() guard keeps the return value an array even if another callback before yours broke the list. Returning an empty array is safe in the sense that it cannot let anything through, but it strips every attribute from every file, so log it if you ever hit that branch.
The sanitizer only checks the value of attributes whose name contains href: there it allows fragments, relative paths, http(s) and a few image data: types and removes javascript:. Every other attribute you add is kept with whatever value the file gives it. Adding onload, onclick or any other on* name lets an uploaded file run script in the browser of everyone who opens it, including your administrators in the media library. Add only names that describe how a drawing looks.
How it works
The filter runs inside esw_svg_attributes::getAttributes() (easy-svg.php, line 91). Every call to easy_svg_sanitizer() builds a new sanitizer and calls setAllowedAttrs( new esw_svg_attributes() ), which applies the filter and lower-cases the result. Uploads, sideloads, the wp_upload_bits check, the new-attachment check, the icon library and add-ons all go through that function, so they all see the same list.
Elements are checked first (see esw_svg_allowed_tags); attributes are only looked at on elements that survive. Mixed-case spellings such as xlink:HrEf are rewritten to lower case when the lower-case name is on the list.
For icons there is one more fixed step: easy_svg_harden_icon_markup() removes every on* attribute and every href that does not start with #, whatever this list allows, because icons are inlined into pages.
Pitfalls
- You cannot strip
aria-*ordata-*here. Removingaria-hiddenfrom the list has no effect, the library keeps those prefixes unconditionally. - Values are not validated. Only
href-like names get a value check. A new attribute keeps any value,javascript:included. - Return an array.
nullor a string from your callback is a fatal error during the upload. - Compare in lower case when removing. The defaults contain mixed spellings such as
filterUnits. Usestrtolower()instead of a plainarray_diff(). - Prefixes are part of the name.
xlink:titleandtitleare separate entries. - Removing common names breaks drawings. Take out
styleorclassand files that colour their shapes through CSS lose their colours. - The XML-RPC path refuses, it does not clean. Files written through
wp_upload_bits()are refused when the sanitizer would change them, so a stricter list means more refused uploads there. - The legacy global cannot change the list.
setAllowedAttrs()on the old global$sanitizeris overwritten on every copy. Use the filter.