MOBILE-3947 icons: Add new fonts to Ionicons using addIcons
parent
dc5d22f503
commit
6c99166055
|
@ -70,6 +70,7 @@ Thumbs.db
|
||||||
/src/assets/lib
|
/src/assets/lib
|
||||||
/src/assets/lang/*
|
/src/assets/lang/*
|
||||||
/src/assets/env.json
|
/src/assets/env.json
|
||||||
|
/src/assets/fonts/icons.json
|
||||||
|
|
||||||
/moodle.config.*.json
|
/moodle.config.*.json
|
||||||
!/moodle.config.example.json
|
!/moodle.config.example.json
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
const { writeFile, readdirSync, statSync, readFileSync } = require('fs');
|
||||||
|
|
||||||
|
const FONTS_PATH = 'src/assets/fonts';
|
||||||
|
const ICONS_JSON_FILE_PATH = 'src/assets/fonts/icons.json';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get object with the map of icons for all fonts.
|
||||||
|
*
|
||||||
|
* @returns Icons map.
|
||||||
|
*/
|
||||||
|
function getIconsMap() {
|
||||||
|
const config = JSON.parse(readFileSync('moodle.config.json'));
|
||||||
|
let icons = {};
|
||||||
|
|
||||||
|
const fonts = readdirSync(FONTS_PATH);
|
||||||
|
fonts.forEach(font => {
|
||||||
|
const fontPath = `${FONTS_PATH}/${font}`;
|
||||||
|
if (statSync(fontPath).isFile()) {
|
||||||
|
// Not a font, ignore.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
icons = {
|
||||||
|
...icons,
|
||||||
|
...getFontIconsMap(config.iconsPrefixes, font, fontPath),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return icons;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get object with the map of icons for a certain font.
|
||||||
|
*
|
||||||
|
* @param prefixes Prefixes to add to the icons.
|
||||||
|
* @param fontName Font name.
|
||||||
|
* @param fontPath Font path.
|
||||||
|
* @returns Icons map.
|
||||||
|
*/
|
||||||
|
function getFontIconsMap(prefixes, fontName, fontPath) {
|
||||||
|
const icons = {};
|
||||||
|
const fontLibraries = readdirSync(fontPath);
|
||||||
|
|
||||||
|
fontLibraries.forEach(libraryName => {
|
||||||
|
const libraryPath = `${fontPath}/${libraryName}`;
|
||||||
|
if (statSync(libraryPath).isFile()) {
|
||||||
|
// Not a font library, ignore.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const libraryPrefixes = prefixes?.[fontName]?.[libraryName];
|
||||||
|
if (!libraryPrefixes || !libraryPrefixes.length) {
|
||||||
|
console.warn(`WARNING: There is no prefix for the library ${fontName}/${libraryName}. Adding icons without prefix is ` +
|
||||||
|
'discouraged, please add a prefix for your library in moodle.config.json file, in the iconsPrefixes property.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const libraryIcons = readdirSync(libraryPath);
|
||||||
|
libraryIcons.forEach(iconFileName => {
|
||||||
|
if (!iconFileName.endsWith('.svg')) {
|
||||||
|
// Only accept svg files.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iconFileName.includes('_')) {
|
||||||
|
throw Error(`Icon ${libraryPath}/${iconFileName} has an invalid name, it cannot contain '_'. `
|
||||||
|
+ 'Please rename it to use \'-\' instead.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const iconName = iconFileName.replace('.svg', '');
|
||||||
|
const iconPath = `${libraryPath}/${iconFileName}`.replace('src/', '');
|
||||||
|
|
||||||
|
if (!libraryPrefixes || !libraryPrefixes.length) {
|
||||||
|
icons[iconName] = iconPath;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
libraryPrefixes.forEach(prefix => {
|
||||||
|
icons[`${prefix}-${iconName}`] = iconPath;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return icons;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task to build a JSON file with the list of icons to add to Ionicons.
|
||||||
|
*/
|
||||||
|
class BuildIconsJsonTask {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the task.
|
||||||
|
*
|
||||||
|
* @param done Function to call when done.
|
||||||
|
*/
|
||||||
|
run(done) {
|
||||||
|
const icons = getIconsMap();
|
||||||
|
|
||||||
|
writeFile(ICONS_JSON_FILE_PATH, JSON.stringify(icons), done);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = BuildIconsJsonTask;
|
|
@ -15,6 +15,7 @@
|
||||||
const BuildLangTask = require('./gulp/task-build-lang');
|
const BuildLangTask = require('./gulp/task-build-lang');
|
||||||
const BuildBehatPluginTask = require('./gulp/task-build-behat-plugin');
|
const BuildBehatPluginTask = require('./gulp/task-build-behat-plugin');
|
||||||
const BuildEnvTask = require('./gulp/task-build-env');
|
const BuildEnvTask = require('./gulp/task-build-env');
|
||||||
|
const BuildIconsJsonTask = require('./gulp/task-build-icons-json');
|
||||||
const PushTask = require('./gulp/task-push');
|
const PushTask = require('./gulp/task-push');
|
||||||
const OverrideLangTask = require('./gulp/task-override-lang');
|
const OverrideLangTask = require('./gulp/task-override-lang');
|
||||||
const Utils = require('./gulp/utils');
|
const Utils = require('./gulp/utils');
|
||||||
|
@ -47,6 +48,10 @@ gulp.task('env', (done) => {
|
||||||
new BuildEnvTask().run(done);
|
new BuildEnvTask().run(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
gulp.task('icons', (done) => {
|
||||||
|
new BuildIconsJsonTask().run(done);
|
||||||
|
});
|
||||||
|
|
||||||
// Build a Moodle plugin to run Behat tests.
|
// Build a Moodle plugin to run Behat tests.
|
||||||
if (BuildBehatPluginTask.isBehatConfigured()) {
|
if (BuildBehatPluginTask.isBehatConfigured()) {
|
||||||
gulp.task('behat', (done) => {
|
gulp.task('behat', (done) => {
|
||||||
|
@ -63,6 +68,7 @@ gulp.task(
|
||||||
gulp.parallel([
|
gulp.parallel([
|
||||||
'lang',
|
'lang',
|
||||||
'env',
|
'env',
|
||||||
|
'icons',
|
||||||
...(BuildBehatPluginTask.isBehatConfigured() ? ['behat'] : [])
|
...(BuildBehatPluginTask.isBehatConfigured() ? ['behat'] : [])
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
|
|
@ -111,5 +111,16 @@
|
||||||
"long": 3500,
|
"long": 3500,
|
||||||
"sticky": 0
|
"sticky": 0
|
||||||
},
|
},
|
||||||
"disableTokenFile": false
|
"disableTokenFile": false,
|
||||||
|
"iconsPrefixes": {
|
||||||
|
"font-awesome": {
|
||||||
|
"brands": ["fab"],
|
||||||
|
"regular": ["far"],
|
||||||
|
"solid": ["fa", "fas"]
|
||||||
|
},
|
||||||
|
"moodle": {
|
||||||
|
"font-awesome": ["fam"],
|
||||||
|
"moodle": ["moodle"]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 777 B After Width: | Height: | Size: 776 B |
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 294 B |
|
@ -15,6 +15,7 @@
|
||||||
import { AfterViewInit, Directive, ElementRef, Input, OnChanges, SimpleChange } from '@angular/core';
|
import { AfterViewInit, Directive, ElementRef, Input, OnChanges, SimpleChange } from '@angular/core';
|
||||||
import { CoreLogger } from '@singletons/logger';
|
import { CoreLogger } from '@singletons/logger';
|
||||||
import { CoreIcons } from '@singletons/icons';
|
import { CoreIcons } from '@singletons/icons';
|
||||||
|
import { CoreConstants } from '../constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Directive to enable font-awesome 6.4 as ionicons.
|
* Directive to enable font-awesome 6.4 as ionicons.
|
||||||
|
@ -41,65 +42,27 @@ export class CoreFaIconDirective implements AfterViewInit, OnChanges {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detect icon name and use svg.
|
* Validate icon, e.g. checking if it's using a deprecated name.
|
||||||
*/
|
*/
|
||||||
async setIcon(): Promise<void> {
|
async validateIcon(): Promise<void> {
|
||||||
let library = '';
|
if (CoreConstants.BUILD.isDevelopment && !CoreIcons.isIconNamePrefixed(this.name)) {
|
||||||
let iconName = this.name;
|
this.logger.warn(`Not prefixed icon ${this.name} detected, it could be an Ionic icon. Font-awesome is preferred.`);
|
||||||
let font = 'ionicons';
|
|
||||||
const parts = iconName.split('-', 2);
|
|
||||||
if (parts.length === 2) {
|
|
||||||
switch (parts[0]) {
|
|
||||||
case 'far':
|
|
||||||
library = 'regular';
|
|
||||||
font = 'font-awesome';
|
|
||||||
break;
|
|
||||||
case 'fa':
|
|
||||||
case 'fas':
|
|
||||||
library = 'solid';
|
|
||||||
font = 'font-awesome';
|
|
||||||
break;
|
|
||||||
case 'fab':
|
|
||||||
library = 'brands';
|
|
||||||
font = 'font-awesome';
|
|
||||||
break;
|
|
||||||
case 'moodle':
|
|
||||||
library = 'moodle';
|
|
||||||
font = 'moodle';
|
|
||||||
break;
|
|
||||||
case 'fam':
|
|
||||||
library = 'font-awesome';
|
|
||||||
font = 'moodle';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (font === 'ionicons') {
|
if (this.name.includes('_')) {
|
||||||
this.element.removeAttribute('src');
|
// Ionic icons cannot contain a '_' in the name, Ionic doesn't load them, replace it with '-'.
|
||||||
this.logger.warn(`Ionic icon ${this.name} detected`);
|
this.logger.warn(`Icon ${this.name} contains '_' character and it's not allowed, replacing it with '-'.`);
|
||||||
|
this.updateName(this.name.replace(/_/g, '-'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iconName = iconName.substring(parts[0].length + 1);
|
if (this.name.match(/^fa[brs]?-/)) {
|
||||||
|
// It's a font-awesome icon, check if it's using a deprecated name.
|
||||||
// Set it here to avoid loading unexisting icon paths (svg/iconName) caused by the tick delay of the checkIconAlias promise.
|
const iconName = this.name.substring(this.name.indexOf('-') + 1);
|
||||||
let src = CoreIcons.getIconSrc(font, library, iconName);
|
|
||||||
this.element.setAttribute('src', src);
|
|
||||||
|
|
||||||
if (font === 'font-awesome') {
|
|
||||||
const { fileName } = await CoreIcons.getFontAwesomeIconFileName(iconName);
|
const { fileName } = await CoreIcons.getFontAwesomeIconFileName(iconName);
|
||||||
if (fileName !== iconName) {
|
if (fileName !== iconName) {
|
||||||
src = CoreIcons.getIconSrc(font, library, fileName);
|
this.updateName(this.name.replace(iconName, fileName));
|
||||||
this.element.setAttribute('src', src);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.element.classList.add('faicon');
|
|
||||||
CoreIcons.validateIcon(this.name, src);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -123,7 +86,17 @@ export class CoreFaIconDirective implements AfterViewInit, OnChanges {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setIcon();
|
this.validateIcon();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the icon name.
|
||||||
|
*
|
||||||
|
* @param newName New name to use.
|
||||||
|
*/
|
||||||
|
protected updateName(newName: string): void {
|
||||||
|
this.name = newName;
|
||||||
|
this.element.setAttribute('name', newName);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -540,11 +540,11 @@ export class CoreGradesHelperProvider {
|
||||||
text = text.replace('%2F', '/').replace('%2f', '/');
|
text = text.replace('%2F', '/').replace('%2f', '/');
|
||||||
if (text.indexOf('/agg_mean') > -1) {
|
if (text.indexOf('/agg_mean') > -1) {
|
||||||
row.itemtype = 'agg_mean';
|
row.itemtype = 'agg_mean';
|
||||||
row.icon = 'moodle-agg_mean';
|
row.icon = 'moodle-agg-mean';
|
||||||
row.iconAlt = Translate.instant('core.grades.aggregatemean');
|
row.iconAlt = Translate.instant('core.grades.aggregatemean');
|
||||||
} else if (text.indexOf('/agg_sum') > -1) {
|
} else if (text.indexOf('/agg_sum') > -1) {
|
||||||
row.itemtype = 'agg_sum';
|
row.itemtype = 'agg_sum';
|
||||||
row.icon = 'moodle-agg_sum';
|
row.icon = 'moodle-agg-sum';
|
||||||
row.iconAlt = Translate.instant('core.grades.aggregatesum');
|
row.iconAlt = Translate.instant('core.grades.aggregatesum');
|
||||||
} else if (text.indexOf('/outcomes') > -1 || text.indexOf('fa-tasks') > -1 || text.indexOf('fa-list-check') > -1) {
|
} else if (text.indexOf('/outcomes') > -1 || text.indexOf('fa-tasks') > -1 || text.indexOf('fa-list-check') > -1) {
|
||||||
row.itemtype = 'outcome';
|
row.itemtype = 'outcome';
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { CoreIcons } from '@singletons/icons';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add custom icons to Ionicons.
|
||||||
|
*/
|
||||||
|
export default function(): void {
|
||||||
|
CoreIcons.addIconsToIonicons();
|
||||||
|
}
|
|
@ -12,26 +12,29 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Http } from '@singletons';
|
|
||||||
import { CoreConstants } from '../constants';
|
import { CoreConstants } from '../constants';
|
||||||
import { CoreLogger } from './logger';
|
import { CoreLogger } from './logger';
|
||||||
import aliases from '@/assets/fonts/font-awesome/aliases.json';
|
import aliases from '@/assets/fonts/font-awesome/aliases.json';
|
||||||
import { firstValueFrom } from 'rxjs';
|
import { addIcons } from 'ionicons';
|
||||||
|
import icons from '@/assets/fonts/icons.json';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Singleton with helper functions for icon management.
|
* Singleton with helper functions for icon management.
|
||||||
*/
|
*/
|
||||||
export class CoreIcons {
|
export class CoreIcons {
|
||||||
|
|
||||||
/**
|
|
||||||
* Object used to store whether icons exist or not during development.
|
|
||||||
*/
|
|
||||||
private static readonly DEV_ICONS_STATUS: Record<string, Promise<boolean>> = {};
|
|
||||||
|
|
||||||
private static readonly ALIASES = { ...aliases } as unknown as Record<string, string>;
|
private static readonly ALIASES = { ...aliases } as unknown as Record<string, string>;
|
||||||
|
private static readonly CUSTOM_ICONS = { ...icons } as unknown as Record<string, string>;
|
||||||
|
|
||||||
protected static logger = CoreLogger.getInstance('CoreIcons');
|
protected static logger = CoreLogger.getInstance('CoreIcons');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add custom icons to Ionicons.
|
||||||
|
*/
|
||||||
|
static addIconsToIonicons(): void {
|
||||||
|
addIcons(CoreIcons.CUSTOM_ICONS);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check icon alias and returns the new icon name.
|
* Check icon alias and returns the new icon name.
|
||||||
*
|
*
|
||||||
|
@ -55,30 +58,24 @@ export class CoreIcons {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate that an icon exists, or show warning otherwise (only in development and testing environments).
|
* Validate that an icon exists in the list of custom icons for the app, or show warning otherwise
|
||||||
|
* (only in development and testing environments).
|
||||||
*
|
*
|
||||||
* @param name Icon name.
|
* @param font Font Family.
|
||||||
* @param src Icon source url.
|
* @param library Library to use.
|
||||||
|
* @param icon Icon Name.
|
||||||
*/
|
*/
|
||||||
static validateIcon(name: string, src: string): void {
|
static validateIcon(font: string, library: string, icon: string): void {
|
||||||
if (!CoreConstants.BUILD.isDevelopment && !CoreConstants.BUILD.isTesting) {
|
if (!CoreConstants.BUILD.isDevelopment && !CoreConstants.BUILD.isTesting) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(src in CoreIcons.DEV_ICONS_STATUS)) {
|
if (
|
||||||
CoreIcons.DEV_ICONS_STATUS[src] = firstValueFrom(Http.get(src, { responseType: 'text' }))
|
CoreIcons.CUSTOM_ICONS[icon] === undefined &&
|
||||||
.then(() => true)
|
CoreIcons.CUSTOM_ICONS[CoreIcons.prefixIconName(font, library, icon)] === undefined
|
||||||
.catch(() => false);
|
) {
|
||||||
|
this.logger.error(`Icon ${icon} not found`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line promise/catch-or-return
|
|
||||||
CoreIcons.DEV_ICONS_STATUS[src].then(exists => {
|
|
||||||
if (exists) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.logger.error(`Icon ${name} not found`);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -174,8 +171,7 @@ export class CoreIcons {
|
||||||
|
|
||||||
newIcon.setAttribute('src', src);
|
newIcon.setAttribute('src', src);
|
||||||
|
|
||||||
newIcon.classList.add('faicon');
|
CoreIcons.validateIcon('font-awesome', library, iconName);
|
||||||
CoreIcons.validateIcon(iconName, src);
|
|
||||||
|
|
||||||
icon.parentElement?.insertBefore(newIcon, icon);
|
icon.parentElement?.insertBefore(newIcon, icon);
|
||||||
icon.remove();
|
icon.remove();
|
||||||
|
@ -195,4 +191,34 @@ export class CoreIcons {
|
||||||
return `assets/fonts/${font}/${library}/${icon}.svg`;
|
return `assets/fonts/${font}/${library}/${icon}.svg`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefix an icon name using the library prefix.
|
||||||
|
*
|
||||||
|
* @param font Font Family.
|
||||||
|
* @param library Library to use.
|
||||||
|
* @param icon Icon Name.
|
||||||
|
* @returns Prefixed icon name.
|
||||||
|
*/
|
||||||
|
static prefixIconName(font: string, library: string, icon: string): string {
|
||||||
|
const prefixes = CoreConstants.CONFIG.iconsPrefixes?.[font]?.[library];
|
||||||
|
if (!prefixes || !prefixes.length) {
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${prefixes[0]}-${icon}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an icon name contains any of the prefixes configured for icons.
|
||||||
|
* If it doesn't then it probably is an Ionicon.
|
||||||
|
*
|
||||||
|
* @param icon Icon Name.
|
||||||
|
* @returns Whether icon is prefixed.
|
||||||
|
*/
|
||||||
|
static isIconNamePrefixed(icon: string): boolean {
|
||||||
|
return Object.values(CoreConstants.CONFIG.iconsPrefixes ?? {})
|
||||||
|
.some(library => Object.values(library)
|
||||||
|
.some(prefixes => prefixes.some(prefix => icon.startsWith(`${prefix}-`))));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { CoreConstants } from '@/core/constants';
|
||||||
import { CoreIcons } from '@singletons/icons';
|
import { CoreIcons } from '@singletons/icons';
|
||||||
|
|
||||||
describe('CoreIcons singleton', () => {
|
describe('CoreIcons singleton', () => {
|
||||||
|
@ -81,4 +82,43 @@ describe('CoreIcons singleton', () => {
|
||||||
.toEqual('assets/fonts/font-awesome/solid/square-check.svg');
|
.toEqual('assets/fonts/font-awesome/solid/square-check.svg');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('prefixes icons names', () => {
|
||||||
|
// Arrange.
|
||||||
|
CoreConstants.CONFIG.iconsPrefixes = {
|
||||||
|
foo: {
|
||||||
|
bar: ['fo', 'for'],
|
||||||
|
baz: ['foz'],
|
||||||
|
},
|
||||||
|
lorem: {
|
||||||
|
ipsum: ['lorip'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act and assert.
|
||||||
|
expect(CoreIcons.prefixIconName('foo', 'bar', 'myicon')).toEqual('fo-myicon');
|
||||||
|
expect(CoreIcons.prefixIconName('foo', 'baz', 'myicon')).toEqual('foz-myicon');
|
||||||
|
expect(CoreIcons.prefixIconName('lorem', 'ipsum', 'myicon')).toEqual('lorip-myicon');
|
||||||
|
expect(CoreIcons.prefixIconName('invalid', 'invalid', 'myicon')).toEqual('myicon');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('check if an icon is prefixed', () => {
|
||||||
|
// Arrange.
|
||||||
|
CoreConstants.CONFIG.iconsPrefixes = {
|
||||||
|
foo: {
|
||||||
|
bar: ['fo', 'for'],
|
||||||
|
baz: ['foz'],
|
||||||
|
},
|
||||||
|
lorem: {
|
||||||
|
ipsum: ['lorip'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act and assert.
|
||||||
|
expect(CoreIcons.isIconNamePrefixed('fo-myicon')).toEqual(true);
|
||||||
|
expect(CoreIcons.isIconNamePrefixed('foz-myicon')).toEqual(true);
|
||||||
|
expect(CoreIcons.isIconNamePrefixed('lorip-myicon')).toEqual(true);
|
||||||
|
expect(CoreIcons.isIconNamePrefixed('myicon')).toEqual(false);
|
||||||
|
expect(CoreIcons.isIconNamePrefixed('fox-myicon')).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -75,4 +75,5 @@ export interface EnvironmentConfig {
|
||||||
disableTokenFile: boolean; // Disable the use of tokenpluginfile.php for downloading files (so it fallbacks to pluginfile.php)
|
disableTokenFile: boolean; // Disable the use of tokenpluginfile.php for downloading files (so it fallbacks to pluginfile.php)
|
||||||
demoMode?: boolean; // Whether to run the app in "demo mode".
|
demoMode?: boolean; // Whether to run the app in "demo mode".
|
||||||
hideInformativeLinks?: boolean; // Whether to hide informative links.
|
hideInformativeLinks?: boolean; // Whether to hide informative links.
|
||||||
|
iconsPrefixes?: Record<string, Record<string, string[]>>; // Prefixes for custom font icons (located in src/assets/fonts).
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue