X-Git-Url: https://git.openstreetmap.org/rails.git/blobdiff_plain/ca92fe3359ce2a751763b1bb0bfe824a89b20853..8a1298df6bfa53337aed01435337a7a9cf1cdf31:/vendor/assets/iD/iD.js?ds=sidebyside diff --git a/vendor/assets/iD/iD.js b/vendor/assets/iD/iD.js index 6cc200808..c3bc0c3eb 100644 --- a/vendor/assets/iD/iD.js +++ b/vendor/assets/iD/iD.js @@ -1,6 +1,10 @@ (function () { var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + function getDefaultExportFromCjs (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; + } + function createCommonjsModule(fn, basedir, module) { return module = { path: basedir, @@ -11,10 +15,6 @@ }, fn(module, module.exports), module.exports; } - function getCjsExportFromNamespace (n) { - return n && n['default'] || n; - } - function commonjsRequire () { throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs'); } @@ -18330,7 +18330,7 @@ if (_loadPromise) { return _loadPromise; } return _loadPromise = Promise.all([ - // load the list of langauges + // load the list of languages _mainFileFetcher.get('languages'), // load the list of supported locales _mainFileFetcher.get('locales') @@ -18506,7 +18506,7 @@ localizer.languageName = function (code, options) { - if (_languageNames[code]) { // name in locale langauge + if (_languageNames[code]) { // name in locale language // e.g. "German" return _languageNames[code]; } @@ -18521,9 +18521,9 @@ return localizer.t('translate.language_and_code', { language: langInfo.nativeName, code: code }); } else if (langInfo.base && langInfo.script) { - var base = langInfo.base; // the code of the langauge this is based on + var base = langInfo.base; // the code of the language this is based on - if (_languageNames[base]) { // base language name in locale langauge + if (_languageNames[base]) { // base language name in locale language var scriptCode = langInfo.script; var script = _scriptNames[scriptCode] || scriptCode; // e.g. "Serbian (Cyrillic)" @@ -18857,7 +18857,7 @@ if (_this.suggestion) { var path = presetID.split('/'); path.pop(); // remove brand name - // NOTE: insert an en-dash, not a hypen (to avoid conflict with fr - nl names in Brussels etc) + // NOTE: insert an en-dash, not a hyphen (to avoid conflict with fr - nl names in Brussels etc) return _this.originalName + ' – ' + _t('presets.presets.' + path.join('/') + '.name'); } return _this.t('name', { 'default': _this.originalName }); @@ -18881,7 +18881,7 @@ }; - _this.reference = function (geom) { + _this.reference = function () { // Lookup documentation on Wikidata... var qid = _this.tags.wikidata || _this.tags['brand:wikidata'] || _this.tags['operator:wikidata']; if (qid) { @@ -18892,15 +18892,6 @@ var key = _this.originalReference.key || Object.keys(utilObjectOmit(_this.tags, 'name'))[0]; var value = _this.originalReference.value || _this.tags[key]; - if (geom === 'relation' && key === 'type') { - if (value in _this.tags) { - key = value; - value = _this.tags[key]; - } else { - return { rtype: value }; - } - } - if (value === '*') { return { key: key }; } else { @@ -21869,7 +21860,7 @@ var sign = d3_polygonArea(points) > 0 ? 1 : -1; var ids, i, j, k; - // we need atleast two key nodes for the algorithm to work + // we need at least two key nodes for the algorithm to work if (!keyNodes.length) { keyNodes = [nodes[0]]; keyPoints = [points[0]]; @@ -21884,8 +21875,8 @@ } // key points and nodes are those connected to the ways, - // they are projected onto the circle, inbetween nodes are moved - // to constant intervals between key nodes, extra inbetween nodes are + // they are projected onto the circle, in between nodes are moved + // to constant intervals between key nodes, extra in between nodes are // added if necessary. for (i = 0; i < keyPoints.length; i++) { var nextKeyNodeIndex = (i + 1) % keyNodes.length; @@ -21948,7 +21939,7 @@ graph = graph.replace(node); } - // add new inbetween nodes if necessary + // add new in between nodes if necessary for (j = 0; j < numberNewPoints; j++) { angle = startAngle + (indexRange + j) * eachAngle; loc = projection.invert([ @@ -21976,7 +21967,7 @@ // Check for other ways that share these keyNodes.. // If keyNodes are adjacent in both ways, - // we can add inBetween nodes to that shared way too.. + // we can add inBetweenNodes to that shared way too.. if (indexRange === 1 && inBetweenNodes.length) { var startIndex1 = way.nodes.lastIndexOf(startNode.id); var endIndex1 = way.nodes.lastIndexOf(endNode.id); @@ -22168,7 +22159,7 @@ var action = function(graph) { ids.forEach(function(id) { - if (graph.hasEntity(id)) { // It may have been deleted aready. + if (graph.hasEntity(id)) { // It may have been deleted already. graph = actions[graph.entity(id).type](id)(graph); } }); @@ -22579,7 +22570,7 @@ }; } - // Disconect the ways at the given node. + // Disconnect the ways at the given node. // // Optionally, disconnect only the given ways. // @@ -22746,7 +22737,18 @@ extractedLoc = entity.extent(graph).center(); } - var isBuilding = entity.tags.building && entity.tags.building !== 'no'; + var indoorAreaValues = { + area: true, + corridor: true, + elevator: true, + level: true, + room: true + }; + + var isBuilding = (entity.tags.building && entity.tags.building !== 'no') || + (entity.tags['building:part'] && entity.tags['building:part'] !== 'no'); + + var isIndoorArea = fromGeometry === 'area' && entity.tags.indoor && indoorAreaValues[entity.tags.indoor]; var entityTags = Object.assign({}, entity.tags); // shallow copy var pointTags = {}; @@ -22767,6 +22769,10 @@ key.match(/^building:.{1,}/) || key.match(/^roof:.{1,}/)) { continue; } } + // leave `indoor` tag on the area + if (isIndoorArea && key === 'indoor') { + continue; + } // copy the tag from the entity to the point pointTags[key] = entityTags[key]; @@ -22775,13 +22781,16 @@ if (keysToCopyAndRetain.indexOf(key) !== -1 || key.match(/^addr:.{1,}/)) { continue; + } else if (isIndoorArea && key === 'level') { + // leave `level` on both features + continue; } // remove the tag from the entity delete entityTags[key]; } - if (!isBuilding && fromGeometry === 'area') { + if (!isBuilding && !isIndoorArea && fromGeometry === 'area') { // ensure that areas keep area geometry entityTags.area = 'yes'; } @@ -23684,7 +23693,7 @@ QAItem.prototype.update = function update (props) { var this$1 = this; - // You can't override this inital information + // You can't override this initial information var ref = this; var loc = ref.loc; var service = ref.service; @@ -28188,7 +28197,10 @@ // prevent operations during low zoom selection if (!context.map().withinEditableZoom()) { return; } + if (_operation.availableForKeypress && !_operation.availableForKeypress()) { return; } + event.preventDefault(); + var disabled = _operation.disabled(); if (disabled) { @@ -29435,7 +29447,6 @@ function behavior(selection) { - _pointerId = null; var matchesSelector = utilPrefixDOMProperty('matchesSelector'); var delegate = pointerdown; @@ -29801,7 +29812,7 @@ for (k = 0; k < rings.length; k++) { if (k === activeIndex) { continue; } - // make sure active ring doesnt cross passive rings + // make sure active ring doesn't cross passive rings if (geoHasLineIntersections(rings[activeIndex].nodes, rings[k].nodes, entity.id)) { return 'multipolygonRing'; } @@ -31149,7 +31160,7 @@ return _t(("QA.improveOSM.directions." + (compass[dir]))); } - // Errors shouldn't obscure eachother + // Errors shouldn't obscure each other function preventCoincident(loc, bumpUp) { var coincident = false; do { @@ -33837,7 +33848,7 @@ } } - // Issues shouldn't obscure eachother + // Issues shouldn't obscure each other function preventCoincident$1(loc) { var coincident = false; do { @@ -34878,7 +34889,7 @@ // // There is some logic here to batch up clicks into a _mlyClicks array // because the user might click on a lot of markers quickly and nodechanged - // may be called out of order asychronously. + // may be called out of order asynchronously. // // Clicks are added to the array in `selectedImage` and removed here. // @@ -39769,6 +39780,14 @@ return x.join('='); }).join(','), popup = window.open('about:blank', 'oauth_window', settings); + + oauth.popupWindow = popup; + + if (!popup) { + var error = new Error('Popup was blocked'); + error.status = 'popup-blocked'; + throw error; + } } // Request a request token. When this is complete, the popup @@ -39833,6 +39852,21 @@ } }; + oauth.bringPopupWindowToFront = function() { + var brougtPopupToFront = false; + try { + // This may cause a cross-origin error: + // `DOMException: Blocked a frame with origin "..." from accessing a cross-origin frame.` + if (oauth.popupWindow && !oauth.popupWindow.closed) { + oauth.popupWindow.focus(); + brougtPopupToFront = true; + } + } catch (err) { + // Bringing popup window to front failed (probably because of the cross-origin error mentioned above) + } + return brougtPopupToFront; + }; + oauth.bootstrapToken = function(oauth_token, callback) { // ## Getting an request token // At this point we have an `oauth_token`, brought in from a function @@ -40135,8 +40169,8 @@ loading: authLoading, done: authDone }); - - var _blacklists = ['.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*']; + // hardcode default block of Google Maps + var _imageryBlocklists = [/.*\.google(apis)?\..*\/(vt|kh)[\?\/].*([xyz]=.*){3}.*/]; var _tileCache = { toLoad: {}, loaded: {}, inflight: {}, seen: {}, rtree: new RBush() }; var _noteCache = { toLoad: {}, loaded: {}, inflight: {}, inflightPost: {}, note: {}, closed: {}, rtree: new RBush() }; var _userCache = { toLoad: {}, user: {} }; @@ -40309,11 +40343,11 @@ return new osmNode({ id: uid, visible: typeof obj.visible === 'boolean' ? obj.visible : true, - version: obj.version.toString(), - changeset: obj.changeset.toString(), + version: obj.version && obj.version.toString(), + changeset: obj.changeset && obj.changeset.toString(), timestamp: obj.timestamp, user: obj.user, - uid: obj.uid.toString(), + uid: obj.uid && obj.uid.toString(), loc: [parseFloat(obj.lon), parseFloat(obj.lat)], tags: obj.tags }); @@ -40323,11 +40357,11 @@ return new osmWay({ id: uid, visible: typeof obj.visible === 'boolean' ? obj.visible : true, - version: obj.version.toString(), - changeset: obj.changeset.toString(), + version: obj.version && obj.version.toString(), + changeset: obj.changeset && obj.changeset.toString(), timestamp: obj.timestamp, user: obj.user, - uid: obj.uid.toString(), + uid: obj.uid && obj.uid.toString(), tags: obj.tags, nodes: getNodesJSON(obj) }); @@ -40337,11 +40371,11 @@ return new osmRelation({ id: uid, visible: typeof obj.visible === 'boolean' ? obj.visible : true, - version: obj.version.toString(), - changeset: obj.changeset.toString(), + version: obj.version && obj.version.toString(), + changeset: obj.changeset && obj.changeset.toString(), timestamp: obj.timestamp, user: obj.user, - uid: obj.uid.toString(), + uid: obj.uid && obj.uid.toString(), tags: obj.tags, members: getMembersJSON(obj) }); @@ -41031,17 +41065,22 @@ return callback(err, null); } - // update blacklists + // update blocklists var elements = xml.getElementsByTagName('blacklist'); var regexes = []; for (var i = 0; i < elements.length; i++) { - var regex = elements[i].getAttribute('regex'); // needs unencode? - if (regex) { - regexes.push(regex); + var regexString = elements[i].getAttribute('regex'); // needs unencode? + if (regexString) { + try { + var regex = new RegExp(regexString); + regexes.push(regex); + } catch (e) { + /* noop */ + } } } if (regexes.length) { - _blacklists = regexes; + _imageryBlocklists = regexes; } if (_rateLimitError) { @@ -41061,7 +41100,7 @@ // Calls `status` and dispatches an `apiStatusChange` event if the returned // status differs from the cached status. reloadApiStatus: function() { - // throttle to avoid unncessary API calls + // throttle to avoid unnecessary API calls if (!this.throttledReloadApiStatus) { var that = this; this.throttledReloadApiStatus = throttle(function() { @@ -41433,8 +41472,8 @@ }, - imageryBlacklists: function() { - return _blacklists; + imageryBlocklists: function() { + return _imageryBlocklists; }, @@ -41608,7 +41647,6 @@ // { // key: 'string', // value: 'string', - // rtype: 'string', // langCode: 'string' // } // @@ -41617,7 +41655,7 @@ var that = this; var titles = []; var result = {}; - var rtypeSitelink = params.rtype ? ('Relation:' + params.rtype).replace(/_/g, ' ').trim() : false; + var rtypeSitelink = (params.key === 'type' && params.value) ? ('Relation:' + params.value).replace(/_/g, ' ').trim() : false; var keySitelink = params.key ? this.toSitelink(params.key) : false; var tagSitelink = (params.key && params.value) ? this.toSitelink(params.key, params.value) : false; var localeSitelink; @@ -41726,10 +41764,6 @@ // key: 'string', // required // value: 'string' // optional // } - // -or- - // { - // rtype: 'rtype' // relation type (e.g. 'multipolygon') - // } // // Get an result object used to display tag documentation // { @@ -44345,6 +44379,8 @@ } }); + var turf_bboxClip = /*@__PURE__*/getDefaultExportFromCjs(bboxClip_1); + var fastJsonStableStringify = function (data, opts) { if (!opts) { opts = {}; } if (typeof opts === 'function') { opts = { cmp: opts }; } @@ -47827,7 +47863,7 @@ // Clip to tile bounds if (geometry.type === 'MultiPolygon') { var isClipped = false; - var featureClip = bboxClip_1(feature, tile.extent.rectangle()); + var featureClip = turf_bboxClip(feature, tile.extent.rectangle()); if (!fastDeepEqual(feature.geometry, featureClip.geometry)) { // feature = featureClip; isClipped = true; @@ -48038,7 +48074,7 @@ type: 'item', // the language to search language: lang, - // the langauge for the label and description in the result + // the language for the label and description in the result uselang: lang, limit: 10, origin: '*' @@ -48429,7 +48465,10 @@ mainEnter .append('div') .attr('class', 'comment-text') - .html(function(d) { return d.html; }); + .html(function(d) { return d.html; }) + .selectAll('a') + .attr('rel', 'noopener nofollow') + .attr('target', '_blank'); comments .call(replaceAvatars); @@ -50119,17 +50158,13 @@ return section; } - // Pass `which` object of the form: + // Pass `what` object of the form: // { // key: 'string', // required // value: 'string' // optional // } // -or- // { - // rtype: 'string' // relation type (e.g. 'multipolygon') - // } - // -or- - // { // qid: 'string' // brand wikidata (e.g. 'Q37158') // } // @@ -50290,7 +50325,7 @@ tagReference.body = function(selection) { - var itemID = what.qid || what.rtype || (what.key + '-' + what.value); + var itemID = what.qid || (what.key + '-' + (what.value || '')); _body = selection.selectAll('.tag-reference-body') .data([itemID], function(d) { return d; }); @@ -50534,20 +50569,11 @@ bindTypeahead(key, value); } - var reference; - - if (typeof d.value !== 'string') { - reference = uiTagReference({ key: d.key }); - } else { - var isRelation = _entityIDs && _entityIDs.some(function(entityID) { - return context.entity(entityID).type === 'relation'; - }); - if (isRelation && d.key === 'type') { - reference = uiTagReference({ rtype: d.value }); - } else { - reference = uiTagReference({ key: d.key, value: d.value }); - } + var referenceOptions = { key: d.key }; + if (typeof d.value === 'string') { + referenceOptions.value = d.value; } + var reference = uiTagReference(referenceOptions); if (_state === 'hover') { reference.showing(false); @@ -52026,7 +52052,7 @@ .append('div') .attr('class', 'qa-details-subsection'); - // Suggested Fix (musn't exist for every issue type) + // Suggested Fix (mustn't exist for every issue type) if (issueString(_qaItem, 'fix')) { var div$1 = detailsEnter .append('div') @@ -52044,7 +52070,7 @@ .attr('target', '_blank'); } - // Common Pitfalls (musn't exist for every issue type) + // Common Pitfalls (mustn't exist for every issue type) if (issueString(_qaItem, 'trap')) { var div$2 = detailsEnter .append('div') @@ -53138,7 +53164,7 @@ if (includeDrawNode) { if (parentWay.isClosed()) { // don't test the last segment for closed ways - #4655 - // (still test the first segement) + // (still test the first segment) nodes.pop(); } } else { // discount the draw node @@ -53166,23 +53192,23 @@ var nextMode; - if (context.graph() === startGraph) { // we've undone back to the beginning + if (context.graph() === startGraph) { + // We've undone back to the initial state before we started drawing. + // Just exit the draw mode without undoing whatever we did before + // we entered the draw mode. nextMode = modeSelect(context, [wayID]); } else { - context.history() - .on('undone.draw', null); - // remove whatever segment was drawn previously - context.undo(); + // The `undo` only removed the temporary edit, so here we have to + // manually undo to actually remove the last node we added. We can't + // use the `undo` function since the initial "add" graph doesn't have + // an annotation and so cannot be undone to. + context.pop(1); - if (context.graph() === startGraph) { // we've undone back to the beginning - nextMode = modeSelect(context, [wayID]); - } else { - // continue drawing - nextMode = mode; - } + // continue drawing + nextMode = mode; } - // clear the redo stack by adding and removing an edit + // clear the redo stack by adding and removing a blank edit context.perform(actionNoop()); context.pop(1); @@ -53213,7 +53239,7 @@ _headNodeID = typeof _nodeIndex === 'number' ? _origWay.nodes[_nodeIndex] : (_origWay.isClosed() ? _origWay.nodes[_origWay.nodes.length - 2] : _origWay.nodes[_origWay.nodes.length - 1]); _wayGeometry = _origWay.geometry(context.graph()); - _annotation = _t((_origWay.isDegenerate() ? + _annotation = _t((_origWay.nodes.length === (_origWay.isClosed() ? 2 : 1) ? 'operations.start.annotation.' : 'operations.continue.annotation.') + _wayGeometry ); @@ -53565,10 +53591,6 @@ var operation = function() { - if (!getSelectionText()) { - event.preventDefault(); - } - var graph = context.graph(); var selected = groupEntities(getFilteredIdsToCopy(), graph); var canCopy = []; @@ -53643,11 +53665,6 @@ } - function getSelectionText() { - return window.getSelection().toString(); - } - - operation.available = function() { return getFilteredIdsToCopy().length > 0; }; @@ -53662,6 +53679,13 @@ }; + operation.availableForKeypress = function() { + var selection = window.getSelection && window.getSelection(); + // if the user has text selected then let them copy that, not the selected feature + return !selection || !selection.toString(); + }; + + operation.tooltip = function() { var disable = operation.disabled(); return disable ? @@ -53746,12 +53770,13 @@ }); _nodes = utilGetAllNodes(_wayIDs, context.graph()); _coords = _nodes.map(function(n) { return n.loc; }); - _extent = utilTotalExtent(ways, context.graph()); // actions for connected nodes shared by at least two selected ways var sharedActions = []; + var sharedNodes = []; // actions for connected nodes var unsharedActions = []; + var unsharedNodes = []; _nodes.forEach(function(node) { var action = actionDisconnect(node.id).limitWays(_wayIDs); @@ -53768,8 +53793,10 @@ if (count > 1) { sharedActions.push(action); + sharedNodes.push(node); } else { unsharedActions.push(action); + unsharedNodes.push(node); } } }); @@ -53780,11 +53807,13 @@ if (sharedActions.length) { // if any nodes are shared, only disconnect the selected ways from each other _actions = sharedActions; + _extent = utilTotalExtent(sharedNodes, context.graph()); _descriptionID += 'conjoined'; _annotationID = 'from_each_other'; } else { // if no nodes are shared, disconnect the selected ways from all connected ways _actions = unsharedActions; + _extent = utilTotalExtent(unsharedNodes, context.graph()); if (_wayIDs.length === 1) { _descriptionID += context.graph().geometry(_wayIDs[0]); } else { @@ -54627,7 +54656,7 @@ for (var i = 0; i < selectedIDs.length; i++) { var entity = context.hasEntity(selectedIDs[i]); if (!entity || entity.geometry(graph) !== 'vertex') { - return []; // selection includes some not vertexes + return []; // selection includes some not vertices } var currParents = graph.parentWays(entity).map(function(w) { return w.id; }); @@ -55519,7 +55548,7 @@ var maxdist = 500; // Don't allow the hash location to change too much while drawing - // This can happen if the user accidently hit the back button. #3996 + // This can happen if the user accidentally hit the back button. #3996 if (mode && mode.id.match(/^draw/) !== null && dist > maxdist) { context.enter(modeBrowse(context)); return; @@ -55870,7 +55899,7 @@ function segmentBBox(segment) { var extent = segment.extent(head); - // extent can be null if the node entites aren't in the graph for some reason + // extent can be null if the node entities aren't in the graph for some reason if (!extent) { return null; } var bbox = extent.bbox(); @@ -57457,12 +57486,6 @@ return featureType === 'highway' || featureType === 'railway' || featureType === 'waterway'; } - - function getFeatureTypeForCrossingCheck(way, graph) { - var feature = getFeatureWithFeatureTypeTagsForWay(way, graph); - return getFeatureType(feature, graph); - } - // discard var ignoredBuildings = { demolished: true, dismantled: true, proposed: true, razed: true @@ -57489,9 +57512,7 @@ } - function isLegitCrossing(way1, featureType1, way2, featureType2) { - var tags1 = way1.tags; - var tags2 = way2.tags; + function isLegitCrossing(tags1, featureType1, tags2, featureType2) { // assume 0 by default var level1 = tags1.level || '0'; @@ -57578,13 +57599,24 @@ var featureTypes = [featureType1, featureType2]; if (featureTypes.indexOf('highway') !== -1) { if (featureTypes.indexOf('railway') !== -1) { + if (!bothLines) { return {}; } + + var isTram = entity1.tags.railway === 'tram' || entity2.tags.railway === 'tram'; + if (osmPathHighwayTagValues[entity1.tags.highway] || osmPathHighwayTagValues[entity2.tags.highway]) { - // path-rail connections use this tag - return bothLines ? { railway: 'crossing' } : {}; + + // path-tram connections use this tag + if (isTram) { return { railway: 'tram_crossing' }; } + + // other path-rail connections use this tag + return { railway: 'crossing' }; } else { - // road-rail connections use this tag - return bothLines ? { railway: 'level_crossing' } : {}; + // path-tram connections use this tag + if (isTram) { return { railway: 'tram_level_crossing' }; } + + // other road-rail connections use this tag + return { railway: 'level_crossing' }; } } @@ -57610,7 +57642,8 @@ var edgeCrossInfos = []; if (way1.type !== 'way') { return edgeCrossInfos; } - var way1FeatureType = getFeatureTypeForCrossingCheck(way1, graph); + var taggedFeature1 = getFeatureWithFeatureTypeTagsForWay(way1, graph); + var way1FeatureType = getFeatureType(taggedFeature1, graph); if (way1FeatureType === null) { return edgeCrossInfos; } var checkedSingleCrossingWays = {}; @@ -57621,7 +57654,7 @@ var n1, n2, nA, nB, nAId, nBId; var segment1, segment2; var oneOnly; - var segmentInfos, segment2Info, way2, way2FeatureType; + var segmentInfos, segment2Info, way2, taggedFeature2, way2FeatureType; var way1Nodes = graph.childNodes(way1); var comparedWays = {}; for (i = 0; i < way1Nodes.length - 1; i++) { @@ -57656,11 +57689,12 @@ way2 = graph.hasEntity(segment2Info.wayId); if (!way2) { continue; } - + taggedFeature2 = getFeatureWithFeatureTypeTagsForWay(way2, graph); // only check crossing highway, waterway, building, and railway - way2FeatureType = getFeatureTypeForCrossingCheck(way2, graph); + way2FeatureType = getFeatureType(taggedFeature2, graph); + if (way2FeatureType === null || - isLegitCrossing(way1, way1FeatureType, way2, way2FeatureType)) { + isLegitCrossing(taggedFeature1.tags, way1FeatureType, taggedFeature2.tags, way2FeatureType)) { continue; } @@ -57862,12 +57896,12 @@ } else if (context.graph().geometry(this.entityIds[0]) === 'line' && context.graph().geometry(this.entityIds[1]) === 'line') { - // don't recommend adding bridges to waterways since they're uncommmon + // don't recommend adding bridges to waterways since they're uncommon if (allowsBridge(selectedFeatureType) && selectedFeatureType !== 'waterway') { fixes.push(makeAddBridgeOrTunnelFix('add_a_bridge', 'temaki-bridge', 'bridge')); } - // don't recommend adding tunnels under waterways since they're uncommmon + // don't recommend adding tunnels under waterways since they're uncommon var skipTunnelFix = otherFeatureType === 'waterway' && selectedFeatureType !== 'waterway'; if (allowsTunnel(selectedFeatureType) && !skipTunnelFix) { fixes.push(makeAddBridgeOrTunnelFix('add_a_tunnel', 'temaki-tunnel', 'tunnel')); @@ -59439,18 +59473,10 @@ }; var matchGroups = {adult_gaming_centre:["amenity/casino","amenity/gambling","leisure/adult_gaming_centre"],beauty:["shop/beauty","shop/hairdresser_supply"],bed:["shop/bed","shop/furniture"],beverages:["shop/alcohol","shop/beverages"],camping:["leisure/park","tourism/camp_site","tourism/caravan_site"],car_parts:["shop/car_parts","shop/car_repair","shop/tires","shop/tyres"],confectionery:["shop/candy","shop/chocolate","shop/confectionery"],convenience:["shop/beauty","shop/chemist","shop/convenience","shop/cosmetics","shop/newsagent"],coworking:["amenity/coworking_space","office/coworking","office/coworking_space"],electronics:["office/telecommunication","shop/computer","shop/electronics","shop/hifi","shop/mobile","shop/mobile_phone","shop/telecommunication"],fashion:["shop/accessories","shop/bag","shop/botique","shop/clothes","shop/department_store","shop/fashion","shop/fashion_accessories","shop/sports","shop/shoes"],financial:["amenity/bank","office/accountant","office/financial","office/financial_advisor","office/tax_advisor","shop/tax"],fitness:["leisure/fitness_centre","leisure/fitness_center","leisure/sports_centre","leisure/sports_center"],food:["amenity/cafe","amenity/fast_food","amenity/ice_cream","amenity/restaurant","shop/bakery","shop/ice_cream","shop/pastry","shop/tea","shop/coffee"],fuel:["amenity/fuel","shop/gas","shop/convenience;gas","shop/gas;convenience"],gift:["shop/gift","shop/card","shop/cards","shop/stationery"],hardware:["shop/carpet","shop/diy","shop/doityourself","shop/doors","shop/electrical","shop/flooring","shop/hardware","shop/power_tools","shop/tool_hire","shop/tools","shop/trade"],health_food:["shop/health","shop/health_food","shop/herbalist","shop/nutrition_supplements"],houseware:["shop/houseware","shop/interior_decoration"],lodging:["tourism/hotel","tourism/motel"],money_transfer:["amenity/money_transfer","shop/money_transfer"],outdoor:["shop/outdoor","shop/sports"],rental:["amenity/bicycle_rental","amenity/boat_rental","amenity/car_rental","amenity/truck_rental","amenity/vehicle_rental","shop/rental"],school:["amenity/childcare","amenity/college","amenity/kindergarten","amenity/language_school","amenity/prep_school","amenity/school","amenity/university"],supermarket:["shop/food","shop/frozen_food","shop/greengrocer","shop/grocery","shop/supermarket","shop/wholesale"],variety_store:["shop/variety_store","shop/supermarket","shop/discount","shop/convenience"],vending:["amenity/vending_machine","shop/vending_machine"],wholesale:["shop/wholesale","shop/supermarket","shop/department_store"]}; - var match_groups = { + var require$$0 = { matchGroups: matchGroups }; - var match_groups$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - matchGroups: matchGroups, - 'default': match_groups - }); - - var require$$0 = getCjsExportFromNamespace(match_groups$1); - var matchGroups$1 = require$$0.matchGroups; @@ -61852,7 +61878,7 @@ .on('redone.validator', validator.validate); // redo // but not on 'change' (e.g. while drawing) - // When user chages editing modes: + // When user changes editing modes: context .on('exit.validator', validator.validate); @@ -62437,7 +62463,7 @@ // Guess a type based on the tokens present in the template // (This is for 'custom' source, where we don't know) if (!source.type) { - if (/\{(proj|wkid|bbox)\}/.test(_template)) { + if (/SERVICE=WMS|\{(proj|wkid|bbox)\}/.test(_template)) { source.type = 'wms'; source.projection = 'EPSG:3857'; // guess } else if (/\{(x|y)\}/.test(_template)) { @@ -62484,23 +62510,30 @@ switch (key) { case 'width': case 'height': - return tileSize; + return tileSize; case 'proj': - return projection; + return projection; case 'wkid': - return projection.replace(/^EPSG:/, ''); + return projection.replace(/^EPSG:/, ''); case 'bbox': - return minXmaxY.x + ',' + maxXminY.y + ',' + maxXminY.x + ',' + minXmaxY.y; + // WMS 1.3 flips x/y for some coordinate systems including EPSG:4326 - #7557 + if (projection === 'EPSG:4326' && + // The CRS parameter implies version 1.3 (prior versions use SRS) + /VERSION=1.3|CRS={proj}/.test(source.template())) { + return maxXminY.y + ',' + minXmaxY.x + ',' + minXmaxY.y + ',' + maxXminY.x; + } else { + return minXmaxY.x + ',' + maxXminY.y + ',' + maxXminY.x + ',' + minXmaxY.y; + } case 'w': - return minXmaxY.x; + return minXmaxY.x; case 's': - return maxXminY.y; + return maxXminY.y; case 'n': - return maxXminY.x; + return maxXminY.x; case 'e': - return minXmaxY.y; + return minXmaxY.y; default: - return token; + return token; } }); @@ -63446,6 +63479,7 @@ context.history().photoOverlaysUsed(photoOverlaysUsed); }; + var _checkedBlocklists; background.sources = function (extent, zoom, includeCurrent) { if (!_imageryIndex) { return []; } // called before init()? @@ -63456,9 +63490,22 @@ var currSource = baseLayer.source(); + var osm = context.connection(); + var blocklists = osm && osm.imageryBlocklists(); + + if (blocklists && blocklists !== _checkedBlocklists) { + _imageryIndex.backgrounds.forEach(function (source) { + source.isBlocked = blocklists.some(function(blocklist) { + return blocklist.test(source.template()); + }); + }); + _checkedBlocklists = blocklists; + } + return _imageryIndex.backgrounds.filter(function (source) { + if (includeCurrent && currSource === source) { return true; } // optionally always include the current imagery + if (source.isBlocked) { return false; } // even bundled sources may be blocked - #7905 if (!source.polygon) { return true; } // always include imagery with worldwide coverage - if (includeCurrent && currSource === source) { return true; } // optionally include the current imagery if (zoom && zoom < 6) { return false; } // optionally exclude local imagery at low zooms return visible[source.id]; // include imagery visible in given extent }); @@ -63475,30 +63522,26 @@ background.baseLayerSource = function(d) { if (!arguments.length) { return baseLayer.source(); } - // test source against OSM imagery blacklists.. + // test source against OSM imagery blocklists.. var osm = context.connection(); if (!osm) { return background; } - var blacklists = osm.imageryBlacklists(); + var blocklists = osm.imageryBlocklists(); var template = d.template(); var fail = false; var tested = 0; var regex; - for (var i = 0; i < blacklists.length; i++) { - try { - regex = new RegExp(blacklists[i]); - fail = regex.test(template); - tested++; - if (fail) { break; } - } catch (e) { - /* noop */ - } + for (var i = 0; i < blocklists.length; i++) { + regex = blocklists[i]; + fail = regex.test(template); + tested++; + if (fail) { break; } } // ensure at least one test was run. if (!tested) { - regex = new RegExp('.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*'); + regex = /.*\.google(apis)?\..*\/(vt|kh)[\?\/].*([xyz]=.*){3}.*/; fail = regex.test(template); } @@ -67987,28 +68030,24 @@ drawData.template = function(val, src) { if (!arguments.length) { return _template; } - // test source against OSM imagery blacklists.. + // test source against OSM imagery blocklists.. var osm = context.connection(); if (osm) { - var blacklists = osm.imageryBlacklists(); + var blocklists = osm.imageryBlocklists(); var fail = false; var tested = 0; var regex; - for (var i = 0; i < blacklists.length; i++) { - try { - regex = new RegExp(blacklists[i]); - fail = regex.test(val); - tested++; - if (fail) { break; } - } catch (e) { - /* noop */ - } + for (var i = 0; i < blocklists.length; i++) { + regex = blocklists[i]; + fail = regex.test(val); + tested++; + if (fail) { break; } } // ensure at least one test was run. if (!tested) { - regex = new RegExp('.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*'); + regex = /.*\.google(apis)?\..*\/(vt|kh)[\?\/].*([xyz]=.*){3}.*/; fail = regex.test(val); } } @@ -70129,7 +70168,7 @@ /** * drawImages() - * drawImages is the method that is returned (and that runs) everytime 'svgStreetside()' is called. + * drawImages is the method that is returned (and that runs) every time 'svgStreetside()' is called. * 'svgStreetside()' is called from index.js */ function drawImages(selection) { @@ -72657,7 +72696,7 @@ function addChildVertices(entity) { - // avoid redunant work and infinite recursion of circular relations + // avoid redundant work and infinite recursion of circular relations if (seenIds[entity.id]) { return; } seenIds[entity.id] = true; @@ -72721,7 +72760,7 @@ } // Collect important vertices from the `entities` list.. - // (during a paritial redraw, it will not contain everything) + // (during a partial redraw, it will not contain everything) for (var i = 0; i < entities.length; i++) { var entity = entities[i]; var geometry = entity.geometry(graph); @@ -73776,7 +73815,7 @@ ); // On Firefox Windows and Linux we always get +/- the scroll line amount (default 3) - // There doesn't seem to be any scroll accelleration. + // There doesn't seem to be any scroll acceleration. // This multiplier increases the speed a little bit - #5512 if (detected.os !== 'mac') { dY *= 5; @@ -75936,7 +75975,7 @@ .selectAll('.background-info-span-vintage') .text(metadata.vintage); - // update other metdata + // update other metadata metadataKeys.forEach(function(k) { if (k === 'zoom' || k === 'vintage') { return; } // done already var val = result[k]; @@ -76921,7 +76960,7 @@ point: _t('modes.add_point.title'), line: _t('modes.add_line.title'), area: _t('modes.add_area.title'), - note: _t('modes.add_note.title'), + note: _t('modes.add_note.label'), delete: _t('operations.delete.title'), move: _t('operations.move.title'), orthogonalize: _t('operations.orthogonalize.title'), @@ -83224,7 +83263,7 @@ .preset(_presets.length === 1 ? _presets[0] : _mainPresetIndex.item('point')) ); - // NOTE: split on en-dash, not a hypen (to avoid conflict with hyphenated names) + // NOTE: split on en-dash, not a hyphen (to avoid conflict with hyphenated names) var names = _presets.length === 1 ? _presets[0].name().split(' – ') : [_t('inspector.multiple_types')]; var label = selection.select('.label-inner'); @@ -83254,9 +83293,8 @@ if (!utilArrayIdentical(val, _presets)) { _presets = val; - var geometries = entityGeometries(); - if (_presets.length === 1 && geometries.length) { - _tagReference = uiTagReference(_presets[0].reference(geometries[0])) + if (_presets.length === 1) { + _tagReference = uiTagReference(_presets[0].reference()) .showing(false); } } @@ -85774,7 +85812,7 @@ } // Remove whatever is after the last ' – ' - // NOTE: split/join on en-dash, not a hypen (to avoid conflict with fr - nl names in Brussels etc) + // NOTE: split/join on en-dash, not a hyphen (to avoid conflict with fr - nl names in Brussels etc) function cleanName(name) { var parts = name.split(' – '); if (parts.length > 1) { @@ -87743,8 +87781,6 @@ .call(langCombo) .merge(_langInput); - utilGetSetValue(_langInput, language()[1]); - _langInput .on('blur', changeLang) .on('change', changeLang); @@ -87794,14 +87830,33 @@ } - function language() { + function defaultLanguageInfo(skipEnglishFallback) { + var langCode = _mainLocalizer.languageCode().toLowerCase(); + + for (var i in _dataWikipedia) { + var d = _dataWikipedia[i]; + // default to the language of iD's current locale + if (d[2] === langCode) { return d; } + } + + // fallback to English + return skipEnglishFallback ? ['', '', ''] : ['English', 'English', 'en']; + } + + + function language(skipEnglishFallback) { var value = utilGetSetValue(_langInput).toLowerCase(); - var locale = _mainLocalizer.localeCode().toLowerCase(); - var localeLanguage; - return _dataWikipedia.find(function (d) { - if (d[2] === locale) { localeLanguage = d; } - return d[0].toLowerCase() === value || d[1].toLowerCase() === value || d[2] === value; - }) || localeLanguage || ['English', 'English', 'en']; + + for (var i in _dataWikipedia) { + var d = _dataWikipedia[i]; + // return the language already set in the UI, if supported + if (d[0].toLowerCase() === value || + d[1].toLowerCase() === value || + d[2] === value) { return d; } + } + + // fallback to English + return defaultLanguageInfo(skipEnglishFallback); } @@ -87819,10 +87874,11 @@ function change(skipWikidata) { var value = utilGetSetValue(_titleInput); var m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/); - var l = m && _dataWikipedia.find(function (d) { return m[1] === d[2]; }); + var langInfo = m && _dataWikipedia.find(function (d) { return m[1] === d[2]; }); var syncTags = {}; - if (l) { + if (langInfo) { + var nativeLangName = langInfo[1]; // Normalize title http://www.mediawiki.org/wiki/API:Query#Title_normalization value = decodeURIComponent(m[2]).replace(/_/g, ' '); if (m[3]) { @@ -87837,7 +87893,7 @@ value += '#' + anchor.replace(/_/g, ' '); } value = value.slice(0, 1).toUpperCase() + value.slice(1); - utilGetSetValue(_langInput, l[1]); + utilGetSetValue(_langInput, nativeLangName); utilGetSetValue(_titleInput, value); } @@ -87901,14 +87957,19 @@ function updateForTags(tags) { var value = typeof tags[field.key] === 'string' ? tags[field.key] : ''; + // Expect tag format of `tagLang:tagArticleTitle`, e.g. `fr:Paris`, with + // optional suffix of `#anchor` var m = value.match(/([^:]+):([^#]+)(?:#(.+))?/); - var l = m && _dataWikipedia.find(function (d) { return m[1] === d[2]; }); + var tagLang = m && m[1]; + var tagArticleTitle = m && m[2]; var anchor = m && m[3]; + var tagLangInfo = tagLang && _dataWikipedia.find(function (d) { return tagLang === d[2]; }); // value in correct format - if (l) { - utilGetSetValue(_langInput, l[1]); - utilGetSetValue(_titleInput, m[2] + (anchor ? ('#' + anchor) : '')); + if (tagLangInfo) { + var nativeLangName = tagLangInfo[1]; + utilGetSetValue(_langInput, nativeLangName); + utilGetSetValue(_titleInput, tagArticleTitle + (anchor ? ('#' + anchor) : '')); if (anchor) { try { // Best-effort `anchorencode:` implementation @@ -87917,16 +87978,19 @@ anchor = anchor.replace(/ /g, '_'); } } - _wikiURL = 'https://' + m[1] + '.wikipedia.org/wiki/' + - m[2].replace(/ /g, '_') + (anchor ? ('#' + anchor) : ''); + _wikiURL = 'https://' + tagLang + '.wikipedia.org/wiki/' + + tagArticleTitle.replace(/ /g, '_') + (anchor ? ('#' + anchor) : ''); // unrecognized value format } else { utilGetSetValue(_titleInput, value); if (value && value !== '') { utilGetSetValue(_langInput, ''); - _wikiURL = "https://en.wikipedia.org/wiki/Special:Search?search=" + value; + var defaultLangInfo = defaultLanguageInfo(); + _wikiURL = "https://" + (defaultLangInfo[2]) + ".wikipedia.org/w/index.php?fulltext=1&search=" + value; } else { + var shownOrDefaultLangInfo = language(true /* skipEnglishFallback */); + utilGetSetValue(_langInput, shownOrDefaultLangInfo[1]); _wikiURL = ''; } } @@ -88501,7 +88565,8 @@ var graph = context.graph(); var geometries = Object.keys(_entityIDs.reduce(function(geoms, entityID) { - return geoms[graph.entity(entityID).geometry(graph)] = true; + geoms[graph.entity(entityID).geometry(graph)] = true; + return geoms; }, {})); var presetsManager = _mainPresetIndex; @@ -89063,7 +89128,7 @@ function changeRole(d) { - if (d === 0) { return; } // called on newrow (shoudn't happen) + if (d === 0) { return; } // called on newrow (shouldn't happen) if (_inChange) { return; } // avoid accidental recursive call #5731 var oldRole = d.member.role; @@ -89107,7 +89172,7 @@ function deleteMembership(d) { this.blur(); // avoid keeping focus on the button - if (d === 0) { return; } // called on newrow (shoudn't happen) + if (d === 0) { return; } // called on newrow (shouldn't happen) // remove the hover-highlight styling utilHighlightEntities([d.relation.id], false, context); @@ -90298,7 +90363,7 @@ .append('div') .attr('class', 'label-inner'); - // NOTE: split/join on en-dash, not a hypen (to avoid conflict with fr - nl names in Brussels etc) + // NOTE: split/join on en-dash, not a hyphen (to avoid conflict with fr - nl names in Brussels etc) label.selectAll('.namepart') .data(preset.name().split(' – ')) .enter() @@ -90337,7 +90402,7 @@ }; item.preset = preset; - item.reference = uiTagReference(preset.reference(entityGeometries()[0])); + item.reference = uiTagReference(preset.reference()); return item; } @@ -90868,15 +90933,15 @@ .classed('inspector-hidden', false) .classed('inspector-hover', false); - if (!inspector.entityIDs() || !utilArrayIdentical(inspector.entityIDs(), ids) || inspector.state() !== 'select') { - inspector - .state('select') - .entityIDs(ids) - .newFeature(newFeature); + // reload the UI even if the ids are the same since the entities + // themselves may have changed + inspector + .state('select') + .entityIDs(ids) + .newFeature(newFeature); - inspectorWrap - .call(inspector); - } + inspectorWrap + .call(inspector); } else { inspector @@ -117991,7 +118056,7 @@ var context = utilRebind({}, dispatch$1, 'on'); var _deferred = new Set(); - context.version = '2.18.3'; + context.version = '2.18.5'; context.privacyVersion = '20200407'; // iD will alter the hash so cache the parameters intended to setup the session