diff --git a/lib/compile/index.js b/lib/compile/index.js index 570db36..610206a 100644 --- a/lib/compile/index.js +++ b/lib/compile/index.js @@ -7,20 +7,21 @@ var doT = require('dot') , resolve = require('./resolve'); var RULES = require('./rules') - , validateTemplateStr = fs.readFileSync(__dirname + '/validate.dot.js') - , validateTemplate = doT.compile(validateTemplateStr); + , validateGenerator = require('./validate'); + // , validateTemplateStr = fs.readFileSync(__dirname + '/validate.dot.js') + // , validateTemplate = doT.compile(validateTemplateStr); module.exports = compile; function compile(schema) { var self = this; - var validateCode = validateTemplate({ + var validateCode = validateGenerator({ isRoot: true, schema: schema, schemaPath: '', RULES: RULES, - validate: validateTemplate, + validate: validateGenerator, copy: copy, toHash: toHash, resolveRef: resolveRef, @@ -63,19 +64,11 @@ function copy(o, to) { } -function getDataType(data) { - if (data === null) return 'null'; - if (Array.isArray(data)) return 'array'; - return typeof data; -} - - function checkDataType(dataType) { switch (dataType) { case 'null': return 'data === null'; case 'array': return 'Array.isArray(data)'; case 'object': return '(data && typeof data == "object" && !Array.isArray(data))'; - // case 'object': return 'Object.prototype.toString.call(data).slice(8,-1) == "Object"'; case 'integer': return '(typeof data == "number" && !(data % 1))' default: return 'typeof data == "' + dataType + '"'; } diff --git a/lib/compile/rules/properties.dot.js b/lib/compile/rules/properties.dot.js index 15645e6..c0a6482 100644 --- a/lib/compile/rules/properties.dot.js +++ b/lib/compile/rules/properties.dot.js @@ -17,11 +17,8 @@ function (data, dataPath) { var $propertyKeys = Object.keys(it.schema || {}) , $pProperties = it.parentSchema.patternProperties || {} , $pPropertyKeys = $pProperties && Object.keys($pProperties) - , $aProperties = it.parentSchema.additionalProperties; - }} - - {{ - var $noAdditional = $aProperties === false + , $aProperties = it.parentSchema.additionalProperties + , $noAdditional = $aProperties === false , $additionalIsSchema = typeof $aProperties == 'object' && Object.keys($aProperties).length , $checkAdditional = $noAdditional || $additionalIsSchema; diff --git a/lib/compile/validate.dot.js b/lib/compile/validate.dot.js index 600ca3d..f20eebe 100644 --- a/lib/compile/validate.dot.js +++ b/lib/compile/validate.dot.js @@ -6,7 +6,7 @@ * * runtime: * "validate" is a variable name to which this function will be assigned - * copy, getDataType etc. are defined in the parent scope in index.js + * validateRef etc. are defined in the parent scope in index.js */ }} function (data{{? !it.isRoot }}, dataPath{{?}}) { @@ -66,4 +66,4 @@ function (data{{? !it.isRoot }}, dataPath{{?}}) { } return $use; } -}} \ No newline at end of file +}} diff --git a/lib/compile/validate.js b/lib/compile/validate.js new file mode 100644 index 0000000..d15a9ad --- /dev/null +++ b/lib/compile/validate.js @@ -0,0 +1,72 @@ +/** + * schema compilation (render) time: + * it = { schema, RULES, _validate, opts } + * it.validate - this template function, + * it is used recursively to generate code for subschemas + * + * runtime: + * "validate" is a variable name to which this function will be assigned + * validateRef etc. are defined in the parent scope in index.js + */ + +module.exports = function (it) { + if (it.isRoot) { + it.isRoot = false; + var out = '\nfunction (data) { \n "use strict"; \n'; + out += 'var dataPath = ""; \n'; + out += 'var errs = validate.errors.length = 0; \n'; + } else { + var out = '\nfunction (data, dataPath) { \n "use strict"; \n'; + out += 'var errs = validate.errors.length; \n'; + } + + + it.RULES.forEach(function (rulesGroup) { + if (shouldUseGroup(rulesGroup)) { + if (rulesGroup.type) out += 'if (' + (it.checkDataType(rulesGroup.type)) + ') { \n'; + + rulesGroup.rules.forEach(function (rule) { + if (shouldUseRule(rule)) { + if (rule.inline) out += rule.code(it) + ' \n'; + else { + var $it = it.copy(it); + $it.schema = it.schema[rule.keyword]; + $it.schemaPath = it.schemaPath + '.' + rule.keyword; + $it.parentSchema = it.schema; + $it.parentSchemaPath = it.schemaPath; + + if (!it.opts.allErrors) out += 'var valid = '; + out += '(' + rule.code($it) + ')(data, dataPath); \n'; + } + if (!it.opts.allErrors) out += ' if (!valid) return false; \n'; + } + }); + + if (rulesGroup.type) out += ' } \n'; + } + }); + + out += it.opts.allErrors + ? 'return errs == validate.errors.length; \n' + : 'return true; \n'; + + return out + '} \n'; + + + function shouldUseGroup(rulesGroup) { + return rulesGroup.rules.some(function(rule) { + return shouldUseRule(rule); + }); + } + + function shouldUseRule(rule) { + var use = it.schema.hasOwnProperty(rule.keyword); + if (!use && rule.keyword == 'properties') { + var pProperties = it.schema.patternProperties + , aProperties = it.schema.additionalProperties; + use = (pProperties && Object.keys(pProperties).length) || + (aProperties === false || typeof aProperties == 'object'); + } + return use; + } +} diff --git a/package.json b/package.json index ed3d89d..5f92c53 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ajv", - "version": "0.1.4", + "version": "0.1.5", "description": "Another JSON schema Validator", "main": "lib/ajv.js", "scripts": {