docs: async function collecticonsCompile (params) {
    const {
      dirPath,
      fontName,
      sassPlaceholder,
      cssClass,
      fontTypes,
      styleFormats,
      styleDest,
      styleName,
      fontDest,
      authorName,
      authorUrl,
      className,
      previewDest,
      preview,
      catalogDest,
      noFileOutput,
  
      experimentalFontOnCatalog,
      experimentalDisableStyles
    } = defaultsDeep({}, params, defaults);
  
    if (experimentalFontOnCatalog) {
      logger.warn('experimentalFontOnCatalog is an experimental feature and may not work as expected and/or change at anytime.');
    }
  
    if (experimentalDisableStyles) {
      logger.warn('experimentalDisableStyles is an experimental feature and may not work as expected and/or change at anytime.');
    }
  
    await validateDirPath(dirPath);
  
    // Validate options incompatibility.
    if (!sassPlaceholder && !cssClass) {
      throw userError(['Error: sassPlaceholder and/or cssClass are required'], 'PLC_CLASS_EXC');
    }
  
    logger.debug('Font types:', fontTypes);
    if (fontTypes.some(t => validFontTypes.indexOf(t) === -1)) {
      throw userError(['Error: invalid font type value'], 'FONT_TYPE');
    }
  
    logger.debug('Styles formats:', styleFormats);
    if (styleFormats.some(t => validStyleFormats.indexOf(t) === -1)) {
      throw userError(['Error: invalid style format value'], 'STYLE_TYPE');
    }
  
    // Verify cssClass with styleFormats.
    if (styleFormats.length === 1 && styleFormats[0] === 'css' && !cssClass) {
      throw userError(['Error: cssClass can not be false when styleFormats is only css'], 'CLASS_CSS_FORMAT');
    }
  
    // Warn about ignores cssCalss for css style when there is more than one style
    if (styleFormats.indexOf('css') !== -1 && !cssClass) {
      logger.warn('cssClass value "false" will be ignored for "css" output.');
    }
  
    const dir = await fs.readdir(dirPath);
    const svgsFiles = dir.filter(o => o.endsWith('.svg'));
  
    logger.debug('Found', svgsFiles.length, 'icons in', dirPath);
    logger.debug(dir);
  
    if (!svgsFiles.length) {
      logger.warn('No icons found in', dirPath);
      return null;
    }
  
    // Unicode Private Use Area start.
    // http://en.wikipedia.org/wiki/Private_Use_(Unicode)
    let currentCodepoint = 0xf101;
  
    // Generates codepoints for each icon.
    const icons = svgsFiles.map(svg => ({
      file: path.resolve('.', dirPath, svg),
      name: path.basename(svg, path.extname(svg)),
      codepoint: currentCodepoint++
    }));
  
    const fonts = await generateFont({
      fontName,
      icons
    });
  
    // Store all files to be, so that they can be written to disk.
    let virtualFiles = [
      // {
      //   path: String
      //   contents: Buffer
      // }
    ];
  
    if (fontDest) {
      logger.debug('Font embed disabled. Fonts will be rendered to', fontDest);
      virtualFiles = virtualFiles.concat(
        fontTypes.map(type => ({
          path: path.join(fontDest, `${fontName}.${type}`),
          contents: fonts[type]
        }))
      );
    }
  
    let includedFonts = {};
    if (fontTypes.indexOf('woff') !== -1) {
      includedFonts = {
        ...includedFonts,
        woff: {
          contents: fonts.woff,
          path: path.relative(styleDest, path.join(fontDest || '', `${fontName}.woff`))
        }
      };
    }
  
    if (fontTypes.indexOf('woff2') !== -1) {
      includedFonts = {
        ...includedFonts,
        woff2: {
          contents: fonts.woff2,
          path: path.relative(styleDest, path.join(fontDest || '', `${fontName}.woff2`))
        }
      };
    }
  
    const styleOptions = {
      fontName,
      embed: !fontDest,
      fonts: includedFonts,
      authorName,
      authorUrl,
      className,
      icons,
      sassPlaceholder,
      cssClass,
      dateFormatted: process.env.NODE_ENV === 'test' ? 'January 1st, 2019' : formatHumanDate(new Date())
    };
  
    if (!experimentalDisableStyles && styleFormats.indexOf('sass') !== -1) {
      logger.debug('Rendering sass file');
      virtualFiles = virtualFiles.concat({
        path: path.join(styleDest, `${styleName}.scss`),
        contents: Buffer.from(await renderSass(styleOptions))
      });
    }
  
    if (!experimentalDisableStyles && styleFormats.indexOf('css') !== -1) {
      logger.debug('Rendering css file');
      virtualFiles = virtualFiles.concat({
        path: path.join(styleDest, `${styleName}.css`),
        contents: Buffer.from(await renderCss(styleOptions))
      });
    }
  
    if (preview) {
      logger.debug('Rendering preview file');
      virtualFiles = virtualFiles.concat({
        path: path.join(previewDest, 'preview.html'),
        contents: Buffer.from(await renderPreview({
          fontName,
          font: { contents: fonts.woff2 },
          className,
          icons
        }))
      });
    }
  
    if (catalogDest) {
      logger.debug('Rendering catalog file');
      virtualFiles = virtualFiles.concat({
        path: path.join(catalogDest, 'catalog.json'),
        contents: Buffer.from(await renderCatalog({
          fontName,
          fonts: experimentalFontOnCatalog ? includedFonts : null,
          className,
          icons
        }))
      });
    }
  
    logger.debug('All files rendered');
    logger.debug(virtualFiles);
  
    if (noFileOutput) return virtualFiles;
  
    return Promise.all(virtualFiles.map(async (file) => {
      await fs.ensureDir(path.dirname(file.path));
      await fs.writeFile(file.path, file.contents);
    }));
  }