Extract tag cleaning code to utilCleanTags, add tests

(closes #4925)
This commit is contained in:
Bryan Housel
2018-03-22 14:45:37 -04:00
parent c44551be77
commit c08d79e488
5 changed files with 122 additions and 47 deletions
+2 -47
View File
@@ -20,7 +20,7 @@ import { uiRawMembershipEditor } from './raw_membership_editor';
import { uiRawTagEditor } from './raw_tag_editor';
import { uiTagReference } from './tag_reference';
import { uiPresetEditor } from './preset_editor';
import { utilRebind } from '../util';
import { utilCleanTags, utilRebind } from '../util';
export function uiEntityEditor(context) {
@@ -213,51 +213,6 @@ export function uiEntityEditor(context) {
}
function clean(orig) {
function cleanVal(k, v) {
function keepSpaces(k) {
return /_hours|_times|:conditional$/.test(k);
}
function skip(k) {
return /^(description|note|fixme)$/.test(k);
}
if (skip(k)) return v;
var cleaned = v
.split(';')
.map(function(s) { return s.trim(); })
.join(keepSpaces(k) ? '; ' : ';');
// The code below is not intended to validate websites and emails.
// It is only intended to prevent obvious copy-paste errors. (#2323)
// clean website- and email-like tags
if (k.indexOf('website') !== -1 ||
k.indexOf('email') !== -1 ||
cleaned.indexOf('http') === 0) {
cleaned = cleaned
.replace(/[\u200B-\u200F\uFEFF]/g, ''); // strip LRM and other zero width chars
}
return cleaned;
}
var out = {};
for (var k in orig) {
if (!k) continue;
var v = orig[k];
if (v !== undefined) {
out[k] = cleanVal(k, v);
}
}
return out;
}
// Tag changes that fire on input can all get coalesced into a single
// history operation when the user leaves the field. #2342
function changeTags(changed, onInput) {
@@ -274,7 +229,7 @@ export function uiEntityEditor(context) {
}
if (!onInput) {
tags = clean(tags);
tags = utilCleanTags(tags);
}
if (!_isEqual(entity.tags, tags)) {
+43
View File
@@ -0,0 +1,43 @@
export function utilCleanTags(tags) {
var out = {};
for (var k in tags) {
if (!k) continue;
var v = tags[k];
if (v !== undefined) {
out[k] = cleanValue(k, v);
}
}
return out;
function cleanValue(k, v) {
function keepSpaces(k) {
return /_hours|_times|:conditional$/.test(k);
}
function skip(k) {
return /^(description|note|fixme)$/.test(k);
}
if (skip(k)) return v;
var cleaned = v
.split(';')
.map(function(s) { return s.trim(); })
.join(keepSpaces(k) ? '; ' : ';');
// The code below is not intended to validate websites and emails.
// It is only intended to prevent obvious copy-paste errors. (#2323)
// clean website- and email-like tags
if (k.indexOf('website') !== -1 ||
k.indexOf('email') !== -1 ||
cleaned.indexOf('http') === 0) {
cleaned = cleaned
.replace(/[\u200B-\u200F\uFEFF]/g, ''); // strip LRM and other zero width chars
}
return cleaned;
}
}
+1
View File
@@ -1,5 +1,6 @@
export { utilAsyncMap } from './util';
export { utilCallWhenIdle } from './call_when_idle';
export { utilCleanTags } from './clean_tags';
export { utilDisplayName } from './util';
export { utilDisplayNameForPath } from './util';
export { utilDisplayType } from './util';
+1
View File
@@ -129,6 +129,7 @@
<script src='spec/ui/fields/localized.js'></script>
<script src='spec/ui/fields/wikipedia.js'></script>
<script src='spec/util/clean_tags.js'></script>
<script src='spec/util/session_mutex.js'></script>
<script src='spec/util/suggest_names.js'></script>
<script src='spec/util/util.js'></script>
+75
View File
@@ -0,0 +1,75 @@
describe('iD.utilCleanTags', function() {
it('handles empty tags object', function() {
var t = {};
var result = iD.utilCleanTags(t);
expect(result).to.eql({});
});
it('discards empty keys', function() {
var t = { '': 'bar' };
var result = iD.utilCleanTags(t);
expect(result).to.eql({});
});
it('discards undefined values', function() {
var t = { 'foo': undefined };
var result = iD.utilCleanTags(t);
expect(result).to.eql({});
});
it('trims whitespace', function() {
var t = {
'leading': ' value',
'trailing': 'value ',
'both': ' value '
};
var result = iD.utilCleanTags(t);
expect(result).to.eql({
'leading': 'value',
'trailing': 'value',
'both': 'value'
});
});
it('trims semicolon delimited whitespace', function() {
var t = {
'leading': ' value1; value2',
'trailing': 'value1 ;value2 ',
'both': ' value1 ; value2 '
};
var result = iD.utilCleanTags(t);
expect(result).to.eql({
'leading': 'value1;value2',
'trailing': 'value1;value2',
'both': 'value1;value2'
});
});
it('does not clean description, note, fixme', function() {
var t = {
'description': ' value',
'note': 'value ',
'fixme': ' value '
};
var result = iD.utilCleanTags(t);
expect(result).to.eql(t);
});
it('uses semicolon-space delimiting for opening_hours, conditional: tags', function() {
var t = {
'opening_hours': ' Mo-Su 08:00-18:00 ;Apr 10-15 off;Jun 08:00-14:00 ; Aug off; Dec 25 off ',
'collection_times': ' Mo 10:00-12:00,12:30-15:00 ;Tu-Fr 08:00-12:00,12:30-15:00;Sa 08:00-12:00 ',
'maxspeed:conditional': ' 120 @ (06:00-20:00) ;80 @ wet ',
'restriction:conditional': ' no_u_turn @ (Mo-Fr 09:00-10:00,15:00-16:00;SH off) '
};
var result = iD.utilCleanTags(t);
expect(result).to.eql({
'opening_hours': 'Mo-Su 08:00-18:00; Apr 10-15 off; Jun 08:00-14:00; Aug off; Dec 25 off',
'collection_times': 'Mo 10:00-12:00,12:30-15:00; Tu-Fr 08:00-12:00,12:30-15:00; Sa 08:00-12:00',
'maxspeed:conditional': '120 @ (06:00-20:00); 80 @ wet',
'restriction:conditional': 'no_u_turn @ (Mo-Fr 09:00-10:00,15:00-16:00; SH off)'
});
});
});