From 770cffe7de26a9c00c2d6fd6f729d0805bdffdca Mon Sep 17 00:00:00 2001 From: SilentSpike Date: Tue, 26 Feb 2019 21:16:54 +0000 Subject: [PATCH] Add email and website format validation Simple validation following the HTML5 standard for emails as we don't expect POIs to have convoluted email addresses. Only checks the `website` and `email` tags as these are what iD currently supports with fields. --- data/core.yaml | 11 +++- dist/locales/en.json | 12 +++++ modules/validations/index.js | 3 +- modules/validations/invalid_format.js | 72 +++++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 modules/validations/invalid_format.js diff --git a/data/core.yaml b/data/core.yaml index 08a9301d9..7e61c9c20 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -1406,6 +1406,15 @@ en: feature: message: '{feature} lists Google as a data source' reference: "Google products are proprietary and must not be used as references." + invalid_format: + title: Invalid Formatting + tip: Find features tagged with invalid value formatting + email: + message: '{feature} is tagged with an invalid email address' + reference: 'Email addresses must be of the form "local-part@domain".' + website: + message: '{feature} is tagged with an invalid website' + reference: 'Websites should start with a "http" or "https" scheme.' missing_role: title: Missing Roles message: "{member} has no role within {relation}" @@ -1921,4 +1930,4 @@ en: wikidata: identifier: "Identifier" label: "Label" - description: "Description" + description: "Description" \ No newline at end of file diff --git a/dist/locales/en.json b/dist/locales/en.json index 0c4af83c9..d5ad3be6f 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -1740,6 +1740,18 @@ "reference": "Google products are proprietary and must not be used as references." } }, + "invalid_format": { + "title": "Invalid Formatting", + "tip": "Find features tagged with invalid value formatting", + "email": { + "message": "{feature} is tagged with an invalid email address", + "reference": "Email addresses must be of the form \"local-part@domain\"." + }, + "website": { + "message": "{feature} is tagged with an invalid website", + "reference": "Websites should start with a \"http\" or \"https\" scheme." + } + }, "missing_role": { "title": "Missing Roles", "message": "{member} has no role within {relation}", diff --git a/modules/validations/index.js b/modules/validations/index.js index cecaafeb5..bf3bd8abc 100644 --- a/modules/validations/index.js +++ b/modules/validations/index.js @@ -6,10 +6,11 @@ export { validationFixmeTag } from './fixme_tag'; export { validationGenericName } from './generic_name'; export { validationImpossibleOneway } from './impossible_oneway'; export { validationIncompatibleSource } from './incompatible_source'; +export { validationFormatting } from './invalid_format'; export { validationMaprules } from './maprules'; export { validationMissingRole } from './missing_role'; export { validationMissingTag } from './missing_tag'; export { validationOutdatedTags } from './outdated_tags'; export { validationPrivateData } from './private_data'; export { validationTagSuggestsArea } from './tag_suggests_area'; -export { validationUnsquareWay } from './unsquare_way'; +export { validationUnsquareWay } from './unsquare_way'; \ No newline at end of file diff --git a/modules/validations/invalid_format.js b/modules/validations/invalid_format.js new file mode 100644 index 000000000..37d9247b5 --- /dev/null +++ b/modules/validations/invalid_format.js @@ -0,0 +1,72 @@ +import { t } from '../util/locale'; +import { utilDisplayLabel } from '../util'; +import { validationIssue } from '../core/validation'; + +export function validationFormatting() { + var type = 'invalid_format'; + + var validation = function(entity, context) { + var issues = []; + if (entity.tags.website) { + var valid_scheme = /^https?:\/\//i; + + if (!valid_scheme.test(entity.tags.website)) { + issues.push(new validationIssue({ + type: type, + subtype: 'website', + severity: 'warning', + message: function() { + var entity = context.hasEntity(this.entityIds[0]); + return entity ? t('issues.invalid_format.website.message', { feature: utilDisplayLabel(entity, context) }) : ''; + }, + reference: showReferenceWebsite, + entityIds: [entity.id] + })); + + function showReferenceWebsite(selection) { + selection.selectAll('.issue-reference') + .data([0]) + .enter() + .append('div') + .attr('class', 'issue-reference') + .text(t('issues.invalid_format.website.reference')); + } + } + } + + if (entity.tags.email) { + // Same regex as used by HTML5 "email" inputs + // Emails in OSM are going to be official so they should be pretty simple + var valid_email = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/; + + if (!valid_email.test(entity.tags.email)) { + issues.push(new validationIssue({ + type: type, + subtype: 'email', + severity: 'warning', + message: function() { + var entity = context.hasEntity(this.entityIds[0]); + return entity ? t('issues.invalid_format.email.message', { feature: utilDisplayLabel(entity, context) }) : ''; + }, + reference: showReferenceEmail, + entityIds: [entity.id] + })); + + function showReferenceEmail(selection) { + selection.selectAll('.issue-reference') + .data([0]) + .enter() + .append('div') + .attr('class', 'issue-reference') + .text(t('issues.invalid_format.email.reference')); + } + } + } + + return issues; + }; + + validation.type = type; + + return validation; +} \ No newline at end of file