twitst4tz

twitter statistics web application
Log | Files | Refs | README | LICENSE

keyword.js (3909B)


      1 'use strict';
      2 
      3 var IDENTIFIER = /^[a-z_$][a-z0-9_$-]*$/i;
      4 var customRuleCode = require('./dotjs/custom');
      5 var definitionSchema = require('./definition_schema');
      6 
      7 module.exports = {
      8   add: addKeyword,
      9   get: getKeyword,
     10   remove: removeKeyword,
     11   validate: validateKeyword
     12 };
     13 
     14 
     15 /**
     16  * Define custom keyword
     17  * @this  Ajv
     18  * @param {String} keyword custom keyword, should be unique (including different from all standard, custom and macro keywords).
     19  * @param {Object} definition keyword definition object with properties `type` (type(s) which the keyword applies to), `validate` or `compile`.
     20  * @return {Ajv} this for method chaining
     21  */
     22 function addKeyword(keyword, definition) {
     23   /* jshint validthis: true */
     24   /* eslint no-shadow: 0 */
     25   var RULES = this.RULES;
     26   if (RULES.keywords[keyword])
     27     throw new Error('Keyword ' + keyword + ' is already defined');
     28 
     29   if (!IDENTIFIER.test(keyword))
     30     throw new Error('Keyword ' + keyword + ' is not a valid identifier');
     31 
     32   if (definition) {
     33     this.validateKeyword(definition, true);
     34 
     35     var dataType = definition.type;
     36     if (Array.isArray(dataType)) {
     37       for (var i=0; i<dataType.length; i++)
     38         _addRule(keyword, dataType[i], definition);
     39     } else {
     40       _addRule(keyword, dataType, definition);
     41     }
     42 
     43     var metaSchema = definition.metaSchema;
     44     if (metaSchema) {
     45       if (definition.$data && this._opts.$data) {
     46         metaSchema = {
     47           anyOf: [
     48             metaSchema,
     49             { '$ref': 'https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/data.json#' }
     50           ]
     51         };
     52       }
     53       definition.validateSchema = this.compile(metaSchema, true);
     54     }
     55   }
     56 
     57   RULES.keywords[keyword] = RULES.all[keyword] = true;
     58 
     59 
     60   function _addRule(keyword, dataType, definition) {
     61     var ruleGroup;
     62     for (var i=0; i<RULES.length; i++) {
     63       var rg = RULES[i];
     64       if (rg.type == dataType) {
     65         ruleGroup = rg;
     66         break;
     67       }
     68     }
     69 
     70     if (!ruleGroup) {
     71       ruleGroup = { type: dataType, rules: [] };
     72       RULES.push(ruleGroup);
     73     }
     74 
     75     var rule = {
     76       keyword: keyword,
     77       definition: definition,
     78       custom: true,
     79       code: customRuleCode,
     80       implements: definition.implements
     81     };
     82     ruleGroup.rules.push(rule);
     83     RULES.custom[keyword] = rule;
     84   }
     85 
     86   return this;
     87 }
     88 
     89 
     90 /**
     91  * Get keyword
     92  * @this  Ajv
     93  * @param {String} keyword pre-defined or custom keyword.
     94  * @return {Object|Boolean} custom keyword definition, `true` if it is a predefined keyword, `false` otherwise.
     95  */
     96 function getKeyword(keyword) {
     97   /* jshint validthis: true */
     98   var rule = this.RULES.custom[keyword];
     99   return rule ? rule.definition : this.RULES.keywords[keyword] || false;
    100 }
    101 
    102 
    103 /**
    104  * Remove keyword
    105  * @this  Ajv
    106  * @param {String} keyword pre-defined or custom keyword.
    107  * @return {Ajv} this for method chaining
    108  */
    109 function removeKeyword(keyword) {
    110   /* jshint validthis: true */
    111   var RULES = this.RULES;
    112   delete RULES.keywords[keyword];
    113   delete RULES.all[keyword];
    114   delete RULES.custom[keyword];
    115   for (var i=0; i<RULES.length; i++) {
    116     var rules = RULES[i].rules;
    117     for (var j=0; j<rules.length; j++) {
    118       if (rules[j].keyword == keyword) {
    119         rules.splice(j, 1);
    120         break;
    121       }
    122     }
    123   }
    124   return this;
    125 }
    126 
    127 
    128 /**
    129  * Validate keyword definition
    130  * @this  Ajv
    131  * @param {Object} definition keyword definition object.
    132  * @param {Boolean} throwError true to throw exception if definition is invalid
    133  * @return {boolean} validation result
    134  */
    135 function validateKeyword(definition, throwError) {
    136   validateKeyword.errors = null;
    137   var v = this._validateKeyword = this._validateKeyword
    138                                   || this.compile(definitionSchema, true);
    139 
    140   if (v(definition)) return true;
    141   validateKeyword.errors = v.errors;
    142   if (throwError)
    143     throw new Error('custom keyword definition is invalid: '  + this.errorsText(v.errors));
    144   else
    145     return false;
    146 }