diff --git a/modules/osm/index.js b/modules/osm/index.js index b225beaac..755b7d91c 100644 --- a/modules/osm/index.js +++ b/modules/osm/index.js @@ -35,6 +35,8 @@ export { osmOneWayTags, osmPavedTags, osmIsInterestingTag, + osmLifecyclePrefixes, + osmRemoveLifecyclePrefix, osmRoutableHighwayTagValues, osmFlowingWaterwayTagValues, osmRailwayTrackTagValues diff --git a/modules/osm/tags.js b/modules/osm/tags.js index 48e9dcffa..731873286 100644 --- a/modules/osm/tags.js +++ b/modules/osm/tags.js @@ -8,6 +8,33 @@ export function osmIsInterestingTag(key) { key.indexOf('tiger:') !== 0; } +export const osmLifecyclePrefixes = { + // nonexistent, might be built + proposed: true, planned: true, + // under maintentance or between groundbreaking and opening + construction: true, + // existent but not functional + disused: true, + // dilapidated to nonexistent + abandoned: true, was: true, + // nonexistent, still may appear in imagery + dismantled: true, razed: true, demolished: true, destroyed: true, removed: true, obliterated: true, + // existent occasionally, e.g. stormwater drainage basin + intermittent: true +}; + +/** @param {string} key */ +export function osmRemoveLifecyclePrefix(key) { + const keySegments = key.split(':'); + if (keySegments.length === 1) return key; + + if (keySegments[0] in osmLifecyclePrefixes) { + return key.slice(keySegments[0].length + 1); + } + + return key; +} + export var osmAreaKeys = {}; export function osmSetAreaKeys(value) { osmAreaKeys = value; @@ -44,13 +71,14 @@ export function osmTagSuggestingArea(tags) { if (tags.area === 'no') return null; var returnTags = {}; - for (var key in tags) { + for (var realKey in tags) { + const key = osmRemoveLifecyclePrefix(realKey); if (key in osmAreaKeys && !(tags[key] in osmAreaKeys[key])) { - returnTags[key] = tags[key]; + returnTags[realKey] = tags[realKey]; return returnTags; } if (key in osmAreaKeysExceptions && tags[key] in osmAreaKeysExceptions[key]) { - returnTags[key] = tags[key]; + returnTags[realKey] = tags[realKey]; return returnTags; } } diff --git a/modules/renderer/features.js b/modules/renderer/features.js index a0b0f74e5..453faeb0a 100644 --- a/modules/renderer/features.js +++ b/modules/renderer/features.js @@ -1,7 +1,7 @@ import { dispatch as d3_dispatch } from 'd3-dispatch'; import { prefs } from '../core/preferences'; -import { osmEntity } from '../osm'; +import { osmEntity, osmLifecyclePrefixes } from '../osm'; import { utilRebind } from '../util/rebind'; import { utilArrayGroupBy, utilArrayUnion, utilQsString, utilStringQs } from '../util'; @@ -42,17 +42,6 @@ export function rendererFeatures(context) { 'pedestrian': true }; - var past_futures = { - 'proposed': true, - 'construction': true, - 'abandoned': true, - 'dismantled': true, - 'disused': true, - 'razed': true, - 'demolished': true, - 'obliterated': true - }; - var _cullFactor = 1; var _cache = {}; var _rules = {}; @@ -210,7 +199,7 @@ export function rendererFeatures(context) { for (var i = 0; i < strings.length; i++) { var s = strings[i]; - if (past_futures[s] || past_futures[tags[s]]) { return true; } + if (osmLifecyclePrefixes[s] || osmLifecyclePrefixes[tags[s]]) return true; } return false; }); diff --git a/modules/svg/tag_classes.js b/modules/svg/tag_classes.js index 61b4c7e0c..e358e9903 100644 --- a/modules/svg/tag_classes.js +++ b/modules/svg/tag_classes.js @@ -1,5 +1,5 @@ import { select as d3_select } from 'd3-selection'; -import { osmPathHighwayTagValues, osmPavedTags, osmSemipavedTags } from '../osm/tags'; +import { osmPathHighwayTagValues, osmPavedTags, osmSemipavedTags, osmLifecyclePrefixes } from '../osm/tags'; export function svgTagClasses() { @@ -9,20 +9,7 @@ export function svgTagClasses() { 'leisure', 'military', 'place', 'man_made', 'route', 'attraction', 'building:part', 'indoor' ]; - var statuses = [ - // nonexistent, might be built - 'proposed', 'planned', - // under maintentance or between groundbreaking and opening - 'construction', - // existent but not functional - 'disused', - // dilapidated to nonexistent - 'abandoned', - // nonexistent, still may appear in imagery - 'dismantled', 'razed', 'demolished', 'obliterated', - // existent occasionally, e.g. stormwater drainage basin - 'intermittent' - ]; + var statuses = Object.keys(osmLifecyclePrefixes); var secondaries = [ 'oneway', 'bridge', 'tunnel', 'embankment', 'cutting', 'barrier', 'surface', 'tracktype', 'footway', 'crossing', 'service', 'sport', diff --git a/test/spec/osm/tags.js b/test/spec/osm/tags.js new file mode 100644 index 000000000..ae9d9c5f9 --- /dev/null +++ b/test/spec/osm/tags.js @@ -0,0 +1,23 @@ +describe('iD.osmRemoveLifecyclePrefix', function () { + it('removes the lifecycle prefix from a tag key', function () { + expect(iD.osmRemoveLifecyclePrefix('was:natural')).to.equal('natural'); + expect(iD.osmRemoveLifecyclePrefix('destroyed:seamark:type')).to.equal('seamark:type'); + }); + + it('ignores invalid lifecycle prefixes', function () { + expect(iD.osmRemoveLifecyclePrefix('ex:leisure')).to.equal('ex:leisure'); + }); +}); + + +describe('osmTagSuggestingArea', function () { + beforeEach(function () { + iD.osmSetAreaKeys({ leisure: {} }); + }); + + it('handles features with a lifecycle prefixes', function () { + expect(iD.osmTagSuggestingArea({ leisure: 'stadium' })).to.eql({ leisure: 'stadium' }); + expect(iD.osmTagSuggestingArea({ 'disused:leisure': 'stadium' })).to.eql({ 'disused:leisure': 'stadium' }); + expect(iD.osmTagSuggestingArea({ 'ex:leisure': 'stadium' })).to.be.null; + }); +});