function SVGSpriteBase(spriter, config, data, key) {
  this._spriter = spriter;
  this.config = config;
  this.key = key || this.mode;
  this.data = data;
  this.data.mode = this.mode;
  this.data.key = this.key;

  // Resolve file paths
  this.config.dest = path.resolve(this._spriter.config.dest, this.config.dest);

  if ('sprite' in this.config) {
    const spritePath = path.dirname(this.config.sprite);
    let spriteName = path.basename(this.config.sprite) || 'sprite';

    if (!spriteName.includes('.')) {
      spriteName += '.svg';
    }

    this.config.sprite = path.resolve(this.config.dest, path.join(spritePath, spriteName));
  }

  // Prepare the rendering configurations
  if ('render' in this.config && isObject(this.config.render)) {
    for (const [extension, value] of Object.entries(this.config.render)) {
      const folder = path.dirname(path.dirname(path.dirname(__dirname)));
      const file = path.join('tmpl', this.tmpl, `sprite.${extension}`);
      const renderConfig = {
        template: path.resolve(folder, file),
        dest: path.join(this.config.dest, `sprite.${extension}`)
      };

      if (isObject(value)) {
        if ('template' in value) {
          renderConfig.template = path.resolve(process.cwd(), value.template);
        }

        if ('dest' in value) {
          renderConfig.dest = path.resolve(this.config.dest, value.dest);
          if (!new RegExp(`\\.${extension}$`, 'i').test(renderConfig.dest)) {
            renderConfig.dest += `.${extension}`;
          }
        }
      } else if (value !== true) {
        delete this.config.render[extension];
        continue;
      }

      this.config.render[extension] = renderConfig;
    }

    this._cssDest = 'css' in this.config.render ? path.dirname(this.config.render.css.dest) : this.config.dest;
  } else {
    this._cssDest = this.config.dest;
  }

  // Cache busting
  this.config.bust = Boolean(this.config.bust);

  // Prepare the CSS prefix
  this.config.prefix = this.config.prefix.trim();
  if (!/%s/g.test(this.config.prefix.split('%%').join(''))) {
    this.config.prefix += '%s';
  }

  // Refine the base data
  this.data = merge(this.data, this._initData({
    padding: this._spriter.config.shape.spacing.padding,
    sprite: path.relative(this._cssDest, this.config.sprite).split(path.sep).join('/')
  }));

  this._init();
}
Sprite base class

@param {SVGSpriter} spriter      SVG spriter
@param {object} config           Configuration
@param {object} data             Base data
@param {string} key              Mode key