UNPKG

bemhint-deps-specification

Version:

Plugin for bemhint which checks *.deps.js to be written by specification

136 lines (113 loc) 4.35 kB
var _ = require('lodash'), vm = require('vm'); function stringValidation(val, field, addError, expected) { _.isString(val) || addError( 'Invalid type (' + typeof val + ')' + ' in "' + field + '":' + ' expected ' + concatExpected(expected, 'string', ' or ')); } function arrayOfStringsValidation(val, field, addError) { val.forEach(function(innerVal, i) { stringValidation(innerVal, field + '[' + i + ']', addError); }); } function booleanOrStringValidation(val, field, addError, expected) { _.isBoolean(val) || stringValidation( val, field, addError, concatExpected(expected, 'boolean')); } function stringOrArrayOfStringsValidation(val, field, addError) { (_.isArray(val)? arrayOfStringsValidation : stringValidation)(val, field, addError, 'array'); } function depsItemValidation(val, field, validFields, addError, expected) { _.isPlainObject(val)? _.forEach(val, function(innerVal, innerField) { validFields.hasOwnProperty(innerField)? fieldsValidations[innerField] && fieldsValidations[innerField](innerVal, field + '.' + innerField, addError) : addError('Invalid field (' + innerField + ')' + (field ? ' in "' + field + '"' : '')); }) : stringValidation(val, field, addError, concatExpected(expected, 'object')); } function arrayOfDepsItemsValidation(val, field, validFields, addError) { val.forEach(function(innerVal, i) { depsItemValidation(innerVal, field + '[' + i + ']', validFields, addError); }); } function depsItemOrArrayOfDepsItemsValidation(val, field, validFields, addError) { (_.isArray(val)? arrayOfDepsItemsValidation : depsItemValidation)(val, field, validFields, addError, 'array'); } function topLevelDepsValidation(val, field, addError) { depsItemOrArrayOfDepsItemsValidation(val, field, validTopLevelFields, addError); } var validElemFields = { elem : true, mod : true, mods : true, val : true, tech : true, mustDeps : true, shouldDeps : true, noDeps : true, include : true }, validTopLevelFields = _.merge(validElemFields, { block : true, elems : true, }), fieldsValidations = { block: stringValidation, elem: stringOrArrayOfStringsValidation, elems: function(val, field, addError) { depsItemOrArrayOfDepsItemsValidation(val, field, validElemFields, addError); }, mod : stringValidation, mods: function(val, field, addError) { if (_.isArray(val)) { arrayOfStringsValidation(val, field, addError); } else if (_.isPlainObject(val)) { // If mods in object type notation, like this - { disabled : true, focused : 'yes' } _.forEach(val, function(innerVal, innerField) { (_.isArray(innerVal)? arrayOfStringsValidation : booleanOrStringValidation) (innerVal, field + '.' + innerField, addError, 'array'); }); } else { addError('Invalid declaration type (' + typeof val + ') in "' + field + '": expected array or object'); } }, val : booleanOrStringValidation, tech : stringValidation, mustDeps : topLevelDepsValidation, shouldDeps : topLevelDepsValidation, noDeps : topLevelDepsValidation, include : function(val, field, addError) { val === false || addError('Invalid value (' + val + ') in "' + field + '": expected false'); } }; function concatExpected(old, add, delim) { return old ? old + (delim || ', ') + add : add; } module.exports = { configure: function() { return { techs: { 'deps.js': true } } }, forEachTech: function(tech, entity) { tech.content && topLevelDepsValidation( vm.runInThisContext(tech.content), // TODO: catch errors '', function(error) { entity.addError({ msg : 'Deps validation error', tech : tech.name, value : error }); }); } };