diff --git a/data/core.yaml b/data/core.yaml index 32b6d4644..612a9579a 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -1234,7 +1234,7 @@ en: message: "{multipolygon} has misplaced tags." tip: Multipolygons should be tagged on their relation, not their outer way. tag_suggests_area: - message: '{feature} should be an area based on the tags: {tags}' + message: "{feature} should be a closed area based on the tag: {tag}" tip: Areas must have connected endpoints. fix: add_connection_vertex: @@ -1256,9 +1256,9 @@ en: remove_generic_name: title: Remove the name undo_redo: Removed a generic name. - remove_tags: - title: Remove the tags - undo_redo: Removed tags. + remove_tag: + title: Remove the tag + undo_redo: Removed tag. select_preset: title: Select a feature type tag_as_disconnected: diff --git a/dist/locales/en.json b/dist/locales/en.json index 41d8ddf71..c165e7183 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -1511,7 +1511,7 @@ "tip": "Multipolygons should be tagged on their relation, not their outer way." }, "tag_suggests_area": { - "message": "{feature} should be an area based on the tags: {tags}", + "message": "{feature} should be a closed area based on the tag: {tag}", "tip": "Areas must have connected endpoints." }, "fix": { @@ -1541,9 +1541,9 @@ "title": "Remove the name", "undo_redo": "Removed a generic name." }, - "remove_tags": { - "title": "Remove the tags", - "undo_redo": "Removed tags." + "remove_tag": { + "title": "Remove the tag", + "undo_redo": "Removed tag." }, "select_preset": { "title": "Select a feature type" diff --git a/modules/osm/way.js b/modules/osm/way.js index 3c98c8833..f53a69b89 100644 --- a/modules/osm/way.js +++ b/modules/osm/way.js @@ -193,8 +193,12 @@ _extend(osmWay.prototype, { return true; }, + // returns an objects with the tag that implies this is an area, if any + tagSuggestingArea: function() { + + if (this.tags.area === 'yes') return { area: 'yes' }; + if (this.tags.area === 'no') return null; - isArea: function() { // `highway` and `railway` are typically linear features, but there // are a few exceptions that should be treated as areas, even in the // absence of a proper `area=yes` or `areaKeys` tag.. see #4194 @@ -211,20 +215,27 @@ _extend(osmWay.prototype, { wash: true } }; + var returnTags = {}; + for (var key in this.tags) { + if (key in areaKeys && !(this.tags[key] in areaKeys[key])) { + returnTags[key] = this.tags[key]; + return returnTags; + } + if (key in lineKeys && this.tags[key] in lineKeys[key]) { + returnTags[key] = this.tags[key]; + return returnTags; + } + } + return null; + }, + + isArea: function() { if (this.tags.area === 'yes') return true; if (!this.isClosed() || this.tags.area === 'no') return false; - for (var key in this.tags) { - if (key in areaKeys && !(this.tags[key] in areaKeys[key])) { - return true; - } - if (key in lineKeys && this.tags[key] in lineKeys[key]) { - return true; - } - } - return false; + return this.tagSuggestingArea() !== null; }, diff --git a/modules/validations/tag_suggests_area.js b/modules/validations/tag_suggests_area.js index b77702853..e3b1469eb 100644 --- a/modules/validations/tag_suggests_area.js +++ b/modules/validations/tag_suggests_area.js @@ -1,4 +1,3 @@ -import _isEmpty from 'lodash-es/isEmpty'; import _clone from 'lodash-es/clone'; import { t } from '../util/locale'; import { @@ -17,40 +16,23 @@ import { import { geoHasSelfIntersections, geoSphericalDistance } from '../geo'; -// https://github.com/openstreetmap/josm/blob/mirror/src/org/ -// openstreetmap/josm/data/validation/tests/UnclosedWays.java#L80 export function validationTagSuggestsArea() { - function tagSuggestsArea(tags) { - if (_isEmpty(tags)) return false; - - var areaKeys = ['area', 'building', 'landuse', 'shop', 'tourism']; - for (var i = 0; i < areaKeys.length; i++) { - var key = areaKeys[i]; - if (tags[key] !== undefined && tags[key] !== 'no') { - if (key === 'tourism' && tags[key] === 'artwork') { - continue; // exception for tourism=artwork - #5206 - } else { - var returnTags = {}; - returnTags[key] = tags[key]; - return returnTags; - } - } - } - - return false; - } - var type = 'tag_suggests_area'; var validation = function(entity, context) { + + if (entity.type !== 'way') { + return []; + } + var issues = []; var graph = context.graph(); - var geometry = entity.geometry(graph); - var suggestingTags = (geometry === 'line' ? tagSuggestsArea(entity.tags) : undefined); + var tagSuggestingArea = entity.tagSuggestingArea(); + var tagSuggestsArea = !entity.isClosed() && tagSuggestingArea; - if (suggestingTags) { - var tagText = utilTagText({ tags: suggestingTags }); + if (tagSuggestsArea) { + var tagText = utilTagText({ tags: tagSuggestingArea }); var fixes = []; var nodes = graph.childNodes(entity), testNodes; @@ -96,16 +78,16 @@ export function validationTagSuggestsArea() { })); } fixes.push(new validationIssueFix({ - title: t('issues.fix.remove_tags.title'), + title: t('issues.fix.remove_tag.title'), onClick: function() { var entity = this.issue.entities[0]; var tags = _clone(entity.tags); - for (var key in suggestingTags) { + for (var key in tagSuggestingArea) { delete tags[key]; } context.perform( actionChangeTags(entity.id, tags), - t('issues.fix.remove_tags.undo_redo') + t('issues.fix.remove_tag.undo_redo') ); } })); @@ -113,7 +95,7 @@ export function validationTagSuggestsArea() { issues.push(new validationIssue({ type: type, severity: 'warning', - message: t('issues.tag_suggests_area.message', { feature: featureLabel, tags: tagText }), + message: t('issues.tag_suggests_area.message', { feature: featureLabel, tag: tagText }), tooltip: t('issues.tag_suggests_area.tip'), entities: [entity], fixes: fixes