You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							146 lines
						
					
					
						
							3.8 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							146 lines
						
					
					
						
							3.8 KiB
						
					
					
				
								'use strict';
							 | 
						|
								
							 | 
						|
								var IDENTIFIER = /^[a-z_$][a-z0-9_$-]*$/i;
							 | 
						|
								var customRuleCode = require('./dotjs/custom');
							 | 
						|
								var definitionSchema = require('./definition_schema');
							 | 
						|
								
							 | 
						|
								module.exports = {
							 | 
						|
								  add: addKeyword,
							 | 
						|
								  get: getKeyword,
							 | 
						|
								  remove: removeKeyword,
							 | 
						|
								  validate: validateKeyword
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Define custom keyword
							 | 
						|
								 * @this  Ajv
							 | 
						|
								 * @param {String} keyword custom keyword, should be unique (including different from all standard, custom and macro keywords).
							 | 
						|
								 * @param {Object} definition keyword definition object with properties `type` (type(s) which the keyword applies to), `validate` or `compile`.
							 | 
						|
								 * @return {Ajv} this for method chaining
							 | 
						|
								 */
							 | 
						|
								function addKeyword(keyword, definition) {
							 | 
						|
								  /* jshint validthis: true */
							 | 
						|
								  /* eslint no-shadow: 0 */
							 | 
						|
								  var RULES = this.RULES;
							 | 
						|
								  if (RULES.keywords[keyword])
							 | 
						|
								    throw new Error('Keyword ' + keyword + ' is already defined');
							 | 
						|
								
							 | 
						|
								  if (!IDENTIFIER.test(keyword))
							 | 
						|
								    throw new Error('Keyword ' + keyword + ' is not a valid identifier');
							 | 
						|
								
							 | 
						|
								  if (definition) {
							 | 
						|
								    this.validateKeyword(definition, true);
							 | 
						|
								
							 | 
						|
								    var dataType = definition.type;
							 | 
						|
								    if (Array.isArray(dataType)) {
							 | 
						|
								      for (var i=0; i<dataType.length; i++)
							 | 
						|
								        _addRule(keyword, dataType[i], definition);
							 | 
						|
								    } else {
							 | 
						|
								      _addRule(keyword, dataType, definition);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    var metaSchema = definition.metaSchema;
							 | 
						|
								    if (metaSchema) {
							 | 
						|
								      if (definition.$data && this._opts.$data) {
							 | 
						|
								        metaSchema = {
							 | 
						|
								          anyOf: [
							 | 
						|
								            metaSchema,
							 | 
						|
								            { '$ref': 'https://raw.githubusercontent.com/ajv-validator/ajv/master/lib/refs/data.json#' }
							 | 
						|
								          ]
							 | 
						|
								        };
							 | 
						|
								      }
							 | 
						|
								      definition.validateSchema = this.compile(metaSchema, true);
							 | 
						|
								    }
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  RULES.keywords[keyword] = RULES.all[keyword] = true;
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								  function _addRule(keyword, dataType, definition) {
							 | 
						|
								    var ruleGroup;
							 | 
						|
								    for (var i=0; i<RULES.length; i++) {
							 | 
						|
								      var rg = RULES[i];
							 | 
						|
								      if (rg.type == dataType) {
							 | 
						|
								        ruleGroup = rg;
							 | 
						|
								        break;
							 | 
						|
								      }
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if (!ruleGroup) {
							 | 
						|
								      ruleGroup = { type: dataType, rules: [] };
							 | 
						|
								      RULES.push(ruleGroup);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    var rule = {
							 | 
						|
								      keyword: keyword,
							 | 
						|
								      definition: definition,
							 | 
						|
								      custom: true,
							 | 
						|
								      code: customRuleCode,
							 | 
						|
								      implements: definition.implements
							 | 
						|
								    };
							 | 
						|
								    ruleGroup.rules.push(rule);
							 | 
						|
								    RULES.custom[keyword] = rule;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  return this;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Get keyword
							 | 
						|
								 * @this  Ajv
							 | 
						|
								 * @param {String} keyword pre-defined or custom keyword.
							 | 
						|
								 * @return {Object|Boolean} custom keyword definition, `true` if it is a predefined keyword, `false` otherwise.
							 | 
						|
								 */
							 | 
						|
								function getKeyword(keyword) {
							 | 
						|
								  /* jshint validthis: true */
							 | 
						|
								  var rule = this.RULES.custom[keyword];
							 | 
						|
								  return rule ? rule.definition : this.RULES.keywords[keyword] || false;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Remove keyword
							 | 
						|
								 * @this  Ajv
							 | 
						|
								 * @param {String} keyword pre-defined or custom keyword.
							 | 
						|
								 * @return {Ajv} this for method chaining
							 | 
						|
								 */
							 | 
						|
								function removeKeyword(keyword) {
							 | 
						|
								  /* jshint validthis: true */
							 | 
						|
								  var RULES = this.RULES;
							 | 
						|
								  delete RULES.keywords[keyword];
							 | 
						|
								  delete RULES.all[keyword];
							 | 
						|
								  delete RULES.custom[keyword];
							 | 
						|
								  for (var i=0; i<RULES.length; i++) {
							 | 
						|
								    var rules = RULES[i].rules;
							 | 
						|
								    for (var j=0; j<rules.length; j++) {
							 | 
						|
								      if (rules[j].keyword == keyword) {
							 | 
						|
								        rules.splice(j, 1);
							 | 
						|
								        break;
							 | 
						|
								      }
							 | 
						|
								    }
							 | 
						|
								  }
							 | 
						|
								  return this;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Validate keyword definition
							 | 
						|
								 * @this  Ajv
							 | 
						|
								 * @param {Object} definition keyword definition object.
							 | 
						|
								 * @param {Boolean} throwError true to throw exception if definition is invalid
							 | 
						|
								 * @return {boolean} validation result
							 | 
						|
								 */
							 | 
						|
								function validateKeyword(definition, throwError) {
							 | 
						|
								  validateKeyword.errors = null;
							 | 
						|
								  var v = this._validateKeyword = this._validateKeyword
							 | 
						|
								                                  || this.compile(definitionSchema, true);
							 | 
						|
								
							 | 
						|
								  if (v(definition)) return true;
							 | 
						|
								  validateKeyword.errors = v.errors;
							 | 
						|
								  if (throwError)
							 | 
						|
								    throw new Error('custom keyword definition is invalid: '  + this.errorsText(v.errors));
							 | 
						|
								  else
							 | 
						|
								    return false;
							 | 
						|
								}
							 | 
						|
								
							 |