for $name — either a real * Lucide kebab-case name (e.g. 'bar-chart-3') or a legacy * dashicons- name via Icon_Data::DASHICON_ALIASES, so a * migration can swap `` for * `Icon::render('x')` without first having to look up x's Lucide * equivalent by hand. Falls back to a plain circle for an unmapped * name — same fallback Icon.js uses, so a typo reads as "a circle * showed up somewhere," not a fatal error or a missing-icon gap. */ public static function render( $name, $size = 16, $class = '', $stroke_width = 1.9 ) { echo wp_kses( self::html( $name, $size, $class, $stroke_width ), self::allowed_svg_html() ); } public static function allowed_svg_html() { $attrs = [ 'class' => true, 'width' => true, 'height' => true, 'viewbox' => true, 'fill' => true, 'stroke' => true, 'stroke-width' => true, 'stroke-linecap' => true, 'stroke-linejoin' => true, 'aria-hidden' => true, 'focusable' => true, 'd' => true, 'cx' => true, 'cy' => true, 'r' => true, 'rx' => true, 'ry' => true, 'x' => true, 'y' => true, 'x1' => true, 'x2' => true, 'y1' => true, 'y2' => true, 'points' => true ]; return [ 'svg' => $attrs, 'path' => $attrs, 'circle' => $attrs, 'rect' => $attrs, 'line' => $attrs, 'polyline' => $attrs, 'polygon' => $attrs, 'ellipse' => $attrs ]; } public static function html( $name, $size = 16, $class = '', $stroke_width = 1.9 ) { $key = Icon_Data::DASHICON_ALIASES[ $name ] ?? $name; $nodes = Icon_Data::ICONS[ $key ] ?? Icon_Data::ICONS['circle'] ?? [ [ 'circle', [ 'cx' => '12', 'cy' => '12', 'r' => '10' ] ], ]; $attrs = sprintf( 'width="%1$d" height="%1$d" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="%2$s" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"', (int) $size, esc_attr( $stroke_width ) ); $class_attr = $class ? ' class="' . esc_attr( $class ) . '"' : ''; $inner = ''; foreach ( $nodes as $node ) { list( $tag, $node_attrs ) = $node; $tag = preg_replace( '/[^a-zA-Z0-9-]/', '', $tag ); // Fixed set from Icon_Data — belt-and-suspenders against ever echoing an unexpected tag name. $inner .= '<' . $tag; foreach ( $node_attrs as $attr_name => $attr_value ) { $attr_name = preg_replace( '/[^a-zA-Z0-9-]/', '', $attr_name ); $inner .= ' ' . $attr_name . '="' . esc_attr( $attr_value ) . '"'; } $inner .= '/>'; } return '' . $inner . ''; } }