Convert to component?
I'm also kinda wondering why this is helper?
It'd be great if we could wrap this in something like:
{{#if this.someCondition}}
<InlineSvg @path={{this.path}} ...attributes />
{{/if}}
there the invocation could then become:
<MyIcon class='blue' />
This can be as for Glimmer component, not sure if worth to do with classic component?
Related issue with class attributes #36 .
Context
I wanted to create a component for custom (uploaded) Font Awesome icons so that I can keep the default way of installing FA packages via package manager and using the component provided by FA for all icons and handle only custom icons this way.
Disclaimer
This is a very minimal implementation which I'll further extend so I have one component to render all FA icons from the kit.
Please note that all SVGs are manually optimized to the same format FA uses, the regular expressions can easily fail if optimization is not done that way.
Also, this is in an addon, hence the addon namespace. (obviously it has the respective app export)
addon/components/icon.ts
import Component from '@glimmer/component';
import { htmlSafe } from '@ember/string';
import { assert } from '@ember/debug';
import { dottify } from 'ember-inline-svg/utils/general';
import type { SafeString } from '@ember/template/-private/handlebars';
const XMLNS_RE = /xmlns="([^"]*)"/;
const VIEWBOX_RE = /viewBox="([^"]*)"/;
const SVG_CONTENT_RE = /^<svg[^>]*>(.*)<\/svg>$/;
function extract(tag: string, attrRe: RegExp): string {
return (tag.match(attrRe) as RegExpMatchArray)[1];
}
interface Args {
path: string;
}
export default class IconComponent extends Component<Args> {
xmlns!: string;
viewBox!: string;
svgContent!: SafeString;
constructor(owner: unknown, args: Args) {
super(owner, args);
// @ts-expect-error not bothering to type resolveRegistration
const svgs = owner.resolveRegistration('svgs:main') || [];
const svg = svgs[dottify(this.args.path)];
assert('No SVG found for ' + this.args.path, svg);
this.xmlns = extract(svg, XMLNS_RE);
this.viewBox = extract(svg, VIEWBOX_RE);
this.svgContent = htmlSafe(extract(svg, SVG_CONTENT_RE));
}
}
addon/components/icon.hbs
<svg xmlns={{this.xmlns}} viewBox={{this.viewBox}} ...attributes>
{{this.svgContent}}
</svg>