From 0edd10001e3710794902095833c3e7818269edaf Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Wed, 27 Mar 2019 13:31:32 -0400 Subject: [PATCH] Removing more lodash: isEmpty, isNumber, some map/reduce/forEach (re: #6087) --- build_data.js | 64 ++++++++++++++++----------------- data/update_locales.js | 5 ++- modules/core/context.js | 14 ++++---- modules/core/history.js | 29 ++++++++------- modules/services/maprules.js | 6 ++-- modules/services/osm.js | 20 ++++++----- modules/svg/data.js | 10 +++--- modules/svg/mapillary_images.js | 4 +-- modules/ui/entity_editor.js | 4 +-- 9 files changed, 80 insertions(+), 76 deletions(-) diff --git a/build_data.js b/build_data.js index b7374586a..a399a0a24 100644 --- a/build_data.js +++ b/build_data.js @@ -1,10 +1,6 @@ /* eslint-disable no-console */ const requireESM = require('esm')(module); -const _cloneDeep = requireESM('lodash-es/cloneDeep').default; const _forEach = requireESM('lodash-es/forEach').default; -const _isEmpty = requireESM('lodash-es/isEmpty').default; -const _merge = requireESM('lodash-es/merge').default; -const _toPairs = requireESM('lodash-es/toPairs').default; const colors = require('colors/safe'); const fs = require('fs'); @@ -243,7 +239,7 @@ function suggestionsToPresets(presets) { name: name, icon: preset.icon, geometry: preset.geometry, - tags: _merge({}, preset.tags, wikidataTag), + tags: Object.assign({}, preset.tags, wikidataTag), addTags: suggestion.tags, removeTags: suggestion.tags, reference: preset.reference, @@ -285,34 +281,33 @@ function generatePresets(tstrings, faIcons) { } }); - presets = _merge(presets, suggestionsToPresets(presets)); + presets = Object.assign(presets, suggestionsToPresets(presets)); return presets; } function generateTranslations(fields, presets, tstrings) { - var translations = _cloneDeep(tstrings); + var translations = JSON.parse(JSON.stringify(tstrings)); // deep clone _forEach(translations.fields, function(field, id) { var f = fields[id]; + var options = field.options || {}; + var optkeys = Object.keys(options); + if (f.keys) { - field['label#'] = _forEach(f.keys).map(function(key) { return key + '=*'; }).join(', '); - if (!_isEmpty(field.options)) { - _forEach(field.options, function(v,k) { - if (id === 'access') { - field.options[k]['title#'] = field.options[k]['description#'] = 'access=' + k; - } else { - field.options[k + '#'] = k + '=yes'; - } - }); - } + field['label#'] = f.keys.map(function(k) { return k + '=*'; }).join(', '); + optkeys.forEach(function(k) { + if (id === 'access') { + options[k]['title#'] = options[k]['description#'] = 'access=' + k; + } else { + options[k + '#'] = k + '=yes'; + } + }); } else if (f.key) { field['label#'] = f.key + '=*'; - if (!_isEmpty(field.options)) { - _forEach(field.options, function(v,k) { - field.options[k + '#'] = f.key + '=' + k; - }); - } + optkeys.forEach(function(k) { + options[k + '#'] = f.key + '=' + k; + }); } if (f.placeholder) { @@ -322,11 +317,16 @@ function generateTranslations(fields, presets, tstrings) { _forEach(translations.presets, function(preset, id) { var p = presets[id]; - if (!_isEmpty(p.tags)) - preset['name#'] = _toPairs(p.tags).map(function(pair) { return pair[0] + '=' + pair[1]; }).join(', '); + var tags = p.tags || {}; + var keys = Object.keys(tags); + + if (keys.length) { + preset['name#'] = keys.map(function(k) { return k + '=' + tags[k]; }).join(', '); + } if (p.searchable !== false) { - if (p.terms && p.terms.length) + if (p.terms && p.terms.length) { preset['terms#'] = 'terms: ' + p.terms.join(); + } preset.terms = ''; } else { delete preset.terms; @@ -612,13 +612,13 @@ function writeEnJson(tstrings) { var core = YAML.load(data[0]); var imagery = YAML.load(data[1]); var community = YAML.load(data[2]); - var en = _merge( - core, - { en: { presets: tstrings } }, - imagery, - { en: { community: community.en } } - ); - return writeFileProm('dist/locales/en.json', JSON.stringify(en, null, 4)); + + var enjson = core; + enjson.en.presets = tstrings; + enjson.en.imagery = imagery.en.imagery; + enjson.en.community = community.en; + + return writeFileProm('dist/locales/en.json', JSON.stringify(enjson, null, 4)); }); } diff --git a/data/update_locales.js b/data/update_locales.js index 106b38e4f..a88584acd 100644 --- a/data/update_locales.js +++ b/data/update_locales.js @@ -1,7 +1,6 @@ /* Downloads the latest translations from Transifex */ const requireESM = require('esm')(module); -const _isEmpty = requireESM('lodash-es/isEmpty').default; const _merge = requireESM('lodash-es/merge').default; const fs = require('fs'); @@ -50,7 +49,7 @@ asyncMap(resources, getResource, function(err, results) { asyncMap(Object.keys(locale), function(code, done) { - if (code === 'en' || _isEmpty(locale[code])) { + if (code === 'en' || !Object.keys(locale[code]).length) { done(); } else { var obj = {}; @@ -104,7 +103,7 @@ function getResource(resource, callback) { preset.terms = preset.terms.replace(/<.*>/, '').trim(); if (!preset.terms) { delete preset.terms; - if (_isEmpty(preset)) { + if (!Object.keys(preset).length) { delete presets[key]; } } diff --git a/modules/core/context.js b/modules/core/context.js index dffe15a9d..a9acf4d8f 100644 --- a/modules/core/context.js +++ b/modules/core/context.js @@ -1,9 +1,6 @@ import _cloneDeep from 'lodash-es/cloneDeep'; import _debounce from 'lodash-es/debounce'; -import _each from 'lodash-es/each'; import _forOwn from 'lodash-es/forOwn'; -import _isObject from 'lodash-es/isObject'; -import _isString from 'lodash-es/isString'; import { dispatch as d3_dispatch } from 'd3-dispatch'; import { json as d3_json } from 'd3-request'; @@ -42,9 +39,9 @@ export function coreContext() { function traverser(v, k, obj) { parents.push(k); - if (_isObject(v)) { + if (typeof v === 'object') { _forOwn(v, traverser); - } else if (_isString(v)) { + } else if (typeof v === 'string') { obj[k] = parents.join('.'); } parents.pop(); @@ -434,7 +431,7 @@ export function coreContext() { /* reset (aka flush) */ context.reset = context.flush = function() { context.debouncedSave.cancel(); - _each(services, function(service) { + Object.values(services).forEach(function(service) { if (service && typeof service.reset === 'function') { service.reset(context); } @@ -513,7 +510,7 @@ export function coreContext() { d3_json(maprules, function (err, mapcss) { if (err) return; services.maprules.init(); - _each(mapcss, function(mapcssSelector) { + mapcss.forEach(function(mapcssSelector) { return services.maprules.addRule(mapcssSelector); }); }); @@ -529,7 +526,7 @@ export function coreContext() { context.zoomOutFurther = map.zoomOutFurther; context.redrawEnable = map.redrawEnable; - _each(services, function(service) { + Object.values(services).forEach(function(service) { if (service && typeof service.init === 'function') { service.init(context); } @@ -538,6 +535,7 @@ export function coreContext() { background.init(); features.init(); photos.init(); + if (utilStringQs(window.location.hash).presets) { var external = utilStringQs(window.location.hash).presets; presets.fromExternal(external, function(externalPresets) { diff --git a/modules/core/history.js b/modules/core/history.js index 5598cc623..ab941b1de 100644 --- a/modules/core/history.js +++ b/modules/core/history.js @@ -1,9 +1,7 @@ import _cloneDeep from 'lodash-es/cloneDeep'; import _cloneDeepWith from 'lodash-es/cloneDeepWith'; import _groupBy from 'lodash-es/groupBy'; -import _isEmpty from 'lodash-es/isEmpty'; import _forEach from 'lodash-es/forEach'; -import _map from 'lodash-es/map'; import { dispatch as d3_dispatch } from 'd3-dispatch'; import { easeLinear as d3_easeLinear } from 'd3-ease'; @@ -128,7 +126,8 @@ export function coreHistory(context) { merge: function(entities, extent) { - _stack[0].graph.rebase(entities, _map(_stack, 'graph'), false); + var stack = _stack.map(function(state) { return state.graph; }); + _stack[0].graph.rebase(entities, stack, false); _tree.rebase(entities, false); dispatch.call('change', this, undefined, extent); @@ -494,7 +493,8 @@ export function coreHistory(context) { // the _stack even if the current _stack doesn't have them (for // example when iD has been restarted in a different region) var baseEntities = h.baseEntities.map(function(d) { return osmEntity(d); }); - _stack[0].graph.rebase(baseEntities, _map(_stack, 'graph'), true); + var stack = _stack.map(function(state) { return state.graph; }); + _stack[0].graph.rebase(baseEntities, stack, true); _tree.rebase(baseEntities, true); // When we restore a modified way, we also need to fetch any missing @@ -508,7 +508,7 @@ export function coreHistory(context) { var missing = nodeIDs .filter(function(n) { return !_stack[0].graph.hasEntity(n); }); - if (!_isEmpty(missing) && osm) { + if (missing.length && osm) { loadComplete = false; context.redrawEnable(false); @@ -517,20 +517,25 @@ export function coreHistory(context) { var childNodesLoaded = function(err, result) { if (!err) { - var visible = _groupBy(result.data, 'visible'); - if (!_isEmpty(visible.true)) { - missing = utilArrayDifference(missing, _map(visible.true, 'id')); - _stack[0].graph.rebase(visible.true, _map(_stack, 'graph'), true); - _tree.rebase(visible.true, true); + var visibleGroups = _groupBy(result.data, 'visible'); + var visibles = visibleGroups.true || []; // alive nodes + var invisibles = visibleGroups.false || []; // deleted nodes + + if (visibles.length) { + var visibleIDs = visibles.map(function(entity) { return entity.id; }); + var stack = _stack.map(function(state) { return state.graph; }); + missing = utilArrayDifference(missing, visibleIDs); + _stack[0].graph.rebase(visibles, stack, true); + _tree.rebase(visibles, true); } // fetch older versions of nodes that were deleted.. - _forEach(visible.false, function(entity) { + invisibles.forEach(function(entity) { osm.loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded); }); } - if (err || _isEmpty(missing)) { + if (err || !missing.length) { loading.close(); context.redrawEnable(true); dispatch.call('change'); diff --git a/modules/services/maprules.js b/modules/services/maprules.js index 37544046d..3350eb427 100644 --- a/modules/services/maprules.js +++ b/modules/services/maprules.js @@ -1,5 +1,4 @@ import _isMatch from 'lodash-es/isMatch'; -import _reduce from 'lodash-es/reduce'; import { areaKeys } from '../core/context'; import { utilArrayIntersection } from '../util'; @@ -108,7 +107,7 @@ export default { // list of rules only relevant to tag checks... filterRuleChecks: function(selector) { var _ruleChecks = this._ruleChecks; - return _reduce(Object.keys(selector), function(rules, key) { + return Object.keys(selector).reduce(function(rules, key) { if (['geometry', 'error', 'warning'].indexOf(key) === -1) { rules.push(_ruleChecks[key](selector[key])); } @@ -124,8 +123,7 @@ export default { }); }; - var selectorKeys = Object.keys(selector); - var tagMap = _reduce(selectorKeys, function (expectedTags, key) { + var tagMap = Object.keys(selector).reduce(function (expectedTags, key) { var values; var isRegex = /regex/gi.test(key); var isEqual = /equals/gi.test(key); diff --git a/modules/services/osm.js b/modules/services/osm.js index c76aa6065..1bcd0f082 100644 --- a/modules/services/osm.js +++ b/modules/services/osm.js @@ -2,8 +2,6 @@ import _chunk from 'lodash-es/chunk'; import _cloneDeep from 'lodash-es/cloneDeep'; import _forEach from 'lodash-es/forEach'; import _groupBy from 'lodash-es/groupBy'; -import _isEmpty from 'lodash-es/isEmpty'; -import _map from 'lodash-es/map'; import _throttle from 'lodash-es/throttle'; import rbush from 'rbush'; @@ -513,11 +511,11 @@ export default { var that = this; _forEach(_groupBy(utilArrayUniq(ids), osmEntity.id.type), function(v, k) { - var type = k + 's'; - var osmIDs = _map(v, osmEntity.id.toOSM); + var type = k + 's'; // nodes, ways, relations + var osmIDs = v.map(function(id) { return osmEntity.id.toOSM(id); }); var options = { skipSeen: false }; - _forEach(_chunk(osmIDs, 150), function(arr) { + _chunk(osmIDs, 150).forEach(function(arr) { that.loadFromAPI( '/api/0.6/' + type + '?' + type + '=' + arr.join(), function(err, entities) { @@ -783,16 +781,16 @@ export default { var tiles = tiler.zoomExtent([_tileZoom, _tileZoom]).getTiles(projection); // abort inflight requests that are no longer needed - var hadRequests = !_isEmpty(_tileCache.inflight); + var hadRequests = hasInflightRequests(); abortUnwantedRequests(_tileCache, tiles); - if (hadRequests && _isEmpty(_tileCache.inflight)) { + if (hadRequests && !hasInflightRequests()) { dispatch.call('loaded'); // stop the spinner } // issue new requests.. tiles.forEach(function(tile) { if (_tileCache.loaded[tile.id] || _tileCache.inflight[tile.id]) return; - if (_isEmpty(_tileCache.inflight)) { + if (!hasInflightRequests()) { dispatch.call('loading'); // start the spinner } @@ -807,13 +805,17 @@ export default { if (callback) { callback(err, Object.assign({ data: parsed }, tile)); } - if (_isEmpty(_tileCache.inflight)) { + if (!hasInflightRequests()) { dispatch.call('loaded'); // stop the spinner } }, options ); }); + + function hasInflightRequests() { + return Object.keys(_tileCache.inflight).length; + } }, diff --git a/modules/svg/data.js b/modules/svg/data.js index 5f2886e16..ec53f5aef 100644 --- a/modules/svg/data.js +++ b/modules/svg/data.js @@ -1,5 +1,4 @@ import _flatten from 'lodash-es/flatten'; -import _isEmpty from 'lodash-es/isEmpty'; import _throttle from 'lodash-es/throttle'; import { @@ -345,7 +344,8 @@ export function svgData(projection, context, dispatch) { break; } - if (!_isEmpty(gj)) { + gj = gj || {}; + if (Object.keys(gj).length) { _geojson = ensureIDs(gj); _src = extension + ' data file'; this.fitZoom(); @@ -380,7 +380,8 @@ export function svgData(projection, context, dispatch) { drawData.hasData = function() { - return !!(_template || !_isEmpty(_geojson)); + var gj = _geojson || {}; + return !!(_template || Object.keys(gj).length); }; @@ -434,7 +435,8 @@ export function svgData(projection, context, dispatch) { _geojson = null; _src = null; - if (!_isEmpty(gj)) { + gj = gj || {}; + if (Object.keys(gj).length) { _geojson = ensureIDs(gj); _src = src || 'unknown.geojson'; } diff --git a/modules/svg/mapillary_images.js b/modules/svg/mapillary_images.js index 188183d31..3367139e6 100644 --- a/modules/svg/mapillary_images.js +++ b/modules/svg/mapillary_images.js @@ -1,5 +1,5 @@ import _throttle from 'lodash-es/throttle'; -import _isNumber from 'lodash-es/isNumber'; + import { select as d3_select } from 'd3-selection'; import { svgPath, svgPointTransform } from './index'; import { services } from '../services'; @@ -111,7 +111,7 @@ export function svgMapillaryImages(projection, context, dispatch) { function transform(d) { var t = svgPointTransform(projection)(d); - if (d.pano && _isNumber(viewerCompassAngle)) { + if (d.pano && viewerCompassAngle !== null && isFinite(viewerCompassAngle)) { t += ' rotate(' + Math.floor(viewerCompassAngle) + ',0,0)'; } else if (d.ca) { t += ' rotate(' + Math.floor(d.ca) + ',0,0)'; diff --git a/modules/ui/entity_editor.js b/modules/ui/entity_editor.js index 330a776b5..d32f46e72 100644 --- a/modules/ui/entity_editor.js +++ b/modules/ui/entity_editor.js @@ -1,4 +1,3 @@ -import _isEmpty from 'lodash-es/isEmpty'; import _isEqual from 'lodash-es/isEqual'; import { dispatch as d3_dispatch } from 'd3-dispatch'; @@ -254,7 +253,8 @@ export function uiEntityEditor(context) { var match = context.presets().match(entity, graph); var activePreset = entityEditor.preset(); - var weakPreset = activePreset && _isEmpty(activePreset.addTags); + var weakPreset = activePreset && + Object.keys(activePreset.addTags || {}).length === 0; // A "weak" preset doesn't set any tags. (e.g. "Address") // Don't replace a weak preset with a fallback preset (e.g. "Point")