Last active
January 23, 2020 03:07
-
-
Save dead-claudia/c2ded4a72065a3a9e8fded7e7cb5be75 to your computer and use it in GitHub Desktop.
Mithril port of react-fontawesome
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is a direct API port of https://github.com/FortAwesome/react-fontawesome | |
// to Mithril, with a few optimizations for faster vnode creation and more | |
// efficient normalization. It's also combined into a single UMD file and | |
// written to support a pure ES5 environment without transpiling. It's less than | |
// 200 lines of code excluding this long introductory comment, and is about | |
// 1.2KB min+gzip. | |
// | |
// Here's a few example vnodes: | |
// | |
// ```js | |
// m(FontAwesomeIcon, {icon: "spinner", size: "xs"}) | |
// m(FontAwesomeIcon, {icon: "spinner", fixedWidth: true}) | |
// m(FontAwesomeIcon, {icon: faCoffee}) | |
// ``` | |
// | |
// This file is licensed under the following license (ISC License): | |
// | |
// Copyright (c) 2019 and later, Isiah Meadows <[email protected]>. | |
// | |
// Permission to use, copy, modify, and/or distribute this software for any | |
// purpose with or without fee is hereby granted, provided that the above | |
// copyright notice and this permission notice appear in all copies. | |
// | |
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | |
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | |
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | |
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | |
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE | |
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |
// PERFORMANCE OF THIS SOFTWARE. | |
;(function (factory) { | |
if (typeof module === "object" && module.exports) { | |
module.exports = factory( | |
require("mithril/render/vnode"), | |
require("@fortawesome/fontawesome-svg-core") | |
) | |
} else { | |
window.FontAwesomeIcon = factory(m.vnode, FontAwesome) | |
} | |
})(function (Vnode, FontAwesome) { | |
"use strict" | |
var magicProp = new RegExp("^(" + [ | |
// Mithril keys | |
"key", | |
"oninit", "oncreate", | |
"onbeforeupdate", "onupdate", | |
"onbeforeremove", "onremove", | |
// Style keys | |
"class", "className", | |
// Font Awesome keys | |
"border", "mask", "fixedWidth", "inverse", "flip", "icon", "listItem", | |
"pull", "pulse", "rotation", "size", "spin", "symbol", "title", "transform", | |
].join("|") + ")$") | |
var shouldLog = console && typeof console.error === "function" | |
try { | |
shouldLog = process.env.NODE_ENV !== "production" | |
} catch (e) { | |
// ignore | |
} | |
return { | |
view: function (vnode) { | |
var iconOpts = { | |
symbol: vnode.attrs.symbol, | |
title: vnode.attrs.title, | |
} | |
var classObject = Object.create(null) | |
if (vnode.attrs.spin) classObject["fa-spin"] = true | |
if (vnode.attrs.pulse) classObject["fa-pulse"] = true | |
if (vnode.attrs.fixedWidth) classObject["fa-fw"] = true | |
if (vnode.attrs.inverse) classObject["fa-inverse"] = true | |
if (vnode.attrs.border) classObject["fa-border"] = true | |
if (vnode.attrs.listItem) classObject["fa-li"] = true | |
if (vnode.attrs.flip === "horizontal" || vnode.attrs.flip === "both") { | |
classObject["fa-flip-horizontal"] = true | |
} | |
if (vnode.attrs.flip === "vertical" || vnode.attrs.flip === "both") { | |
classObject["fa-flip-vertical"] = true | |
} | |
if (vnode.attrs.size) { | |
classObject["fa-" + vnode.attrs.size] = true | |
} | |
if (vnode.attrs.rotation) { | |
classObject["fa-rotate-" + vnode.attrs.rotation] = true | |
} | |
if (vnode.attrs.pull) { | |
classObject["fa-pull-" + vnode.attrs.pull] = true | |
} | |
appendClassString(classObject, vnode.attrs.class) | |
appendClassString(classObject, vnode.attrs.className) | |
var classes = Object.keys(classObject) | |
if (classes.length) iconOpts.classes = classes | |
var mask = normalizeIconArgs(vnode.attrs.mask) | |
if (mask) iconOpts.mask = mask | |
var transform = typeof vnode.attrs.transform === "string" | |
? FontAwesome.parse.transform(vnode.attrs.transform) | |
: vnode.attrs.transform | |
if (Array.isArray(transform) ? transform.length : transform) { | |
iconOpts.transform = transform | |
} | |
var iconLookup = normalizeIconArgs(vnode.attrs.icon) | |
var renderedIcon = FontAwesome.icon(iconLookup, iconOpts) | |
if (!renderedIcon) { | |
if (shouldLog) console.error("Could not find icon", iconLookup) | |
return void 0 | |
} | |
var result = convert(renderedIcon.abstract[0]) | |
if (typeof result !== "string") { | |
for (var key in vnode.attrs) { | |
if (Object.prototype.hasOwnProperty.call(vnode.attrs, key)) { | |
if (key === "style") { | |
for (key in vnode.attrs.style) { | |
if (Object.prototype.hasOwnProperty.call( | |
vnode.attrs.style, key | |
)) { | |
result.attrs.style[key] = vnode.attrs.style[key] | |
} | |
} | |
} else if (!magicProp.test(key)) { | |
result.attrs.style[key] = vnode.attrs[key] | |
} | |
} | |
} | |
} | |
return result | |
} | |
} | |
function convert(element) { | |
if (typeof element === "string") { | |
return Vnode("#", void 0, void 0, element, void 0, void 0) | |
} | |
var hasKey = false | |
for (var key in element.attributes) { | |
if (Object.prototype.hasOwnProperty.call(element.attributes, key)) { | |
hasKey = true | |
if (key === "style") { | |
var properties = element.attributes[key].split(";") | |
var target = element.attributes[key] = {} | |
for (var i = 0; i < properties.length; i++) { | |
var pair = properties[i] | |
if (!/^\s*(:\s*)?$/.test(pair)) { | |
var index = pair.indexOf(":") | |
target[pair.slice(0, index).trim()] = | |
pair.slice(index + 1).trim() | |
} | |
} | |
} | |
} | |
} | |
var children, text | |
if (element.children && element.children.length) { | |
if ( | |
element.children.length === 1 && | |
typeof element.children[0] === "string" | |
) { | |
text = element.children[0] | |
} else { | |
children = element.children | |
for (i = 0; i < children.length; i++) { | |
children[i] = convert(children[i]) | |
} | |
} | |
} | |
return Vnode( | |
element.tag, void 0, hasKey ? element.attributes : void 0, | |
children, text, void 0 | |
) | |
} | |
function appendClassString(classObject, string) { | |
if (!string) return | |
var list = string.trim().split(/\s+/g) | |
for (var i = 0; i < list.length; i++) classObject[list[i]] = true | |
} | |
function normalizeIconArgs(icon) { | |
if (typeof icon === "string") { | |
return {prefix: "fas", iconName: icon} | |
} else if (Array.isArray(icon) && icon.length === 2) { | |
return {prefix: icon[0], iconName: icon[1]} | |
} else if (typeof icon === "object" && icon.prefix && icon.iconName) { | |
return icon | |
} else { | |
return void 0 | |
} | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment