-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add JavaScript library that includes an `icons` object, `toSvg` function and `replace` function.
- Loading branch information
Showing
3 changed files
with
138 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/** | ||
* @file Exposes `feather` object. | ||
*/ | ||
|
||
import icons from '../dist/icons.json'; | ||
import toSvg from './to-svg'; | ||
import replace from './replace'; | ||
|
||
module.exports = { icons, toSvg, replace }; |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/** | ||
* @file Implements `replace` function. | ||
*/ | ||
|
||
/* global document, DOMParser */ | ||
|
||
import icons from '../dist/icons.json'; | ||
import toSvg from './to-svg'; | ||
|
||
/** | ||
* Replace all elements that have a `data-feather` attribute with SVG markup | ||
* corresponding to the element's `data-feather` attribute value. | ||
* @param {Object} options | ||
*/ | ||
export default function replace(options = {}) { | ||
if (typeof document === 'undefined') { | ||
throw new Error('`feather.replace()` only works in a browser environment.'); | ||
} | ||
|
||
const elementsToReplace = document.querySelectorAll('[data-feather]'); | ||
|
||
Array.from(elementsToReplace).forEach(element => replaceElement(element, options)); | ||
} | ||
|
||
/** | ||
* Replace single element with SVG markup | ||
* corresponding to the element's `data-feather` attribute value. | ||
* @param {Element} element | ||
* @param {Object} options | ||
*/ | ||
function replaceElement(element, options) { | ||
const key = element.getAttribute('data-feather'); | ||
|
||
if (!key) { | ||
console.error('The required `data-feather` attribute has no value.'); | ||
return; | ||
} | ||
|
||
if (!icons[key]) { | ||
console.error(`No icon matching '${key}'. See the complete list of icons at https://feathericons.com`); | ||
return; | ||
} | ||
|
||
const elementClassAttr = element.getAttribute('class'); | ||
const classNames = ( | ||
options.class ? `${options.class} ${elementClassAttr}` : elementClassAttr | ||
); | ||
|
||
const svgString = toSvg(key, Object.assign({}, options, { class: classNames })); | ||
const svgDocument = new DOMParser().parseFromString(svgString, 'image/svg+xml'); | ||
const svgElement = svgDocument.querySelector('svg'); | ||
|
||
element.parentNode.replaceChild(svgElement, element); | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/** | ||
* @file Implements `toSvg` function. | ||
*/ | ||
|
||
import icons from '../dist/icons.json'; | ||
|
||
const DEFAULT_OPTIONS = { | ||
xmlns: 'http://www.w3.org/2000/svg', | ||
width: 24, | ||
height: 24, | ||
viewBox: '0 0 24 24', | ||
fill: 'none', | ||
stroke: 'currentColor', | ||
'stroke-width': 2, | ||
'stroke-linecap': 'round', | ||
'stroke-linejoin': 'round', | ||
}; | ||
|
||
/** | ||
* Create an SVG string. | ||
* @param {string} key - Icon name. | ||
* @param {Object} options | ||
* @returns {string} | ||
*/ | ||
export default function toSvg(key, options = {}) { | ||
if (!key) { | ||
throw new Error('The required `key` (icon name) parameter is missing.'); | ||
} | ||
|
||
if (!icons[key]) { | ||
throw new Error(`No icon matching '${key}'. See the complete list of icons at https://feathericons.com`); | ||
} | ||
|
||
const combinedOptions = Object.assign({}, DEFAULT_OPTIONS, options); | ||
|
||
combinedOptions.class = addDefaultClassNames(combinedOptions.class, key); | ||
|
||
const attributes = optionsToAtrributes(combinedOptions); | ||
|
||
return `<svg ${attributes}>${icons[key]}</svg>`; | ||
} | ||
|
||
/** | ||
* Add default class names. | ||
* @param {string} classNames - One or more class names seperated by spaces. | ||
* @param {string} key - Icon name. | ||
* @returns {string} | ||
*/ | ||
function addDefaultClassNames(classNames, key) { | ||
// convert class names string into an array | ||
const classNamesArray = classNames ? classNames.trim().split(/\s+/) : []; | ||
|
||
// use Set to avoid duplicate class names | ||
const classNamesSet = new Set(classNamesArray); | ||
|
||
// add default class names | ||
classNamesSet.add('feather').add(`feather-${key}`); | ||
|
||
return Array.from(classNamesSet).join(' '); | ||
} | ||
|
||
/** | ||
* Convert options object to string of html attributes. | ||
* @param {Object} options | ||
* @returns {string} | ||
*/ | ||
function optionsToAtrributes(options) { | ||
const attributes = []; | ||
|
||
Object.keys(options).forEach(key => { | ||
attributes.push(`${key}="${options[key]}"`); | ||
}); | ||
|
||
return attributes.join(' '); | ||
} |