From a5ad2b166b007ab992469705de95b0617b71b163 Mon Sep 17 00:00:00 2001
From: Yury Delendik <ydelendik@mozilla.com>
Date: Tue, 7 Feb 2017 08:53:33 -0600
Subject: [PATCH] Moves sed processing into the preprocessing tasks and merging
 tasks.

---
 gulpfile.js  | 121 +++++++++++++++++++++++++++++++++++++-------
 make.js      | 139 ++++++---------------------------------------------
 package.json |   1 +
 3 files changed, 119 insertions(+), 142 deletions(-)

diff --git a/gulpfile.js b/gulpfile.js
index 5c9fecaa9..a1c9b5865 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -21,6 +21,7 @@ var fs = require('fs');
 var gulp = require('gulp');
 var gutil = require('gulp-util');
 var rename = require('gulp-rename');
+var replace = require('gulp-replace');
 var mkdirp = require('mkdirp');
 var rimraf = require('rimraf');
 var runSequence = require('run-sequence');
@@ -96,6 +97,10 @@ function stripCommentHeaders(content) {
   return content;
 }
 
+function getVersionJSON() {
+  return JSON.parse(fs.readFileSync(BUILD_DIR + 'version.json').toString());
+}
+
 function checkChromePreferencesFile(chromePrefsPath, webPrefsPath) {
   var chromePrefs = JSON.parse(fs.readFileSync(chromePrefsPath).toString());
   var chromePrefsKeys = Object.keys(chromePrefs.properties);
@@ -179,8 +184,7 @@ function bundle(filename, outfilename, pathPrefix, initFiles, amdName, defines,
 }
 
 function createBundle(defines) {
-  var versionJSON = JSON.parse(
-    fs.readFileSync(BUILD_DIR + 'version.json').toString());
+  var versionJSON = getVersionJSON();
 
   console.log();
   console.log('### Bundling files into pdf.js');
@@ -256,8 +260,7 @@ function createBundle(defines) {
 }
 
 function createWebBundle(defines) {
-  var versionJSON = JSON.parse(
-    fs.readFileSync(BUILD_DIR + 'version.json').toString());
+  var versionJSON = getVersionJSON();
 
   var template, files, outputName, amdName;
   if (defines.COMPONENTS) {
@@ -384,12 +387,7 @@ gulp.task('default', function() {
   });
 });
 
-gulp.task('extension', function (done) {
-  console.log();
-  console.log('### Building extensions');
-
-  runSequence('locale', 'firefox', 'chromium', done);
-});
+gulp.task('extension', ['firefox', 'chromium']);
 
 gulp.task('buildnumber', function (done) {
   console.log();
@@ -683,6 +681,10 @@ gulp.task('minified-pre', ['buildnumber', 'locale'], function () {
   ]);
 });
 
+gulp.task('minified', ['minified-pre'], function (done) {
+  runSequence('minifiedpost', done);
+});
+
 gulp.task('firefox-pre', ['buildnumber', 'locale'], function () {
   console.log();
   console.log('### Building Firefox extension');
@@ -690,11 +692,20 @@ gulp.task('firefox-pre', ['buildnumber', 'locale'], function () {
 
   var FIREFOX_BUILD_CONTENT_DIR = FIREFOX_BUILD_DIR + '/content/',
       FIREFOX_EXTENSION_DIR = 'extensions/firefox/',
-      FIREFOX_CONTENT_DIR = EXTENSION_SRC_DIR + '/firefox/content/';
+      FIREFOX_CONTENT_DIR = EXTENSION_SRC_DIR + '/firefox/content/',
+      FIREFOX_PREF_PREFIX = 'extensions.uriloader@pdf.js',
+      FIREFOX_STREAM_CONVERTER_ID = '6457a96b-2d68-439a-bcfa-44465fbcdbb1',
+      FIREFOX_STREAM_CONVERTER2_ID = '6457a96b-2d68-439a-bcfa-44465fbcdbb2';
 
   // Clear out everything in the firefox extension build directory
   rimraf.sync(FIREFOX_BUILD_DIR);
 
+  var localizedMetadata =
+    fs.readFileSync(FIREFOX_EXTENSION_DIR + 'metadata.inc').toString();
+  var chromeManifestLocales =
+    fs.readFileSync(FIREFOX_EXTENSION_DIR + 'chrome.manifest.inc').toString();
+  var version = getVersionJSON().version;
+
   return merge([
     createBundle(defines).pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR + 'build')),
     createWebBundle(defines).pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR + 'web')),
@@ -718,8 +729,15 @@ gulp.task('firefox-pre', ['buildnumber', 'locale'], function () {
     gulp.src(FIREFOX_CONTENT_DIR + 'PdfJsTelemetry-addon.jsm')
         .pipe(rename('PdfJsTelemetry.jsm'))
         .pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR)),
-    gulp.src(FIREFOX_EXTENSION_DIR + '**/*.{rdf,png,manifest}',
-             {base: FIREFOX_EXTENSION_DIR})
+    gulp.src(FIREFOX_EXTENSION_DIR + '*.png')
+        .pipe(gulp.dest(FIREFOX_BUILD_DIR)),
+    gulp.src(FIREFOX_EXTENSION_DIR + 'chrome.manifest')
+        .pipe(replace(/#.*PDFJS_SUPPORTED_LOCALES.*\n/, chromeManifestLocales))
+        .pipe(gulp.dest(FIREFOX_BUILD_DIR)),
+    gulp.src(FIREFOX_EXTENSION_DIR + '*.rdf')
+        .pipe(replace(/\bPDFJSSCRIPT_VERSION\b/g, version))
+        .pipe(replace(/.*<!--\s*PDFJS_LOCALIZED_METADATA\s*-->.*\n/,
+                      localizedMetadata))
         .pipe(gulp.dest(FIREFOX_BUILD_DIR)),
     gulp.src(FIREFOX_EXTENSION_DIR + 'chrome/content.js',
              {base: FIREFOX_EXTENSION_DIR})
@@ -730,18 +748,54 @@ gulp.task('firefox-pre', ['buildnumber', 'locale'], function () {
         .pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR + '/web')),
 
     preprocessJS(FIREFOX_CONTENT_DIR + 'PdfStreamConverter.jsm', defines, true)
+        .pipe(replace(/\bPDFJSSCRIPT_STREAM_CONVERTER_ID\b/g,
+                      FIREFOX_STREAM_CONVERTER_ID))
+        .pipe(replace(/\bPDFJSSCRIPT_STREAM_CONVERTER2_ID\b/g,
+                      FIREFOX_STREAM_CONVERTER2_ID))
+        .pipe(replace(/\bPDFJSSCRIPT_PREF_PREFIX\b/g, FIREFOX_PREF_PREFIX))
         .pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR)),
     preprocessJS(FIREFOX_CONTENT_DIR + 'PdfJsNetwork.jsm', defines, true)
         .pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR)),
     preprocessJS(FIREFOX_CONTENT_DIR + 'PdfjsContentUtils.jsm', defines, true)
         .pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR)),
     preprocessJS(FIREFOX_CONTENT_DIR + 'PdfjsChromeUtils.jsm', defines, true)
+        .pipe(replace(/\bPDFJSSCRIPT_PREF_PREFIX\b/g, FIREFOX_PREF_PREFIX))
         .pipe(gulp.dest(FIREFOX_BUILD_CONTENT_DIR)),
     preprocessJS(FIREFOX_EXTENSION_DIR + 'bootstrap.js', defines, true)
         .pipe(gulp.dest(FIREFOX_BUILD_DIR)),
   ]);
 });
 
+gulp.task('firefox', ['firefox-pre'], function (done) {
+  var FIREFOX_EXTENSION_FILES =
+        ['bootstrap.js',
+         'install.rdf',
+         'chrome.manifest',
+         'icon.png',
+         'icon64.png',
+         'content',
+         'chrome',
+         'locale',
+         'LICENSE'],
+      FIREFOX_EXTENSION_NAME = 'pdf.js.xpi';
+
+  var zipExecOptions = {
+    cwd: FIREFOX_BUILD_DIR,
+    // Set timezone to UTC before calling zip to get reproducible results.
+    env: {'TZ': 'UTC'},
+  };
+
+  exec('zip -r ' + FIREFOX_EXTENSION_NAME + ' ' +
+       FIREFOX_EXTENSION_FILES.join(' '), zipExecOptions, function (err) {
+    if (err) {
+      done(new Error('Cannot exec zip: ' + err));
+      return;
+    }
+    console.log('extension created: ' + FIREFOX_EXTENSION_NAME);
+    done();
+  });
+});
+
 gulp.task('mozcentral-pre', ['buildnumber', 'locale'], function () {
   console.log();
   console.log('### Building mozilla-central extension');
@@ -752,11 +806,16 @@ gulp.task('mozcentral-pre', ['buildnumber', 'locale'], function () {
       MOZCENTRAL_CONTENT_DIR = MOZCENTRAL_EXTENSION_DIR + 'content/',
       FIREFOX_EXTENSION_DIR = 'extensions/firefox/',
       MOZCENTRAL_L10N_DIR = MOZCENTRAL_DIR + 'browser/locales/en-US/pdfviewer/',
-      FIREFOX_CONTENT_DIR = EXTENSION_SRC_DIR + '/firefox/content/';
+      FIREFOX_CONTENT_DIR = EXTENSION_SRC_DIR + '/firefox/content/',
+      MOZCENTRAL_PREF_PREFIX = 'pdfjs',
+      MOZCENTRAL_STREAM_CONVERTER_ID = 'd0c5195d-e798-49d4-b1d3-9324328b2291',
+      MOZCENTRAL_STREAM_CONVERTER2_ID = 'd0c5195d-e798-49d4-b1d3-9324328b2292';
 
   // Clear out everything in the firefox extension build directory
   rimraf.sync(MOZCENTRAL_DIR);
 
+  var version = getVersionJSON().version;
+
   return merge([
     createBundle(defines).pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR + 'build')),
     createWebBundle(defines).pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR + 'web')),
@@ -780,6 +839,7 @@ gulp.task('mozcentral-pre', ['buildnumber', 'locale'], function () {
              {base: FIREFOX_EXTENSION_DIR})
         .pipe(gulp.dest(MOZCENTRAL_L10N_DIR)),
     gulp.src(FIREFOX_EXTENSION_DIR + 'README.mozilla')
+        .pipe(replace(/\bPDFJSSCRIPT_VERSION\b/g, version))
         .pipe(gulp.dest(MOZCENTRAL_EXTENSION_DIR)),
     gulp.src('LICENSE').pipe(gulp.dest(MOZCENTRAL_EXTENSION_DIR)),
     gulp.src(FIREFOX_EXTENSION_DIR + 'tools/l10n.js')
@@ -788,16 +848,24 @@ gulp.task('mozcentral-pre', ['buildnumber', 'locale'], function () {
     preprocessJS(FIREFOX_CONTENT_DIR + 'PdfJs.jsm', defines, true)
         .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR)),
     preprocessJS(FIREFOX_CONTENT_DIR + 'PdfStreamConverter.jsm', defines, true)
+        .pipe(replace(/\bPDFJSSCRIPT_STREAM_CONVERTER_ID\b/g,
+                      MOZCENTRAL_STREAM_CONVERTER_ID))
+        .pipe(replace(/\bPDFJSSCRIPT_STREAM_CONVERTER2_ID\b/g,
+                      MOZCENTRAL_STREAM_CONVERTER2_ID))
+        .pipe(replace(/\bPDFJSSCRIPT_PREF_PREFIX\b/g, MOZCENTRAL_PREF_PREFIX))
         .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR)),
     preprocessJS(FIREFOX_CONTENT_DIR + 'PdfJsNetwork.jsm', defines, true)
         .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR)),
     preprocessJS(FIREFOX_CONTENT_DIR + 'PdfjsContentUtils.jsm', defines, true)
         .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR)),
     preprocessJS(FIREFOX_CONTENT_DIR + 'PdfjsChromeUtils.jsm', defines, true)
+        .pipe(replace(/\bPDFJSSCRIPT_PREF_PREFIX\b/g, MOZCENTRAL_PREF_PREFIX))
         .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR)),
   ]);
 });
 
+gulp.task('mozcentral', ['mozcentral-pre']);
+
 gulp.task('chromium-pre', ['buildnumber', 'locale'], function () {
   console.log();
   console.log('### Building Chromium extension');
@@ -808,6 +876,9 @@ gulp.task('chromium-pre', ['buildnumber', 'locale'], function () {
 
   // Clear out everything in the chrome extension build directory
   rimraf.sync(CHROME_BUILD_DIR);
+
+  var version = getVersionJSON().version;
+
   return merge([
     createBundle(defines).pipe(gulp.dest(CHROME_BUILD_CONTENT_DIR + 'build')),
     createWebBundle(defines).pipe(gulp.dest(CHROME_BUILD_CONTENT_DIR + 'web')),
@@ -830,14 +901,26 @@ gulp.task('chromium-pre', ['buildnumber', 'locale'], function () {
         .pipe(gulp.dest(CHROME_BUILD_CONTENT_DIR + 'web')),
 
     gulp.src('LICENSE').pipe(gulp.dest(CHROME_BUILD_DIR)),
-    gulp.src('extensions/chromium/*.{json,html,js,css,png}')
+    gulp.src('extensions/chromium/manifest.json')
+        .pipe(replace(/\bPDFJSSCRIPT_VERSION\b/g, version))
         .pipe(gulp.dest(CHROME_BUILD_DIR)),
-    gulp.src('extensions/chromium/**/*.{json,html,js,css,png}',
-             {base: 'extensions/chromium/'})
+    gulp.src([
+      'extensions/chromium/**/*.{html,js,css,png}',
+      'extensions/chromium/preferences_schema.json'
+    ], {base: 'extensions/chromium/'})
         .pipe(gulp.dest(CHROME_BUILD_DIR)),
   ]);
 });
 
+gulp.task('chromium', ['chromium-pre'], function (done) {
+  // Bundle the files to a Chrome extension file .crx if path to key is set
+  if (!process.env['PDFJS_CHROME_KEY']) {
+    done();
+    return;
+  }
+  runSequence('signchromium', done);
+});
+
 gulp.task('jsdoc', function (done) {
   console.log();
   console.log('### Generating documentation (JSDoc)');
@@ -860,6 +943,10 @@ gulp.task('jsdoc', function (done) {
   });
 });
 
+gulp.task('web-pre', ['generic', 'extension', 'jsdoc']);
+
+gulp.task('dist-pre', ['generic', 'singlefile', 'components', 'minified']);
+
 gulp.task('publish', ['generic'], function (done) {
   var version = JSON.parse(
     fs.readFileSync(BUILD_DIR + 'version.json').toString()).version;
diff --git a/make.js b/make.js
index 3dab25f5c..405549839 100644
--- a/make.js
+++ b/make.js
@@ -42,13 +42,7 @@ var ROOT_DIR = __dirname + '/', // absolute path to project's root
     DIST_DIR = BUILD_DIR + 'dist/',
     SINGLE_FILE_DIR = BUILD_DIR + 'singlefile/',
     COMPONENTS_DIR = BUILD_DIR + 'components/',
-    REPO = 'git@github.com:mozilla/pdf.js.git',
-    MOZCENTRAL_PREF_PREFIX = 'pdfjs',
-    FIREFOX_PREF_PREFIX = 'extensions.uriloader@pdf.js',
-    MOZCENTRAL_STREAM_CONVERTER_ID = 'd0c5195d-e798-49d4-b1d3-9324328b2291',
-    FIREFOX_STREAM_CONVERTER_ID = '6457a96b-2d68-439a-bcfa-44465fbcdbb1',
-    MOZCENTRAL_STREAM_CONVERTER2_ID = 'd0c5195d-e798-49d4-b1d3-9324328b2292',
-    FIREFOX_STREAM_CONVERTER2_ID = '6457a96b-2d68-439a-bcfa-44465fbcdbb2';
+    REPO = 'git@github.com:mozilla/pdf.js.git';
 
 function getCurrentVersion() {
   // The 'build/version.json' file is created by 'buildnumber' task.
@@ -101,9 +95,7 @@ target.jsdoc = function() {
 // into place.
 //
 target.web = function() {
-  target.generic();
-  target.extension();
-  target.jsdoc();
+  execGulp('web-pre');
 
   cd(ROOT_DIR);
   echo();
@@ -158,10 +150,7 @@ target.web = function() {
 };
 
 target.dist = function() {
-  target.generic();
-  target.singlefile();
-  target.components();
-  target.minified();
+  execGulp('dist-pre');
 
   var DIST_REPO_URL = 'https://github.com/mozilla/pdfjs-dist';
   var VERSION = getCurrentVersion();
@@ -305,8 +294,10 @@ target.singlefile = function() {
 // modern HTML5 browsers.
 //
 target.minified = function() {
-  execGulp('minified-pre');
+  execGulp('minified');
+};
 
+target.minifiedpost = function () {
   var viewerFiles = [
     'web/compatibility.js',
     'external/webL10n/l10n.js',
@@ -361,135 +352,33 @@ target.buildnumber = function() {
 // make firefox
 //
 target.firefox = function() {
-  execGulp('firefox-pre');
-
-  cd(ROOT_DIR);
-  var FIREFOX_BUILD_CONTENT_DIR = FIREFOX_BUILD_DIR + '/content/',
-      FIREFOX_EXTENSION_FILES =
-        ['bootstrap.js',
-         'install.rdf',
-         'chrome.manifest',
-         'icon.png',
-         'icon64.png',
-         'content',
-         'chrome',
-         'locale',
-         'LICENSE'],
-      FIREFOX_EXTENSION_NAME = 'pdf.js.xpi';
-
-  // Remove '.DS_Store' and other hidden files
-  find(FIREFOX_BUILD_DIR).forEach(function(file) {
-    if (file.match(/^\./)) {
-      rm('-f', file);
-    }
-  });
-
-  // Update the build version number
-  var VERSION = getCurrentVersion();
-  sed('-i', /PDFJSSCRIPT_VERSION/, VERSION,
-      FIREFOX_BUILD_DIR + '/install.rdf');
-  sed('-i', /PDFJSSCRIPT_VERSION/, VERSION,
-      FIREFOX_BUILD_DIR + '/update.rdf');
-
-  sed('-i', /PDFJSSCRIPT_STREAM_CONVERTER_ID/, FIREFOX_STREAM_CONVERTER_ID,
-      FIREFOX_BUILD_CONTENT_DIR + 'PdfStreamConverter.jsm');
-  sed('-i', /PDFJSSCRIPT_STREAM_CONVERTER2_ID/, FIREFOX_STREAM_CONVERTER2_ID,
-      FIREFOX_BUILD_CONTENT_DIR + 'PdfStreamConverter.jsm');
-  sed('-i', /PDFJSSCRIPT_PREF_PREFIX/, FIREFOX_PREF_PREFIX,
-      FIREFOX_BUILD_CONTENT_DIR + 'PdfStreamConverter.jsm');
-  sed('-i', /PDFJSSCRIPT_PREF_PREFIX/, FIREFOX_PREF_PREFIX,
-      FIREFOX_BUILD_CONTENT_DIR + 'PdfjsChromeUtils.jsm');
-
-  // Update localized metadata
-  var localizedMetadata = cat(EXTENSION_SRC_DIR + '/firefox/metadata.inc');
-  sed('-i', /.*PDFJS_LOCALIZED_METADATA.*\n/, localizedMetadata,
-      FIREFOX_BUILD_DIR + '/install.rdf');
-  var chromeManifest = cat(EXTENSION_SRC_DIR + '/firefox/chrome.manifest.inc');
-  sed('-i', /.*PDFJS_SUPPORTED_LOCALES.*\n/, chromeManifest,
-      FIREFOX_BUILD_DIR + '/chrome.manifest');
-
-  // Set timezone to UTC before calling zip to get reproducible results.
-  process.env.TZ = 'UTC';
-
-  // Create the xpi
-  cd(FIREFOX_BUILD_DIR);
-  exec('zip -r ' + FIREFOX_EXTENSION_NAME + ' ' +
-       FIREFOX_EXTENSION_FILES.join(' '));
-  echo('extension created: ' + FIREFOX_EXTENSION_NAME);
-  cd(ROOT_DIR);
+  execGulp('firefox');
 };
 
 //
 // make mozcentral
 //
 target.mozcentral = function() {
-  execGulp('mozcentral-pre');
-
-  cd(ROOT_DIR);
-
-  var MOZCENTRAL_DIR = BUILD_DIR + 'mozcentral/',
-      MOZCENTRAL_EXTENSION_DIR = MOZCENTRAL_DIR + 'browser/extensions/pdfjs/',
-      MOZCENTRAL_CONTENT_DIR = MOZCENTRAL_EXTENSION_DIR + 'content/';
-
-  // Remove '.DS_Store' and other hidden files
-  find(MOZCENTRAL_DIR).forEach(function(file) {
-    if (file.match(/^\./)) {
-      rm('-f', file);
-    }
-  });
-
-  // Update the build version number
-  var VERSION = getCurrentVersion();
-  sed('-i', /PDFJSSCRIPT_VERSION/, VERSION,
-      MOZCENTRAL_EXTENSION_DIR + 'README.mozilla');
-
-  sed('-i', /PDFJSSCRIPT_STREAM_CONVERTER_ID/, MOZCENTRAL_STREAM_CONVERTER_ID,
-      MOZCENTRAL_CONTENT_DIR + 'PdfStreamConverter.jsm');
-  sed('-i', /PDFJSSCRIPT_STREAM_CONVERTER2_ID/, MOZCENTRAL_STREAM_CONVERTER2_ID,
-      MOZCENTRAL_CONTENT_DIR + 'PdfStreamConverter.jsm');
-  sed('-i', /PDFJSSCRIPT_PREF_PREFIX/, MOZCENTRAL_PREF_PREFIX,
-      MOZCENTRAL_CONTENT_DIR + 'PdfStreamConverter.jsm');
-  sed('-i', /PDFJSSCRIPT_PREF_PREFIX/, MOZCENTRAL_PREF_PREFIX,
-      MOZCENTRAL_CONTENT_DIR + 'PdfjsChromeUtils.jsm');
+  execGulp('mozcentral');
 };
 
 //
 // make chrome
 //
 target.chromium = function() {
-  execGulp('chromium-pre');
+  execGulp('chromium');
+};
 
+target.signchromium = function () {
   cd(ROOT_DIR);
 
-  var CHROME_BUILD_DIR = BUILD_DIR + '/chromium/',
-      CHROME_BUILD_CONTENT_DIR = CHROME_BUILD_DIR + '/content/';
-
-  // Update the build version number
-  var VERSION = getCurrentVersion();
-  sed('-i', /PDFJSSCRIPT_VERSION/, VERSION,
-      CHROME_BUILD_DIR + '/manifest.json');
-
-  // Allow PDF.js resources to be loaded by adding the files to
-  // the "web_accessible_resources" section.
-  var file_list = ls('-RA', CHROME_BUILD_CONTENT_DIR);
-  var public_chrome_files = file_list.reduce(function(war, file) {
-    // Exclude directories (naive: Exclude paths without dot)
-    if (file.indexOf('.') !== -1) {
-      // Only add a comma after the first file
-      if (war) {
-        war += ',\n';
-      }
-      war += JSON.stringify('content/' + file);
-    }
-    return war;
-  }, '');
-  sed('-i', /"content\/\*"/, public_chrome_files,
-      CHROME_BUILD_DIR + '/manifest.json');
+  var CHROME_BUILD_DIR = BUILD_DIR + '/chromium/';
 
   // Bundle the files to a Chrome extension file .crx if path to key is set
   var pem = env['PDFJS_CHROME_KEY'];
   if (!pem) {
-    return;
+    echo('The PDFJS_CHROME_KEY must be specified.');
+    exit(1);
   }
 
   echo();
diff --git a/package.json b/package.json
index 96caf5e48..b64829700 100644
--- a/package.json
+++ b/package.json
@@ -7,6 +7,7 @@
     "esprima": "^2.7.2",
     "gulp": "^3.9.1",
     "gulp-rename": "^1.2.2",
+    "gulp-replace": "^0.5.4",
     "gulp-util": "^3.0.7",
     "gulp-zip": "^3.2.0",
     "jasmine": "^2.5.2",