diff --git a/lib/compile/rules.js b/lib/compile/rules.js index 271b343d2..68195f75e 100644 --- a/lib/compile/rules.js +++ b/lib/compile/rules.js @@ -7,7 +7,7 @@ module.exports = function rules() { var RULES = [ { type: 'number', rules: [ { 'maximum': ['exclusiveMaximum'] }, - { 'minimum': ['exclusiveMinimum'] }, 'multipleOf'] }, + { 'minimum': ['exclusiveMinimum'] }, 'multipleOf', 'format'] }, { type: 'string', rules: [ 'maxLength', 'minLength', 'pattern', 'format' ] }, { type: 'array', diff --git a/lib/dot/definitions.def b/lib/dot/definitions.def index 99002bb7d..bb40d18c9 100644 --- a/lib/dot/definitions.def +++ b/lib/dot/definitions.def @@ -2,6 +2,7 @@ {{ var $lvl = it.level; var $dataLvl = it.dataLevel; + var $type = it.schema.type || ''; var $schema = it.schema[$keyword]; var $schemaPath = it.schemaPath + it.util.getProperty($keyword); var $errSchemaPath = it.errSchemaPath + '/' + $keyword; diff --git a/lib/dot/format.jst b/lib/dot/format.jst index 590e4956e..b2894611e 100644 --- a/lib/dot/format.jst +++ b/lib/dot/format.jst @@ -77,11 +77,15 @@ var $isObject = typeof $format == 'object' && !($format instanceof RegExp) && $format.validate; + var $types = $isObject && $format.types || ['string']; if ($isObject) { var $async = $format.async === true; $format = $format.validate; } }} + {{? $types.indexOf($type) === -1 }} + {{# def.skipFormat }} + {{?}} {{? $async }} {{ if (!it.async) throw new Error('async format in sync schema'); diff --git a/spec/ajv.spec.js b/spec/ajv.spec.js index 73d09c108..71785f24e 100644 --- a/spec/ajv.spec.js +++ b/spec/ajv.spec.js @@ -386,27 +386,71 @@ describe('Ajv', function () { describe('addFormat method', function() { - it('should add format as regular expression', function() { - ajv.addFormat('identifier', /^[a-z_$][a-z0-9_$]*$/i); - testFormat(); - }); + describe.skip('without any type restrictions specified', function() { + it('should add format as regular expression', function() { + ajv.addFormat('identifier', /^[a-z_$][a-z0-9_$]*$/i); + testFormat(); + }); - it('should add format as string', function() { - ajv.addFormat('identifier', '^[A-Za-z_$][A-Za-z0-9_$]*$'); - testFormat(); - }); + it('should add format as string', function() { + ajv.addFormat('identifier', '^[A-Za-z_$][A-Za-z0-9_$]*$'); + testFormat(); + }); + + it('should add format as function', function() { + ajv.addFormat('identifier', function (str) { return /^[a-z_$][a-z0-9_$]*$/i.test(str); }); + testFormat(); + }); - it('should add format as function', function() { - ajv.addFormat('identifier', function (str) { return /^[a-z_$][a-z0-9_$]*$/i.test(str); }); - testFormat(); + it('should add format as object', function() { + ajv.addFormat('identifier', { + validate: function (str) { return /^[a-z_$][a-z0-9_$]*$/i.test(str); }, + }); + testFormat(); + }); + + function testFormat() { + var validate = ajv.compile({ format: 'identifier' }); + validate('Abc1') .should.equal(true); + validate('123') .should.equal(false); + validate(123) .should.equal(true); + } }); - function testFormat() { - var validate = ajv.compile({ format: 'identifier' }); - validate('Abc1') .should.equal(true); - validate('123') .should.equal(false); - validate(123) .should.equal(true); - } + describe('with type restrictions specified', function() { + it('should apply the format to the type specified', function() { + + ajv.addFormat('positive', { + types: ['number'], + validate: function(x) { + return x >= 0; + } + }); + + var validate = ajv.compile({ + type: 'number', + format: 'positive' + }); + validate(-12.3) .should.equal(false); + validate(12.3) .should.equal(true); + }); + + it('should not fail types not specified', function() { + ajv.addFormat('positive', { + types: ['number'], + validate: function(x) { + return x >= 0; + } + }); + + var validate = ajv.compile({ + type: 'string', + format: 'positive' + }); + validate('Abc1') .should.equal(true); + }); + + }); });