Skip to content

Commit

Permalink
define a schema for relation members
Browse files Browse the repository at this point in the history
  • Loading branch information
k-yle committed Jan 5, 2025
1 parent 54c2a7d commit 31f9af7
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 6 deletions.
26 changes: 24 additions & 2 deletions lib/build.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import chalk from 'chalk';
import fs from 'fs';
import { globSync } from 'glob';
import jsonschema from 'jsonschema';
import { Validator } from 'jsonschema';
import path from 'path';
import shell from 'shelljs';
import YAML from 'js-yaml';
Expand All @@ -21,6 +21,8 @@ const discardedSchema = require('../schemas/discarded.json');

let _currBuild = null;

const jsonschema = new Validator();

function validateData(options) {
const START = '🔬 ' + chalk.yellow('Validating schema...');
const END = '👍 ' + chalk.green('schema okay');
Expand Down Expand Up @@ -203,6 +205,9 @@ function read(f) {


function validateSchema(file, instance, schema) {
// add this schema to the cache, so $ref can be resolved faster
jsonschema.addSchema(schema);

let validationErrors = jsonschema.validate(instance, schema).errors;

if (validationErrors.length) {
Expand Down Expand Up @@ -362,6 +367,15 @@ function generatePresets(dataDir, tstrings, searchableFieldIDs, listReusedIcons)
if (!icons[icon]) icons[icon] = [];
icons[icon].push(id);
}

if (preset.relation) {
tstrings.presets[id].relation_roles = {};
for (const member of preset.relation.members) {
for (const role in member.roles) {
tstrings.presets[id].relation_roles[role] = member.roles[role];
}
}
}
});

if (listReusedIcons) {
Expand Down Expand Up @@ -454,8 +468,10 @@ function generateTranslations(fields, presets, tstrings, searchableFieldIDs) {
let tags = preset.tags || {};
let keys = Object.keys(tags);

const tagsString = keys.map(k => `${k}=${tags[k]}`).join(' + ');

if (keys.length) {
yamlPreset['#name'] = keys.map(k => `${k}=${tags[k]}`).join(' + ');
yamlPreset['#name'] = tagsString;
if (yamlPreset.aliases) {
yamlPreset['#name'] += ' | ' + yamlPreset.aliases.split('\n').join(', ');
}
Expand All @@ -466,6 +482,12 @@ function generateTranslations(fields, presets, tstrings, searchableFieldIDs) {
yamlPreset['#name'] += ` | Local preset for countries ${preset.locationSet.include.map(country => `"${country.toUpperCase()}"`).join(', ')}`;
}

if (yamlPreset.relation_roles) {
for (const role in yamlPreset.relation_roles) {
yamlPreset.relation_roles[`#${role}`] = `Relation role “${role}” when used with ${tagsString}`;
}
}

if (preset.searchable !== false) {
if (yamlPreset.terms) {
yamlPreset['#terms'] = 'terms: ' + yamlPreset.terms;
Expand Down
11 changes: 8 additions & 3 deletions schemas/field.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,7 @@
"minItems": 1,
"uniqueItems": true,
"items": {
"type": "string",
"enum": ["point", "vertex", "line", "area", "relation"]
"$ref": "#/$defs/Geometry"
}
},
"default": {
Expand Down Expand Up @@ -294,5 +293,11 @@
{ "required": ["keys"] }
]}
]}
]
],
"$defs": {
"Geometry": {
"type": "string",
"enum": ["point", "vertex", "line", "area", "relation"]
}
}
}
82 changes: 81 additions & 1 deletion schemas/preset.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,88 @@
}
},
"additionalProperties": false
},
"relation": {
"$ref": "#/$defs/RelationSchema"
},
"relationCrossReference": {
"description": "A preset can reference the relation schema from another preset",
"type": "string",
"pattern": "^\\{.+\\}$"
}
},
"additionalProperties": false,
"required": ["name", "geometry", "tags"]
"required": ["name", "geometry", "tags"],
"$defs": {
"RelationSchema": {
"type": "object",
"properties": {
"optionalTags": {
"type": "object",
"description": "Only useful for specifying placeholders which are referenced in members.*.matchTags",
"examples": [{ "route": "$1" }],
"additionalProperties": {
"type": "string"
}
},
"id": {
"type": "string",
"description": "The “permanent relation type ID”, this should match the value of https://osm.wiki/Property:P41 in the OSM wiki’s wikibase system."
},
"allowDuplicateMembers": {
"type": "boolean",
"default": true
},
"members": {
"type": "array",
"items": {
"type": "object",
"properties": {
"roles": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "Map of roles to their label in the default language. An empty string is allowed as key."
},
"geometry": {
"type": "array",
"items": {
"$ref": "field.json#/$defs/Geometry"
},
"description": "If not specified, any geometry is allowed"
},
"matchTags": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"examples": [
[{}],
[{ "a": 1, "b": 2 }],
[{ "a": 1 }, { "b": 2 }]
],
"description": "`*` can be used as a tag value. If multiple array items are specified, only 1 needs to match."
},
"min": {
"type": "integer",
"description": "If unspecified, there is no minimum"
},
"max": {
"type": "integer",
"description": "If unspecified, there is no maximum"
}
},
"required": ["matchTags"],
"additionalProperties": false
}
}
},
"required": ["id", "allowDuplicateMembers", "members"],
"additionalProperties": false
}
}
}

0 comments on commit 31f9af7

Please sign in to comment.