Skip to content

Commit

Permalink
icon fonts support
Browse files Browse the repository at this point in the history
  • Loading branch information
lekoala committed May 21, 2021
1 parent e1804d9 commit e04ed80
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 15 deletions.
83 changes: 70 additions & 13 deletions last-icon.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,31 @@ const ALIASES = Object.assign(
mi: "material",
em: "emojicc",
fl: "flags",
in: "iconoir",
},
(window.LastIcon && window.LastIcon.aliases) || {}
);
const ENABLE_ICONS = (window.LastIcon && window.LastIcon.fonts) || [];
const FONT_ICONS = {
material: {
class: "material-icons-{type}",
types: {
baseline: "",
twotone: "two-tone",
},
},
boxicons: {
class: "bx {prefix}-{icon}",
},
bootstrap: {
class: "bi-{icon}",
},
fontawesome: {
class: "{prefix} fa-{icon}",
},
iconoir: {
class: "iconoir-{icon}",
},
};
const TYPES = Object.assign(
{
boxicons: "solid",
Expand All @@ -34,6 +55,13 @@ const PREFIXES = Object.assign(
regular: "bx",
logos: "bxl",
},
fontawesome: {
solid: "fas",
regular: "far",
light: "fal",
duotone: "fad",
brands: "fab",
},
},
(window.LastIcon && window.LastIcon.prefixes) || {}
);
Expand All @@ -46,7 +74,7 @@ const PATHS = Object.assign(
boxicons: "https://cdn.jsdelivr.net/npm/[email protected]/svg/{type}/{prefix}-{icon}.svg",
cssgg: "https://cdn.jsdelivr.net/npm/[email protected]/icons/svg/{icon}.svg",
tabler: "https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/{icon}.svg",
// type: solid, regular, brands
// type: solid, regular, brands, light, duotone
fontawesome: "https://cdn.jsdelivr.net/npm/@fortawesome/[email protected]/svgs/{type}/{icon}.svg",
bytesize: "https://cdn.jsdelivr.net/npm/[email protected]/dist/icons/{icon}.svg",
supertiny: "https://cdn.jsdelivr.net/npm/[email protected]/images/svg/{icon}.svg",
Expand All @@ -55,7 +83,6 @@ const PATHS = Object.assign(
// type : 4x3 or 1x1
flags: "https://cdn.jsdelivr.net/npm/[email protected]/flags/{type}/{icon}.svg",
emojicc: "https://cdn.jsdelivr.net/npm/[email protected]/svg/{icon}.svg",
iconoir: "https://cdn.jsdelivr.net/gh/lucaburgio/iconoir/icons/{icon}.svg"
},
(window.LastIcon && window.LastIcon.paths) || {}
);
Expand All @@ -80,7 +107,6 @@ class LastIcon extends HTMLElement {
* @return {Promise<String, Error>}
*/
static getIconSvg(iconName, iconSet, iconType) {
let iconPrefix = (PREFIXES[iconSet] && PREFIXES[iconSet][iconType]) || null;
let iconUrl = PATHS[iconSet];
let cacheKey = iconSet + "-" + iconName;
if (iconType) {
Expand All @@ -96,14 +122,7 @@ class LastIcon extends HTMLElement {
});
}

// Replace placeholders
iconUrl = iconUrl.replace("{icon}", iconName);
if (iconType) {
iconUrl = iconUrl.replace("{type}", iconType);
}
if (iconPrefix) {
iconUrl = iconUrl.replace("{prefix}", iconPrefix);
}
iconUrl = LastIcon.replacePlaceholders(iconUrl, iconName, iconSet, iconType);

// If we have it in cache
if (iconUrl && CACHE[cacheKey]) {
Expand All @@ -123,19 +142,57 @@ class LastIcon extends HTMLElement {
return CACHE[cacheKey];
}

/**
* @param {string} value
* @param {string} iconName
* @param {string} iconSet
* @param {string} iconType
* @return {string}
*/
static replacePlaceholders(value, iconName, iconSet, iconType) {
let iconPrefix = (PREFIXES[iconSet] && PREFIXES[iconSet][iconType]) || null;
value = value.replace("{icon}", iconName);
if (iconType) {
value = value.replace("{type}", iconType);
} else {
// Maybe we want to remove the type like in material icons
value = value.replace("-{type}", "");
}
if (iconPrefix) {
value = value.replace("{prefix}", iconPrefix);
}
return value;
}

/**
* @param {object} inst
* @param {string} iconName
* @param {string} iconSet
* @param {string} iconType
*/
static refreshIcon(inst, iconName, iconSet, iconType) {
if (ENABLE_ICONS.includes(iconSet)) {
LastIcon.log("Using font for " + iconName);
let iconClass = FONT_ICONS[iconSet]["class"];
let nameAsClass = iconClass.includes("{icon}");
let fontType = iconType;
if (FONT_ICONS[iconSet]["types"] && iconType in FONT_ICONS[iconSet]["types"]) {
fontType = FONT_ICONS[iconSet]["types"][iconType];
}
iconClass = LastIcon.replacePlaceholders(iconClass, iconName, iconSet, fontType);
if (nameAsClass) {
inst.innerHTML = '<i class="' + iconClass + '"></i>';
} else {
inst.innerHTML = '<i class="' + iconClass + '">' + iconName + "</i>";
}
return;
}
LastIcon.getIconSvg(iconName, iconSet, iconType)
.then((iconData) => {
if (inst.stroke) {
iconData = iconData.replace(/stroke-width="([0-9]*)"/, 'stroke-width="' + inst.stroke + '"');
}
if (FIX_FILL.indexOf(inst.set) !== -1) {
if (FIX_FILL.includes(inst.set)) {
iconData = iconData.replace(/(<svg.*?)>/, '$1 fill="currentColor">');
}
inst.innerHTML = iconData;
Expand Down
2 changes: 1 addition & 1 deletion last-icon.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "last-icon",
"version": "1.1.0",
"version": "1.2.0",
"description": "One custom icon element to rule them all",
"main": "last-icon.js",
"scripts": {
Expand Down
62 changes: 62 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,68 @@ window.LastIconPreload["material-account_box-twotone"] = LastIconPreloader("http

Thanks to the debug flag, it's easy to find the cache key and the matching url.

## Using fonts

If you find yourself preloading a lot of stuff... it might actually be easier to use the icon font instead. Indeed, it
is fully cached by the browser and will not have any display glitch. Obviously, the downside is that you have
to load the whole font, but it's cached after the first load. The advantage of using LastIcon over regular icons
is that is allows you to switch easily between one way or the other.

First of all, load your fonts

```html
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Two+Tone" rel="stylesheet">
```

And after that, use the font config to tell Last Icon to use the font over the svg icons

```js
window.LastIcon = {
debug: true,
types: {
material: "twotone",
},
fonts: ["material"]
};
```

And then, update your styles:

```css
l-i {
--size: 1em;
display: inline-flex;
width: var(--size);
height: var(--size);
vertical-align: middle;

svg {
display: block;
width: 100%;
height: 100%;
}
i {
font-size: var(--size) !important;
color: currentColor;
}
}
p,
button,
a,
span {
l-i {
vertical-align: -0.125em;
}
}

.material-icons-two-tone {
background-color: currentColor;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
```

## Demo

See demo.html or the following pen https://codepen.io/lekoalabe/pen/eYvdjqY

0 comments on commit e04ed80

Please sign in to comment.