text: /*
    All configurable options are defined inside build.config
    Please adjust this to your site's settings
  */
  
  /*******************************
              Set-up
  *******************************/
  
  
  var
    gulp         = require('gulp-help')(require('gulp')),
  
    // node components & oddballs
    console      = require('better-console'),
    del          = require('del'),
    extend       = require('extend'),
    fs           = require('fs'),
    path         = require('path'),
    runSequence  = require('run-sequence'),
    wrench       = require('wrench'),
  
    // gulp dependencies
    autoprefixer = require('gulp-autoprefixer'),
    clone        = require('gulp-clone'),
    concat       = require('gulp-concat'),
    concatCSS    = require('gulp-concat-css'),
    copy         = require('gulp-copy'),
    debug        = require('gulp-debug'),
    flatten      = require('gulp-flatten'),
    header       = require('gulp-header'),
    jeditor      = require('gulp-json-editor'),
    karma        = require('gulp-karma'),
    less         = require('gulp-less'),
    minifyCSS    = require('gulp-minify-css'),
    notify       = require('gulp-notify'),
    plumber      = require('gulp-plumber'),
    print        = require('gulp-print'),
    prompt       = require('gulp-prompt'),
    rename       = require('gulp-rename'),
    replace      = require('gulp-replace'),
    sourcemaps   = require('gulp-sourcemaps'),
    uglify       = require('gulp-uglify'),
    util         = require('gulp-util'),
    watch        = require('gulp-watch'),
  
    // config
    banner       = require('./tasks/banner'),
    commonjs_header = require('./tasks/commonjs_header'),
    comments     = require('./tasks/comments'),
    defaults     = require('./tasks/defaults'),
    log          = require('./tasks/log'),
    questions    = require('./tasks/questions'),
    settings     = require('./tasks/gulp-settings'),
  
    // admin
    release      = require('./tasks/admin/release'),
    git          = require('gulp-git'),
    githubAPI    = require('github'),
  
    oAuth        = fs.existsSync('./tasks/admin/oauth.js')
      ? require('./tasks/admin/oauth')
      : false,
    github,
  
  
    // local
    runSetup   = false,
    overwrite  = true,
    config,
    package,
    github,
  
    version,
  
    // derived
    base,
    clean,
    output,
    source,
    assetPaths,
    componentGlob,
  
    // temporary
    folder
  ;
  
  
  /*******************************
            Read Settings
  *******************************/
  
  try {
    // try to load json
    var
      config  = require(defaults.files.config),
      package = (fs.existsSync(defaults.files.npm))
        ? require(defaults.files.npm)
        : false
    ;
  }
  catch(error) {
    if(error.code === 'MODULE_NOT_FOUND') {
      console.error('No semantic.json config found');
    }
    var config = false;
  }
  
  /*******************************
     Values Derived From Config
  *******************************/
  
  var
    getConfigValues = function() {
  
      if(!config) {
        runSetup = true;
        config = defaults;
      }
      config = extend(true, {}, defaults, config);
  
      // shorthand
      base    = config.base;
      clean   = config.paths.clean;
      output  = config.paths.output;
      source  = config.paths.source;
  
      version = (package !== undefined)
        ? package.version || 'Unknown'
        : 'Unknown'
      ;
  
      // create glob for matching filenames from components in semantic.json
      componentGlob = (typeof config.components == 'object')
        ? (config.components.length > 1)
          ? '{' + config.components.join(',') + '}'
          : config.components[0]
        : ''
      ;
  
      // relative paths
      assetPaths = {
        uncompressed : path.relative(output.uncompressed, output.themes),
        compressed   : path.relative(output.compressed, output.themes),
        packaged     : path.relative(output.packaged, output.themes)
      };
  
      // add base to values
      for(var folder in source) {
        if(source.hasOwnProperty(folder)) {
          source[folder] = path.normalize(base + source[folder]);
        }
      }
      for(folder in output) {
        if(output.hasOwnProperty(folder)) {
          output[folder] = path.normalize(base + output[folder]);
        }
      }
      clean = base + clean;
    }
  ;
  
  getConfigValues();
  
  /*******************************
               Tasks
  *******************************/
  
  gulp.task('default', false, [
    'check install'
  ]);
  
  gulp.task('watch', 'Watch for site/theme changes (Default Task)', function(callback) {
  
    console.log('Watching source files for changes');
  
    if(!fs.existsSync(config.files.theme)) {
      console.error('Cant compile LESS. Run "gulp install" to create a theme config file');
      return;
    }
  
  
    // watching changes in style
    gulp
      .watch([
        source.config,
        source.definitions   + '**/*.less',
        source.site          + '**/*.{overrides,variables}',
        source.themes        + '**/*.{overrides,variables}'
      ], function(file) {
        var
          srcPath,
          stream,
          compressedStream,
          uncompressedStream
        ;
  
        gulp.src(file.path)
          .pipe(print(log.modified))
        ;
  
        // recompile only definition file
        srcPath = util.replaceExtension(file.path, '.less');
        srcPath = srcPath.replace(config.regExp.themePath, source.definitions);
        srcPath = srcPath.replace(source.site, source.definitions);
  
        // get relative asset path (path returns wrong path? hardcoded)
        assetPaths.source = path.relative(srcPath, path.resolve(source.themes));
        // assetPaths.source = '../../themes';
  
  
        if( fs.existsSync(srcPath) ) {
  
          // unified css stream
          stream = gulp.src(srcPath)
            .pipe(plumber())
            //.pipe(sourcemaps.init())
            .pipe(less(settings.less))
            .pipe(replace(comments.variables.in, comments.variables.out))
            .pipe(replace(comments.large.in, comments.large.out))
            .pipe(replace(comments.small.in, comments.small.out))
            .pipe(replace(comments.tiny.in, comments.tiny.out))
            .pipe(autoprefixer(settings.prefix))
          ;
  
          // use 2 concurrent streams from same source
          uncompressedStream = stream.pipe(clone());
          compressedStream   = stream.pipe(clone());
  
          uncompressedStream
            .pipe(plumber())
            .pipe(replace(assetPaths.source, assetPaths.uncompressed))
            //.pipe(sourcemaps.write('/', settings.sourcemap))
            .pipe(header(banner, settings.header))
            .pipe(gulp.dest(output.uncompressed))
            .pipe(print(log.created))
            .on('end', function() {
              gulp.start('package uncompressed css');
            })
          ;
  
          compressedStream = stream
            .pipe(plumber())
            .pipe(clone())
            .pipe(replace(assetPaths.source, assetPaths.compressed))
            .pipe(minifyCSS(settings.minify))
            .pipe(rename(settings.rename.minCSS))
            //.pipe(sourcemaps.write('/', settings.sourcemap))
            .pipe(header(banner, settings.header))
            .pipe(gulp.dest(output.compressed))
            .pipe(print(log.created))
            .on('end', function() {
              gulp.start('package compressed css');
            })
          ;
  
        }
      })
    ;
  
    // watch changes in assets
    gulp
      .watch([
        source.themes   + '**/assets/**'
      ], function(file) {
        // copy assets
        gulp.src(file.path, { base: source.themes })
          .pipe(gulp.dest(output.themes))
          .pipe(print(log.created))
        ;
      })
    ;
  
    // watch changes in js
    gulp
      .watch([
        source.definitions   + '**/*.js'
      ], function(file) {
        gulp.src(file.path)
          .pipe(plumber())
          .pipe(gulp.dest(output.uncompressed))
          .pipe(print(log.created))
          .pipe(sourcemaps.init())
          .pipe(uglify(settings.uglify))
          .pipe(rename(settings.rename.minJS))
          .pipe(gulp.dest(output.compressed))
          .pipe(print(log.created))
          .on('end', function() {
            gulp.start('package compressed js');
            gulp.start('package uncompressed js');
          })
        ;
      })
    ;
  
  });
  
  // Builds all files
  gulp.task('build', 'Builds all files from source', function(callback) {
    var
      stream,
      compressedStream,
      uncompressedStream
    ;
  
    console.info('Building Semantic');
  
    if(!fs.existsSync(config.files.theme)) {
      console.error('Cant build LESS. Run "gulp install" to create a theme config file');
      return;
    }
  
    // get relative asset path (path returns wrong path?)
    // assetPaths.source = path.relative(srcPath, path.resolve(source.themes));
    assetPaths.source = '../../themes'; // hardcoded
  
    // copy assets
    gulp.src(source.themes + '**/assets/**')
      .pipe(gulp.dest(output.themes))
    ;
  
    // javascript stream
    gulp.src(source.definitions + '**/*.js')
      .pipe(plumber())
      .pipe(flatten())
      .pipe(gulp.dest(output.uncompressed))
      .pipe(print(log.created))
      // .pipe(sourcemaps.init())
      .pipe(uglify(settings.uglify))
      .pipe(rename(settings.rename.minJS))
      .pipe(header(banner, settings.header))
      .pipe(gulp.dest(output.compressed))
      .pipe(print(log.created))
      .on('end', function() {
        gulp.start('package compressed js');
        gulp.start('package uncompressed js');
      })
    ;
  
    // unified css stream
    stream = gulp.src(source.definitions + '**/*.less')
      .pipe(plumber())
      //.pipe(sourcemaps.init())
      .pipe(less(settings.less))
      .pipe(flatten())
      .pipe(replace(comments.variables.in, comments.variables.out))
      .pipe(replace(comments.large.in, comments.large.out))
      .pipe(replace(comments.small.in, comments.small.out))
      .pipe(replace(comments.tiny.in, comments.tiny.out))
      .pipe(autoprefixer(settings.prefix))
    ;
  
    // use 2 concurrent streams from same source to concat release
    uncompressedStream = stream.pipe(clone());
    compressedStream   = stream.pipe(clone());
  
    uncompressedStream
      .pipe(plumber())
      .pipe(replace(assetPaths.source, assetPaths.uncompressed))
      //.pipe(sourcemaps.write('/', settings.sourcemap))
      .pipe(header(banner, settings.header))
      .pipe(gulp.dest(output.uncompressed))
      .pipe(print(log.created))
      .on('end', function() {
        gulp.start('package uncompressed css');
      })
    ;
  
    compressedStream = stream
      .pipe(plumber())
      .pipe(clone())
      .pipe(replace(assetPaths.source, assetPaths.compressed))
      .pipe(minifyCSS(settings.minify))
      .pipe(rename(settings.rename.minCSS))
      //.pipe(sourcemaps.write('/', settings.sourcemap))
      .pipe(header(banner, settings.header))
      .pipe(gulp.dest(output.compressed))
      .pipe(print(log.created))
      .on('end', function() {
        callback();
        gulp.start('package compressed css');
      })
    ;
  
  });
  
  // cleans distribution files
  gulp.task('clean', 'Clean dist folder', function(callback) {
    return del([clean], settings.del, callback);
  });
  
  gulp.task('version', 'Displays current version of Semantic', function(callback) {
    console.log('Semantic UI ' + version);
  });
  
  /*--------------
      Internal
  ---------------*/
  
  gulp.task('package uncompressed css', false, function() {
    return gulp.src(output.uncompressed + '**/' + componentGlob + '!(*.min|*.map).css')
      .pipe(plumber())
      .pipe(replace(assetPaths.uncompressed, assetPaths.packaged))
      .pipe(concatCSS('semantic.css'))
        .pipe(gulp.dest(output.packaged))
        .pipe(print(log.created))
    ;
  });
  
  gulp.task('package compressed css', false, function() {
    return gulp.src(output.uncompressed + '**/' + componentGlob + '!(*.min|*.map).css')
      .pipe(plumber())
      .pipe(replace(assetPaths.uncompressed, assetPaths.packaged))
      .pipe(concatCSS('semantic.min.css'))
        .pipe(minifyCSS(settings.minify))
        .pipe(header(banner, settings.header))
        .pipe(gulp.dest(output.packaged))
        .pipe(print(log.created))
    ;
  });
  
  gulp.task('package uncompressed js', false, function() {
    return gulp.src(output.uncompressed + '**/' + componentGlob + '!(*.min|*.map).js')
      .pipe(plumber())
      .pipe(replace(assetPaths.uncompressed, assetPaths.packaged))
      .pipe(concat('semantic.js'))
        .pipe(header(commonjs_header))
        .pipe(header(banner, settings.header))
        .pipe(gulp.dest(output.packaged))
        .pipe(print(log.created))
    ;
  });
  
  gulp.task('package compressed js', false, function() {
    return gulp.src(output.uncompressed + '**/' + componentGlob + '!(*.min|*.map).js')
      .pipe(plumber())
      .pipe(replace(assetPaths.uncompressed, assetPaths.packaged))
      .pipe(concat('semantic.min.js'))
        .pipe(uglify(settings.uglify))
        .pipe(header(banner, settings.header))
        .pipe(gulp.dest(output.packaged))
        .pipe(print(log.created))
    ;
  });
  
  
  /*--------------
       Config
  ---------------*/
  
  gulp.task('check install', false, function () {
    setTimeout(function() {
      if( runSetup || !fs.existsSync(config.files.site)) {
        console.log('No semantic.json file found. Starting install...');
        gulp.start('install');
      }
      else {
        gulp.start('watch');
      }
    }, 50);
  });
  
  gulp.task('install', 'Set-up project for first time', function () {
    console.clear();
    gulp
      .src('gulpfile.js')
      .pipe(prompt.prompt(questions.setup, function(answers) {
        var
          siteVariable      = /@siteFolder .*\'(.*)/mg,
  
          siteDestination   = answers.site || config.folders.site,
  
          pathToSite        = path.relative(path.resolve(config.folders.theme), path.resolve(siteDestination)),
          sitePathReplace   = "@siteFolder   : '" + pathToSite + "/';",
  
          configExists      = fs.existsSync(config.files.config),
          themeConfigExists = fs.existsSync(config.files.theme),
          siteExists        = fs.existsSync(siteDestination),
  
          jsonSource        = (configExists)
            ? config.files.config
            : config.templates.config,
          json = {
            paths: {
              source: {},
              output: {}
            }
          }
        ;
  
        // exit if config exists and user specifies no overwrite
        if(answers.overwrite !== undefined && answers.overwrite == 'no') {
          return;
        }
  
        console.clear();
        console.log('Installing');
        console.log('------------------------------');
  
        // create site files
        if(siteExists) {
          console.info('Site folder exists, merging files (no overwrite)', siteDestination);
        }
        else {
          console.info('Creating site theme folder', siteDestination);
        }
        // copy recursively without overwrite
        wrench.copyDirSyncRecursive(config.templates.site, siteDestination, settings.wrench.recursive);
  
        // adjust less variable for site folder location
        console.info('Adjusting @siteFolder', sitePathReplace);
        if(themeConfigExists) {
          gulp.src(config.files.site)
            .pipe(plumber())
            .pipe(replace(siteVariable, sitePathReplace))
            .pipe(gulp.dest(config.folders.theme))
          ;
        }
        else {
          console.info('Creating src/theme.config (LESS config)');
          gulp.src(config.templates.theme)
            .pipe(plumber())
            .pipe(rename({ extname : '' }))
            .pipe(replace(siteVariable, sitePathReplace))
            .pipe(gulp.dest(config.folders.theme))
          ;
        }
  
  
        // determine semantic.json config
        if(answers.components) {
          json.components = answers.components;
        }
        if(answers.dist) {
          answers.dist = answers.dist;
          json.paths.output = {
            packaged     : answers.dist + '/',
            uncompressed : answers.dist + '/components/',
            compressed   : answers.dist + '/components/',
            themes       : answers.dist + '/themes/'
          };
        }
        if(answers.site) {
          json.paths.source.site = answers.site + '/';
        }
        if(answers.packaged) {
          json.paths.output.packaged = answers.packaged + '/';
        }
        if(answers.compressed) {
          json.paths.output.compressed = answers.compressed + '/';
        }
        if(answers.uncompressed) {
          json.paths.output.uncompressed = answers.uncompressed + '/';
        }
  
        // write semantic.json
        if(configExists) {
          console.info('Extending semantic.json (Gulp config)');
          gulp.src(jsonSource)
            .pipe(plumber())
            .pipe(rename(settings.rename.json)) // preserve file extension
            .pipe(jeditor(json))
            .pipe(gulp.dest('./'))
          ;
        }
        else {
          console.info('Creating semantic.json (Gulp config)');
          gulp.src(jsonSource)
            .pipe(plumber())
            .pipe(rename({ extname : '' })) // remove .template from ext
            .pipe(jeditor(json))
            .pipe(gulp.dest('./'))
          ;
        }
        console.log('');
        console.log('');
      }))
      .pipe(prompt.prompt(questions.cleanup, function(answers) {
        if(answers.cleanup == 'yes') {
          del(config.setupFiles);
        }
        if(answers.build == 'yes') {
          config = require(config.files.config);
          getConfigValues();
          gulp.start('build');
        }
      }))
    ;
  });
  
  /*******************************
            Admin Tasks
  *******************************/
  
  var
    adminQuestions = require('./tasks/admin/questions'),
    newVersion = false
  ;
  
  /* Moves watched files to static site generator output */
  gulp.task('serve-docs', false, function () {
    config = require('./tasks/admin/docs.json');
    getConfigValues();
  
  
    // copy source files
    gulp
      .watch([
        'src/**/*.*'
      ], function(file) {
        console.clear();
        return gulp.src(file.path, { base: 'src/' })
          .pipe(gulp.dest(output.less))
          .pipe(print(log.created))
        ;
      })
    ;
    gulp.start('watch');
  });
  
  
  /* Builds files to docs source */
  gulp.task('build-docs', false, function () {
    console.clear();
    // pushes to docpad files
    config = require('./tasks/admin/docs.json');
    getConfigValues();
    gulp.start('build');
  
    // copy source
    gulp.src('src/**/*.*')
      .pipe(gulp.dest(output.less))
      .pipe(print(log.created))
    ;
  
  });
  
  
  /* Release */
  gulp.task('release', false, function() {
    // gulp bump
    // Ask for release type (minor, major, patch)
    // Bump package.json
    // Bump composer.json
    if(!oAuth) {
      console.error('Must add node include tasks/admin/oauth.js with oauth token for GitHub');
      return;
    }
  
    github = new githubAPI({
      version    : '3.0.0',
      debug      : true,
      protocol   : 'https',
      timeout    : 5000
    });
  
    github.authenticate({
      type: 'oauth',
      token: oAuth.token
    });
  
    // gulp build
    //runSequence('update git');
    runSequence('build', 'create repos', 'update git');
  
    // #Create SCSS Version
    // #Create RTL Release
  
  });
  
  /* Build Component Release Only */
  gulp.task('build release', false, function() {
    runSequence('build', 'create repos');
  });
  
  
  /*--------------
      Internal
  ---------------*/
  
  
  gulp.task('create repos', false, function(callback) {
    var
      stream,
      index,
      tasks = []
    ;
  
    for(index in release.components) {
  
      var
        component            = release.components[index]
      ;
  
      // streams... designed to save time and make coding fun...
      (function(component) {
  
        var
          outputDirectory      = release.outputRoot + component,
          isJavascript         = fs.existsSync(output.compressed + component + '.js'),
          isCSS                = fs.existsSync(output.compressed + component + '.css'),
          capitalizedComponent = component.charAt(0).toUpperCase() + component.slice(1),
          packageName          = release.packageRoot + component,
          repoName             = release.repoRoot + capitalizedComponent,
          gitURL               = 'https://github.com/' + release.org + '/' + repoName + '.git',
          repoURL              = 'https://github.com/' + release.org + '/' + repoName + '/',
          regExp               = {
            match            : {
              // readme
              name              : '{component}',
              titleName         : '{Component}',
              // release notes
              spacedVersions    : /(###.*\n)\n+(?=###)/gm,
              spacedLists       : /(^- .*\n)\n+(?=^-)/gm,
              trim              : /^\s+|\s+$/g,
              unrelatedNotes    : new RegExp('^((?!(^.*(' + component + ').*$|###.*)).)*$', 'gmi'),
              whitespace        : /\n\s*\n\s*\n/gm,
              // npm
              export            : /\$\.fn\.\w+\s*=\s*function\(parameters\)\s*{/g,
              formExport        : /\$\.fn\.\w+\s*=\s*function\(fields, parameters\)\s*{/g,
              settingsExport    : /\$\.fn\.\w+\.settings\s*=/g,
              settingsReference : /\$\.fn\.\w+\.settings/g,
              jQuery            : /jQuery/g
            },
            replace : {
              // readme
              name              : component,
              titleName         : capitalizedComponent,
              // release notes
              spacedVersions    : '',
              spacedLists       : '$1',
              trim              : '',
              unrelatedNotes    : '',
              whitespace        : '\n\n',
              // npm
              export            :  'module.exports = function(parameters) {\n  var _module = module;\n',
              formExport        :  'module.exports = function(fields, parameters) {\n  var _module = module;\n',
              settingsExport    :  'module.exports.settings =',
              settingsReference :  '_module.exports.settings',
              jQuery            :  'require("jquery")'
            }
          },
          task = {
            all      : component + ' creating',
            repo     : component + ' create repo',
            bower    : component + ' create bower.json',
            readme   : component + ' create README',
            readme   : component + ' create README',
            npm      : component + ' create NPM Module',
            notes    : component + ' create release notes',
            composer : component + ' create composer.json',
            package  : component + ' create package.json'
          }
        ;
  
        // copy dist files into output folder adjusting asset paths
        gulp.task(task.repo, false, function() {
          return gulp.src(release.source + component + '.*')
            .pipe(plumber())
            .pipe(flatten())
            .pipe(replace(release.paths.source, release.paths.output))
            .pipe(gulp.dest(outputDirectory))
          ;
        });
  
        // create npm module
        gulp.task(task.npm, false, function() {
          return gulp.src(release.source + component + '!(*.min|*.map).js')
            .pipe(plumber())
            .pipe(flatten())
            .pipe(replace(regExp.match.export, regExp.replace.export))
            .pipe(replace(regExp.match.formExport, regExp.replace.formExport))
            .pipe(replace(regExp.match.settingsExport, regExp.replace.settingsExport))
            .pipe(replace(regExp.match.settingsReference, regExp.replace.settingsReference))
            .pipe(replace(regExp.match.jQuery, regExp.replace.jQuery))
            .pipe(rename('index.js'))
            .pipe(gulp.dest(outputDirectory))
          ;
        });
  
        // create readme
        gulp.task(task.readme, false, function() {
          return gulp.src(release.templates.readme)
            .pipe(plumber())
            .pipe(flatten())
            .pipe(replace(regExp.match.name, regExp.replace.name))
            .pipe(replace(regExp.match.titleName, regExp.replace.titleName))
            .pipe(gulp.dest(outputDirectory))
          ;
        });
  
        // extend bower.json
        gulp.task(task.bower, false, function() {
          return gulp.src(release.templates.bower)
            .pipe(plumber())
            .pipe(flatten())
            .pipe(jeditor(function(bower) {
              bower.name = packageName;
              bower.description = capitalizedComponent + ' - Semantic UI';
              if(isJavascript) {
                if(isCSS) {
                  bower.main = [
                    component + '.js',
                    component + '.css'
                  ];
                }
                else {
                  bower.main = [
                    component + '.js'
                  ];
                }
                bower.dependencies = {
                  jquery: '>=1.8'
                };
              }
              else {
                bower.main = [
                  component + '.css'
                ];
              }
              return bower;
            }))
            .pipe(gulp.dest(outputDirectory))
          ;
        });
  
        // extend package.json
        gulp.task(task.package, false, function() {
          return gulp.src(release.templates.package)
            .pipe(plumber())
            .pipe(flatten())
            .pipe(jeditor(function(package) {
              if(isJavascript) {
                package.dependencies = {
                  jquery: 'x.x.x'
                };
                package.main = 'index.js';
              }
              package.name = packageName;
              if(version) {
                package.version = version;
              }
              package.title       = 'Semantic UI - ' + capitalizedComponent;
              package.description = 'Single component release of ' + component;
              package.repository  = {
                type : 'git',
                url  : gitURL
              };
              return package;
            }))
            .pipe(gulp.dest(outputDirectory))
          ;
        });
  
        // extend composer.json
        gulp.task(task.composer, false, function() {
          return gulp.src(release.templates.composer)
            .pipe(plumber())
            .pipe(flatten())
            .pipe(jeditor(function(composer) {
              if(isJavascript) {
                composer.dependencies = {
                  jquery: 'x.x.x'
                };
                composer.main = component + '.js';
              }
              composer.name        = 'semantic/' + component;
              if(version) {
                composer.version     = version;
              }
              composer.description = 'Single component release of ' + component;
              return composer;
            }))
            .pipe(gulp.dest(outputDirectory))
          ;
        });
  
        // create release notes
        gulp.task(task.notes, false, function() {
          return gulp.src(release.templates.notes)
            .pipe(plumber())
            .pipe(flatten())
            // Remove release notes for lines not mentioning component
            .pipe(replace(regExp.match.unrelatedNotes, regExp.replace.unrelatedNotes))
            .pipe(replace(regExp.match.whitespace, regExp.replace.whitespace))
            .pipe(replace(regExp.match.spacedVersions, regExp.replace.spacedVersions))
            .pipe(replace(regExp.match.spacedLists, regExp.replace.spacedLists))
            .pipe(replace(regExp.match.trim, regExp.replace.trim))
            .pipe(gulp.dest(outputDirectory))
          ;
        });
  
        // synchronous tasks in orchestrator? I think not
        gulp.task(task.all, false, function(callback) {
          runSequence([
            task.repo,
            task.npm,
            task.bower,
            task.readme,
            task.package,
            task.composer,
            task.notes
          ], callback);
        });
  
        tasks.push(task.all);
  
      })(component);
    }
  
    runSequence(tasks, callback);
  
  });
  gulp.task('register repos', false, function(callback) {
    var
      index = -1,
      total = release.components.length,
      process = require('child_process'),
      stream,
      stepRepo
    ;
    console.log('Registering repos with package managers');
  
    // Do Git commands synchronously per component, to avoid issues
    stepRepo = function() {
      index = index + 1;
      if(index >= total) {
        return;
      }
      var
        component            = release.components[index],
        outputDirectory      = release.outputRoot + component + '/',
        capitalizedComponent = component.charAt(0).toUpperCase() + component.slice(1),
        packageName          = release.packageRoot + component,
        repoName             = release.repoRoot + capitalizedComponent,
        gitURL               = 'https://github.com/' + release.org + '/' + repoName + '.git',
        exec                 = process.exec,
        execSettings         = {cwd: outputDirectory},
        registerBower        = 'bower register ' + packageName + ' ' + gitURL,
        registerNPM          = 'npm publish'
  
      ;
      /* One time register
      exec(registerBower, execSettings, function(err, stdout, stderr) {
        stepRepo();
      });
      */
      /* Update npm
      exec(registerNPM, execSettings, function(err, stdout, stderr) {
        console.log(err, stdout, stderr);
        stepRepo();
      });
      */
    }
    stepRepo();
  });
  
  gulp.task('update git', false, function() {
    var
      index = -1,
      total = release.components.length,
      stream,
      stepRepo
    ;
    console.log('Handling git');
  
    // Do Git commands synchronously per component, to avoid issues
    stepRepo = function() {
  
      index = index + 1;
      if(index >= total) {
        return;
      }
  
      var
        component            = release.components[index],
        outputDirectory      = release.outputRoot + component + '/',
        capitalizedComponent = component.charAt(0).toUpperCase() + component.slice(1),
        repoName             = release.repoRoot + capitalizedComponent,
        gitURL               = 'https://github.com/' + release.org + '/' + repoName + '.git',
        repoURL              = 'https://github.com/' + release.org + '/' + repoName + '/',
        gitOptions           = { cwd: outputDirectory },
        quietOptions         = { args: '-q', cwd: outputDirectory },
        isRepository         = fs.existsSync(outputDirectory + '.git/')
        componentPackage     = fs.existsSync(outputDirectory + 'package.json' )
          ? require(outputDirectory + 'package.json')
          : false,
        commitArgs = (oAuth.name !== undefined && oAuth.email !== undefined)
          ? '--author "' + oAuth.name + ' <' + oAuth.email + '>"'
          : '',
        isNewVersion  = (version && componentPackage.version != version),
        mergeMessage  = 'Merged from upstream',
        commitMessage = (isNewVersion)
          ? 'Updated component to version ' + version
          : 'Updated component release from Semantic-UI (Automatic)'
      ;
  
      console.log('Processing repository:' + outputDirectory);
  
      if(isRepository) {
        commitFiles();
      }
      else {
        createRepo();
      }
  
      // standard path
      function commitFiles() {
        // commit files
        console.log('Committing files', commitArgs);
        gulp.src('**/*', gitOptions)
          .pipe(git.add(gitOptions))
          .pipe(git.commit(commitMessage, { args: commitArgs, cwd: outputDirectory }))
          .on('error', function(error) {
            console.log('Nothing new to commit');
            stepRepo();
          })
          .on('finish', function(callback) {
            pullFiles();
          })
        ;
      }
      function pullFiles() {
        console.log('Pulling files');
        git.pull('origin', 'master', { args: '', cwd: outputDirectory }, function(error) {
          if(error && error.message.search("Couldn't find remote ref") != -1) {
            createRepo();
          }
          else {
            console.log('Pull completed successfully');
            mergeCommit();
          }
        });
      };
      function mergeCommit() {
        // commit files
        console.log('Adding merge commit', commitArgs);
        gulp.src('', gitOptions)
          .pipe(git.add(gitOptions))
          .pipe(git.commit(mergeMessage, { args: commitArgs, cwd: outputDirectory }))
          .on('error', function(error) {
            console.log('Nothing new to merge', error);
          })
          .on('finish', function(callback) {
            if(1) {
              tagFiles();
            }
            else {
              pushFiles();
            }
          })
        ;
      }
      function tagFiles() {
        console.log('Tagging new version ', version);
        git.tag(version, 'Updated version from semantic-ui (automatic)', function (err) {
          pushFiles();
        });
      }
      function pushFiles() {
        console.log('Pushing files');
        git.push('origin', 'master', { args: '', cwd: outputDirectory }, function(error) {
          if(error && error.message.search("Couldn't find remote ref") == -1) {
            createRepo();
          }
          console.log('Push completed successfully');
          stepRepo();
        });
      };
  
      // set-up path
      function createRepo() {
        console.log('Creating repository ' + repoURL);
        github.repos.createFromOrg({
          org      : release.org,
          name     : repoName,
          homepage : release.homepage
        }, function() {
          if(isRepository) {
            addRemote();
          }
          else {
            initRepo();
          }
        });
      }
      function initRepo() {
        console.log('Initializing repository in ' + outputDirectory);
        git.init(gitOptions, function(error) {
          if(error) {
            console.error('Error initializing repo');
            return;
          }
          addRemote();
        });
      }
      function addRemote() {
        console.log('Adding remote origin as ' + gitURL);
        git.addRemote('origin', gitURL, gitOptions, firstPushFiles);
      }
      function firstPushFiles() {
        console.log('Pushing files');
        git.push('origin', 'master', { args: '-u', cwd: outputDirectory }, function(error) {
          if(error) {
            console.log(error);
            pullFiles();
          }
          else {
            console.log('First push completed successfully');
            stepRepo();
          }
        });
      };
  
    };
  
    return stepRepo();
  
  });
  