Skip to content

Commit

Permalink
feat: Add JavaScript library
Browse files Browse the repository at this point in the history
Add JavaScript library that includes an `icons` object, `toSvg` function and `replace` function.
  • Loading branch information
colebemis authored and Cole Bemis committed Jul 3, 2017
1 parent ae164db commit 71f502f
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/index.js
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 };
54 changes: 54 additions & 0 deletions src/replace.js
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);
}
75 changes: 75 additions & 0 deletions src/to-svg.js
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(' ');
}

0 comments on commit 71f502f

Please sign in to comment.