Index: frontend/node_modules/ajv/scripts/.eslintrc.yml
===================================================================
--- frontend/node_modules/ajv/scripts/.eslintrc.yml	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/ajv/scripts/.eslintrc.yml	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,3 @@
+rules:
+  no-console: 0
+  no-empty: [2, allowEmptyCatch: true]
Index: frontend/node_modules/ajv/scripts/bundle.js
===================================================================
--- frontend/node_modules/ajv/scripts/bundle.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/ajv/scripts/bundle.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,61 @@
+'use strict';
+
+var fs = require('fs')
+  , path = require('path')
+  , browserify = require('browserify')
+  , uglify = require('uglify-js');
+
+var pkg = process.argv[2]
+  , standalone = process.argv[3]
+  , compress = process.argv[4];
+
+var packageDir = path.join(__dirname, '..');
+if (pkg != '.') packageDir = path.join(packageDir, 'node_modules', pkg);
+
+var json = require(path.join(packageDir, 'package.json'));
+
+var distDir = path.join(__dirname, '..', 'dist');
+if (!fs.existsSync(distDir)) fs.mkdirSync(distDir);
+
+var bOpts = {};
+if (standalone) bOpts.standalone = standalone;
+
+browserify(bOpts)
+.require(path.join(packageDir, json.main), {expose: json.name})
+.bundle(function (err, buf) {
+  if (err) {
+    console.error('browserify error:', err);
+    process.exit(1);
+  }
+
+  var outputFile = path.join(distDir, json.name);
+  var uglifyOpts = {
+    warnings: true,
+    compress: {},
+    output: {
+      preamble: '/* ' + json.name + ' ' + json.version + ': ' + json.description + ' */'
+    }
+  };
+  if (compress) {
+    var compressOpts = compress.split(',');
+    for (var i=0, il = compressOpts.length; i<il; ++i) {
+      var pair = compressOpts[i].split('=');
+      uglifyOpts.compress[pair[0]] = pair.length < 1 || pair[1] != 'false';
+    }
+  }
+  if (standalone) {
+    uglifyOpts.sourceMap = {
+      filename: json.name + '.min.js',
+      url: json.name + '.min.js.map'
+    };
+  }
+
+  var result = uglify.minify(buf.toString(), uglifyOpts);
+  fs.writeFileSync(outputFile + '.min.js', result.code);
+  if (result.map) fs.writeFileSync(outputFile + '.min.js.map', result.map);
+  if (standalone) fs.writeFileSync(outputFile + '.bundle.js', buf);
+  if (result.warnings) {
+    for (var j=0, jl = result.warnings.length; j<jl; ++j)
+      console.warn('UglifyJS warning:', result.warnings[j]);
+  }
+});
Index: frontend/node_modules/ajv/scripts/compile-dots.js
===================================================================
--- frontend/node_modules/ajv/scripts/compile-dots.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/ajv/scripts/compile-dots.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,73 @@
+//compile doT templates to js functions
+'use strict';
+
+var glob = require('glob')
+  , fs = require('fs')
+  , path = require('path')
+  , doT = require('dot')
+  , beautify = require('js-beautify').js_beautify;
+
+var defsRootPath = process.argv[2] || path.join(__dirname, '../lib');
+
+var defs = {};
+var defFiles = glob.sync('./dot/**/*.def', { cwd: defsRootPath });
+defFiles.forEach(function (f) {
+  var name = path.basename(f, '.def');
+  defs[name] = fs.readFileSync(path.join(defsRootPath, f));
+});
+
+var filesRootPath = process.argv[3] || path.join(__dirname, '../lib');
+var files = glob.sync('./dot/**/*.jst', { cwd: filesRootPath });
+
+var dotjsPath = path.join(filesRootPath, './dotjs');
+try { fs.mkdirSync(dotjsPath); } catch(e) {}
+
+console.log('\n\nCompiling:');
+
+var FUNCTION_NAME = /function\s+anonymous\s*\(it[^)]*\)\s*{/;
+var OUT_EMPTY_STRING = /out\s*\+=\s*'\s*';/g;
+var ISTANBUL = /'(istanbul[^']+)';/g;
+var ERROR_KEYWORD = /\$errorKeyword/g;
+var ERROR_KEYWORD_OR = /\$errorKeyword\s+\|\|/g;
+var VARS = [
+  '$errs', '$valid', '$lvl', '$data', '$dataLvl',
+  '$errorKeyword', '$closingBraces', '$schemaPath',
+  '$validate'
+];
+
+files.forEach(function (f) {
+  var keyword = path.basename(f, '.jst');
+  var targetPath = path.join(dotjsPath, keyword + '.js');
+  var template = fs.readFileSync(path.join(filesRootPath, f));
+  var code = doT.compile(template, defs);
+  code = code.toString()
+             .replace(OUT_EMPTY_STRING, '')
+             .replace(FUNCTION_NAME, 'function generate_' + keyword + '(it, $keyword, $ruleType) {')
+             .replace(ISTANBUL, '/* $1 */');
+  removeAlwaysFalsyInOr();
+  VARS.forEach(removeUnusedVar);
+  code = "'use strict';\nmodule.exports = " + code;
+  code = beautify(code, { indent_size: 2 }) + '\n';
+  fs.writeFileSync(targetPath, code);
+  console.log('compiled', keyword);
+
+  function removeUnusedVar(v) {
+    v = v.replace(/\$/g, '\\$$');
+    var regexp = new RegExp(v + '[^A-Za-z0-9_$]', 'g');
+    var count = occurrences(regexp);
+    if (count == 1) {
+      regexp = new RegExp('var\\s+' + v + '\\s*=[^;]+;|var\\s+' + v + ';');
+      code = code.replace(regexp, '');
+    }
+  }
+
+  function removeAlwaysFalsyInOr() {
+    var countUsed = occurrences(ERROR_KEYWORD);
+    var countOr = occurrences(ERROR_KEYWORD_OR);
+    if (countUsed == countOr + 1) code = code.replace(ERROR_KEYWORD_OR, '');
+  }
+
+  function occurrences(regexp) {
+    return (code.match(regexp) || []).length;
+  }
+});
Index: frontend/node_modules/ajv/scripts/info
===================================================================
--- frontend/node_modules/ajv/scripts/info	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/ajv/scripts/info	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,10 @@
+#!/usr/bin/env node
+
+'use strict';
+
+var fs = require('fs');
+var name = process.argv[2] || '.';
+var property = process.argv[3] || 'version';
+if (name != '.') name = 'node_modules/' + name;
+var json = JSON.parse(fs.readFileSync(name + '/package.json', 'utf8'));
+console.log(json[property]);
Index: frontend/node_modules/ajv/scripts/prepare-tests
===================================================================
--- frontend/node_modules/ajv/scripts/prepare-tests	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/ajv/scripts/prepare-tests	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,12 @@
+#!/usr/bin/env sh
+
+set -e
+
+mkdir -p .browser
+
+echo
+echo Preparing browser tests:
+
+find spec -type f -name '*.spec.js' | \
+xargs -I {} sh -c \
+'export f="{}"; echo $f; browserify $f -t require-globify -t brfs -x ajv -u buffer -o $(echo $f | sed -e "s/spec/.browser/");'
Index: frontend/node_modules/ajv/scripts/publish-built-version
===================================================================
--- frontend/node_modules/ajv/scripts/publish-built-version	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/ajv/scripts/publish-built-version	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+
+set -e
+
+if [[ -n $TRAVIS_TAG && $TRAVIS_JOB_NUMBER =~ ".3" ]]; then
+  echo "About to publish $TRAVIS_TAG to ajv-dist..."
+
+  git config user.email "$GIT_USER_EMAIL"
+  git config user.name "$GIT_USER_NAME"
+
+  git clone https://${GITHUB_TOKEN}@github.com/ajv-validator/ajv-dist.git ../ajv-dist
+
+  rm -rf ../ajv-dist/dist
+  mkdir ../ajv-dist/dist
+  cp ./dist/ajv.* ../ajv-dist/dist
+  cat bower.json | sed 's/"name": "ajv"/"name": "ajv-dist"/' > ../ajv-dist/bower.json
+  cd ../ajv-dist
+
+  if [[ `git status --porcelain` ]]; then
+    echo "Changes detected. Updating master branch..."
+    git add -A
+    git commit -m "updated by travis build #$TRAVIS_BUILD_NUMBER"
+    git push --quiet origin master > /dev/null 2>&1
+  fi
+
+  echo "Publishing tag..."
+
+  git tag $TRAVIS_TAG
+  git push --tags > /dev/null 2>&1
+
+  echo "Done"
+fi
Index: frontend/node_modules/ajv/scripts/travis-gh-pages
===================================================================
--- frontend/node_modules/ajv/scripts/travis-gh-pages	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/ajv/scripts/travis-gh-pages	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+set -e
+
+if [[ "$TRAVIS_BRANCH" == "master" && "$TRAVIS_PULL_REQUEST" == "false" && $TRAVIS_JOB_NUMBER =~ ".3" ]]; then
+  git diff --name-only $TRAVIS_COMMIT_RANGE | grep -qE '\.md$|^LICENSE$|travis-gh-pages$' && {
+    rm -rf ../gh-pages
+    git clone -b gh-pages --single-branch https://${GITHUB_TOKEN}@github.com/ajv-validator/ajv.git ../gh-pages
+    mkdir -p ../gh-pages/_source
+    cp *.md ../gh-pages/_source
+    cp LICENSE ../gh-pages/_source
+    currentDir=$(pwd)
+    cd ../gh-pages
+    $currentDir/node_modules/.bin/gh-pages-generator
+    # remove logo from README
+    sed -i -E "s/<img[^>]+ajv_logo[^>]+>//" index.md
+    git config user.email "$GIT_USER_EMAIL"
+    git config user.name "$GIT_USER_NAME"
+    git add .
+    git commit -am "updated by travis build #$TRAVIS_BUILD_NUMBER"
+    git push --quiet origin gh-pages > /dev/null 2>&1
+  }
+fi
