maikschneider / bw_icons

TYPO3 extensions that provides an icon picker for TCA and RTE.
GNU General Public License v2.0
1 stars 2 forks source link

Add support for Google's Material Icons #48

Closed LiquidPL closed 4 months ago

LiquidPL commented 4 months ago

Hi,

would it be possible to add support for Material Icons to this extension? The problem here is that these don't use the typical FontAwesome-style way of being embedded into a webpage with classes, instead the icon name is being inserted directly into the selector:

<span class="material-icons">example_icon</span>

Because of that, there's no list of available icons in the stylesheet, and there is also a need to override the way the icons are being rendered in the backend.

I can handle the first part with a custom provider in my own project, but because these use a different markup, they will not show up in the backend icon picker:

Screenshot_20240613_153401

It would be great if there was a way to override the way how an icon is rendered in the backend (without XCLASS-ing the ViewHelper or overriding the template), to handle situations like that.

maikschneider commented 4 months ago

Hey @LiquidPL, thanks for the feedback!

Making the markup configurable should be pretty easy. I think about something like this:

materialicons = Blueways\BwIcons\Provider\CssIconProvider
materialicons {
   title = Material Icons
   file = fileadmin/material-icons/material.css
   markup = <span class="material-icons">###ICON###</span>
}

When looking into the material icon stylessheet, I noticed that the icon names (glyphs) are not part of the file. This causes the CssIconProvider to return an empty set of icons. How did you manage to display the material icons in the wizard? Do you use SVG icons or did you create a custom provider? Could you please link the files you used?

LiquidPL commented 4 months ago

Hi, yeah I've created a custom provider to load the list of the icons. I have noticed that the Google Fonts website loads a json file from some API endpoint that contains a list of all the icons, with all the relevant metadata. My provider downloads that file to load the icon list, and then also extends CssIconProvider so that the backend module controller will load the relevant stylesheet:

mod.tx_bwicons {
  materialicons = ...\Provider\MaterialIconProvider
  materialicons {
    title = Material Icons
    metadata = https://fonts.google.com/metadata/icons?incomplete=false
    file = https://fonts.googleapis.com/icon?family=Material+Icons
  }
}

The provider itself works more or less like this (not including setting up any necessary caching and other things):

class MaterialIconProvider extends CssIconProvider
{
    public function getIcons(): array
    {
        $iconsJson = $this->getIconsJson();
        $icons = [];

        foreach ($iconsJson as $icon) {
            $category = $icon['categories'][0];

            if (array_key_exists($category, $icons) === false) {
                $icons[$category] = [];
            }

            $icons[$category][] = $icon['name'];
        }

        // needs to be downloaded manually because CssIconProvider would
        // omit the necessary classes from the original file
        GeneralUtility::writeFileToTypo3tempDir($this->getTempPath() . '/font.css', GeneralUtility::getUrl($this->options['file']));

        return $icons;
    }

    private function getIconsJson(): array
    {
        if (
            array_key_exists('metadata', $this->options) === false
            || GeneralUtility::isValidUrl($this->options['metadata']) === false
        ) {
            return [];
        }

        $content = GeneralUtility::getUrl($this->options['metadata']);

        if (!$content) {
            return [];
        }

        // for some reason the google fonts endpoint returns garbage
        // at the beginning of the file
        // should be cached
        return json_decode(substr($content, 5), true);
    }
}

One thing that also comes to mind is that there needs to be a way to recognize what provider a given icon was provided by, otherwise the ViewHelper would have no clue if an icon is from the standard CssIconProvider or from this one.

maikschneider commented 4 months ago

Ah, clever solution! Could you check out PR #49 - there you can configure the markup for one specific Provider.

LiquidPL commented 4 months ago

Yeah, I just did - looks really good to me.

maikschneider commented 4 months ago

Nice. I just released a new version. Do you need a backport to <v12?

LiquidPL commented 4 months ago

No, V12 is fine for me. I've also opened #50, since I missed that the form field also needs updated handling.