replace.js 1.57 KB
Newer Older
Cole Bemis's avatar
Cole Bemis committed
1 2
/* eslint-env browser */
import classnames from 'classnames/dedupe';
3

Cole Bemis's avatar
Cole Bemis committed
4
import icons from './icons';
5 6

/**
Cole Bemis's avatar
Cole Bemis committed
7
 * Replace all HTML elements that have a `data-feather` attribute with SVG markup
8
 * corresponding to the element's `data-feather` attribute value.
Cole Bemis's avatar
Cole Bemis committed
9
 * @param {Object} attrs
10
 */
Cole Bemis's avatar
Cole Bemis committed
11
function replace(attrs = {}) {
12 13 14 15 16 17
  if (typeof document === 'undefined') {
    throw new Error('`feather.replace()` only works in a browser environment.');
  }

  const elementsToReplace = document.querySelectorAll('[data-feather]');

Cole Bemis's avatar
Cole Bemis committed
18 19 20
  Array.from(elementsToReplace).forEach(element =>
    replaceElement(element, attrs),
  );
21 22 23
}

/**
Cole Bemis's avatar
Cole Bemis committed
24
 * Replace a single HTML element with SVG markup
25
 * corresponding to the element's `data-feather` attribute value.
Cole Bemis's avatar
Cole Bemis committed
26 27
 * @param {HTMLElement} element
 * @param {Object} attrs
28
 */
Cole Bemis's avatar
Cole Bemis committed
29 30 31 32 33 34 35 36 37 38 39 40 41
function replaceElement(element, attrs = {}) {
  const elementAttrs = getAttrs(element);
  const name = elementAttrs['data-feather'];
  delete elementAttrs['data-feather'];

  const svgString = icons[name].toSvg({
    ...attrs,
    ...elementAttrs,
    ...{ class: classnames(attrs.class, elementAttrs.class) },
  });
  const svgDocument = new DOMParser().parseFromString(
    svgString,
    'image/svg+xml',
42 43 44 45 46
  );
  const svgElement = svgDocument.querySelector('svg');

  element.parentNode.replaceChild(svgElement, element);
}
Cole Bemis's avatar
Cole Bemis committed
47 48 49 50 51 52 53 54 55 56 57 58 59 60

/**
 * Get the attributes of an HTML element.
 * @param {HTMLElement} element
 * @returns {Object}
 */
function getAttrs(element) {
  return Array.from(element.attributes).reduce((attrs, attr) => {
    attrs[attr.name] = attr.value;
    return attrs;
  }, {});
}

export default replace;