diff --git a/modules/presets/collection.js b/modules/presets/collection.js index df87d8430..3f4715b01 100644 --- a/modules/presets/collection.js +++ b/modules/presets/collection.js @@ -65,10 +65,21 @@ export function presetCollection(collection) { return index === 0; } - function sortPresets(nameProp) { + function sortPresets(nameProp, aliasesProp) { return function sortNames(a, b) { let aCompare = a[nameProp](); let bCompare = b[nameProp](); + if (aliasesProp) { + // also search in aliases + const findMatchingAlias = strings => { + if (strings.some(s => s === value)) + return strings.find(s => s === value); + else + return strings.find(s => s.includes(value)); + } + aCompare = findMatchingAlias([aCompare].concat(a[aliasesProp]())); + bCompare = findMatchingAlias([bCompare].concat(b[aliasesProp]())); + } // priority if search string matches preset name exactly - #4325 if (value === aCompare) return -1; @@ -99,7 +110,7 @@ export function presetCollection(collection) { // matches value to preset.name const leadingNames = searchable .filter(a => leading(a.searchName()) || a.searchAliases().some(leading)) - .sort(sortPresets('searchName')); + .sort(sortPresets('searchName', 'searchAliases')); // matches value to preset suggestion name const leadingSuggestions = suggestions @@ -108,7 +119,7 @@ export function presetCollection(collection) { const leadingNamesStripped = searchable .filter(a => leading(a.searchNameStripped()) || a.searchAliasesStripped().some(leading)) - .sort(sortPresets('searchNameStripped')); + .sort(sortPresets('searchNameStripped', 'searchAliasesStripped')); const leadingSuggestionsStripped = suggestions .filter(a => leadingStrict(a.searchNameStripped())) diff --git a/modules/presets/preset.js b/modules/presets/preset.js index 15de0317d..65f983780 100644 --- a/modules/presets/preset.js +++ b/modules/presets/preset.js @@ -28,7 +28,7 @@ export function presetPreset(presetID, preset, addable, allFields, allPresets) { _this.originalName = _this.name || ''; - _this.originalAliases = _this.aliases || ''; + _this.originalAliases = (_this.aliases || []).join('\n'); _this.originalScore = _this.matchScore || 1; @@ -126,12 +126,10 @@ export function presetPreset(presetID, preset, addable, allFields, allPresets) { return null; }; - _this.aliases = () => { - return _this.t('aliases', { 'default': _this.originalAliases }).trim().split(/\s*\n\s*/); + return _this.t('aliases', { 'default': _this.originalAliases }).trim().split(/\s*[\r\n]+\s*/); }; - _this.terms = () => _this.t('terms', { 'default': _this.originalTerms }) .toLowerCase().trim().split(/\s*,+\s*/); diff --git a/test/spec/presets/collection.js b/test/spec/presets/collection.js index 298a37e69..b2cb84e85 100644 --- a/test/spec/presets/collection.js +++ b/test/spec/presets/collection.js @@ -28,7 +28,7 @@ describe('iD.presetCollection', function() { { name: 'Ğṝȁß', tags: { landuse: 'ğṝȁß' }, geometry: ['point', 'area'], terms: [] } ), park: iD.presetPreset('__TEST/leisure/park', - { name: 'Park', tags: { leisure: 'park' }, geometry: ['point', 'area'], terms: [ 'grass' ], matchScore: 0.5 } + { name: 'Park', tags: { leisure: 'park' }, geometry: ['point', 'area'], aliases: ['Field'], terms: [ 'grass' ], matchScore: 0.5 } ), parking: iD.presetPreset('__TEST/amenity/parking', { name: 'Parking', tags: { amenity: 'parking' }, geometry: ['point', 'area'], terms: [ 'cars' ] } @@ -86,6 +86,11 @@ describe('iD.presetCollection', function() { expect(result.indexOf(p.park), 'Park').to.be.within(3,5); // 6. 'Park' (similar term 'grass') }); + it('matches alias', function() { + var result = c.search('Field', 'area').collection; + expect(result.indexOf(p.park)).to.eql(0); // 1. 'Park' (by alias) + }); + it('sorts preset with matchScore penalty below others', function() { var result = c.search('par', 'point').matchGeometry('point').collection; expect(result.indexOf(p.parking), 'Parking').to.eql(0); // 1. 'Parking' (default matchScore)