feat: Add JavaScript library

Add JavaScript library that includes an `icons` object, `toSvg` function and `replace` function.
This commit is contained in:
Cole Bemis 2017-07-03 15:05:29 -07:00 committed by Cole Bemis
parent ae164db70f
commit 71f502fc95
3 changed files with 138 additions and 0 deletions

9
src/index.js Normal file
View File

@ -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 };

54
src/replace.js Normal file
View File

@ -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);
}

75
src/to-svg.js Normal file
View File

@ -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(' ');
}