diff --git a/.gitignore b/.gitignore index 4b0dc57..5e9a6cb 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,5 @@ lib/dotjs/*.js .browser # Ajv bundle -ajv.bundle.js +ajv.bundle.* +ajv.min.* diff --git a/README.md b/README.md index 424ff47..34295ac 100644 --- a/README.md +++ b/README.md @@ -100,14 +100,14 @@ __Please note__: every time validation function or `ajv.validate` are called `er You can require ajv directly from the code you browserify - in this case ajv will be a part of your bundle. -If you need to use ajv in several bundles you can create a separate browserified bundle using `npm run bundle` script (thanks to [siddo420](https://github.com/siddo420)). +If you need to use ajv in several bundles you can create a separate UMD bundle using `npm run bundle` script (thanks to [siddo420](https://github.com/siddo420)). Then you need to load ajv in the browser: ``` - + ``` -Now you can use it as shown above - `require` will be global and you can `require('ajv')`. +This bundle can be used with different module systems or creates global `Ajv` if no module system is found. Ajv was tested with these browsers: diff --git a/karma.conf.js b/karma.conf.js index 0f04e07..0e80879 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -15,7 +15,8 @@ module.exports = function(config) { // list of files / patterns to load in the browser files: [ - '.browser/ajv.beautify.js', + 'ajv.min.js', + 'node_modules/chai/chai.js', '.browser/*.spec.js' ], diff --git a/karma.sauce.js b/karma.sauce.js index 6fc1885..8b98996 100644 --- a/karma.sauce.js +++ b/karma.sauce.js @@ -102,7 +102,8 @@ module.exports = function(config) { // list of files / patterns to load in the browser files: [ - '.browser/ajv.beautify.js', + 'ajv.min.js', + 'node_modules/chai/chai.js', '.browser/*.spec.js' ], diff --git a/lib/compile/index.js b/lib/compile/index.js index ac3f630..eb41215 100644 --- a/lib/compile/index.js +++ b/lib/compile/index.js @@ -5,7 +5,7 @@ var resolve = require('./resolve') , equal = require('./equal') , stableStringify = require('json-stable-stringify'); -try { var beautify = require('' + 'js-beautify').js_beautify; } catch(e) {} +var beautify = (function() { try { return require('' + 'js-beautify').js_beautify; } catch(e) {} })(); var validateGenerator = require('../dotjs/validate'); diff --git a/lib/dot/definitions.def b/lib/dot/definitions.def index cbcc3a8..448337d 100644 --- a/lib/dot/definitions.def +++ b/lib/dot/definitions.def @@ -1,16 +1,16 @@ {{## def.setupKeyword: {{ - var $lvl = it.level - , $dataLvl = it.dataLevel - , $schema = it.schema[$keyword] - , $schemaPath = it.schemaPath + '.' + $keyword - , $errSchemaPath = it.errSchemaPath + '/' + $keyword - , $breakOnError = !it.opts.allErrors - , $errorKeyword; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + '.' + $keyword; + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; - var $data = 'data' + ($dataLvl || '') - , $valid = 'valid' + $lvl - , $errs = 'errs__' + $lvl; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $errs = 'errs__' + $lvl; }} #}} @@ -30,8 +30,8 @@ {{## def.setupNextLevel: {{ - var $it = it.util.copy(it) - , $closingBraces = ''; + var $it = it.util.copy(it); + var $closingBraces = ''; $it.level++; }} #}} diff --git a/lib/keyword.js b/lib/keyword.js index cc57274..d363530 100644 --- a/lib/keyword.js +++ b/lib/keyword.js @@ -1,7 +1,5 @@ 'use strict'; -var util = require('./compile/util'); - var IDENTIFIER = /^[a-z_$][a-z0-9_$]*$/i; /** diff --git a/package.json b/package.json index 13a35d4..75806ab 100644 --- a/package.json +++ b/package.json @@ -14,9 +14,9 @@ "test-fast": "AJV_FAST_TEST=true npm run test-spec", "test-debug": "mocha spec/*.spec.js --debug-brk -R spec", "test-cov": "istanbul cover -x '**/spec/**' node_modules/mocha/bin/_mocha -- spec/*.spec.js -R spec", - "bundle": "browserify -r ./lib/ajv.js:ajv -o ajv.bundle.js", + "bundle": "browserify -r ./lib/ajv.js:ajv -o ajv.bundle.js -s Ajv && uglifyjs ajv.bundle.js -o ajv.min.js -c pure_getters -m --source-map ajv.min.js.map -r Ajv --preamble '/* Ajv JSON-schema validator */'", "build": "node scripts/compile-dots.js", - "test-browser": "scripts/prepare-tests && karma start --single-run --browsers PhantomJS", + "test-browser": "npm run bundle && scripts/prepare-tests && karma start --single-run --browsers PhantomJS", "test": "npm run jshint && npm run build && npm run test-cov && npm run test-browser", "prepublish": "npm run build", "watch": "watch 'npm run build' ./lib/dot" @@ -60,6 +60,7 @@ "phantomjs": "^1.9.18", "pre-commit": "^1.1.1", "require-globify": "^1.3.0", + "uglify-js": "^2.6.1", "watch": "^0.16.0" } } diff --git a/scripts/compile-dots.js b/scripts/compile-dots.js index b0a7f2e..f848bc3 100644 --- a/scripts/compile-dots.js +++ b/scripts/compile-dots.js @@ -20,6 +20,8 @@ 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 VARS = ['$errs', '$valid', '$lvl', '$data', '$dataLvl', + '$errorKeyword', '$closingBraces', '$schemaPath']; files.forEach(function (f) { var keyword = path.basename(f, '.jst'); @@ -30,8 +32,19 @@ files.forEach(function (f) { .replace(OUT_EMPTY_STRING, '') .replace(FUNCTION_NAME, 'function generate_' + keyword + '(it, $keyword) {') .replace(ISTANBUL, '/* $1 */'); + 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 = (code.match(regexp) || []).length; + if (count == 1) { + regexp = new RegExp('var\\s+' + v + '\\s*=[^;]+;|var\\s+' + v + ';'); + code = code.replace(regexp, ''); + } + } }); diff --git a/scripts/prepare-tests b/scripts/prepare-tests index 155ecd0..c08093f 100755 --- a/scripts/prepare-tests +++ b/scripts/prepare-tests @@ -4,8 +4,6 @@ set -e mkdir -p .browser -browserify -r js-beautify -r ./lib/ajv.js:ajv -o .browser/ajv.beautify.js - find spec -type f -name '*.spec.js' | \ xargs -I {} sh -c \ -'export f="{}"; browserify $f -t require-globify -t brfs -x ajv -o $(echo $f | sed -e "s/spec/.browser/");' +'export f="{}"; browserify $f -t require-globify -t brfs -x ajv -u buffer -o $(echo $f | sed -e "s/spec/.browser/");' diff --git a/spec/ajv.js b/spec/ajv.js new file mode 100644 index 0000000..c4638a4 --- /dev/null +++ b/spec/ajv.js @@ -0,0 +1 @@ +module.exports = typeof window == 'object' ? window.Ajv : require('' + '../lib/ajv'); diff --git a/spec/ajv.spec.js b/spec/ajv.spec.js index 1bbf29d..f3810fc 100644 --- a/spec/ajv.spec.js +++ b/spec/ajv.spec.js @@ -1,8 +1,8 @@ 'use strict'; -var Ajv = require(typeof window == 'object' ? 'ajv' : '../lib/ajv') - , should = require('chai').should() +var Ajv = require('./ajv') + , should = require('./chai').should() , stableStringify = require('json-stable-stringify'); diff --git a/spec/ajv_instances.js b/spec/ajv_instances.js index 2511100..53c7a8c 100644 --- a/spec/ajv_instances.js +++ b/spec/ajv_instances.js @@ -1,7 +1,6 @@ 'use strict'; -var Ajv = require(typeof window == 'object' ? 'ajv' : '../lib/ajv') - , util = require('../lib/compile/util'); +var Ajv = require('./ajv'); module.exports = getAjvInstances; @@ -13,8 +12,8 @@ function getAjvInstances(options, extraOpts) { function _getAjvInstances(opts, useOpts) { var optNames = Object.keys(opts); if (optNames.length) { - opts = util.copy(opts); - var useOpts1 = util.copy(useOpts) + opts = copy(opts); + var useOpts1 = copy(useOpts) , optName = optNames[0]; useOpts1[optName] = opts[optName]; delete opts[optName]; @@ -23,3 +22,10 @@ function _getAjvInstances(opts, useOpts) { return instances.concat(instances1); } else return [ Ajv(useOpts) ]; } + + +function copy(o, to) { + to = to || {}; + for (var key in o) to[key] = o[key]; + return to; +} diff --git a/spec/ajv_options.js b/spec/ajv_options.js new file mode 100644 index 0000000..5c1227e --- /dev/null +++ b/spec/ajv_options.js @@ -0,0 +1,18 @@ +'use strict'; + +var isBrowser = typeof window == 'object'; +var fullTest = isBrowser || !process.env.AJV_FAST_TEST; + +var options = fullTest + ? { + allErrors: true, + verbose: true, + format: 'full', + inlineRefs: false, + jsonPointers: true, + } + : { allErrors: true }; + +if (fullTest && !isBrowser) options.beautify = true; + +module.exports = options; diff --git a/spec/async.spec.js b/spec/async.spec.js index f3b3d19..f1067dd 100644 --- a/spec/async.spec.js +++ b/spec/async.spec.js @@ -1,9 +1,8 @@ 'use strict'; -var Ajv = require(typeof window == 'object' ? 'ajv' : '../lib/ajv') - , should = require('chai').should() - , stableStringify = require('json-stable-stringify'); +var Ajv = require('./ajv') + , should = require('./chai').should(); describe('compileAsync method', function() { diff --git a/spec/chai.js b/spec/chai.js new file mode 100644 index 0000000..16998c1 --- /dev/null +++ b/spec/chai.js @@ -0,0 +1 @@ +module.exports = typeof window == 'object' ? window.chai : require('' + 'chai'); diff --git a/spec/custom.spec.js b/spec/custom.spec.js index 06c0d77..944340d 100644 --- a/spec/custom.spec.js +++ b/spec/custom.spec.js @@ -1,7 +1,7 @@ 'use strict'; var getAjvInstances = require('./ajv_instances') - , should = require('chai').should() + , should = require('./chai').should() , equal = require('../lib/compile/equal') , customRules = require('./custom_rules'); diff --git a/spec/equal.spec.js b/spec/equal.spec.js index 6ffd066..c2b7a71 100644 --- a/spec/equal.spec.js +++ b/spec/equal.spec.js @@ -1,7 +1,7 @@ 'use strict'; var equal = require('../lib/compile/equal') - , should = require('chai').should(); + , should = require('./chai').should(); describe('equal', function() { diff --git a/spec/errors.spec.js b/spec/errors.spec.js index bdbf07e..c0ba277 100644 --- a/spec/errors.spec.js +++ b/spec/errors.spec.js @@ -1,8 +1,8 @@ 'use strict'; -var Ajv = require(typeof window == 'object' ? 'ajv' : '../lib/ajv') - , should = require('chai').should(); +var Ajv = require('./ajv') + , should = require('./chai').should(); describe('Validation errors', function () { diff --git a/spec/issues.spec.js b/spec/issues.spec.js index b1d6278..1135c9c 100644 --- a/spec/issues.spec.js +++ b/spec/issues.spec.js @@ -1,7 +1,7 @@ 'use strict'; -var Ajv = require(typeof window == 'object' ? 'ajv' : '../lib/ajv') - , should = require('chai').should(); +var Ajv = require('./ajv') + , should = require('./chai').should(); describe('issue #50: references with "definitions"', function () { diff --git a/spec/json-schema.spec.js b/spec/json-schema.spec.js index e538989..4023cae 100644 --- a/spec/json-schema.spec.js +++ b/spec/json-schema.spec.js @@ -1,19 +1,10 @@ 'use strict'; var jsonSchemaTest = require('json-schema-test') - , getAjvInstances = require('./ajv_instances'); + , getAjvInstances = require('./ajv_instances') + , options = require('./ajv_options'); -var isBrowser = typeof window == 'object'; - -var fullTest = isBrowser || !process.env.AJV_FAST_TEST; -var instances = getAjvInstances(fullTest ? { - beautify: true, - allErrors: true, - verbose: true, - format: 'full', - inlineRefs: false, - jsonPointers: true, -} : { allErrors: true }); +var instances = getAjvInstances(options); var remoteRefs = { // for JSON-Schema-Test-Suite @@ -55,6 +46,7 @@ jsonSchemaTest(instances, { skip: [ 'optional/zeroTerminatedFloats' ], + assert: require('./chai').assert, afterError: function (res) { console.log('ajv options:', res.validator.opts); }, diff --git a/spec/options.spec.js b/spec/options.spec.js index b48c372..5dcb176 100644 --- a/spec/options.spec.js +++ b/spec/options.spec.js @@ -1,8 +1,8 @@ 'use strict'; -var Ajv = require(typeof window == 'object' ? 'ajv' : '../lib/ajv') - , should = require('chai').should(); +var Ajv = require('./ajv') + , should = require('./chai').should() describe('Ajv Options', function () { diff --git a/spec/resolve.spec.js b/spec/resolve.spec.js index 7218e54..2741895 100644 --- a/spec/resolve.spec.js +++ b/spec/resolve.spec.js @@ -1,8 +1,8 @@ 'use strict'; -var Ajv = require(typeof window == 'object' ? 'ajv' : '../lib/ajv') - , should = require('chai').should() +var Ajv = require('./ajv') + , should = require('./chai').should() , getAjvInstances = require('./ajv_instances'); diff --git a/spec/v5.spec.js b/spec/v5.spec.js index 5e9d0d4..af672d8 100644 --- a/spec/v5.spec.js +++ b/spec/v5.spec.js @@ -1,24 +1,16 @@ 'use strict'; var jsonSchemaTest = require('json-schema-test') - , getAjvInstances = require('./ajv_instances'); + , getAjvInstances = require('./ajv_instances') + , options = require('./ajv_options'); -var isBrowser = typeof window == 'object'; - -var fullTest = isBrowser || !process.env.AJV_FAST_TEST; -var instances = getAjvInstances(fullTest ? { - beautify: true, - allErrors: true, - verbose: true, - format: 'full', - inlineRefs: false, - jsonPointers: true, -} : { allErrors: true }, { v5: true }); +var instances = getAjvInstances(options, { v5: true }); jsonSchemaTest(instances, { description: 'v5 schemas tests of ' + instances.length + ' ajv instances with different options', suites: testSuites(), + assert: require('./chai').assert, afterError: function (res) { console.log('ajv options:', res.validator.opts); },