All files / src avdo.ts

90.7% Statements 39/43
64.29% Branches 9/14
83.33% Functions 10/12
92.31% Lines 36/39
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 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102    1x 1x 1x 1x 1x 1x 1x 1x 1x                         1x                                         1x 6x   6x 6x 1x   5x   6x                         1x 2x 1x     1x 1x 1x 1x 1x 1x 1x       1x     1x 1x       1x 1x 1x     1x 1x         1x  
import { JsApi } from './jsapi';
import { Plugin } from './plugins/_types';
import { collapseGroups } from './plugins/collapseGroups';
import { convertPathData } from './plugins/convertPathData';
import { js2xml } from './js2xml';
import { mergePaths } from './plugins/mergePaths';
import { processPlugins } from './plugins/_plugins';
import { removeComments } from './plugins/removeComments';
import { removeEmptyGroups } from './plugins/removeEmptyGroups';
import { removeXMLProcInst } from './plugins/removeXMLProcInst';
import { xml2js } from './xml2js';
 
// import * as cleanupAttrs from './plugins/cleanupAttrs';
// import * as cleanupIDs from './plugins/cleanupIDs';
// import * as cleanupNumericValues from './plugins/cleanupNumericValues';
// import * as convertColors from './plugins/convertColors';
// import * as removeUnknownsAndDefaults from './plugins/removeUnknownsAndDefaults';
// import * as removeUselessStrokeAndFill from './plugins/removeUselessStrokeAndFill';
// import * as removeHiddenElems from './plugins/removeHiddenElems';
// import * as convertTransform from './plugins/convertTransform';
// import * as removeUnusedNS from './plugins/removeUnusedNS';
// import * as sortAttrs from './plugins/sortAttrs';
 
export const plugins: { [name: string]: Plugin } = {
  // The order is from https://github.com/svg/svgo/blob/master/.svgo.yml
  removeXMLProcInst,
  removeComments,
  // cleanupAttrs,
  // cleanupIDs,
  // cleanupNumericValues,
  // convertColors,
  // removeUnknownsAndDefaults,
  // removeUselessStrokeAndFill,
  // removeHiddenElems,
  collapseGroups,
  convertPathData,
  // convertTransform,
  removeEmptyGroups,
  mergePaths,
  // removeUnusedNS,
  // sortAttrs,
};
 
// Arrange plugins by type - this is what plugins() expects.
const optimizedPluginsData = (function(plugins: Plugin[]) {
  return plugins.map(item => [item]).reduce(
    (arr, item) => {
      const last = arr[arr.length - 1];
      if (last && item[0].type === last[0].type) {
        last.push(item[0]);
      } else {
        arr.push(item);
      }
      return arr;
    },
    [] as Plugin[][]
  );
})(Array.from(Object.values(plugins)));
 
export interface Options {
  plugins?: Plugin[][];
  multipass?: boolean;
  // TODO: make it possible to configure indentation too
  pretty?: boolean;
}
 
export class Avdo {
  constructor(private readonly Ioptions: Options = {}) {
    options.plugins = options.plugins || optimizedPluginsData;
  }
 
  optimize(xml: string): Promise<string> {
    return new Promise((resolve, reject) => {
      const maxPassCount = this.options.multipass ? 10 : 1;
      let counter = 0;
      let prevResultSize = Number.POSITIVE_INFINITY;
      const onSuccess = (result: string) => {
        Iif (++counter < maxPassCount && result.length < prevResultSize) {
          prevResultSize = result.length;
          this.optimizeOnce(result, onSuccess, onFail);
        } else {
          resolve(result);
        }
      };
      const onFail = error => reject(error);
      this.optimizeOnce(xml, onSuccess, onFail);
    });
  }
 
  private optimizeOnce(xml: string, onSuccess, onFail) {
    const { options } = this;
    xml2js(
      xml,
      jsApi => {
        jsApi = processPlugins(jsApi, options.plugins);
        onSuccess(js2xml(jsApi, { pretty: options.pretty }));
      },
      error => onFail(error),
    );
  }
}