Source: engine/ur/IconTemplate.js

(function() {
    /** SVG icon template handling for UR harmonization */
    Help4.engine.ur.IconTemplate = class {
        static ICON_THEME_MAP = {
            horizon: 'sap_horizon',
            belize: 'sap_belize',
            quartz: 'sap_fiori_3'
        };

        static CSS_VAR_PREFIX = '--help4-sap-ui-icon';
        static SVG_CLASS_TO_VAR = {
            sapSvgIconNegative: {fill: `var(${this.CSS_VAR_PREFIX}-negative)`},  // orig color: #fa6161 !important
            sapSvgIconCritical: {fill: `var(${this.CSS_VAR_PREFIX}-critical)`},  // #f7bf00 !important
            sapSvgIconPositive: {fill: `var(${this.CSS_VAR_PREFIX}-positive)`},  // #6dad1f !important
            sapSvgIconBase:     {fill: `var(${this.CSS_VAR_PREFIX}-base)`}       // #1d232a !important
        };

        /**
         * Load icon library matching current theme
         * @param {Help4.engine.ur.UrHarmonizationEngine} engine
         */
        static async prepare(engine) {
            const {dom, existingSvg, currentBase, loadIcons} = _checkCurrent.call(this, engine);
            if (!loadIcons) return;

            // create a copy of the icons in the Companion DOM
            let response = await fetch(`/sap/public/icmandir/its/ls/theming/Base/baseLib/${currentBase}/svg/libs/SAPGUI-icons.svg`);
            if (!response.ok && engine._mock) response = await fetch(`${currentBase}-SAPGUI-icons.svg`);  // attempt loading directly from mock system
            engine._failedIconBase = response.ok ? null : currentBase;   // do not reset on app navigation, template comes from top origin

            if (!response.ok) {
                engine._log?.('CMP: Unable to load icon library', response, undefined, Help4.engine.ur.Connection.LOG_LEVEL.WARNING);
                return;
            }

            const svgText = await response.text();
            if (svgText.startsWith('<?xml ') && svgText.includes('<svg ')) {
                const {Element} = Help4;
                const {SVG_CLASS_TO_VAR} = this;
                const {ICON_LIB_ID} = engine.constructor;

                const {content} = Element.create('template', {html: svgText});

                // rename ids to be Help4-specific
                content.querySelectorAll('symbol[id]')
                .forEach(s => s.id = `${ICON_LIB_ID}-${s.id}`);

                content.querySelectorAll('path[class]')
                .forEach(path => {
                    const style = SVG_CLASS_TO_VAR[path.getAttribute('class')];
                    if (style) {
                        path.removeAttribute('class');
                        Help4.extendObject(path.style, style);
                    }
                });

                /** @type {Node} */
                const svg = content.querySelector('svg')?.cloneNode(true) || document.createElement('svg');
                Element.setAttribute(svg, {
                    id: ICON_LIB_ID,
                    style: {display: 'none'},
                    'data-theme': currentBase
                });

                existingSvg
                    ? existingSvg.replaceWith(svg)
                    : dom.appendChild(svg);
            }
        }
    }

    /**
     * @memberof Help4.engine.ur
     * @private
     * @param {Help4.engine.ur.UrHarmonizationEngine} engine
     * @returns {{dom: ShadowRoot|HTMLElement, existingSvg: ?HTMLElement, currentBase: string, loadIcons: boolean}}
     */
    function _checkCurrent(engine) {
        const {ICON_THEME_MAP} = this;
        const {
            _failedIconBase,
            constructor: {ICON_LIB_ID},
            controller
        } = engine;

        const {CMP4, core: {theme}} = controller.getConfiguration();
        const dom = /** @type {ShadowRoot|HTMLElement} */ CMP4 ? controller.getDom2('shadow') : controller.getDom();
        const existingSvg = /** @type {HTMLElement} */ dom.querySelector('#' + ICON_LIB_ID);
        const currentBase = /** @type {string} */ Object.entries(ICON_THEME_MAP).find(([key]) => theme.includes(key))?.[1] || 'sap_horizon';
        const loadedBase = /** @type {string} */ existingSvg ? existingSvg.dataset.help4Theme : '';
        // load icons if they haven't failed to load before and the existing SVG is outdated
        const loadIcons = currentBase !== _failedIconBase && (!existingSvg || currentBase !== loadedBase);

        return {dom, existingSvg, currentBase, loadIcons};
    }
})();