diff --git a/README.md b/README.md index d645c3f70..cc6992d4d 100644 --- a/README.md +++ b/README.md @@ -1144,6 +1144,7 @@ Defaults: - `"full"` - more restrictive and slow validation. E.g., 25:00:00 and 2015/14/33 will be invalid time and date in 'full' mode but it will be valid in 'fast' mode. - `false` - ignore all format keywords. - _formats_: an object with custom formats. Keys and values will be passed to `addFormat` method. +- _keywords_: an object with custom keywords. Keys and values will be passed to `addKeyword` method. - _unknownFormats_: handling of unknown formats. Option values: - `true` (default) - if an unknown format is encountered the exception is thrown during schema compilation. If `format` keyword value is [$data reference](#data-reference) and it is unknown the validation will fail. - `[String]` - an array of unknown format names that will be ignored. This option can be used to allow usage of third party schemas with format(s) for which you don't have definitions, but still fail if another unknown format is used. If `format` keyword value is [$data reference](#data-reference) and it is not in this array the validation will fail. diff --git a/lib/ajv.d.ts b/lib/ajv.d.ts index 29cdee59a..cb600e168 100644 --- a/lib/ajv.d.ts +++ b/lib/ajv.d.ts @@ -171,6 +171,7 @@ declare namespace ajv { unicode?: boolean; format?: false | string; formats?: object; + keywords?: object; unknownFormats?: true | string[] | 'ignore'; schemas?: Array | object; schemaId?: '$id' | 'id' | 'auto'; @@ -252,6 +253,9 @@ declare namespace ajv { formats: { [index: string]: FormatDefinition | undefined; }; + keywords: { + [index: string]: KeywordDefinition | undefined; + }; compositeRule: boolean; validate: (schema: object) => boolean; util: { diff --git a/lib/ajv.js b/lib/ajv.js index 611b93835..06a45b650 100644 --- a/lib/ajv.js +++ b/lib/ajv.js @@ -69,6 +69,7 @@ function Ajv(opts) { this._metaOpts = getMetaSchemaOptions(this); if (opts.formats) addInitialFormats(this); + if (opts.keywords) addInitialKeywords(this); addDefaultMetaSchema(this); if (typeof opts.meta == 'object') this.addMetaSchema(opts.meta); if (opts.nullable) this.addKeyword('nullable', {metaSchema: {type: 'boolean'}}); @@ -467,6 +468,14 @@ function addInitialFormats(self) { } +function addInitialKeywords(self) { + for (var name in self._opts.keywords) { + var keyword = self._opts.keywords[name]; + self.addKeyword(name, keyword); + } +} + + function checkUnique(self, id) { if (self._schemas[id] || self._refs[id]) throw new Error('schema with key or id "' + id + '" already exists'); diff --git a/spec/options/options_validation.spec.js b/spec/options/options_validation.spec.js index e362826bc..3f86b2fc7 100644 --- a/spec/options/options_validation.spec.js +++ b/spec/options/options_validation.spec.js @@ -26,12 +26,35 @@ describe('validation options', function() { }}); var validate = ajv.compile({ format: 'identifier' }); + validate('Abc1') .should.equal(true); validate('123') .should.equal(false); validate(123) .should.equal(true); }); }); + describe('keywords', function() { + it('should add keywords from options', function() { + var ajv = new Ajv({ keywords: { + string: { + validate: function (schema, data ) { + + console.log(">>", data); + return /^[a-z_$][a-z0-9_$]*$/i.test(data); + } + } + }}); + + var validate = ajv.compile({ string: true }); + + validate('Abc1') .should.equal(true); + validate('foo bar').should.equal(false); + validate('123').should.equal(false); + validate(123).should.equal(false); + validate(123).should.equal(false); + }); + }); + describe('uniqueItems', function() { it('should not validate uniqueItems with uniqueItems option == false', function() {