@publidata/utils-fontawesome
Version:
Collection of methods to handle opening hours
195 lines (169 loc) • 5.79 kB
JavaScript
const FontAwesomeApi = require("../FontAwesomeApi/index.js");
const { isValidFa, isFaKit } = require("../validators");
/**
* Provides methods to fetch svgs from FontAwesome
*/
class FontAwesomeUtils {
api;
static _kit;
static _token;
static _cache = new Map();
constructor(token, kit) {
this._kit = kit;
this._token = token;
if (this._token) this.api = new FontAwesomeApi(this._token);
}
/**
* Set the token to use for the api
* @param {string} token
* @returns {void}
* @memberof FontAwesomeSvg
* @example FontAwesome.setToken("TOKEN");
*/
setToken(token) {
this._token = token;
this.api = new FontAwesomeApi(this._token);
}
/**
* Set the kit to use for the api
* @param {string} kit
* @returns {void}
* @memberof FontAwesomeSvg
* @example
* FontAwesomeSvg.setKit("2BC39F11-A80E-4DB4-AA7A-41FC26176101");
*/
setKit(kit) {
this._kit = kit;
}
/**
* Clear the cache
* @returns {void}
* @memberof FontAwesomeSvg
* @example FontAwesome.clearCache();
*/
clearCache() {
FontAwesomeUtils._cache.clear();
}
/**
* Fetch the svg from FontAwesome
* @param {string} fa
* @returns {Promise<string>}
* @memberof FontAwesomeSvg
* @example
* const fa = "fas fa-nop";
* FontAwesomeSvg.toSgv(fa).then(res => {
* console.log(res);
* });
*/
toSvg(fa) {
return new Promise((resolve, reject) => {
if (!isValidFa(fa)) return reject(Error("Invalid FontAwesome object"));
// Check cache first
if (FontAwesomeUtils._cache.has(fa)) {
return resolve(FontAwesomeUtils._cache.get(fa));
}
const iconName = fa.replace("fa-", "").split(" ")[1];
if (!this._token) reject(Error("FontAwesome token not set"));
if (!isFaKit(fa)) {
return this.api.getIcon(iconName).then((icon) => {
const svg = icon?.html;
if (svg) FontAwesomeUtils._cache.set(fa, svg);
resolve(svg);
});
}
if (!this._kit) reject(Error("FontAwesome kit not set"));
this.api.kitIcons(this._kit, [iconName]).then((icons) => {
if (!icons.length) reject(Error("Invalid FontAwesome custom icon"));
const asSvg = faKitAsSvg(icons[0]);
if (!asSvg)
console.log(
`Error while converting to svg, this icon is invalid : ${iconName} for kit ${this._kit}`
);
if (asSvg) FontAwesomeUtils._cache.set(fa, asSvg);
resolve(asSvg);
});
});
}
toSvgs(fas) {
return new Promise((resolve, reject) => {
if (!Array.isArray(fas)) reject(Error("Invalid FontAwesome array"));
const cleanFas = fas.filter(isValidFa);
const kitFas = cleanFas.filter(isFaKit);
const nativeFas = cleanFas.filter((fa) => !isFaKit(fa));
const hasSvgKey = (fa) => fa.svg;
if (!this._token) reject(Error("FontAwesome token not set"));
// Separate cached and uncached native icons
const cachedNative = [];
const uncachedNative = [];
nativeFas.forEach((fa) => {
if (FontAwesomeUtils._cache.has(fa)) {
cachedNative.push({ fa, svg: FontAwesomeUtils._cache.get(fa) });
} else {
uncachedNative.push(fa);
}
});
// Fetch only uncached native icons using API in a single request
const nativeIconsToFetch = uncachedNative.map((fa) => {
const [prefix, iconName] = fa.replace("fa-", "").split(" ");
return { prefix, iconName };
});
const nativeIconsPromise = nativeIconsToFetch.length > 0
? this.api.getIcons(nativeIconsToFetch).then((icons) => {
const results = icons.map((icon, index) => {
const fa = uncachedNative[index];
const svg = icon?.html;
if (svg) FontAwesomeUtils._cache.set(fa, svg);
return { fa, svg };
});
return [...cachedNative, ...results.filter(hasSvgKey)];
})
: Promise.resolve(cachedNative);
if (!kitFas.length) {
return nativeIconsPromise.then(resolve);
}
if (!this._kit) reject(Error("FontAwesome kit not set"));
// Separate cached and uncached kit icons
const cachedKit = [];
const uncachedKit = [];
const uncachedKitNames = [];
kitFas.forEach((fa) => {
if (FontAwesomeUtils._cache.has(fa)) {
cachedKit.push({ fa, svg: FontAwesomeUtils._cache.get(fa) });
} else {
uncachedKit.push(fa);
uncachedKitNames.push(fa?.replace("fa-", "")?.split(" ")[1]);
}
});
if (!uncachedKitNames.length) {
return nativeIconsPromise.then((nativeSgvs) => {
resolve([...nativeSgvs, ...cachedKit]);
});
}
Promise.all([
nativeIconsPromise,
this.api.kitIcons(this._kit, uncachedKitNames)
]).then(([nativeSgvs, icons]) => {
let kitSgvs = icons
.map((icon, index) => {
const fa = `fak fa-${icon.name}`;
const svg = faKitAsSvg(icon);
if (!svg)
console.log(
`Error while converting to svg, this icon is invalid : ${uncachedKitNames[index]} for kit ${this._kit}`
);
if (svg) FontAwesomeUtils._cache.set(fa, svg);
return { fa, svg };
})
.filter(hasSvgKey);
const sgvs = [...nativeSgvs, ...cachedKit, ...kitSgvs];
resolve(sgvs);
});
});
}
}
const faKitAsSvg = icon => {
if (!icon) return null;
const { height, width, path } = icon;
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}"><path d="${path}"></path></svg>`;
};
module.exports = new FontAwesomeUtils();