<commit_before>var PageTransitions = (function() {

	var $main = $( '#pt-main' ),
  $pages = $main.children( 'div.pt-page' ),
  $iterate = $( '#showPageLeft' ),
  animcursor = 1,
  pagesCount = $pages.length,
  current = 0,
  next = 1,
  isAnimating = false,
  isPage1 = true,
  animEndEventNames = {
   'WebkitAnimation' : 'webkitAnimationEnd',
   'OAnimation' : 'oAnimationEnd',
   'msAnimation' : 'MSAnimationEnd',
   'animation' : 'animationend'
 },
		// animation end event name
		animEndEventName = animEndEventNames[ Modernizr.prefixed( 'animation' ) ],

    transEndEventNames = {
    'WebkitTransition' : 'webkitTransitionEnd',// Saf 6, Android Browser
    'MozTransition'    : 'transitionend',      // only for FF < 15
    'transition'       : 'transitionend'       // IE10, Opera, Chrome, FF 15+, Saf 7+
  },

    //transition end event names
    transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
		// support css animations
		support = Modernizr.cssanimations;

   function init() {

    $pages.each( function() {
     var $page = $( this );
     $page.removeClass("pt-page-current");
     $page.removeClass("pt-page-not-current");
     $page.data( 'originalClassList', $page.attr( 'class' ) );
   } );

    $pages.eq( current ).addClass( 'pt-page-current' );
    $pages.eq( next ).addClass( 'pt-page-not-current' );

    $(document).ready(function(){
      $(".showPageLeft").each(function() {
        $(this).on( 'click', function() {
          if( isAnimating || !isPage1) {
            return false;
          }
          if( animcursor > 2 ) {
            animcursor = 1;
          }
          nextPage( animcursor );
          animcursor++;
          isPage1 = false;
        });
      });
      $(".showPageRight").each(function() {
        $(this).on( 'click', function() {
          if( isAnimating) {
            return false;
          }
          if( animcursor > 2 ) {
            animcursor = 1;
          }
          nextPage( animcursor );
          animcursor++;
          isPage1 = !isPage1;
        });
      });
    });

  }

  function nextPage( animation ) {

    if( isAnimating ) {
      return false;
    }

    isAnimating = true;

    var $currPage = $pages.eq( current );

    if( current < pagesCount - 1 ) {
      ++current;
    }
    else {
      current = 0;
    }
    if( next < pagesCount - 1 ) {
      ++next;
    }
    else {
      next = 0;
    }

    var $nextPage = $pages.eq( current ).addClass( 'pt-page-current' ),
    outClass = '', inClass = '';
    var move = $(window).width();
    var trigger = false;
    if (move < 768)
    {
      trigger = true;
      move = move + 300;
    }
    else{
      if (trigger = true)
        move = move - 300;
    }
    switch( animation ) {

      case 1:
      outClass = 'pt-page-moveToLeft';
      inClass = 'pt-page-moveFromRight';
      $('#showPageRight').css("left", move+"px");
      $('#showPageRight').css("right", "auto");
      $('#showPageRight').toggleClass('current').animate({
        left: "-="+(move - 300)+'px'
          // left: "-="+move,
        }, 200, function() {
          $('#showPageRight').html("")
        // Animation complete.
      });
      break;
      case 2:
      outClass = 'pt-page-moveToRight';
      inClass = 'pt-page-moveFromLeft';

      $('#showPageRight').css("left", "auto");
      $('#showPageRight').css("right", (move - 300)+"px");
      $('#showPageRight').toggleClass('current').animate({
        right: "-="+(move - 300)+'px'
      }, 200, function() {
        $('#showPageRight').html("")
      });
      break;
    }

    $currPage.addClass( outClass ).on( animEndEventName, function() {
      $currPage.off( animEndEventName );
      onEndAnimation( $currPage, $nextPage );
    }).on( transEndEventName, function() {
      $currPage.off( transEndEventName );
      onEndAnimation( $currPage, $nextPage );
    } );

    $nextPage.addClass( inClass ).on( animEndEventName, function() {
      $nextPage.off( animEndEventName );
      onEndAnimation( $currPage, $nextPage );
    }).on( transEndEventName, function() {
      $nextPage.off( transEndEventName );
      onEndAnimation( $currPage, $nextPage );
    } );

    if( !support ) {
     onEndAnimation( $currPage, $nextPage );
   }

 }

 function onEndAnimation( $outpage, $inpage ) {
  resetPage( $outpage, $inpage );
  isAnimating = false;
}

function resetPage( $outpage, $inpage ) {
  $outpage.attr( 'class', $outpage.data( 'originalClassList') + ' pt-page-not-current');
  $inpage.attr( 'class', $inpage.data( 'originalClassList' ) + ' pt-page-current' );
  PageTransitions.init();
}

init();

return { init : init };

})();

var elementPosition = $('.filters').offset();
var windowChange1 = true;
var windowChange2 = true;
var windowHeight;
$(window).scroll(function(){
  if (windowChange1)
  {
    windowHeight = $(window).height();
    windowChange1 = false;
  }
  if($(window).scrollTop() > elementPosition.top){
  $('.filters').css({'position':'fixed',/*'top':'0px'*/});
  $('.filtersOverride').css({'height': '100%'})
    // $('#page2').css({'height': windowHeight + 'px', 'top': '-52px' })
  } else {
    var offset = (0 - ($(window).scrollTop() - elementPosition.top))
    var height = $(window).height() - offset;
    $('.filters').css({'position':'absolute', 'top':'52px'});
    // $('.filtersOverride').css({'height': height + 'px'})
    // $('#page2').css({'height': height + 'px', 'top': (0 - (52 - offset)) + 'px'})
  }
});
$(document).ready(function(){

  $('[data-toggle="popover"]').popover({trigger: 'hover','placement': 'bottom', 'html': true});

  if (windowChange2)
  {
    windowHeight = $(window).height();
    windowChange2 = false;
  }
  var elementPosition = $('.filters').offset();
  if($(window).scrollTop() > elementPosition.top){
    $('.filters').css({'position':'fixed','top':'0px'});
    $('.filtersOverride').css({'height': '100%'})
  $('#page2').css({'height': windowHeight + 'px', /*'top': '-52px' */})
} else {
  var offset = (0 - ($(window).scrollTop() - elementPosition.top))
  var height = $(window).height() - offset;
  $('.filters').css({'position':'absolute', 'top':'52px'});
  $('.filtersOverride').css({'height': height + 'px'})
  $('#page2').css({'height': height + 'px', 'top': /*(0 - (52 - offset)) + 'px'*/ '52px'})
}
$(window).resize(function(){
  windowChange1 = true;
  windowChange2 = true;
  windowHeight = $(window).height();
  var elementPosition = $('.filters').offset();
  if($(window).scrollTop() > elementPosition.top){
      // $('.filters').css({'position':'fixed','top':'0px'});
      // $('.filtersOverride').css({'height': '100%'})
      // $('#page2').css({'height': windowHeight + 'px', 'top': '-52px' })
    } else {
      // var offset = (0 - ($(window).scrollTop() - elementPosition.top))
      // var height = $(window).height() - offset;
      // $('.filters').css({'position':'absolute', 'top':'52px'});
      // $('.filtersOverride').css({'height': height + 'px'})
      // $('#page2').css({'height': height + 'px', 'top': (0 - (52 - offset)) + 'px'})
    }
  });
var toggled = false;
if ($(window).width() > 767)
{
  toggled = true;
  showFilters();
}
$("#showFilters").on("click", function(){
  if (!toggled){
    toggled = true;
    showFilters();
  }
  else {
    toggled = false;
    hideFilters();
  }
});
function showFilters(){
  $('.filters').toggleClass("filtersOverride");
  $( '.filterButton' ).animate({
    right: "+=100px",
    width: "300px"
  }, 300, function() {
  });
  $( '.filtersOverride' ).animate({
    left: "+=300px"
  }, 300, function() {
    $('#showFilters').html("Filters ");
  });
  $( '#pt-main' ).animate({
    'padding-left': "+=300px"
  }, 200, function() {
    $( '#page1' ).animate({
      'padding-top': "-=40px"
    }, 100, function() {
    });
  });
  $(".pt-page-2").animate({
    'padding-left': '+=300px',
  }, 200, function(){
  });
  $( '#showPageRight' ).animate({
    'margin-left': "+=300px"
  }, 200, function() {
  });
  PageTransitions.init();
}
function hideFilters(){

  $( '.filterButton' ).animate({
    right: "-=100px",
    width: "100px"
  }, 300, function() {
  });
  $( '.filtersOverride' ).animate({
    left: "-=300px"
  }, 300, function() {
    $('#showFilters').html("Filters ");
    $('.filters').toggleClass("filtersOverride");
  });
  $( '#page1' ).animate({
    'padding-top': "+=40px"
  }, 100, function() {
    $( '#pt-main' ).animate({
      'padding-left': "-=300px"
    }, 200, function() {
    });
  });
  setTimeout(function() {
    $( '#showPageRight' ).animate({
      'margin-left': "-=300px"
    }, 200, function() {
    });
    $(".pt-page-2").animate({
      'padding-left': '-=300px',
    }, 200, function(){
    });
  }, 100);
  PageTransitions.init();
}

});<commit_msg>Fixed bug for button disapearing on screen size change.<commit_after>var PageTransitions = (function() {

	var $main = $( '#pt-main' ),
  $pages = $main.children( 'div.pt-page' ),
  $iterate = $( '#showPageLeft' ),
  animcursor = 1,
  pagesCount = $pages.length,
  current = 0,
  next = 1,
  isAnimating = false,
  isPage1 = true,
  animEndEventNames = {
   'WebkitAnimation' : 'webkitAnimationEnd',
   'OAnimation' : 'oAnimationEnd',
   'msAnimation' : 'MSAnimationEnd',
   'animation' : 'animationend'
 },
		// animation end event name
		animEndEventName = animEndEventNames[ Modernizr.prefixed( 'animation' ) ],

    transEndEventNames = {
    'WebkitTransition' : 'webkitTransitionEnd',// Saf 6, Android Browser
    'MozTransition'    : 'transitionend',      // only for FF < 15
    'transition'       : 'transitionend'       // IE10, Opera, Chrome, FF 15+, Saf 7+
  },

    //transition end event names
    transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
		// support css animations
		support = Modernizr.cssanimations;

   function init() {

    $pages.each( function() {
     var $page = $( this );
     $page.removeClass("pt-page-current");
     $page.removeClass("pt-page-not-current");
     $page.data( 'originalClassList', $page.attr( 'class' ) );
   } );

    $pages.eq( current ).addClass( 'pt-page-current' );
    $pages.eq( next ).addClass( 'pt-page-not-current' );

    $(document).ready(function(){
      $(".showPageLeft").each(function() {
        $(this).on( 'click', function() {
          if( isAnimating || !isPage1) {
            return false;
          }
          if( animcursor > 2 ) {
            animcursor = 1;
          }
          nextPage( animcursor );
          animcursor++;
          isPage1 = false;
        });
      });
      $(".showPageRight").each(function() {
        $(this).on( 'click', function() {
          if( isAnimating) {
            return false;
          }
          if( animcursor > 2 ) {
            animcursor = 1;
          }
          nextPage( animcursor );
          animcursor++;
          isPage1 = !isPage1;
        });
      });
    });

  }

  function nextPage( animation ) {

    if( isAnimating ) {
      return false;
    }

    isAnimating = true;

    var $currPage = $pages.eq( current );

    if( current < pagesCount - 1 ) {
      ++current;
    }
    else {
      current = 0;
    }
    if( next < pagesCount - 1 ) {
      ++next;
    }
    else {
      next = 0;
    }

    var $nextPage = $pages.eq( current ).addClass( 'pt-page-current' ),
    outClass = '', inClass = '';
    var move = $(window).width();

      console.log("move", move);
    switch( animation ) {

      case 1:
      outClass = 'pt-page-moveToLeft';
      inClass = 'pt-page-moveFromRight';
      $('#showPageRight').css("left", move+"px");
      $('#showPageRight').css("right", "auto");
      $('#showPageRight').toggleClass('current').animate({
        left: "300px",
        right: ""
          // left: "-="+move,
        }, 200, function() {
          $('#showPageRight').html("")
        // Animation complete.
      });
      break;
      case 2:
      outClass = 'pt-page-moveToRight';
      inClass = 'pt-page-moveFromLeft';

      $('#showPageRight').css("left", "auto");
      $('#showPageRight').css("right", (move - 300)+"px");
      $('#showPageRight').toggleClass('current').animate({
        right: "0px",
        left: $('#page1').width + 'px'
      }, 200, function() {
        $('#showPageRight').html("")
      });
      break;
    }

    $currPage.addClass( outClass ).on( animEndEventName, function() {
      $currPage.off( animEndEventName );
      onEndAnimation( $currPage, $nextPage );
    }).on( transEndEventName, function() {
      $currPage.off( transEndEventName );
      onEndAnimation( $currPage, $nextPage );
    } );

    $nextPage.addClass( inClass ).on( animEndEventName, function() {
      $nextPage.off( animEndEventName );
      onEndAnimation( $currPage, $nextPage );
    }).on( transEndEventName, function() {
      $nextPage.off( transEndEventName );
      onEndAnimation( $currPage, $nextPage );
    } );

    if( !support ) {
     onEndAnimation( $currPage, $nextPage );
   }

 }

 function onEndAnimation( $outpage, $inpage ) {
  resetPage( $outpage, $inpage );
  isAnimating = false;
}

function resetPage( $outpage, $inpage ) {
  $outpage.attr( 'class', $outpage.data( 'originalClassList') + ' pt-page-not-current');
  $inpage.attr( 'class', $inpage.data( 'originalClassList' ) + ' pt-page-current' );
  PageTransitions.init();
}

init();

return { init : init };

})();

var elementPosition = $('.filters').offset();
var windowChange1 = true;
var windowChange2 = true;
var windowHeight;
$(window).scroll(function(){
  if (windowChange1)
  {
    windowHeight = $(window).height();
    windowChange1 = false;
  }
  if($(window).scrollTop() > elementPosition.top){
  $('.filters').css({'position':'fixed',/*'top':'0px'*/});
  $('.filtersOverride').css({'height': '100%'})
    // $('#page2').css({'height': windowHeight + 'px', 'top': '-52px' })
  } else {
    var offset = (0 - ($(window).scrollTop() - elementPosition.top))
    var height = $(window).height() - offset;
    $('.filters').css({'position':'absolute', 'top':'52px'});
    // $('.filtersOverride').css({'height': height + 'px'})
    // $('#page2').css({'height': height + 'px', 'top': (0 - (52 - offset)) + 'px'})
  }
});
$(document).ready(function(){

  $('[data-toggle="popover"]').popover({trigger: 'hover','placement': 'bottom', 'html': true});

  if (windowChange2)
  {
    windowHeight = $(window).height();
    windowChange2 = false;
  }
  var elementPosition = $('.filters').offset();
  if($(window).scrollTop() > elementPosition.top){
    $('.filters').css({'position':'fixed','top':'0px'});
    $('.filtersOverride').css({'height': '100%'})
  $('#page2').css({'height': windowHeight + 'px', /*'top': '-52px' */})
} else {
  var offset = (0 - ($(window).scrollTop() - elementPosition.top))
  var height = $(window).height() - offset;
  $('.filters').css({'position':'absolute', 'top':'52px'});
  $('.filtersOverride').css({'height': height + 'px'})
  $('#page2').css({'height': height + 'px', 'top': /*(0 - (52 - offset)) + 'px'*/ '52px'})
}
$(window).resize(function(){
  windowChange1 = true;
  windowChange2 = true;
  windowHeight = $(window).height();
  var elementPosition = $('.filters').offset();
  if($(window).scrollTop() > elementPosition.top){
      // $('.filters').css({'position':'fixed','top':'0px'});
      // $('.filtersOverride').css({'height': '100%'})
      // $('#page2').css({'height': windowHeight + 'px', 'top': '-52px' })
    } else {
      // var offset = (0 - ($(window).scrollTop() - elementPosition.top))
      // var height = $(window).height() - offset;
      // $('.filters').css({'position':'absolute', 'top':'52px'});
      // $('.filtersOverride').css({'height': height + 'px'})
      // $('#page2').css({'height': height + 'px', 'top': (0 - (52 - offset)) + 'px'})
    }
  });
var toggled = false;
if ($(window).width() > 767)
{
  toggled = true;
  showFilters();
}
$("#showFilters").on("click", function(){
  if (!toggled){
    toggled = true;
    showFilters();
  }
  else {
    toggled = false;
    hideFilters();
  }
});
function showFilters(){
  $('.filters').toggleClass("filtersOverride");
  $( '.filterButton' ).animate({
    right: "+=100px",
    width: "300px"
  }, 300, function() {
  });
  $( '.filtersOverride' ).animate({
    left: "+=300px"
  }, 300, function() {
    $('#showFilters').html("Filters ");
  });
  $( '#pt-main' ).animate({
    'padding-left': "+=300px"
  }, 200, function() {
    $( '#page1' ).animate({
      'padding-top': "-=40px"
    }, 100, function() {
    });
  });
  $(".pt-page-2").animate({
    'padding-left': '+=300px',
  }, 200, function(){
  });
  $( '#showPageRight' ).animate({
    'margin-left': "+=300px"
  }, 200, function() {
  });
  PageTransitions.init();
}
function hideFilters(){

  $( '.filterButton' ).animate({
    right: "-=100px",
    width: "100px"
  }, 300, function() {
  });
  $( '.filtersOverride' ).animate({
    left: "-=300px"
  }, 300, function() {
    $('#showFilters').html("Filters ");
    $('.filters').toggleClass("filtersOverride");
  });
  $( '#page1' ).animate({
    'padding-top': "+=40px"
  }, 100, function() {
    $( '#pt-main' ).animate({
      'padding-left': "-=300px"
    }, 200, function() {
    });
  });
  setTimeout(function() {
    $( '#showPageRight' ).animate({
      'margin-left': "-=300px"
    }, 200, function() {
    });
    $(".pt-page-2").animate({
      'padding-left': '-=300px',
    }, 200, function(){
    });
  }, 100);
  PageTransitions.init();
}

});<|endoftext|>


<commit_before><commit_msg>配置gulpfile.js<commit_after>var gulp = require('gulp'), 						// gulp
	util = require('gulp-util'), 					// gulp常用的工具库——gulp-util
	// JS压缩
	uglify = require('gulp-uglify'), 				// JS压缩
	concat = require('gulp-concat'),				// JS合并
	rename = require('gulp-rename')					// 文件重命名
	// CSS预处理任务
	sass = require('gulp-sass'), 					// sass编译——gulp-sass
	// 图片压缩
	imagemin = require('gulp-imagemin'),			// 图片压缩
	pngquant = require('imagemin-pngquant'),		// PNG图片压缩
	// 特殊任务
	watchPath = require('gulp-watch-path'),		    // watch监控——gulp-watch-path
	connect = require('gulp-connect'),				// gulp 服务器插件
	livereload = require('gulp-livereload');		// 自动刷新——gulp-livereload

    // HTML
	gulp.task('html', function () {
		gulp.src('./src/*.html')
			// 输出位置
			.pipe(gulp.dest('./dist'))
			.pipe(connect.reload());
	});

    // 原生css任务
	gulp.task('css', function () {
		gulp.src('./src/css/layout.css')
			// 输出位置
			.pipe(gulp.dest('./dist/css'))
            .pipe(sass())
			.pipe(connect.reload());
	});

  // Sass编译任务
	gulp.task('sass', function () {
		return gulp.src('./src/sass/*.sass')
			// 输出格式 + 错误输出
			.pipe(sass({outputStyle: 'nested'}).on('error', sass.logError))
			// 输出位置(先输出原生css任务,然后输出sass编译)
            .pipe(css())
			.pipe(gulp.dest('./dist/css'))
			// 添加LiveReload插件
			.pipe(connect.reload());
	});

	// JS清理
	gulp.task('minifyjs', function() {
		// 按顺序加载 (暂时保有main部分，分拆后 删除这部分引用)
        return gulp.src([
				'./src/js/call.js',
				'./src/js/statement.js'
			])
            .pipe(concat('main.js'))    		//合并所有js到main.js
			// .pipe(uglify())    				//压缩
			.pipe(rename({suffix: '.min'})) 	//rename压缩后的文件名
            .pipe(gulp.dest('dist/js'))       	//输出到文件夹
			// 刷新页面
			.pipe(connect.reload());
    });

	// 图片压缩
	gulp.task('imagemin',function(){
		gulp.src('./src/images/*.{png,jpg,gif,ico}')
			.pipe(imagemin({
				progressive: true,
				svgPlugins: [{removeViewBox: false}],
				use: [pngquant()]
			}))
			.pipe(gulp.dest('./dist/images/'));
	});

	//Gulp sever服务器
	gulp.task('connect', function() {
		connect.server({
			root: 'dist/',
			livereload: true
		});
	});

	// 在命令行使用 gulp watch 启动此任务
	gulp.task('watch', function() {
        // 监听CSS文件修改，当文件被修改则执行 CSS 任务
	    gulp.watch('src/css/*.css', ['css']);
	    // 监听Sass文件修改，当文件被修改则执行 sass 任务
	    gulp.watch('src/sass/*.sass', ['sass']);
		// 监听HTML文件修改，当HTML文件被修改则执行 HTML 任务
		gulp.watch('src/*.html', ['html']);
		// 监听js文件修改，当JS文件被修改则执行 JS 任务
		gulp.watch('src/js/*.js',['minifyjs']);
	});

    // 默认开启服务器，打开监听
	gulp.task('default', ['connect', 'watch'])
	// 处理任务　html/css/Sass/js
	gulp.task('mini', ['html', 'minifyjs','css','sass'])
<|endoftext|>


<commit_before>var gulp    = require('gulp'),
    gutil   = require('gulp-util');
    clean   = require('gulp-clean'),
    jshint  = require('gulp-jshint'),
    uglify  = require('gulp-uglify'),
    stylish = require('jshint-stylish'),
    colors  = require('colors');

gulp.task('lint', function() {
    console.log('[lint]'.bold.magenta + ' Linting JS files');

    return gulp.src('./src/**/*.js')
        .pipe(jshint())
        .pipe(jshint.reporter(stylish));

});

gulp.task('uglify', function() {

    console.log('[uglify]'.bold.magenta + ' Minifying JS files');

    return gulp.src('./src/**/*.js')
        .pipe(uglify({outSourceMap: true}))
        .pipe(gulp.dest('dist'));

});

// Clean dist/css folder
gulp.task('clean-dist-css', function() {

    console.log('[clean-dist-css]'.bold.magenta + ' Deleting all the files in /dist/css');

    return gulp.src(['dist/css', 'docs/dist/css', '_gh_pages/dist/css'], {read: false})
        .pipe(clean());

});

// Copy dist folder to docs folder
gulp.task('copy-dist', function () {

    console.log('[copy-dist]'.bold.magenta + ' Copying dist folder to docs');

    return gulp.src('dist/**/*', {base: './'})
        .pipe(gulp.dest('docs'))
        .pipe(gulp.dest('_gh_pages'));

});

// Watch files for changes
gulp.task('watch', function() {

    console.log('[watch]'.bold.magenta + ' Watching Sass files for changes');

    // gulp.watch('js/*.js', ['lint', 'scripts']);
    gulp.watch('scss/**/*.scss', ['copy-dist']);

});

// Start dev environment
gulp.task('dev', ['watch', 'jekyll-watch', 'livereload']);

// Default Task
gulp.task('default', ['sass', 'watch']);
<commit_msg>Clean up Gulpfile<commit_after>var gulp    = require('gulp'),
    gutil   = require('gulp-util');
    clean   = require('gulp-clean'),
    jshint  = require('gulp-jshint'),
    uglify  = require('gulp-uglify'),
    stylish = require('jshint-stylish'),
    colors  = require('colors');

gulp.task('lint', function() {
    console.log('[lint]'.bold.magenta + ' Linting JS files');

    return gulp.src('./src/**/*.js')
        .pipe(jshint())
        .pipe(jshint.reporter(stylish));

});

gulp.task('uglify', ['clean'], function() {

    console.log('[uglify]'.bold.magenta + ' Minifying JS files');

    return gulp.src('./src/**/*.js')
        .pipe(uglify({outSourceMap: true}))
        .pipe(gulp.dest('dist'));

});

// Clean dist/css folder
gulp.task('clean', function() {

    console.log('[clean]'.bold.magenta + ' Deleting all the files in /dist');

    return gulp.src(['dist'], {read: false})
        .pipe(clean());

});

// Watch files for changes
gulp.task('watch', function() {

    console.log('[watch]'.bold.magenta + ' Watching JS files for changes');

    gulp.watch('./src/**/*.js', ['lint']);

});

// Default Task
gulp.task('default', ['lint', 'watch']);
<|endoftext|>


<commit_before>'use strict';

var gulp = require('gulp');
var imagemin = require('gulp-imagemin');
var changed = require('gulp-changed');

gulp.task('minimizeImages', function() {
  return gulp.src('img/*.gif')
    .pipe(changed('build'))
    .pipe(imagemin())
    .pipe(gulp.dest('build'));
});

gulp.task('default', ['minimizeImages']);
<commit_msg>Add watch task<commit_after>'use strict';

var gulp = require('gulp');
var imagemin = require('gulp-imagemin');
var changed = require('gulp-changed');
var del = require('del');

gulp.task('minimizeImages', function() {
  return gulp.src('img/*.gif')
    .pipe(changed('build'))
    .pipe(imagemin())
    .pipe(gulp.dest('build'));
});

gulp.task('clean', function(callback) {
  del('build/*', callback);
});

gulp.task('watch', function() {
  gulp.watch('app/**/*', ['minimizeImages']);
});

gulp.task('default', ['minimizeImages']);
<|endoftext|>


<commit_before>function mhnChartingMain()
{
  var div = document.createElement('div');
  var body = document.getElementsByTagName('body')[0];

  div.style.height =          '200px';
  div.style.width =           '400px';
  div.style.marginLeft =      '-200px';   // offset the width for centering.
  div.style.position =        'fixed';
  div.style.backgroundColor = '#aaaaaa';  // grey
  div.style.zIndex =          '1337';     // on top of other DIVs
  div.style.top =             '0';        // at top of the screen
  div.style.left =            '50%';      // centered

  div.innerHTML = "OMG HIYA!";

  body.appendChild(div);
}
<commit_msg>tweaky tweaky. will finish when API ready.<commit_after>function mhnChartingMain()
{
  var div = document.createElement('div');
  var body = document.getElementsByTagName('body')[0];

  // stubbed, for now.
  var name = "fred";
  var key = "fredhasakeyhonestthisistotallylegit";

  div.style.height =          '300px';
  div.style.width =           '760px';
  div.style.marginLeft =      '-380px';   // offset the width for centering.
  div.style.position =        'fixed';
  div.style.backgroundColor = '#aaaaaa';  // grey
  div.style.zIndex =          '1337';     // on top of other DIVs
  div.style.top =             '0';        // at top of the screen
  div.style.left =            '50%';      // centered
  div.style.align =           'left';     // inner elements LHS aligned

  div.innerHTML =
    "
" +
    "<form action=\"http://charting.mhnltd.co.uk/notes\" method=\"post\">" +

    "<input type=\"hidden\" name=\"notes[user]\" value=\"" + name + "\" />" +

    "<input type=\"hidden\" name=\"notes[key]\" value=\"" + key + "\" />" +

    "<input type=\"hidden\" name=\"notes[location]\" value=\"" +
    document.location.href + "\" />" +

    "<input type=\"hidden\" name=\"notes[doctype]\" value=\"webpage\" />" +

    "Title: " +
    "<input type=\"text\" name=\"notes[title]\" value=\"" +
    document.title +
    "\"/>
" +

    "Body: " +
    "<textarea name=\"notes[body]\" rows=\"10\" cols=\"80\"></textarea>
" +

    "Goal: " +
    "<select name=\"notes[goals][]\">" +
    "<option value=\"1\">One</option>" +
    "<option value=\"2\">Two</option>" +
    "<option value=\"3\">Three</option>" +
    "</select>
" +

    "</form>
"

  body.appendChild(div);
}
<|endoftext|>


<commit_before>// Plugins
var gulp          = require('gulp');
var markdown      = require('gulp-markdown');
var concat        = require('gulp-concat');
var del           = require('del');
var connect       = require('gulp-connect');
var sass          = require('gulp-sass');
var minifyCss     = require('gulp-minify-css');
var uglify        = require('gulp-uglify');
var templateCache = require('gulp-angular-templatecache');
var sourcemaps    = require('gulp-sourcemaps');
var open          = require("gulp-open");
var gulpFilter    = require('gulp-filter');
var headerfooter  = require('gulp-headerfooter');
var cheerio       = require('gulp-cheerio');
var foreach       = require('gulp-foreach');
var ext           = require('gulp-ext-replace');

// Configuration
var config       = require('./data/languages');

// Directories
var docs_dir      = 'source/docs/';
var code_temp_dir = '.tmp/code/';
var md_temp_dir   = '.tmp/docs/';

var chapters = [
  md_temp_dir + '01_overview/01_*.html',
  md_temp_dir + '01_overview/02_*.html',
  md_temp_dir + '01_overview/03_*.html',
  md_temp_dir + '01_overview/04_*.html',
  md_temp_dir + '01_overview/05_support/*.html',
  md_temp_dir + '01_overview/06_*.html',
  md_temp_dir + '01_overview/07_*.html',
  md_temp_dir + '02_api_libraries/01_api_libraries/*.html',
  md_temp_dir + '02_api_libraries/02_initialization/*.html',
  md_temp_dir + '02_api_libraries/03_webhooks/01_overview/*.html',
  md_temp_dir + '02_api_libraries/03_webhooks/02_receiving_webhooks/*.html',
  md_temp_dir + '02_api_libraries/03_webhooks/03_reacting_to_webhooks/*.html',
  md_temp_dir + '02_api_libraries/03_webhooks/04_testing_webhooks/*.html',
  md_temp_dir + '02_api_libraries/03_webhooks/05_bill_webhook/*.html',
  md_temp_dir + '02_api_libraries/03_webhooks/06_pre_auth_webhook/*.html',
  md_temp_dir + '02_api_libraries/03_webhooks/07_subscription_webhook/*.html',
  md_temp_dir + '02_api_libraries/04_prepopulation/*.html',
  md_temp_dir + '02_api_libraries/05_deployment/*.html',
  md_temp_dir + '03_setting_up_HTTP_payments/*.html',
  md_temp_dir + '04_making_REST_requests/*.html',
  md_temp_dir + '05_webhooks_http/*.html',
  md_temp_dir + '05_webhooks_http/04_webhook_types/*.html',
  md_temp_dir + '06_guides/*.html',

  md_temp_dir + '07_resources/*.html',
  md_temp_dir + '07_resources/bill/*.html',
  md_temp_dir + '07_resources/bill/02_create_a_one_off_bill/*.html',
  code_temp_dir + '07_resources/bill/02_create_a_one_off_bill/code/*',
  md_temp_dir + '07_resources/bill/03_confirm_a_new_one_off_bill/*.html',
  code_temp_dir + '07_resources/bill/03_confirm_a_new_one_off_bill/code/*',
  md_temp_dir + '07_resources/bill/04_list_all_bills/*.html',
  code_temp_dir + '07_resources/bill/04_list_all_bills/code/*',
  md_temp_dir + '07_resources/bill/05_retrieve_an_existing_bill/*.html',
  code_temp_dir + '07_resources/bill/05_retrieve_an_existing_bill/code/*',
  md_temp_dir + '07_resources/bill/06_retry_a_failed_bill/*.html',
  code_temp_dir + '07_resources/bill/06_retry_a_failed_bill/code/*',
  md_temp_dir + '07_resources/bill/07_cancel_a_pending_bill/*.html',
  code_temp_dir + '07_resources/bill/07_cancel_a_pending_bill/code/*',
  md_temp_dir + '07_resources/bill/08_refund_a_bill/*.html',
  code_temp_dir + '07_resources/bill/08_refund_a_bill/code/*',
  md_temp_dir + '07_resources/bill/09_statuses/*.html',

  md_temp_dir + '07_resources/merchant/*.html',

  md_temp_dir + '07_resources/merchant/02_retrieve_merchant_details/*.html',
  code_temp_dir + '07_resources/merchant/02_retrieve_merchant_details/code/*',
  md_temp_dir + '07_resources/payout/*.html',

  md_temp_dir + '07_resources/payout/02_list_all_payouts/*.html',
  code_temp_dir + '07_resources/payout/02_list_all_payouts/code/*',
  md_temp_dir + '07_resources/payout/03_retrieve_an_existing_payout/*.html',
  code_temp_dir + '07_resources/payout/03_retrieve_an_existing_payout/code/*',
  md_temp_dir + '07_resources/preauthorization/*.html',

  md_temp_dir + '07_resources/preauthorization/02_create_a_new_pre-authorization/*.html',
  code_temp_dir + '07_resources/preauthorization/02_create_a_new_pre-authorization/code/*',
  md_temp_dir + '07_resources/preauthorization/03_confirm_a_new_preauthorization/*.html',
  code_temp_dir + '07_resources/preauthorization/03_confirm_a_new_preauthorization/code/*',
  md_temp_dir + '07_resources/preauthorization/04_create_a_bill_under_a_preauthorization/*.html',
  code_temp_dir + '07_resources/preauthorization/04_create_a_bill_under_a_preauthorization/code/*',
  md_temp_dir + '07_resources/preauthorization/05_list_all_pre-authorizations/*.html',
  code_temp_dir + '07_resources/preauthorization/05_list_all_pre-authorizations/code/*',
  md_temp_dir + '07_resources/preauthorization/06_retrieve_an_existing_pre-authorization/*.html',
  code_temp_dir + '07_resources/preauthorization/06_retrieve_an_existing_pre-authorization/code/*',
  md_temp_dir + '07_resources/preauthorization/07_cancel_a_pre-authorization/*.html',
  code_temp_dir + '07_resources/preauthorization/07_cancel_a_pre-authorization/code/*',
  md_temp_dir + '07_resources/preauthorization/08_statuses/*.html',

  md_temp_dir + '07_resources/subscription/*.html',

  md_temp_dir + '07_resources/subscription/02_create_a_new_subscription/*.html',
  code_temp_dir + '07_resources/subscription/02_create_a_new_subscription/code/*',
  md_temp_dir + '07_resources/subscription/03_confirm_a_new_subscription/*.html',
  code_temp_dir + '07_resources/subscription/03_confirm_a_new_subscription/code/*',
  md_temp_dir + '07_resources/subscription/03_list_all_subscriptions/*.html',
  code_temp_dir + '07_resources/subscription/03_list_all_subscriptions/code/*',
  md_temp_dir + '07_resources/subscription/04_retrieve_an_existing_subscription/*.html',
  code_temp_dir + '07_resources/subscription/04_retrieve_an_existing_subscription/code/*',
  md_temp_dir + '07_resources/subscription/05_cancel_a_subscription/*.html',
  code_temp_dir + '07_resources/subscription/05_cancel_a_subscription/code/*',
  md_temp_dir + '07_resources/subscription/06_statuses/*.html',

  md_temp_dir + '07_resources/user/*.html',

  md_temp_dir + '07_resources/user/02_list_all_users/*.html',
  code_temp_dir + '07_resources/user/02_list_all_users/code/*'
]

var code = [
  docs_dir + '**/**/**/code/**/*'
]

var md = [
  docs_dir + '**/*.md'
]

// source/javascripts/
var scripts = [
  'source/javascripts/libs/angular.js',
  'source/javascripts/libs/angular-touch.js',
  'source/javascripts/libs/lodash.js',

  'source/javascripts/config/*',
  'source/javascripts/nav-toggle/*',
  'source/javascripts/scroll-spy/*',
  'source/javascripts/toc-nav/*',
  'source/javascripts/close-when-outside/*',
  'source/javascripts/on-click-anchor/*',

  'source/javascripts/docs.js',
]

// Gulp tasks
gulp.task('default', ['make']);

gulp.task('images', function () {
  return gulp.src('source/images/**')
    .pipe(gulp.dest('./_site/images/'))
    .pipe(connect.reload());
});

gulp.task('sass', function () {
  gulp.src('./source/stylesheets/all.scss')
    .pipe(sourcemaps.init())
      .pipe(sass())
      .pipe(concat('all.css'))
      .pipe(minifyCss())
    .pipe(sourcemaps.write('./'))
    .on('error', function (err) { console.log(err.message); })
    .pipe(gulp.dest('_site/stylesheets/'))
    .pipe(connect.reload());
});

gulp.task('font', function () {
  gulp.src('./source/stylesheets/**/*.css')
    .pipe(concat('font.css'))
    .pipe(minifyCss())
    .on('error', function (err) { console.log(err.message); })
    .pipe(gulp.dest('_site/stylesheets/'))
    .pipe(connect.reload());
});

gulp.task('javascript', function () {
  var jsFilter = gulpFilter(['**/*.js']);
  var htmlFilter = gulpFilter(['**/*.html']);
  gulp.src(scripts)
    .pipe(sourcemaps.init())
      .pipe(htmlFilter)
      // replace this line with GC Angular template generator
      .pipe(templateCache({ base: '/Users/samjewell/gc/api-docs/source/javascripts/', standalone: true }))
      .pipe(htmlFilter.restore())
      .pipe(jsFilter) // defensive step in case html files don't get converted
      .pipe(concat('all.js'))
      //.pipe(uglify())
    .pipe(sourcemaps.write('./'))
    .pipe(gulp.dest('_site/javascripts/'))
    .pipe(connect.reload());
});

gulp.task('prepare:code', function () {
  gulp.src(code)
    .pipe(headerfooter.header('./source/layouts/code-header.html'))
    .pipe(headerfooter.footer('./source/layouts/code-footer.html'))
    .pipe(gulp.dest('.tmp/code/'));
});

gulp.task('prepare:markdown', function () {
  gulp.src(md)
    .pipe(markdown())
    .pipe(headerfooter.header('./source/layouts/doc-header.html'))
    .pipe(headerfooter.footer('./source/layouts/doc-footer.html'))
    .pipe(gulp.dest('.tmp/docs/'));
});

gulp.task('clean', function(cb) {
  del([
    '.tmp',
    '_site',
  ], cb);
});

gulp.task('docs', ['prepare:code', 'prepare:markdown'], function() {
  setTimeout(function() {
    for(var i = 0; i < config.length; i++) {
      var obj = config[i];
      buildLanguage(obj);
    }

  }, 5000);
  //
  // Hacky alert: This timeout is needed for the code files to be read from /tmp
  //
});

gulp.task('server', function () {
  connect.server({
    root: ['_site'],
    port: 9000,
    livereload: true
  });
});

gulp.task('make', ['clean', 'docs', 'images', 'sass', 'font', 'javascript'], function () {
});

gulp.task('watch', ['make', 'server'], function () {
  gulp.watch(['source/docs/**', 'source/layouts/**'], ['docs']);
  gulp.watch(['source/images/**'], ['images']);
  gulp.watch(['source/stylesheets/**',], ['sass']);
  connect.reload();
});

// Functions
function buildLanguage(language){
  var filter = gulpFilter([
    '*.html',
    '!*.*.html',                        // Get rid of ALL language-specific articles
    '*.' + language.extname + '.html',  // Get articles specific to THIS language
    'example.' + language.extname       // Code files for this language
  ]);

  return gulp.src(chapters)
    .pipe(filter)
    .pipe(concat('index.html'))
    .pipe(cheerio({
      run: function ($) {
        $('.content-container__description').each(function () {
          if ($(this).next().hasClass('content-container__code')) {
            $(this).next().after('

');
          }else{
            // Add empty code container
            $(this).after('

');
          };
        });
      }
    }))
    .pipe(headerfooter.header('./source/layouts/header.html'))
    .pipe(headerfooter.footer('./source/layouts/footer.html'))
    .pipe(gulp.dest('./_site/' + language.slug))
    .pipe(connect.reload());
}
<commit_msg>Remove clean from the watch and make tasks - it never works, as always attempted in parallel stream<commit_after>// Plugins
var gulp          = require('gulp');
var markdown      = require('gulp-markdown');
var concat        = require('gulp-concat');
var del           = require('del');
var connect       = require('gulp-connect');
var sass          = require('gulp-sass');
var minifyCss     = require('gulp-minify-css');
var uglify        = require('gulp-uglify');
var templateCache = require('gulp-angular-templatecache');
var sourcemaps    = require('gulp-sourcemaps');
var open          = require("gulp-open");
var gulpFilter    = require('gulp-filter');
var headerfooter  = require('gulp-headerfooter');
var cheerio       = require('gulp-cheerio');
var foreach       = require('gulp-foreach');
var ext           = require('gulp-ext-replace');

// Configuration
var config       = require('./data/languages');

// Directories
var docs_dir      = 'source/docs/';
var code_temp_dir = '.tmp/code/';
var md_temp_dir   = '.tmp/docs/';

var chapters = [
  md_temp_dir + '01_overview/01_*.html',
  md_temp_dir + '01_overview/02_*.html',
  md_temp_dir + '01_overview/03_*.html',
  md_temp_dir + '01_overview/04_*.html',
  md_temp_dir + '01_overview/05_support/*.html',
  md_temp_dir + '01_overview/06_*.html',
  md_temp_dir + '01_overview/07_*.html',
  md_temp_dir + '02_api_libraries/01_api_libraries/*.html',
  md_temp_dir + '02_api_libraries/02_initialization/*.html',
  md_temp_dir + '02_api_libraries/03_webhooks/01_overview/*.html',
  md_temp_dir + '02_api_libraries/03_webhooks/02_receiving_webhooks/*.html',
  md_temp_dir + '02_api_libraries/03_webhooks/03_reacting_to_webhooks/*.html',
  md_temp_dir + '02_api_libraries/03_webhooks/04_testing_webhooks/*.html',
  md_temp_dir + '02_api_libraries/03_webhooks/05_bill_webhook/*.html',
  md_temp_dir + '02_api_libraries/03_webhooks/06_pre_auth_webhook/*.html',
  md_temp_dir + '02_api_libraries/03_webhooks/07_subscription_webhook/*.html',
  md_temp_dir + '02_api_libraries/04_prepopulation/*.html',
  md_temp_dir + '02_api_libraries/05_deployment/*.html',
  md_temp_dir + '03_setting_up_HTTP_payments/*.html',
  md_temp_dir + '04_making_REST_requests/*.html',
  md_temp_dir + '05_webhooks_http/*.html',
  md_temp_dir + '05_webhooks_http/04_webhook_types/*.html',
  md_temp_dir + '06_guides/*.html',

  md_temp_dir + '07_resources/*.html',
  md_temp_dir + '07_resources/bill/*.html',
  md_temp_dir + '07_resources/bill/02_create_a_one_off_bill/*.html',
  code_temp_dir + '07_resources/bill/02_create_a_one_off_bill/code/*',
  md_temp_dir + '07_resources/bill/03_confirm_a_new_one_off_bill/*.html',
  code_temp_dir + '07_resources/bill/03_confirm_a_new_one_off_bill/code/*',
  md_temp_dir + '07_resources/bill/04_list_all_bills/*.html',
  code_temp_dir + '07_resources/bill/04_list_all_bills/code/*',
  md_temp_dir + '07_resources/bill/05_retrieve_an_existing_bill/*.html',
  code_temp_dir + '07_resources/bill/05_retrieve_an_existing_bill/code/*',
  md_temp_dir + '07_resources/bill/06_retry_a_failed_bill/*.html',
  code_temp_dir + '07_resources/bill/06_retry_a_failed_bill/code/*',
  md_temp_dir + '07_resources/bill/07_cancel_a_pending_bill/*.html',
  code_temp_dir + '07_resources/bill/07_cancel_a_pending_bill/code/*',
  md_temp_dir + '07_resources/bill/08_refund_a_bill/*.html',
  code_temp_dir + '07_resources/bill/08_refund_a_bill/code/*',
  md_temp_dir + '07_resources/bill/09_statuses/*.html',

  md_temp_dir + '07_resources/merchant/*.html',

  md_temp_dir + '07_resources/merchant/02_retrieve_merchant_details/*.html',
  code_temp_dir + '07_resources/merchant/02_retrieve_merchant_details/code/*',
  md_temp_dir + '07_resources/payout/*.html',

  md_temp_dir + '07_resources/payout/02_list_all_payouts/*.html',
  code_temp_dir + '07_resources/payout/02_list_all_payouts/code/*',
  md_temp_dir + '07_resources/payout/03_retrieve_an_existing_payout/*.html',
  code_temp_dir + '07_resources/payout/03_retrieve_an_existing_payout/code/*',
  md_temp_dir + '07_resources/preauthorization/*.html',

  md_temp_dir + '07_resources/preauthorization/02_create_a_new_pre-authorization/*.html',
  code_temp_dir + '07_resources/preauthorization/02_create_a_new_pre-authorization/code/*',
  md_temp_dir + '07_resources/preauthorization/03_confirm_a_new_preauthorization/*.html',
  code_temp_dir + '07_resources/preauthorization/03_confirm_a_new_preauthorization/code/*',
  md_temp_dir + '07_resources/preauthorization/04_create_a_bill_under_a_preauthorization/*.html',
  code_temp_dir + '07_resources/preauthorization/04_create_a_bill_under_a_preauthorization/code/*',
  md_temp_dir + '07_resources/preauthorization/05_list_all_pre-authorizations/*.html',
  code_temp_dir + '07_resources/preauthorization/05_list_all_pre-authorizations/code/*',
  md_temp_dir + '07_resources/preauthorization/06_retrieve_an_existing_pre-authorization/*.html',
  code_temp_dir + '07_resources/preauthorization/06_retrieve_an_existing_pre-authorization/code/*',
  md_temp_dir + '07_resources/preauthorization/07_cancel_a_pre-authorization/*.html',
  code_temp_dir + '07_resources/preauthorization/07_cancel_a_pre-authorization/code/*',
  md_temp_dir + '07_resources/preauthorization/08_statuses/*.html',

  md_temp_dir + '07_resources/subscription/*.html',

  md_temp_dir + '07_resources/subscription/02_create_a_new_subscription/*.html',
  code_temp_dir + '07_resources/subscription/02_create_a_new_subscription/code/*',
  md_temp_dir + '07_resources/subscription/03_confirm_a_new_subscription/*.html',
  code_temp_dir + '07_resources/subscription/03_confirm_a_new_subscription/code/*',
  md_temp_dir + '07_resources/subscription/03_list_all_subscriptions/*.html',
  code_temp_dir + '07_resources/subscription/03_list_all_subscriptions/code/*',
  md_temp_dir + '07_resources/subscription/04_retrieve_an_existing_subscription/*.html',
  code_temp_dir + '07_resources/subscription/04_retrieve_an_existing_subscription/code/*',
  md_temp_dir + '07_resources/subscription/05_cancel_a_subscription/*.html',
  code_temp_dir + '07_resources/subscription/05_cancel_a_subscription/code/*',
  md_temp_dir + '07_resources/subscription/06_statuses/*.html',

  md_temp_dir + '07_resources/user/*.html',

  md_temp_dir + '07_resources/user/02_list_all_users/*.html',
  code_temp_dir + '07_resources/user/02_list_all_users/code/*'
]

var code = [
  docs_dir + '**/**/**/code/**/*'
]

var md = [
  docs_dir + '**/*.md'
]

// source/javascripts/
var scripts = [
  'source/javascripts/libs/angular.js',
  'source/javascripts/libs/angular-touch.js',
  'source/javascripts/libs/lodash.js',

  'source/javascripts/config/*',
  'source/javascripts/nav-toggle/*',
  'source/javascripts/scroll-spy/*',
  'source/javascripts/toc-nav/*',
  'source/javascripts/close-when-outside/*',
  'source/javascripts/on-click-anchor/*',

  'source/javascripts/docs.js',
]

// Gulp tasks
gulp.task('default', ['make']);

gulp.task('images', function () {
  return gulp.src('source/images/**')
    .pipe(gulp.dest('./_site/images/'))
    .pipe(connect.reload());
});

gulp.task('sass', function () {
  gulp.src('./source/stylesheets/all.scss')
    .pipe(sourcemaps.init())
      .pipe(sass())
      .pipe(concat('all.css'))
      .pipe(minifyCss())
    .pipe(sourcemaps.write('./'))
    .on('error', function (err) { console.log(err.message); })
    .pipe(gulp.dest('_site/stylesheets/'))
    .pipe(connect.reload());
});

gulp.task('font', function () {
  gulp.src('./source/stylesheets/**/*.css')
    .pipe(concat('font.css'))
    .pipe(minifyCss())
    .on('error', function (err) { console.log(err.message); })
    .pipe(gulp.dest('_site/stylesheets/'))
    .pipe(connect.reload());
});

gulp.task('javascript', function () {
  var jsFilter = gulpFilter(['**/*.js']);
  var htmlFilter = gulpFilter(['**/*.html']);
  gulp.src(scripts)
    .pipe(sourcemaps.init())
      .pipe(htmlFilter)
      // replace this line with GC Angular template generator
      .pipe(templateCache({ base: '/Users/samjewell/gc/api-docs/source/javascripts/', standalone: true }))
      .pipe(htmlFilter.restore())
      .pipe(jsFilter) // defensive step in case html files don't get converted
      .pipe(concat('all.js'))
      //.pipe(uglify())
    .pipe(sourcemaps.write('./'))
    .pipe(gulp.dest('_site/javascripts/'))
    .pipe(connect.reload());
});

gulp.task('prepare:code', function () {
  gulp.src(code)
    .pipe(headerfooter.header('./source/layouts/code-header.html'))
    .pipe(headerfooter.footer('./source/layouts/code-footer.html'))
    .pipe(gulp.dest('.tmp/code/'));
});

gulp.task('prepare:markdown', function () {
  gulp.src(md)
    .pipe(markdown())
    .pipe(headerfooter.header('./source/layouts/doc-header.html'))
    .pipe(headerfooter.footer('./source/layouts/doc-footer.html'))
    .pipe(gulp.dest('.tmp/docs/'));
});

// gulp.task('clean', function(cb) {
//   del([
//     '.tmp',
//     '_site',
//   ], cb);
// });

gulp.task('docs', ['prepare:code', 'prepare:markdown'], function() {
  setTimeout(function() {
    for(var i = 0; i < config.length; i++) {
      var obj = config[i];
      buildLanguage(obj);
    }

  }, 5000);
  //
  // Hacky alert: This timeout is needed for the code files to be read from /tmp
  //
});

gulp.task('server', function () {
  connect.server({
    root: ['_site'],
    port: 9000,
    livereload: true
  });
});

gulp.task('make', ['docs', 'images', 'sass', 'font', 'javascript'], function () {
});

gulp.task('watch', ['make', 'server'], function () {
  gulp.watch(['source/docs/**', 'source/layouts/**'], ['docs']);
  gulp.watch(['source/images/**'], ['images']);
  gulp.watch(['source/stylesheets/**',], ['sass']);
  connect.reload();
});

// Functions
function buildLanguage(language){
  var filter = gulpFilter([
    '*.html',
    '!*.*.html',                        // Get rid of ALL language-specific articles
    '*.' + language.extname + '.html',  // Get articles specific to THIS language
    'example.' + language.extname       // Code files for this language
  ]);

  return gulp.src(chapters)
    .pipe(filter)
    .pipe(concat('index.html'))
    .pipe(cheerio({
      run: function ($) {
        $('.content-container__description').each(function () {
          if ($(this).next().hasClass('content-container__code')) {
            $(this).next().after('

');
          }else{
            // Add empty code container
            $(this).after('

');
          };
        });
      }
    }))
    .pipe(headerfooter.header('./source/layouts/header.html'))
    .pipe(headerfooter.footer('./source/layouts/footer.html'))
    .pipe(gulp.dest('./_site/' + language.slug))
    .pipe(connect.reload());
}
<|endoftext|>


<commit_before>const gulp = require('gulp')
const browserSync = require('browser-sync').create()
const sass = require('gulp-sass')
const plumber = require('gulp-plumber')
const gutil = require('gulp-util')
const fs = require('fs')
const juice = require('juice')
const path = require('path')
const information = require(path.join(__dirname, 'working/information.json'))
const html2txt = require('gulp-html2txt')
const cheerio = require('cheerio')
const mailgun = require('mailgun.js')
const imagemin = require('gulp-imagemin')
const postcss = require('gulp-postcss')
const uncss = require('postcss-uncss')

// Compile sass into CSS & auto-inject into browsers
gulp.task('sass', (done) => {
  return gulp.src('working/scss/*.scss')
    // plumber is used so that the watch task does not break when there is some wrong code
    .pipe(plumber(function (error) {
      gutil.beep()
      console.log(error)
      this.emit('end')
    }))
    .pipe(sass())
    .pipe(gulp.dest('working/css'))
    .pipe(browserSync.stream())
})

// Compile sass into CSS, remove unneeded CSS and dump it into the working folder for use in build process
// it is not neccessary to create a build CSS file just for the purpose of building the final email
gulp.task('css', () => {
  var plugins = [
    uncss({
      html: ['working/index.html']
    })
  ]
  return gulp.src('working/scss/*.scss')
    .pipe(plumber(function (error) {
      gutil.beep()
      console.log(error)
      this.emit('end')
    }))
    .pipe(sass())
    .pipe(postcss(plugins))
    .pipe(gulp.dest('working/css'))
})

/**
* replaces each instance of a replacelist key template in the string for the replacelist value
* @param {string}
* @param {object}
* @return {string}
*/
const replaceLinks = (str, replacelist = {}, customUrl = '') => {
  // there has to be a string to pass through even if replacelist is empty
  if (str.length < 1) throw new Error('File is empty')
  // if there is no replacelist or it is empty, pass through the value
  let html = str
  if (Object.keys(replacelist).length !== 0) {
    for (const key of Object.keys(replacelist)) {
      let replacestring = new RegExp(`#{${key}}`, 'gi')
      let linkWithParameters = `${replacelist[key]}${createParameterString(information.parameters)}`
      if (customUrl) {
        let url = customUrl.replace(/(#{url})/g, linkWithParameters).replace(/(#{report})/g, key)
        html = html.replace(replacestring, url)
      } else {
        html = html.replace(replacestring, linkWithParameters)
      }
    }
    let basicReg = /#{(.*?)}/g
    let els = html.match(basicReg)
    if (els !== null) {
      // find all matches and filter out the fluff
      // TODO think about if a set would be more appropriate as it would only list the unique values
      /*
      let allElements = new Set(els.map(x => x.replace('#{','').replace('}', '')))
      console.log(`Warning: there are still ${allElements.size} elements not replaced: ${[...allElements]}'`)
      */
      let allElements = els.map(x => x.replace('#{', '').replace('}', ''))
      console.log(`Warning: there are still ${allElements.length} instances not replaced: ${allElements}`)
    }
    return html
  } else {
    console.log('Warning: no links are provided, html goes through as is.')
    return str
  }
}

/**
* creates a url parameter string from the links object given
* @param {object}
* @return {string}
*/
const createParameterString = (parameters) => {
  let availableUtmKeys = ['source', 'medium', 'name', 'term', 'content']
  let paramsArr = []
  // check if the parameters exist, otherwise don't bother
  if (parameters.utm || parameters.custom) {
    // loop through all the utm and custom keys
    for (const paramKeys of Object.keys(parameters)) {
      // loop through the inner keys of utm and custom
      for (const key of Object.keys(parameters[paramKeys])) {
        // don't add if it is empty or if it is not a string or number
        if (parameters[paramKeys][key] && (typeof parameters[paramKeys][key] === 'string' || typeof parameters[paramKeys][key] === 'number')) {
          // only add the keys that are valid utm keys, ignore the ones that are not correct
          // IGNORE OR ERROR?
          if (paramKeys === 'utm' && availableUtmKeys.indexOf(key) !== -1) {
            paramsArr.push(`utm_${key}=${parameters[paramKeys][key]}`)
          } else if (paramKeys !== 'utm') { // if the keys are not utm, you are free to add them
            paramsArr.push(`${key}=${parameters[paramKeys][key]}`)
          }
        }
      }
    }
  }
  // joining all parameters in a string
  // if there are no parameters, create an empty string
  let paramsString = paramsArr.length !== 0 ? `?${paramsArr.join('&')}` : ''
  return paramsString
}

/**
* replaces each instance of a href atrribute in the first argument for the values provided in the second argument
* @param {string}
* @param {string}
* @param {function}
* @return {string}
*/
const addParameters = (str, parameters = '', cheerio) => {
  // check if the createParameterString returns a non-empty string
  // to avoid all the work that is not needed
  if (parameters) {
    // load the cheerio instance for appending links
    const $ = cheerio.load(str, { decodeEntities: false })
    // create the parameter string that will be appended to each href

    // add the parameters to each href in the email
    $('a').each(function (i, el) {
      let origHref = $(this).attr('href')
      // if the split method returns an array that is longer than 1 element, it means that there is an existing parameter in it
      // append the parameters only if there is no existing parameters
      if (origHref.split('?').length === 1) {
        $(this).attr('href', origHref + parameters)
      }
    })
    return $.html()
  } else {
    // if there is nothing available, return as is
    return str
  }
}

/**
* replaces each instance of a href atrribute in the first argument for the values provided in the second argument
* @param {string}
* @param {string}
* @return {string}
*/
const createHtml = (html, cssPath) => {
  return new Promise((resolve, reject) => {
    // replace the file path in the html file so that juice can find it, looking from the root of the project
    // replace the path for images since juice needs all files to be present
    let email = html.replace('<link rel="stylesheet" href="css/styles.css">', `<link rel="stylesheet" href="${cssPath}">`).replace('img/', 'working/img/')
    juice.juiceResources(email, { preserveMediaQueries: true, applyStyleTags: true }, (err, html) => {
      if (err) reject(err)
      // just create the html that will be used
      resolve(html)
    })
  })
}
// addParameters(replaceLinks(html, information.links), createParameterString(information.parameters), cheerio)
gulp.task('premailer', (done) => {
  fs.readFile('working/index.html', 'utf-8', (err, html) => {
    if (err) throw err
    createHtml(html, 'working/css/styles.css', addParameters, createParameterString, cheerio).then(html => {
      fs.writeFile('build/index.html', html.replace('working/img/', 'img/'), 'utf8', err => {
        if (err) {
          if (err.code === 'ENOENT') {
            fs.mkdir('build', err => {
              if (err) console.log(err)
              fs.writeFile('build/index.html', html.replace('working/img/', 'img/'), 'utf8', err => {
                if (err) console.log(err)
                done()
              })
            })
          }
        } else {
          done()
        }
      })
    }).catch(e => {
      console.log(e)
    })
  })
})

// convert html to txt
gulp.task('txt', () => {
  return gulp.src('build/index.html')
    .pipe(html2txt())
    .pipe(gulp.dest('build/'))
})

// start up browserSync
gulp.task('browserSync', (done) => {
  browserSync.init({
    server: 'working'
  })
  done()
})

// reload browserSync
gulp.task('reload', (done) => {
  browserSync.reload()
  done()
})

// watch scss and html files for changes
gulp.task('watchSassAndHtml', () => {
  gulp.watch('working/scss/*.scss', gulp.parallel('sass', 'reload'))
  gulp.watch('working/*.html', gulp.series('reload'))
})

// compress images
gulp.task('img', (done) => {
  return gulp.src('working/img/*')
    .pipe(imagemin())
    .pipe(gulp.dest('build/img'))
})

const sendmail = (done) => {
  const credentials = require('./credentials.json')
  const mg = mailgun.client({ username: 'api', key: process.env.MAILGUN_API_KEY || credentials.mailgun.key })
  const information = require('./working/information.json')
  const html = new Promise((resolve, reject) => {
    fs.readFile('./build/index.html', 'utf-8', (err, data) => {
      if (err) throw Error(err)
      if (data.length > 0) {
        let newData = data.replace(/img\/(.*?)"/gi, 'cid:$1"')
        resolve(newData)
      } else {
        reject('Empty file')
      }
    })
  })
  const text = new Promise((resolve, reject) => {
    fs.readFile('./build/index.txt', 'utf-8', (err, data) => {
      if (err) throw Error(err)
      if (data.length > 0) {
        resolve(data)
      } else {
        reject('Empty file')
      }
    })
  })
  const images = new Promise((resolve, reject) => {
    // read the path to the images and return a readStream for each file
    fs.readdir(path.join(__dirname, 'working', 'img'), (err, files) => {
      console.log(files)
      if (err) reject(err)
      const streamOfImages = files.map(img => {
        return fs.createReadStream(path.join(__dirname, 'working', 'img', img))
      })
      resolve(streamOfImages)
    })
  })
  const attachments = new Promise((resolve, reject) => {
    // read the path to the attachments and return a readStream for each file
    fs.readdir(path.join(__dirname, 'working', 'attachments'), (err, files) => {
      if (err) throw Error(err)
      const streamOfFiles = files
      .filter(file => {
        // .gitkeep should not be sent
        return file !== '.gitkeep'
      })
      .map(file => {
        return fs.createReadStream(path.join(__dirname, 'working', 'attachments', file))
      })
      resolve(streamOfFiles)
    })
  })
  Promise.all([html, text, images, attachments]).then(emails => {
    let [html, text, images, attachments] = emails
    mg.messages.create(credentials.mailgun.domain, {
      from: `${information.senderName} ${information.senderEmail}`,
      to: information.recipient,
      subject: information.subject,
      text: text,
      html: html,
      inline: images,
      attachment: attachments
    })
      .then(msg => {
        console.log(msg)
        done()
      }
      ) // logs response data
      .catch(err => {
        console.log(err)
        done()
      }) // logs any error
    done()
  }).catch(err => {
    console.log(err)
    done()
  })
}

gulp.task('links', (done) => {
  fs.readFile('./build/index.html', 'utf-8', (err, data) => {
    if (err) console.log(err)
    fs.writeFile('./build/index.html', replaceLinks(data, information.links), 'utf-8', err => {
      if (err) console.log(err)
      done()
    })
  })
})

gulp.task('inxmailLinks', (done) => {
  fs.readFile('./build/index.html', 'utf-8', (err, data) => {
    if (err) console.log(err)
    let inxRegex = `[%url:unique-count; '#{url}'; '#{report}' ;  ; '#{report}']`
    fs.writeFile('./build/index.html', replaceLinks(data, information.links, inxRegex), 'utf-8', err => {
      if (err) console.log(err)
      done()
    })
  })
})

gulp.task('email', gulp.series('css', 'premailer', 'txt', 'links', sendmail))
gulp.task('build', gulp.series('css', 'premailer', 'img', 'links', 'txt'))
gulp.task('inxmail', gulp.series('css', 'premailer', 'img', 'inxmailLinks', 'txt'))
gulp.task('serve', gulp.series('sass', gulp.parallel('browserSync', 'watchSassAndHtml')))

module.exports = {
  replaceLinks,
  addParameters,
  createParameterString,
  createHtml,
  sendmail
}
<commit_msg>replace all image paths globally instead of just one<commit_after>const gulp = require('gulp')
const browserSync = require('browser-sync').create()
const sass = require('gulp-sass')
const plumber = require('gulp-plumber')
const gutil = require('gulp-util')
const fs = require('fs')
const juice = require('juice')
const path = require('path')
const information = require(path.join(__dirname, 'working/information.json'))
const html2txt = require('gulp-html2txt')
const cheerio = require('cheerio')
const mailgun = require('mailgun.js')
const imagemin = require('gulp-imagemin')
const postcss = require('gulp-postcss')
const uncss = require('postcss-uncss')

// Compile sass into CSS & auto-inject into browsers
gulp.task('sass', (done) => {
  return gulp.src('working/scss/*.scss')
    // plumber is used so that the watch task does not break when there is some wrong code
    .pipe(plumber(function (error) {
      gutil.beep()
      console.log(error)
      this.emit('end')
    }))
    .pipe(sass())
    .pipe(gulp.dest('working/css'))
    .pipe(browserSync.stream())
})

// Compile sass into CSS, remove unneeded CSS and dump it into the working folder for use in build process
// it is not neccessary to create a build CSS file just for the purpose of building the final email
gulp.task('css', () => {
  var plugins = [
    uncss({
      html: ['working/index.html']
    })
  ]
  return gulp.src('working/scss/*.scss')
    .pipe(plumber(function (error) {
      gutil.beep()
      console.log(error)
      this.emit('end')
    }))
    .pipe(sass())
    .pipe(postcss(plugins))
    .pipe(gulp.dest('working/css'))
})

/**
* replaces each instance of a replacelist key template in the string for the replacelist value
* @param {string}
* @param {object}
* @return {string}
*/
const replaceLinks = (str, replacelist = {}, customUrl = '') => {
  // there has to be a string to pass through even if replacelist is empty
  if (str.length < 1) throw new Error('File is empty')
  // if there is no replacelist or it is empty, pass through the value
  let html = str
  if (Object.keys(replacelist).length !== 0) {
    for (const key of Object.keys(replacelist)) {
      let replacestring = new RegExp(`#{${key}}`, 'gi')
      let linkWithParameters = `${replacelist[key]}${createParameterString(information.parameters)}`
      if (customUrl) {
        let url = customUrl.replace(/(#{url})/g, linkWithParameters).replace(/(#{report})/g, key)
        html = html.replace(replacestring, url)
      } else {
        html = html.replace(replacestring, linkWithParameters)
      }
    }
    let basicReg = /#{(.*?)}/g
    let els = html.match(basicReg)
    if (els !== null) {
      // find all matches and filter out the fluff
      // TODO think about if a set would be more appropriate as it would only list the unique values
      /*
      let allElements = new Set(els.map(x => x.replace('#{','').replace('}', '')))
      console.log(`Warning: there are still ${allElements.size} elements not replaced: ${[...allElements]}'`)
      */
      let allElements = els.map(x => x.replace('#{', '').replace('}', ''))
      console.log(`Warning: there are still ${allElements.length} instances not replaced: ${allElements}`)
    }
    return html
  } else {
    console.log('Warning: no links are provided, html goes through as is.')
    return str
  }
}

/**
* creates a url parameter string from the links object given
* @param {object}
* @return {string}
*/
const createParameterString = (parameters) => {
  let availableUtmKeys = ['source', 'medium', 'name', 'term', 'content']
  let paramsArr = []
  // check if the parameters exist, otherwise don't bother
  if (parameters.utm || parameters.custom) {
    // loop through all the utm and custom keys
    for (const paramKeys of Object.keys(parameters)) {
      // loop through the inner keys of utm and custom
      for (const key of Object.keys(parameters[paramKeys])) {
        // don't add if it is empty or if it is not a string or number
        if (parameters[paramKeys][key] && (typeof parameters[paramKeys][key] === 'string' || typeof parameters[paramKeys][key] === 'number')) {
          // only add the keys that are valid utm keys, ignore the ones that are not correct
          // IGNORE OR ERROR?
          if (paramKeys === 'utm' && availableUtmKeys.indexOf(key) !== -1) {
            paramsArr.push(`utm_${key}=${parameters[paramKeys][key]}`)
          } else if (paramKeys !== 'utm') { // if the keys are not utm, you are free to add them
            paramsArr.push(`${key}=${parameters[paramKeys][key]}`)
          }
        }
      }
    }
  }
  // joining all parameters in a string
  // if there are no parameters, create an empty string
  let paramsString = paramsArr.length !== 0 ? `?${paramsArr.join('&')}` : ''
  return paramsString
}

/**
* replaces each instance of a href atrribute in the first argument for the values provided in the second argument
* @param {string}
* @param {string}
* @param {function}
* @return {string}
*/
const addParameters = (str, parameters = '', cheerio) => {
  // check if the createParameterString returns a non-empty string
  // to avoid all the work that is not needed
  if (parameters) {
    // load the cheerio instance for appending links
    const $ = cheerio.load(str, { decodeEntities: false })
    // create the parameter string that will be appended to each href

    // add the parameters to each href in the email
    $('a').each(function (i, el) {
      let origHref = $(this).attr('href')
      // if the split method returns an array that is longer than 1 element, it means that there is an existing parameter in it
      // append the parameters only if there is no existing parameters
      if (origHref.split('?').length === 1) {
        $(this).attr('href', origHref + parameters)
      }
    })
    return $.html()
  } else {
    // if there is nothing available, return as is
    return str
  }
}

/**
* replaces each instance of a href atrribute in the first argument for the values provided in the second argument
* @param {string}
* @param {string}
* @return {string}
*/
const createHtml = (html, cssPath) => {
  return new Promise((resolve, reject) => {
    // replace the file path in the html file so that juice can find it, looking from the root of the project
    // replace the path for images since juice needs all files to be present
    let email = html.replace('<link rel="stylesheet" href="css/styles.css">', `<link rel="stylesheet" href="${cssPath}">`).replace(/img\//g, 'working/img/')
    juice.juiceResources(email, { preserveMediaQueries: true, applyStyleTags: true, webResources: {images: false} }, (err, html) => {
      if (err) reject(err)
      // just create the html that will be used
      resolve(html)
    })
  })
}
// addParameters(replaceLinks(html, information.links), createParameterString(information.parameters), cheerio)
gulp.task('premailer', (done) => {
  fs.readFile('working/index.html', 'utf-8', (err, html) => {
    if (err) throw err
    createHtml(html, 'working/css/styles.css', addParameters, createParameterString, cheerio).then(html => {
      fs.writeFile('build/index.html', html.replace(/working\/img\//g, 'img/'), 'utf8', err => {
        if (err) {
          if (err.code === 'ENOENT') {
            fs.mkdir('build', err => {
              if (err) console.log(err)
              fs.writeFile('build/index.html', html.replace(/working\/img\//g, 'img/'), 'utf8', err => {
                if (err) console.log(err)
                done()
              })
            })
          }
        } else {
          done()
        }
      })
    }).catch(e => {
      console.log(e)
    })
  })
})

// convert html to txt
gulp.task('txt', () => {
  return gulp.src('build/index.html')
    .pipe(html2txt())
    .pipe(gulp.dest('build/'))
})

// start up browserSync
gulp.task('browserSync', (done) => {
  browserSync.init({
    server: 'working'
  })
  done()
})

// reload browserSync
gulp.task('reload', (done) => {
  browserSync.reload()
  done()
})

// watch scss and html files for changes
gulp.task('watchSassAndHtml', () => {
  gulp.watch('working/scss/*.scss', gulp.parallel('sass', 'reload'))
  gulp.watch('working/*.html', gulp.series('reload'))
})

// compress images
gulp.task('img', (done) => {
  return gulp.src('working/img/*')
    .pipe(imagemin())
    .pipe(gulp.dest('build/img'))
})

const sendmail = (done) => {
  const credentials = require('./credentials.json')
  const mg = mailgun.client({ username: 'api', key: process.env.MAILGUN_API_KEY || credentials.mailgun.key })
  const information = require('./working/information.json')
  const html = new Promise((resolve, reject) => {
    fs.readFile('./build/index.html', 'utf-8', (err, data) => {
      if (err) throw Error(err)
      if (data.length > 0) {
        let newData = data.replace(/img\/(.*?)"/gi, 'cid:$1"')
        resolve(newData)
      } else {
        reject('Empty file')
      }
    })
  })
  const text = new Promise((resolve, reject) => {
    fs.readFile('./build/index.txt', 'utf-8', (err, data) => {
      if (err) throw Error(err)
      if (data.length > 0) {
        resolve(data)
      } else {
        reject('Empty file')
      }
    })
  })
  const images = new Promise((resolve, reject) => {
    // read the path to the images and return a readStream for each file
    fs.readdir(path.join(__dirname, 'working', 'img'), (err, files) => {
      console.log(files)
      if (err) reject(err)
      const streamOfImages = files
      .filter(file => {
        // .gitkeep should not be sent
        return file !== '.gitkeep'
      })
      .map(img => {
        return fs.createReadStream(path.join(__dirname, 'working', 'img', img))
      })
      resolve(streamOfImages)
    })
  })
  const attachments = new Promise((resolve, reject) => {
    // read the path to the attachments and return a readStream for each file
    fs.readdir(path.join(__dirname, 'working', 'attachments'), (err, files) => {
      if (err) throw Error(err)
      const streamOfFiles = files
      .filter(file => {
        // .gitkeep should not be sent
        return file !== '.gitkeep'
      })
      .map(file => {
        return fs.createReadStream(path.join(__dirname, 'working', 'attachments', file))
      })
      resolve(streamOfFiles)
    })
  })
  Promise.all([html, text, images, attachments]).then(emails => {
    let [html, text, images, attachments] = emails
    mg.messages.create(credentials.mailgun.domain, {
      from: `${information.senderName} ${information.senderEmail}`,
      to: information.recipient,
      subject: information.subject,
      text: text,
      html: html,
      inline: images,
      attachment: attachments
    })
      .then(msg => {
        console.log(msg)
        done()
      }
      ) // logs response data
      .catch(err => {
        console.log(err)
        done()
      }) // logs any error
    done()
  }).catch(err => {
    console.log(err)
    done()
  })
}

gulp.task('links', (done) => {
  fs.readFile('./build/index.html', 'utf-8', (err, data) => {
    if (err) console.log(err)
    fs.writeFile('./build/index.html', replaceLinks(data, information.links), 'utf-8', err => {
      if (err) console.log(err)
      done()
    })
  })
})

gulp.task('inxmailLinks', (done) => {
  fs.readFile('./build/index.html', 'utf-8', (err, data) => {
    if (err) console.log(err)
    let inxRegex = `[%url:unique-count; '#{url}'; '#{report}' ;  ; '#{report}']`
    fs.writeFile('./build/index.html', replaceLinks(data, information.links, inxRegex), 'utf-8', err => {
      if (err) console.log(err)
      done()
    })
  })
})

gulp.task('email', gulp.series('css', 'premailer', 'txt', 'img', 'links', sendmail))
gulp.task('build', gulp.series('css', 'premailer', 'img', 'links', 'txt'))
gulp.task('inxmail', gulp.series('css', 'premailer', 'img', 'inxmailLinks', 'txt'))
gulp.task('serve', gulp.series('sass', gulp.parallel('browserSync', 'watchSassAndHtml')))

module.exports = {
  replaceLinks,
  addParameters,
  createParameterString,
  createHtml,
  sendmail
}
<|endoftext|>


<commit_before>Modules.VERSION = '1.0.0';
Modules.UTILS = true;

// PrefPanes - handles the preferences tab and all its contents for the add-on
// register(aPane, aModule) - registers a new preferences pane to be appended to the preferences tab
//	aPane - (str) name of the pane, in the form of a aPane.xul overlay to be found in content/
//	(optional) aModule -	(str) name of a module to be loaded alongside the overlay, in the form of a aModule.jsm to be found in resource/modules/;
//				if (bool) true, default to aPane
// unregister(aPane) - unregisters a preferences pane from the preferences tab
//	see register()
// setList(list) - register a set of panes at once
//	list - (iterable) list of arguments to apply to register()
// open() - tries to switch to an already opened add-on preferences tab; if none is found then a new one is opened in the most recent window
// closeAll() - closes all the add-on's preferences tab
this.PrefPanes = {
	chromeUri: 'chrome://'+objPathString+'/content/utils/preferences.xul',
	aboutUri: null,

	get notifyUri () {
		return (this.aboutUri ? this.aboutUri.spec : this.chromeUri) + '#paneAbout';
	},

	panes: new Map(),
	previousVersion: null,

	observe: function(aSubject, aTopic, aData) {
		this.initWindow(aSubject);
	},

	register: function(aPane, aModule) {
		if(!this.panes.has(aPane)) {
			this.panes.set(aPane, {
				module: (aModule === true) ? aPane : aModule
			});
		}
	},

	unregister: function(aPane) {
		if(this.panes.has(aPane)) {
			this.panes.delete(aPane);
		}
	},

	setList: function(list) {
		for(let args of list) {
			this.register.apply(this, args);
		}
	},

	init: function() {
		// we set the add-on status in the API webpage from within the add-on itself
		Messenger.loadInAll('utils/api');

		// always add the about pane to the preferences dialog, it should be the last category in the list
		this.register('utils/about', true);

		Browsers.callOnAll(aWindow => { this.initWindow(aWindow); }, this.chromeUri);
		Browsers.register(this, 'pageshow', this.chromeUri);

		// if defaults.js supplies an addonUUID, use it to register the about: uri linking to the add-on's preferences
		if(addonUUID) {
			this.aboutUri = {
				spec: 'about:'+objPathString,
				manager: Cm.QueryInterface(Ci.nsIComponentRegistrar),

				handler: {
					uri: Services.io.newURI(this.chromeUri, null, null),
					classDescription: 'about: handler for add-on '+objName,
					classID: Components.ID(addonUUID),
					contractID: '@mozilla.org/network/protocol/about;1?what='+objPathString,
					QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule]),
					newChannel: function(aURI) {
						let chan = Services.io.newChannelFromURI(this.uri);
						chan.originalURI = aURI;
						return chan;
					},
					getURIFlags: function(aURI) 0
				},

				load: function() {
					this.manager.registerFactory(this.handler.classID, this.handler.classDescription, this.handler.contractID, this);
				},

				unload: function() {
					this.manager.unregisterFactory(this.handler.classID, this);
				},

				createInstance: function(outer, iid) {
					if(outer) {
						throw Cr.NS_ERROR_NO_AGGREGATION;
					}
					return this.handler;
				}
			};
			this.aboutUri.load();

			Browsers.callOnAll(aWindow => { this.initWindow(aWindow); }, this.aboutUri.spec);
			Browsers.register(this, 'pageshow', this.aboutUri.spec);
		}

		// if we're in a dev version, ignore all this
		if(AddonData.version.contains('a') || AddonData.version.contains('b')) { return; }

		// if we're updating from a version without this module, try to figure out the last version
		if(Prefs.lastVersionNotify == '0' && STARTED == ADDON_UPGRADE && AddonData.oldVersion) {
			Prefs.lastVersionNotify = AddonData.oldVersion;
		}

		// now make sure we notify the user when updating only; when installing for the first time do nothing
		if(Prefs.showTabOnUpdates && Prefs.lastVersionNotify != '0' && Services.vc.compare(Prefs.lastVersionNotify, AddonData.version) < 0) {
			this.previousVersion = Prefs.lastVersionNotify;
			this.openWhenReady();
		}

		// always set the pref to the current version, this also ensures only one notification tab will open per firefox session (and not one per window)
		if(Prefs.lastVersionNotify != AddonData.version) {
			Prefs.lastVersionNotify = AddonData.version;
		}
	},

	uninit: function() {
		Messenger.unloadFromAll('utils/api');

		this.closeAll();

		Browsers.unregister(this, 'pageshow', this.chromeUri);

		if(this.aboutUri) {
			Browsers.unregister(this, 'pageshow', this.aboutUri.spec);
			this.aboutUri.unload();
		}
	},

	// we have to wait for Session Store to finish, otherwise our tab will be overriden by a session-restored tab
	openWhenReady: function() {
		if(typeof(PrefPanes) == 'undefined') { return; }

		var aWindow = window; // most recent window, if it doesn't exist yet it means we're still starting up, so give it a second
		if(!aWindow || !aWindow.SessionStore) {
			aSync(() => { this.openWhenReady(); }, 500);
			return;
		}

		var state = JSON.parse(aWindow.SessionStore.getBrowserState());
		// we're in a window, so "a" window should exist...
		if(state.windows.length == 0) {
			aSync(() => { this.openWhenReady(); }, 500);
			return;
		}

		this.open(aWindow, true);
	},

	open: function(aWindow, loadOnStartup) {
		// first try to switch to an already opened options tab
		for(let tab of aWindow.gBrowser.mTabs) {
			if(tab.linkedBrowser.currentURI.spec.startsWith(this.chromeUri)
			|| (this.aboutUri && tab.linkedBrowser.currentURI.spec.startsWith(this.aboutUri.spec))) {
				aWindow.gBrowser.selectedTab = tab;
				return;
			}
		}

		// no tab was found, so open a new one
		if(loadOnStartup) {
			aWindow.gBrowser.selectedTab = aWindow.gBrowser.addTab(this.notifyUri);
			aWindow.gBrowser.selectedTab.loadOnStartup = true; // for Tab Mix Plus
		}
		else {
			aWindow.gBrowser.selectedTab = aWindow.gBrowser.addTab(this.aboutUri ? this.aboutUri.spec : this.chromeUri);
		}
	},

	closeAll: function() {
		Windows.callOnAll(aWindow => {
			for(let tab of aWindow.gBrowser.mTabs) {
				if(tab.linkedBrowser.currentURI.spec.startsWith(this.chromeUri)
				|| (this.aboutUri && tab.linkedBrowser.currentURI.spec.startsWith(this.aboutUri.spec))) {
					aWindow.gBrowser.removeTab(tab);
				}
			}
		}, 'navigator:browser');
	},

	initWindow: function(aWindow) {
		// prepare the window as usual
		replaceObjStrings(aWindow.document);
		prepareObject(aWindow, objName);

		// load the utils only when the preferences tab is finished with its overlays from this object
		let promises = [];
		for(let pane of this.panes.keys()) {
			promises.push(new Promise(function(resolve, reject) {
				let overlay = pane;
				Overlays.overlayWindow(aWindow, overlay, {
					onLoad: function() {
						resolve();
					}
				});
			}));
		}

		Promise.all(promises).then(() => {
			aWindow[objName].Modules.load("utils/preferencesUtils");

			// if any of the panes require their own module, load it now
			for(let pane of this.panes.values()) {
				if(pane.module) {
					aWindow[objName].Modules.load(pane.module);
				}
			}
		});
	}
};

Modules.LOADMODULE = function() {
	Prefs.setDefaults({
		lastPrefPane: '',
		lastVersionNotify: '0',
		showTabOnUpdates: true
	});

	PrefPanes.init();
};

Modules.UNLOADMODULE = function() {
	PrefPanes.uninit();
};
<commit_msg>fix for firefox 38-40<commit_after>Modules.VERSION = '1.0.1';
Modules.UTILS = true;

// PrefPanes - handles the preferences tab and all its contents for the add-on
// register(aPane, aModule) - registers a new preferences pane to be appended to the preferences tab
//	aPane - (str) name of the pane, in the form of a aPane.xul overlay to be found in content/
//	(optional) aModule -	(str) name of a module to be loaded alongside the overlay, in the form of a aModule.jsm to be found in resource/modules/;
//				if (bool) true, default to aPane
// unregister(aPane) - unregisters a preferences pane from the preferences tab
//	see register()
// setList(list) - register a set of panes at once
//	list - (iterable) list of arguments to apply to register()
// open() - tries to switch to an already opened add-on preferences tab; if none is found then a new one is opened in the most recent window
// closeAll() - closes all the add-on's preferences tab
this.PrefPanes = {
	chromeUri: 'chrome://'+objPathString+'/content/utils/preferences.xul',
	aboutUri: null,

	get notifyUri () {
		return (this.aboutUri ? this.aboutUri.spec : this.chromeUri) + '#paneAbout';
	},

	panes: new Map(),
	previousVersion: null,

	observe: function(aSubject, aTopic, aData) {
		this.initWindow(aSubject);
	},

	register: function(aPane, aModule) {
		if(!this.panes.has(aPane)) {
			this.panes.set(aPane, {
				module: (aModule === true) ? aPane : aModule
			});
		}
	},

	unregister: function(aPane) {
		if(this.panes.has(aPane)) {
			this.panes.delete(aPane);
		}
	},

	setList: function(list) {
		for(let args of list) {
			this.register.apply(this, args);
		}
	},

	init: function() {
		// we set the add-on status in the API webpage from within the add-on itself
		Messenger.loadInAll('utils/api');

		// always add the about pane to the preferences dialog, it should be the last category in the list
		this.register('utils/about', true);

		Browsers.callOnAll(aWindow => { this.initWindow(aWindow); }, this.chromeUri);
		Browsers.register(this, 'pageshow', this.chromeUri);

		// if defaults.js supplies an addonUUID, use it to register the about: uri linking to the add-on's preferences
		if(addonUUID) {
			this.aboutUri = {
				spec: 'about:'+objPathString,
				manager: Cm.QueryInterface(Ci.nsIComponentRegistrar),

				handler: {
					uri: Services.io.newURI(this.chromeUri, null, null),
					classDescription: 'about: handler for add-on '+objName,
					classID: Components.ID(addonUUID),
					contractID: '@mozilla.org/network/protocol/about;1?what='+objPathString,
					QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule]),
					newChannel: function(aURI) {
						let chan = Services.io.newChannelFromURI(this.uri);
						chan.originalURI = aURI;
						return chan;
					},
					getURIFlags: function(aURI) 0
				},

				load: function() {
					this.manager.registerFactory(this.handler.classID, this.handler.classDescription, this.handler.contractID, this);
				},

				unload: function() {
					this.manager.unregisterFactory(this.handler.classID, this);
				},

				createInstance: function(outer, iid) {
					if(outer) {
						throw Cr.NS_ERROR_NO_AGGREGATION;
					}
					return this.handler;
				}
			};
			this.aboutUri.load();

			Browsers.callOnAll(aWindow => { this.initWindow(aWindow); }, this.aboutUri.spec);
			Browsers.register(this, 'pageshow', this.aboutUri.spec);
		}

		// if we're in a dev version, ignore all this
		if(AddonData.version.contains('a') || AddonData.version.contains('b')) { return; }

		// if we're updating from a version without this module, try to figure out the last version
		if(Prefs.lastVersionNotify == '0' && STARTED == ADDON_UPGRADE && AddonData.oldVersion) {
			Prefs.lastVersionNotify = AddonData.oldVersion;
		}

		// now make sure we notify the user when updating only; when installing for the first time do nothing
		if(Prefs.showTabOnUpdates && Prefs.lastVersionNotify != '0' && Services.vc.compare(Prefs.lastVersionNotify, AddonData.version) < 0) {
			this.previousVersion = Prefs.lastVersionNotify;
			this.openWhenReady();
		}

		// always set the pref to the current version, this also ensures only one notification tab will open per firefox session (and not one per window)
		if(Prefs.lastVersionNotify != AddonData.version) {
			Prefs.lastVersionNotify = AddonData.version;
		}

		// current version of firefox has some display issues, this doesn't seem needed in the current Nightly (FF41+)
		if(Services.vc.compare(Services.appinfo.version, '41.0a1') < 0) {
			var sscode = '@namespace url(http://www.w3.org/1999/xhtml);\n';
			sscode += '@-moz-document url("'+this.chromeUri+'")'+(this.aboutUri ? ', url("'+this.aboutUri.spec+'")' : '')+' {\n';
			sscode += '	#bank .hours { height: 100%; }\n';
			sscode += '	#bank .balance { position: relative; height: 50%; top: 0.4em; }\n';
			sscode += '}';
			LOG(sscode);
			Styles.load('PrefPanesFix', sscode, true);
		}
	},

	uninit: function() {
		Styles.unload('PrefPanesFix');

		Messenger.unloadFromAll('utils/api');

		this.closeAll();

		Browsers.unregister(this, 'pageshow', this.chromeUri);

		if(this.aboutUri) {
			Browsers.unregister(this, 'pageshow', this.aboutUri.spec);
			this.aboutUri.unload();
		}
	},

	// we have to wait for Session Store to finish, otherwise our tab will be overriden by a session-restored tab
	openWhenReady: function() {
		if(typeof(PrefPanes) == 'undefined') { return; }

		var aWindow = window; // most recent window, if it doesn't exist yet it means we're still starting up, so give it a second
		if(!aWindow || !aWindow.SessionStore) {
			aSync(() => { this.openWhenReady(); }, 500);
			return;
		}

		var state = JSON.parse(aWindow.SessionStore.getBrowserState());
		// we're in a window, so "a" window should exist...
		if(state.windows.length == 0) {
			aSync(() => { this.openWhenReady(); }, 500);
			return;
		}

		this.open(aWindow, true);
	},

	open: function(aWindow, loadOnStartup) {
		// first try to switch to an already opened options tab
		for(let tab of aWindow.gBrowser.mTabs) {
			if(tab.linkedBrowser.currentURI.spec.startsWith(this.chromeUri)
			|| (this.aboutUri && tab.linkedBrowser.currentURI.spec.startsWith(this.aboutUri.spec))) {
				aWindow.gBrowser.selectedTab = tab;
				return;
			}
		}

		// no tab was found, so open a new one
		if(loadOnStartup) {
			aWindow.gBrowser.selectedTab = aWindow.gBrowser.addTab(this.notifyUri);
			aWindow.gBrowser.selectedTab.loadOnStartup = true; // for Tab Mix Plus
		}
		else {
			aWindow.gBrowser.selectedTab = aWindow.gBrowser.addTab(this.aboutUri ? this.aboutUri.spec : this.chromeUri);
		}
	},

	closeAll: function() {
		Windows.callOnAll(aWindow => {
			for(let tab of aWindow.gBrowser.mTabs) {
				if(tab.linkedBrowser.currentURI.spec.startsWith(this.chromeUri)
				|| (this.aboutUri && tab.linkedBrowser.currentURI.spec.startsWith(this.aboutUri.spec))) {
					aWindow.gBrowser.removeTab(tab);
				}
			}
		}, 'navigator:browser');
	},

	initWindow: function(aWindow) {
		// prepare the window as usual
		replaceObjStrings(aWindow.document);
		prepareObject(aWindow, objName);

		// load the utils only when the preferences tab is finished with its overlays from this object
		let promises = [];
		for(let pane of this.panes.keys()) {
			promises.push(new Promise(function(resolve, reject) {
				let overlay = pane;
				Overlays.overlayWindow(aWindow, overlay, {
					onLoad: function() {
						resolve();
					}
				});
			}));
		}

		Promise.all(promises).then(() => {
			aWindow[objName].Modules.load("utils/preferencesUtils");

			// if any of the panes require their own module, load it now
			for(let pane of this.panes.values()) {
				if(pane.module) {
					aWindow[objName].Modules.load(pane.module);
				}
			}
		});
	}
};

Modules.LOADMODULE = function() {
	Prefs.setDefaults({
		lastPrefPane: '',
		lastVersionNotify: '0',
		showTabOnUpdates: true
	});

	PrefPanes.init();
};

Modules.UNLOADMODULE = function() {
	PrefPanes.uninit();
};
<|endoftext|>


<commit_before>var gulp = require('gulp');
var exists = require('path-exists').sync;
var mainBowerFiles = require('main-bower-files');
var bowerMain = require('bower-main');
var uglify = require('gulp-uglify');
var cleanCSS = require('gulp-clean-css');
var concat = require('gulp-concat');
var sass = require('gulp-ruby-sass');
var del = require('del');
var runSequence = require('run-sequence');
var browserSync = require('browser-sync');

var c = {
    tempDir: 'temp/',
    tempCSSDir: 'temp/css/',
    tempJSDir: 'temp/js/',

    tempVendorCSS: 'vendor.css',
    tempVendorJS: 'vendor.js',

    sassDir: 'src/sass/',
    sassMainFile: 'src/sass/main.scss',
    tempMainCSS: 'main.css',

    jsDir: 'src/js/',
    tempMainJS: 'main.js',

    srcDir: 'src/',
    templateDir: 'templates/',

    resultCSS: 'main.css',
    resultJS: 'main.js',

    resultDir: 'public/assets/',
    resultCSSDir: 'public/assets/',
    resultJSDir: 'public/assets/',
};

gulp.task('clean-temp', function() {
    return del([c.tempDir + '/**/*', c.tempDir + '/*', c.tempDir]);
});

gulp.task('clean-assets', function() {
    return del([c.resultDir + '*.js', c.resultDir + '*.css']);
});

gulp.task('build-bower-assets-css', function() {
    var minifiedCSS = bowerMain('css', 'min.css').minified;

    // Force Gulp to use Bootstrap minified CSS
    minifiedCSS.push('bower_components/bootstrap/dist/css/bootstrap.min.css');

    return gulp.src(minifiedCSS)
        .pipe(concat(c.tempVendorCSS))
        .pipe(gulp.dest(c.tempCSSDir));
});

gulp.task('build-bower-assets-js', function() {
    var minifiedJS = bowerMain('js', 'min.js').minified;

    return gulp.src(minifiedJS)
        .pipe(concat(c.tempVendorJS))
        .pipe(gulp.dest(c.tempJSDir));
});

gulp.task('sass', function() {
    return sass(c.sassMainFile, {style: 'compressed'})
        .pipe(concat(c.tempMainCSS))
        .pipe(gulp.dest(c.tempCSSDir));
});

gulp.task('js', function() {
    return gulp.src([c.jsDir + '*.js', c.jsDir + '**/*.js'])
        .pipe(concat(c.tempMainJS))
        .pipe(gulp.dest(c.tempJSDir));
});

gulp.task('merge-css', function() {
    return gulp.src(c.tempCSSDir + '*.css')
        .pipe(cleanCSS({keepSpecialComments: 0}))
        .pipe(concat(c.resultCSS))
        .pipe(gulp.dest(c.resultCSSDir));
});

gulp.task('merge-js', function() {
    return gulp.src(c.tempJSDir + '*.js')
        .pipe(uglify())
        .pipe(concat(c.resultJS))
        .pipe(gulp.dest(c.resultJSDir));
});

gulp.task('build-bower-assets', ['build-bower-assets-css', 'build-bower-assets-js']);

gulp.task('build-assets', ['sass', 'js']);

gulp.task('default', function(cb) {
    runSequence(['clean-temp', 'clean-assets'],
                ['build-bower-assets', 'build-assets'],
                ['merge-css', 'merge-js'],
               cb);
});

gulp.task('updateCSS', function(cb) {
    del(c.tempDir + c.tempMainCSS);
    del(c.resultCSSDir + '*.css')
    runSequence('sass',
                'merge-css',
                cb);
    browserSync.reload();
});

gulp.task('updateJS', function(cb) {
    del(c.tempDir + c.tempMainJS);
    del(c.resultJSDir + '*.js');
    runSequence('js',
                'merge-js',
                cb);
    browserSync.reload();
});

gulp.task('watch', function() {
    browserSync.init({
        server: false,
    });

    gulp.watch([c.sassDir + '*.*', c.sassDir + '**/*.*'], ['updateCSS']);
    gulp.watch([c.jsDir + '*.*', c.jsDir + '**/*.*'], ['updateJS']);
    gulp.watch([c.srcDir + '*.php', c.srcDir + '**/*.php',
                c.templateDir + '*.phtml', c.templateDir + '**/*.phtml',]).on('change', browserSync.reload);
});
<commit_msg>Add third-party JS and CSS processing to Gulpfile<commit_after>var gulp = require('gulp');
var exists = require('path-exists').sync;
var mainBowerFiles = require('main-bower-files');
var bowerMain = require('bower-main');
var uglify = require('gulp-uglify');
var cleanCSS = require('gulp-clean-css');
var concat = require('gulp-concat');
var sass = require('gulp-ruby-sass');
var del = require('del');
var runSequence = require('run-sequence');
var browserSync = require('browser-sync');

var c = {
    tempDir: 'temp/',
    tempCSSDir: 'temp/css/',
    tempJSDir: 'temp/js/',

    tempVendorCSS: 'vendor.css',
    tempVendorJS: 'vendor.js',

    tempThirdpartyCSS: 'thirdparty.css',
    tempThirdpartyJS: 'thirdparty.js',

    thirdpartyCSSDir: 'thirdparty/css/',
    thirdpartyJSDir: 'thirdparty/js/',

    sassDir: 'src/sass/',
    sassMainFile: 'src/sass/main.scss',
    tempMainCSS: 'main.css',

    jsDir: 'src/js/',
    tempMainJS: 'main.js',

    srcDir: 'src/',
    templateDir: 'templates/',

    resultCSS: 'main.css',
    resultJS: 'main.js',

    resultDir: 'public/assets/',
    resultCSSDir: 'public/assets/',
    resultJSDir: 'public/assets/',
};

gulp.task('clean-temp', function() {
    return del([c.tempDir + '/**/*', c.tempDir + '/*', c.tempDir]);
});

gulp.task('clean-assets', function() {
    return del([c.resultDir + '*.js', c.resultDir + '*.css']);
});

gulp.task('build-bower-assets-css', function() {
    var minifiedCSS = bowerMain('css', 'min.css').minified;

    // Force Gulp to use Bootstrap minified CSS
    minifiedCSS.push('bower_components/bootstrap/dist/css/bootstrap.min.css');

    return gulp.src(minifiedCSS)
        .pipe(concat(c.tempVendorCSS))
        .pipe(gulp.dest(c.tempCSSDir));
});

gulp.task('build-bower-assets-js', function() {
    var minifiedJS = bowerMain('js', 'min.js').minified;

    return gulp.src(minifiedJS)
        .pipe(concat(c.tempVendorJS))
        .pipe(gulp.dest(c.tempJSDir));
});

gulp.task('sass', function() {
    return sass(c.sassMainFile, {style: 'compressed'})
        .pipe(concat(c.tempMainCSS))
        .pipe(gulp.dest(c.tempCSSDir));
});

gulp.task('js', function() {
    return gulp.src([c.jsDir + '*.js', c.jsDir + '**/*.js'])
        .pipe(concat(c.tempMainJS))
        .pipe(gulp.dest(c.tempJSDir));
});

gulp.task('third-party-css', function() {
    return gulp.src([c.thirdpartyCSSDir + '*.css', c.thirdpartyCSSDir + '**/*.css'])
        .pipe(concat(c.tempThirdpartyCSS))
        .pipe(gulp.dest(c.tempCSSDir));
});

gulp.task('third-party-js', function() {
    return gulp.src([c.thirdpartyJSDir + '*.js', c.thirdpartyJSDir + '**/*.js'])
        .pipe(concat(c.tempThirdpartyJS))
        .pipe(gulp.dest(c.tempJSDir));
});

gulp.task('third-party', ['third-party-css', 'third-party-js']);

gulp.task('merge-css', function() {
    return gulp.src(c.tempCSSDir + '*.css')
        .pipe(cleanCSS({keepSpecialComments: 0}))
        .pipe(concat(c.resultCSS))
        .pipe(gulp.dest(c.resultCSSDir));
});

gulp.task('merge-js', function() {
    return gulp.src(c.tempJSDir + '*.js')
        .pipe(uglify())
        .pipe(concat(c.resultJS))
        .pipe(gulp.dest(c.resultJSDir));
});

gulp.task('build-bower-assets', ['build-bower-assets-css', 'build-bower-assets-js']);

gulp.task('build-assets', ['sass', 'js']);

gulp.task('default', function(cb) {
    runSequence(['clean-temp', 'clean-assets'],
                ['build-bower-assets', 'build-assets', 'third-party'],
                ['merge-css', 'merge-js'],
               cb);
});

gulp.task('updateCSS', function(cb) {
    del(c.tempDir + c.tempMainCSS);
    del(c.resultCSSDir + '*.css')
    runSequence('sass',
                'merge-css',
                cb);
    browserSync.reload();
});

gulp.task('updateJS', function(cb) {
    del(c.tempDir + c.tempMainJS);
    del(c.resultJSDir + '*.js');
    runSequence('js',
                'merge-js',
                cb);
    browserSync.reload();
});

gulp.task('watch', function() {
    browserSync.init({
        server: false,
    });

    gulp.watch([c.sassDir + '*.*', c.sassDir + '**/*.*'], ['updateCSS']);
    gulp.watch([c.jsDir + '*.*', c.jsDir + '**/*.*'], ['updateJS']);
    gulp.watch([c.srcDir + '*.php', c.srcDir + '**/*.php',
                c.templateDir + '*.html', c.templateDir + '**/*.phtml',]).on('change', browserSync.reload);
});
<|endoftext|>