From 53820dc75d3d527e7ef1d775f5f55e68819cb0fb Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 19 Mar 2013 15:00:35 -0700 Subject: [PATCH] Validate preset json (fixes #1042) --- build.js | 28 +++++++++++++- data/presets/schema/field.json | 67 +++++++++++++++++++++++++++++++++ data/presets/schema/preset.json | 55 +++++++++++++++++++++++++++ package.json | 3 +- 4 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 data/presets/schema/field.json create mode 100644 data/presets/schema/preset.json diff --git a/build.js b/build.js index 7f77b6de1..e05dd40e2 100644 --- a/build.js +++ b/build.js @@ -2,7 +2,10 @@ var fs = require('fs'), path = require('path'), glob = require('glob'), YAML = require('js-yaml'), - _ = require('./js/lib/lodash'); + _ = require('./js/lib/lodash'), + jsonschema = require('jsonschema'), + fieldSchema = require('./data/presets/schema/field.json'), + presetSchema = require('./data/presets/schema/preset.json'); function read(f) { return JSON.parse(fs.readFileSync(f)); @@ -16,6 +19,21 @@ function rp(f) { return r('presets/' + f); } +function validate(file, instance, schema) { + var result = jsonschema.validate(instance, schema); + if (result.length) { + console.error(file + ": "); + result.forEach(function(error) { + if (error.property) { + console.error(error.property + ' ' + error.message); + } else { + console.error(error); + } + }); + process.exit(1); + } +} + var translations = { fields: {}, presets: {} @@ -25,12 +43,16 @@ var fields = {}; glob.sync(__dirname + '/data/presets/fields/*.json').forEach(function(file) { var field = read(file), id = path.basename(file, '.json'); + + validate(file, field, fieldSchema); + translations.fields[id] = {label: field.label}; if (field.strings) { for (var i in field.strings) { translations.fields[id][i] = field.strings[i]; } } + fields[id] = field; }); fs.writeFileSync('data/presets/fields.json', JSON.stringify(fields, null, 4)); @@ -39,10 +61,14 @@ var presets = {}; glob.sync(__dirname + '/data/presets/presets/**/*.json').forEach(function(file) { var preset = read(file), id = file.match(/presets\/presets\/([^.]*)\.json/)[1]; + + validate(file, preset, presetSchema); + translations.presets[id] = { name: preset.name, terms: (preset.terms || []).join(',') }; + presets[id] = preset; }); fs.writeFileSync('data/presets/presets.json', JSON.stringify(presets, null, 4)); diff --git a/data/presets/schema/field.json b/data/presets/schema/field.json new file mode 100644 index 000000000..f852288c5 --- /dev/null +++ b/data/presets/schema/field.json @@ -0,0 +1,67 @@ +{ + "title": "Field", + "description": "A reusable form element for presets", + "type": "object", + "properties": { + "key": { + "description": "Tag key whose value is to be displayed", + "type": "string" + }, + "keys": { + "description": "Tag keys whose value is to be displayed", + "type": "array", + "items": { + "type": "string" + } + }, + "type": { + "description": "Type of field", + "type": "string", + "enum": [ + "address", + "check", + "combo", + "defaultcheck", + "text", + "number", + "tel", + "email", + "url", + "radio", + "textarea" + ], + "required": true + }, + "label": { + "description": "English label for the form", + "type": "string", + "required": true + }, + "geometry": { + "type": "string" + }, + "default": { + "type": "string" + }, + "indexed": { + "type": "boolean" + }, + "options": { + "type": "array", + "items": { + "type": "string" + } + }, + "universal": { + "type": "boolean", + "default": false + }, + "icon": { + "type": "string" + }, + "strings": { + "type": "object" + } + }, + "additionalProperties": false +} \ No newline at end of file diff --git a/data/presets/schema/preset.json b/data/presets/schema/preset.json new file mode 100644 index 000000000..f2466671a --- /dev/null +++ b/data/presets/schema/preset.json @@ -0,0 +1,55 @@ +{ + "title": "Preset", + "description": "Associates an icon, form fields, and other UI with a set of OSM tags", + "type": "object", + "properties": { + "name": { + "description": "The English name for the feature", + "type": "string", + "required": true + }, + "geometry": { + "description": "Valid geometry types for the feature", + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "type": "string", + "enum": ["point", "vertex", "line", "area"] + }, + "required": true + }, + "tags": { + "description": "Tags that must be present for the preset to match", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "required": true + }, + "fields": { + "description": "Form fields that are displayed for the preset", + "type": "array", + "items": { + "type": "string" + } + }, + "icon": { + "description": "Name of preset icon which represents this preset", + "type": "string" + }, + "terms": { + "description": "English synonyms or related terms", + "type": "array", + "items": { + "type": "string" + } + }, + "searchable": { + "description": "Whether or not the preset will be suggested via search", + "type": "boolean", + "default": true + } + }, + "additionalProperties": false +} \ No newline at end of file diff --git a/package.json b/package.json index 33b2b4079..4cd2317a8 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,8 @@ "mocha-phantomjs": "~1.1.1", "glob": "~3.1.21", "js-yaml": "~2.0.3", - "request": "~2.16.2" + "request": "~2.16.2", + "jsonschema": "~0.3.2" }, "engines": { "node": "~0.8.20"