build-json.js 1.73 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
/**
 * @file Builds `icons.json` from `icons` directory.
 */

/* eslint-disable import/no-extraneous-dependencies */
import fs from 'fs';
import path from 'path';
import RSVP from 'rsvp';
import Svgo from 'svgo';
import parse5 from 'parse5';

const svgFiles = fs.readdirSync(path.resolve(__dirname, '../icons'))
  .filter(file => path.extname(file) === '.svg');

buildIconsObject(svgFiles)
  .then(icons => {
    fs.writeFileSync(
      path.resolve(__dirname, '../dist/icons.json'),
      JSON.stringify(icons),
    );
  });

/**
 * Build an icons object in the format: `{ <icon name>: <svg content> }`.
 * @param {string[]} svgFiles - A list of file names.
 * @returns {RSVP.Promise<Object>}
 */
function buildIconsObject(svgFiles) {
  const icons = {};

  svgFiles.forEach(svgFile => {
    const svg = fs.readFileSync(path.resolve(__dirname, '../icons', svgFile), 'utf8');
    const key = path.basename(svgFile, '.svg');

    icons[key] = optimizeSvg(svg)
      .then(optimizedSvg => getSvgContent(optimizedSvg));
  });

  return RSVP.hash(icons);
}

/**
 * Optimize SVG with `svgo`.
 * @param {string} svg - An SVG string.
 * @returns {RSVP.Promise<string>}
 */
function optimizeSvg(svg) {
  // configure svgo
  const svgo = new Svgo({
    plugins: [
      { convertShapeToPath: false },
      { mergePaths: false },
      { removeAttrs: { attrs: '(fill|stroke.*)' } },
    ],
  });

  return new RSVP.Promise(resolve => {
    svgo.optimize(svg, ({ data }) => resolve(data));
  });
}

/**
 * Get content between opening and closing `<svg>` tags.
 * @param {string} svg - An SVG string.
 * @returns {string}
 */
function getSvgContent(svg) {
  const fragment = parse5.parseFragment(svg);
  const content = parse5.serialize(fragment.childNodes[0]);
  return content;
}