X-Git-Url: https://git.openstreetmap.org/rails.git/blobdiff_plain/95d406937ee33c04d739bf199df669f0167a9ab4..e91c02f2ceb2b72a77846a0c31f5eca22b9b0a65:/vendor/assets/iD/iD.js diff --git a/vendor/assets/iD/iD.js b/vendor/assets/iD/iD.js index 6ac452788..346fdbd66 100644 --- a/vendor/assets/iD/iD.js +++ b/vendor/assets/iD/iD.js @@ -69,7 +69,7 @@ return toString$1.call(it).slice(8, -1); }; - var split$2 = ''.split; + var split$1 = ''.split; // fallback for non-array-like ES3 and non-enumerable old V8 strings var indexedObject = fails(function () { @@ -77,7 +77,7 @@ // eslint-disable-next-line no-prototype-builtins -- safe return !Object('z').propertyIsEnumerable(0); }) ? function (it) { - return classofRaw(it) == 'String' ? split$2.call(it, '') : Object(it); + return classofRaw(it) == 'String' ? split$1.call(it, '') : Object(it); } : Object; // `RequireObjectCoercible` abstract operation @@ -226,7 +226,7 @@ (module.exports = function (key, value) { return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {}); })('versions', []).push({ - version: '3.15.2', + version: '3.15.0', mode: 'global', copyright: '© 2021 Denis Pushkarev (zloirock.ru)' }); @@ -2880,8 +2880,7 @@ var Internal, OwnPromiseCapability, PromiseWrapper, nativeThen; var FORCED$f = isForced_1(PROMISE, function () { - var PROMISE_CONSTRUCTOR_SOURCE = inspectSource(PromiseConstructor); - var GLOBAL_CORE_JS_PROMISE = PROMISE_CONSTRUCTOR_SOURCE !== String(PromiseConstructor); + var GLOBAL_CORE_JS_PROMISE = inspectSource(PromiseConstructor) !== String(PromiseConstructor); // V8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables // https://bugs.chromium.org/p/chromium/issues/detail?id=830565 // We can't detect it synchronously, so just check versions @@ -2889,7 +2888,7 @@ // We can't use @@species feature detection in V8 since it causes // deoptimization and performance degradation // https://github.com/zloirock/core-js/issues/679 - if (engineV8Version >= 51 && /native code/.test(PROMISE_CONSTRUCTOR_SOURCE)) return false; + if (engineV8Version >= 51 && /native code/.test(PromiseConstructor)) return false; // Detect correctness of subclassing with @@species support var promise = new PromiseConstructor(function (resolve) { resolve(1); }); var FakePromise = function (exec) { @@ -6962,20 +6961,20 @@ }); }; - var DOMException$2 = global$1.DOMException; + var DOMException$1 = global$1.DOMException; try { - new DOMException$2(); + new DOMException$1(); } catch (err) { - DOMException$2 = function DOMException(message, name) { + DOMException$1 = function DOMException(message, name) { this.message = message; this.name = name; var error = Error(message); this.stack = error.stack; }; - DOMException$2.prototype = Object.create(Error.prototype); - DOMException$2.prototype.constructor = DOMException$2; + DOMException$1.prototype = Object.create(Error.prototype); + DOMException$1.prototype.constructor = DOMException$1; } function fetch$1(input, init) { @@ -6983,7 +6982,7 @@ var request = new Request(input, init); if (request.signal && request.signal.aborted) { - return reject(new DOMException$2('Aborted', 'AbortError')); + return reject(new DOMException$1('Aborted', 'AbortError')); } var xhr = new XMLHttpRequest(); @@ -7019,7 +7018,7 @@ xhr.onabort = function () { setTimeout(function () { - reject(new DOMException$2('Aborted', 'AbortError')); + reject(new DOMException$1('Aborted', 'AbortError')); }, 0); }; @@ -8348,7 +8347,7 @@ var setMetadata = function (it) { defineProperty(it, METADATA, { value: { - objectID: 'O' + id++, // object ID + objectID: 'O' + ++id, // object ID weakData: {} // weak collections IDs } }); }; @@ -9475,7 +9474,7 @@ } }); - var _marked$2 = /*#__PURE__*/regeneratorRuntime.mark(numbers); + var _marked$3 = /*#__PURE__*/regeneratorRuntime.mark(numbers); function number$1 (x) { return x === null ? NaN : +x; @@ -9587,7 +9586,7 @@ return _context.stop(); } } - }, _marked$2, null, [[2, 13, 16, 19], [23, 34, 37, 40]]); + }, _marked$3, null, [[2, 13, 16, 19], [23, 34, 37, 40]]); } var ascendingBisect = d3_bisector(d3_ascending); @@ -10021,7 +10020,7 @@ return quantile(values, 0.5, valueof); } - var _marked$1 = /*#__PURE__*/regeneratorRuntime.mark(flatten); + var _marked$2 = /*#__PURE__*/regeneratorRuntime.mark(flatten); function flatten(arrays) { var _iterator, _step, array; @@ -10070,7 +10069,7 @@ return _context.stop(); } } - }, _marked$1, null, [[1, 10, 13, 16]]); + }, _marked$2, null, [[1, 10, 13, 16]]); } function merge$4(arrays) { @@ -14163,7 +14162,7 @@ return this.each((typeof params === "function" ? dispatchFunction : dispatchConstant)(type, params)); } - var _marked = /*#__PURE__*/regeneratorRuntime.mark(_callee); + var _marked$1 = /*#__PURE__*/regeneratorRuntime.mark(_callee); function _callee() { var groups, j, m, group, i, n, node; @@ -14210,7 +14209,7 @@ return _context.stop(); } } - }, _marked, this); + }, _marked$1, this); } var root$1 = [null]; @@ -14731,16 +14730,17 @@ var patternIsRegExp = isRegexp(pattern); var flagsAreUndefined = flags === undefined; var groups = []; - var rawPattern = pattern; - var rawFlags, dotAll, sticky, handled, result, state; + var rawPattern, rawFlags, dotAll, sticky, handled, result, state; - if (!thisIsRegExp && patternIsRegExp && flagsAreUndefined && pattern.constructor === RegExpWrapper) { + if (!thisIsRegExp && patternIsRegExp && pattern.constructor === RegExpWrapper && flagsAreUndefined) { return pattern; } - if (patternIsRegExp || pattern instanceof RegExpWrapper) { + if (CORRECT_NEW) { + if (patternIsRegExp && !flagsAreUndefined) pattern = pattern.source; + } else if (pattern instanceof RegExpWrapper) { + if (flagsAreUndefined) flags = regexpFlags.call(pattern); pattern = pattern.source; - if (flagsAreUndefined) flags = 'flags' in rawPattern ? rawPattern.flags : regexpFlags.call(rawPattern); } pattern = pattern === undefined ? '' : String(pattern); @@ -14765,7 +14765,11 @@ groups = handled[1]; } - result = inheritIfRequired(NativeRegExp(pattern, flags), thisIsRegExp ? this : RegExpPrototype, RegExpWrapper); + result = inheritIfRequired( + CORRECT_NEW ? new NativeRegExp(pattern, flags) : NativeRegExp(pattern, flags), + thisIsRegExp ? this : RegExpPrototype, + RegExpWrapper + ); if (dotAll || sticky || groups.length) { state = enforceInternalState(result); @@ -20098,7 +20102,7 @@ }); var name = "iD"; - var version = "2.20.0"; + var version = "2.20.1"; var description = "A friendly editor for OpenStreetMap"; var main = "dist/iD.min.js"; var repository = "github:openstreetmap/iD"; @@ -20107,8 +20111,8 @@ var keywords = ["editor","openstreetmap"]; var license = "ISC"; var scripts = {all:"npm-run-all -s clean build build:legacy dist",build:"npm-run-all -s build:css build:data build:dev","build:css":"node scripts/build_css.js","build:data":"shx mkdir -p dist/data && node scripts/build_data.js","build:dev":"rollup --config config/rollup.config.dev.js","build:legacy":"rollup --config config/rollup.config.legacy.js","build:stats":"rollup --config config/rollup.config.stats.js",clean:"shx rm -f dist/*.js dist/*.map dist/*.css dist/img/*.svg",dist:"npm-run-all -p dist:**","dist:mapillary":"shx mkdir -p dist/mapillary-js && shx cp -R node_modules/mapillary-js/dist/* dist/mapillary-js/","dist:pannellum":"shx mkdir -p dist/pannellum-streetside && shx cp -R node_modules/pannellum/build/* dist/pannellum-streetside/","dist:min:iD":"uglifyjs dist/iD.legacy.js --compress --mangle --output dist/iD.min.js","dist:svg:iD":"svg-sprite --symbol --symbol-dest . --shape-id-generator \"iD-%s\" --symbol-sprite dist/img/iD-sprite.svg \"svg/iD-sprite/**/*.svg\"","dist:svg:community":"svg-sprite --symbol --symbol-dest . --shape-id-generator \"community-%s\" --symbol-sprite dist/img/community-sprite.svg node_modules/osm-community-index/dist/img/*.svg","dist:svg:fa":"svg-sprite --symbol --symbol-dest . --symbol-sprite dist/img/fa-sprite.svg svg/fontawesome/*.svg","dist:svg:maki":"svg-sprite --symbol --symbol-dest . --shape-id-generator \"maki-%s\" --symbol-sprite dist/img/maki-sprite.svg node_modules/@mapbox/maki/icons/*.svg","dist:svg:mapillary:signs":"svg-sprite --symbol --symbol-dest . --symbol-sprite dist/img/mapillary-sprite.svg node_modules/mapillary_sprite_source/package_signs/*.svg","dist:svg:mapillary:objects":"svg-sprite --symbol --symbol-dest . --symbol-sprite dist/img/mapillary-object-sprite.svg node_modules/mapillary_sprite_source/package_objects/*.svg","dist:svg:temaki":"svg-sprite --symbol --symbol-dest . --shape-id-generator \"temaki-%s\" --symbol-sprite dist/img/temaki-sprite.svg node_modules/@ideditor/temaki/icons/*.svg",imagery:"node scripts/update_imagery.js",lint:"eslint scripts test/spec modules","lint:fix":"eslint scripts test/spec modules --fix",start:"npm-run-all -s build start:server",quickstart:"npm-run-all -s build:dev start:server","start:server":"node scripts/server.js",test:"npm-run-all -s lint build:css build:data build:legacy test:spec","test:spec":"phantomjs --web-security=no node_modules/mocha-phantomjs-core/mocha-phantomjs-core.js test/index.html spec",translations:"node scripts/update_locales.js"}; - var dependencies = {"@ideditor/country-coder":"~5.0.3","@ideditor/location-conflation":"~1.0.2","@mapbox/geojson-area":"^0.2.2","@mapbox/sexagesimal":"1.2.0","@mapbox/togeojson":"0.16.0","@mapbox/vector-tile":"^1.3.1","@turf/bbox-clip":"^6.0.0","abortcontroller-polyfill":"^1.4.0","aes-js":"^3.1.2","alif-toolkit":"^1.2.9","core-js":"^3.6.5",diacritics:"1.3.0","fast-deep-equal":"~3.1.1","fast-json-stable-stringify":"2.1.0","lodash-es":"~4.17.15",marked:"~2.0.0","node-diff3":"2.1.0","osm-auth":"1.1.0",pannellum:"2.5.6","polygon-clipping":"~0.15.1",rbush:"3.0.1","whatwg-fetch":"^3.4.1","which-polygon":"2.2.0"}; - var devDependencies = {"@babel/core":"^7.11.6","@babel/preset-env":"^7.11.5","@fortawesome/fontawesome-svg-core":"^1.2.32","@fortawesome/free-brands-svg-icons":"~5.15.1","@fortawesome/free-regular-svg-icons":"~5.15.1","@fortawesome/free-solid-svg-icons":"~5.15.1","@ideditor/temaki":"~4.4.0","@mapbox/maki":"^6.0.0","@rollup/plugin-babel":"^5.2.1","@rollup/plugin-commonjs":"^17.0.0","@rollup/plugin-json":"^4.0.1","@rollup/plugin-node-resolve":"~11.2.0",autoprefixer:"^10.0.1",btoa:"^1.2.1",chai:"^4.1.0","cldr-core":"37.0.0","cldr-localenames-full":"37.0.0",colors:"^1.1.2","concat-files":"^0.1.1",d3:"~6.6.0","editor-layer-index":"github:osmlab/editor-layer-index#gh-pages",eslint:"^7.1.0",gaze:"^1.1.3",glob:"^7.1.0",happen:"^0.3.1","js-yaml":"^4.0.0","json-stringify-pretty-compact":"^3.0.0",mapillary_sprite_source:"^1.8.0","mapillary-js":"4.0.0",minimist:"^1.2.3",mocha:"^7.0.1","mocha-phantomjs-core":"^2.1.0","name-suggestion-index":"~6.0","node-fetch":"^2.6.1","npm-run-all":"^4.0.0","object-inspect":"1.10.3","osm-community-index":"~5.1.0","phantomjs-prebuilt":"~2.1.16",postcss:"^8.1.1","postcss-selector-prepend":"^0.5.0",rollup:"~2.52.8","rollup-plugin-includepaths":"~0.2.3","rollup-plugin-progress":"^1.1.1","rollup-plugin-visualizer":"~4.2.0",shelljs:"^0.8.0",shx:"^0.3.0",sinon:"7.5.0","sinon-chai":"^3.3.0",smash:"0.0","static-server":"^2.2.1","svg-sprite":"1.5.0","uglify-js":"~3.13.0",vparse:"~1.1.0"}; + var dependencies = {"@ideditor/country-coder":"~5.0.3","@ideditor/location-conflation":"~1.0.2","@mapbox/geojson-area":"^0.2.2","@mapbox/sexagesimal":"1.2.0","@mapbox/vector-tile":"^1.3.1","@tmcw/togeojson":"^4.5.0","@turf/bbox-clip":"^6.0.0","abortcontroller-polyfill":"^1.4.0","aes-js":"^3.1.2","alif-toolkit":"^1.2.9","core-js":"^3.6.5",diacritics:"1.3.0","fast-deep-equal":"~3.1.1","fast-json-stable-stringify":"2.1.0","lodash-es":"~4.17.15",marked:"~2.0.0","node-diff3":"2.1.0","osm-auth":"1.1.0",pannellum:"2.5.6",pbf:"^3.2.1","polygon-clipping":"~0.15.1",rbush:"3.0.1","whatwg-fetch":"^3.4.1","which-polygon":"2.2.0"}; + var devDependencies = {"@babel/core":"^7.11.6","@babel/preset-env":"^7.11.5","@fortawesome/fontawesome-svg-core":"^1.2.32","@fortawesome/free-brands-svg-icons":"~5.15.1","@fortawesome/free-regular-svg-icons":"~5.15.1","@fortawesome/free-solid-svg-icons":"~5.15.1","@ideditor/temaki":"~4.4.0","@mapbox/maki":"^6.0.0","@rollup/plugin-babel":"^5.2.1","@rollup/plugin-commonjs":"^17.0.0","@rollup/plugin-json":"^4.0.1","@rollup/plugin-node-resolve":"~11.2.0",autoprefixer:"^10.0.1",btoa:"^1.2.1",chai:"^4.1.0","cldr-core":"37.0.0","cldr-localenames-full":"37.0.0",colors:"^1.1.2","concat-files":"^0.1.1",d3:"~6.6.0","editor-layer-index":"github:osmlab/editor-layer-index#gh-pages",eslint:"^7.1.0",gaze:"^1.1.3",glob:"^7.1.0",happen:"^0.3.1","js-yaml":"^4.0.0","json-stringify-pretty-compact":"^3.0.0",mapillary_sprite_source:"^1.8.0","mapillary-js":"4.0.0",minimist:"^1.2.3",mocha:"^7.0.1","mocha-phantomjs-core":"^2.1.0","name-suggestion-index":"~6.0","node-fetch":"^2.6.1","npm-run-all":"^4.0.0","object-inspect":"1.10.3","osm-community-index":"~5.1.0","phantomjs-prebuilt":"~2.1.16",postcss:"^8.1.1","postcss-selector-prepend":"^0.5.0",rollup:"~2.52.8","rollup-plugin-includepaths":"~0.2.3","rollup-plugin-progress":"^1.1.1","rollup-plugin-visualizer":"~4.2.0",shelljs:"^0.8.0",shx:"^0.3.0",sinon:"7.5.0","sinon-chai":"^3.3.0",smash:"0.0","static-server":"^2.2.1","svg-sprite":"1.5.1","uglify-js":"~3.13.0",vparse:"~1.1.0"}; var engines = {node:">=10"}; var browserslist = ["> 0.2%, last 6 major versions, Firefox ESR, IE 11, maintained node versions"]; var packageJSON = { @@ -27770,7 +27774,7 @@ * @license MIT * @preserve */ - var Node$1 = + var Node = /** @class */ function () { function Node(key, data) { @@ -27797,7 +27801,7 @@ function splay(i, t, comparator) { - var N = new Node$1(null, null); + var N = new Node(null, null); var l = N; var r = N; @@ -27853,7 +27857,7 @@ } function insert(i, data, t, comparator) { - var node = new Node$1(i, data); + var node = new Node(i, data); if (t === null) { node.left = node.right = null; @@ -27876,7 +27880,7 @@ return node; } - function split$1(key, v, comparator) { + function split(key, v, comparator) { var left = null; var right = null; @@ -27952,7 +27956,7 @@ Tree.prototype.add = function (key, data) { - var node = new Node$1(key, data); + var node = new Node(key, data); if (this._root === null) { node.left = node.right = null; @@ -28349,7 +28353,7 @@ Tree.prototype.update = function (key, newKey, newData) { var comparator = this._comparator; - var _a = split$1(key, this._root, comparator), + var _a = split(key, this._root, comparator), left = _a.left, right = _a.right; @@ -28363,7 +28367,7 @@ }; Tree.prototype.split = function (key) { - return split$1(key, this._root, this._comparator); + return split(key, this._root, this._comparator); }; return Tree; @@ -28376,7 +28380,7 @@ var middle = start + Math.floor(size / 2); var key = keys[middle]; var data = values[middle]; - var node = new Node$1(key, data); + var node = new Node(key, data); node.left = loadRecursive(keys, values, start, middle); node.right = loadRecursive(keys, values, middle + 1, end); return node; @@ -28386,11 +28390,11 @@ } function createList(keys, values) { - var head = new Node$1(null, null); + var head = new Node(null, null); var p = head; for (var i = 0; i < keys.length; i++) { - p = p.next = new Node$1(keys[i], values[i]); + p = p.next = new Node(keys[i], values[i]); } p.next = null; @@ -28401,7 +28405,7 @@ var current = root; var Q = []; var done = false; - var head = new Node$1(null, null); + var head = new Node(null, null); var p = head; while (!done) { @@ -28438,7 +28442,7 @@ } function mergeLists(l1, l2, compare) { - var head = new Node$1(null, null); // dummy + var head = new Node(null, null); // dummy var p = head; var p1 = l1; @@ -36943,6 +36947,9 @@ }, this); return utilArrayUniq(results); }, + isCrossing: function isCrossing() { + return this.tags.highway === 'crossing' || this.tags.railway && this.tags.railway.indexOf('crossing') !== -1; + }, isEndpoint: function isEndpoint(resolver) { return resolver["transient"](this, 'isEndpoint', function () { var id = this.id; @@ -42672,7 +42679,7 @@ }; } - function copy$1(source, target) { + function copy(source, target) { return target.domain(source.domain()).range(source.range()).interpolate(source.interpolate()).clamp(source.clamp()).unknown(source.unknown()); } function transformer() { @@ -43176,7 +43183,7 @@ var scale = continuous(); scale.copy = function () { - return copy$1(scale, linear()); + return copy(scale, linear()); }; initRange.apply(scale, arguments); @@ -55604,8 +55611,10 @@ if (connectionTags && (isCrossingIndoors || isCrossingTunnels || isCrossingBridges)) { crossingTypeID += '_connectable'; - } + } // Differentiate based on the loc rounded to 4 digits, since two ways can cross multiple times. + + var uniqueID = '' + crossing.crossPoint[0].toFixed(4) + ',' + crossing.crossPoint[1].toFixed(4); return new validationIssue({ type: type, subtype: subtype, @@ -55628,13 +55637,7 @@ featureTypes: featureTypes, connectionTags: connectionTags }, - // differentiate based on the loc since two ways can cross multiple times - hash: crossing.crossPoint.toString() + // if the edges change then so does the fix - edges.slice().sort(function (edge1, edge2) { - // order to assure hash is deterministic - return edge1[0] < edge2[0] ? -1 : 1; - }).toString() + // ensure the correct connection tags are added in the fix - JSON.stringify(connectionTags), + hash: uniqueID, loc: crossing.crossPoint, dynamicFixes: function dynamicFixes(context) { var mode = context.mode(); @@ -55896,8 +55899,9 @@ edges.forEach(function (edge) { var edgeNodes = [graph.entity(edge[0]), graph.entity(edge[1])]; var nearby = geoSphericalClosestNode(edgeNodes, loc); // if there is already a suitable node nearby, use that + // use the node if node has no interesting tags or if it is a crossing node #8326 - if (!nearby.node.hasInterestingTags() && nearby.distance < mergeThresholdInMeters) { + if ((!nearby.node.hasInterestingTags() || nearby.node.isCrossing()) && nearby.distance < mergeThresholdInMeters) { nodesToMerge.push(nearby.node.id); // else add the new node to the way } else { graph = actionAddMidpoint({ @@ -58121,13 +58125,14 @@ var _resolvedIssueIDs = new Set(); - var _baseCache = validationCache(); // issues before any user edits + var _baseCache = validationCache('base'); // issues before any user edits - var _headCache = validationCache(); // issues after all user edits + var _headCache = validationCache('head'); // issues after all user edits - var _headGraph = null; + var _completeDiff = {}; // complete diff base -> head of what the user changed + var _headIsCurrent = false; var _deferredRIC = new Set(); // Set( RequestIdleCallback handles ) @@ -58141,6 +58146,8 @@ var RETRY = 5000; // wait 5sec before revalidating provisional entities // Allow validation severity to be overridden by url queryparams... + // See: https://github.com/openstreetmap/iD/pull/8243 + // // Each param should contain a urlencoded comma separated list of // `type/subtype` rules. `*` may be used as a wildcard.. // Examples: @@ -58153,7 +58160,14 @@ var _warningOverrides = parseHashParam(context.initialHashParams.validationWarning); - var _disableOverrides = parseHashParam(context.initialHashParams.validationDisable); + var _disableOverrides = parseHashParam(context.initialHashParams.validationDisable); // `parseHashParam()` (private) + // Checks hash parameters for severity overrides + // Arguments + // `param` - a url hash parameter (`validationError`, `validationWarning`, or `validationDisable`) + // Returns + // Array of Objects like { type: RegExp, subtype: RegExp } + // + function parseHashParam(param) { var result = []; @@ -58171,13 +58185,13 @@ }); }); return result; - } - function makeRegExp(str) { - var escaped = str.replace(/[-\/\\^$+?.()|[\]{}]/g, '\\$&') // escape all reserved chars except for the '*' - .replace(/\*/g, '.*'); // treat a '*' like '.*' + function makeRegExp(str) { + var escaped = str.replace(/[-\/\\^$+?.()|[\]{}]/g, '\\$&') // escape all reserved chars except for the '*' + .replace(/\*/g, '.*'); // treat a '*' like '.*' - return new RegExp('^' + escaped + '$'); + return new RegExp('^' + escaped + '$'); + } } // `init()` // Initialize the validator, called once on iD startup // @@ -58225,9 +58239,9 @@ _resolvedIssueIDs.clear(); - _baseCache = validationCache(); - _headCache = validationCache(); - _headGraph = null; + _baseCache = validationCache('base'); + _headCache = validationCache('head'); + _completeDiff = {}; _headIsCurrent = false; } // `reset()` // clear caches, called whenever iD resets after a save or switches sources @@ -58253,23 +58267,23 @@ validator.revalidateUnsquare = function () { - revalidateUnsquare(_headCache, _headGraph); - revalidateUnsquare(_baseCache, context.history().base()); + revalidateUnsquare(_headCache); + revalidateUnsquare(_baseCache); dispatch.call('validated'); }; - function revalidateUnsquare(cache, graph) { + function revalidateUnsquare(cache) { var checkUnsquareWay = _rules.unsquare_way; - if (!graph || typeof checkUnsquareWay !== 'function') return; // uncache existing + if (!cache.graph || typeof checkUnsquareWay !== 'function') return; // uncache existing cache.uncacheIssuesOfType('unsquare_way'); - var buildings = context.history().tree().intersects(geoExtent([-180, -90], [180, 90]), graph) // everywhere + var buildings = context.history().tree().intersects(geoExtent([-180, -90], [180, 90]), cache.graph) // everywhere .filter(function (entity) { return entity.type === 'way' && entity.tags.building && entity.tags.building !== 'no'; }); // rerun for all buildings buildings.forEach(function (entity) { - var detected = checkUnsquareWay(entity, graph); + var detected = checkUnsquareWay(entity, cache.graph); if (!detected.length) return; cache.cacheIssues(detected); }); @@ -58299,54 +58313,46 @@ includeDisabledRules: false }, options); var view = context.map().extent(); - var issues = []; - var seen = new Set(); // collect head issues - caused by user edits - - var cache = _headCache; + var seen = new Set(); + var results = []; // collect head issues - caused by user edits - if (_headGraph) { - Object.values(cache.issuesByIssueID).forEach(function (issue) { - if (!filter(issue, _headGraph, cache)) return; + if (_headCache.graph && _headCache.graph !== _baseCache.graph) { + Object.values(_headCache.issuesByIssueID).forEach(function (issue) { + if (!filter(issue)) return; seen.add(issue.id); - issues.push(issue); + results.push(issue); }); } // collect base issues - not caused by user edits if (opts.what === 'all') { - cache = _baseCache; - Object.values(cache.issuesByIssueID).forEach(function (issue) { - if (!filter(issue, context.history().base(), cache)) return; + Object.values(_baseCache.issuesByIssueID).forEach(function (issue) { + if (!filter(issue)) return; seen.add(issue.id); - issues.push(issue); + results.push(issue); }); } - return issues; + return results; // Filter the issue set to include only what the calling code wants to see. + // Note that we use `context.graph()`/`context.hasEntity()` here, not `cache.graph`, + // because that is the graph that the calling code will be using. - function filter(issue, resolver, cache) { + function filter(issue) { if (!issue) return false; if (seen.has(issue.id)) return false; if (_resolvedIssueIDs.has(issue.id)) return false; if (opts.includeDisabledRules === 'only' && !_disabledRules[issue.type]) return false; if (!opts.includeDisabledRules && _disabledRules[issue.type]) return false; if (opts.includeIgnored === 'only' && !_ignoredIssueIDs.has(issue.id)) return false; - if (!opts.includeIgnored && _ignoredIssueIDs.has(issue.id)) return false; // Sanity check: This issue may be for an entity that not longer exists. - // If we detect this, uncache and return false so it is not included.. + if (!opts.includeIgnored && _ignoredIssueIDs.has(issue.id)) return false; // This issue may involve an entity that doesn't exist in context.graph() + // This can happen because validation is async and rendering the issue lists is async. - var entityIDs = issue.entityIds || []; - - for (var i = 0; i < entityIDs.length; i++) { - var entityID = entityIDs[i]; - - if (!resolver.hasEntity(entityID)) { - cache.uncacheEntityID(entityID); - return false; - } - } + if ((issue.entityIds || []).some(function (id) { + return !context.hasEntity(id); + })) return false; if (opts.where === 'visible') { - var extent = issue.extent(resolver); + var extent = issue.extent(context.graph()); if (!view.intersects(extent)) return false; } @@ -58354,7 +58360,9 @@ } }; // `getResolvedIssues()` // Gets the issues that have been fixed by the user. - // Resolved issues are tracked in the `_resolvedIssueIDs` Set + // + // Resolved issues are tracked in the `_resolvedIssueIDs` Set, + // and they should all be issues that exist in the _baseCache. // // Returns // An Array containing the issues @@ -58362,14 +58370,9 @@ validator.getResolvedIssues = function () { - var collected = new Set(); - Object.values(_baseCache.issuesByIssueID).forEach(function (issue) { - if (_resolvedIssueIDs.has(issue.id)) collected.add(issue); - }); - Object.values(_headCache.issuesByIssueID).forEach(function (issue) { - if (_resolvedIssueIDs.has(issue.id)) collected.add(issue); - }); - return Array.from(collected); + return Array.from(_resolvedIssueIDs).map(function (issueID) { + return _baseCache.issuesByIssueID[issueID]; + }).filter(Boolean); }; // `focusIssue()` // Adjusts the map to focus on the given issue. // (requires the issue to have a reasonable extent defined) @@ -58380,15 +58383,57 @@ validator.focusIssue = function (issue) { - var extent = issue.extent(context.graph()); - if (!extent) return; - var setZoom = Math.max(context.map().zoom(), 19); - context.map().unobscuredCenterZoomEase(extent.center(), setZoom); // select the first entity + // Note that we use `context.graph()`/`context.hasEntity()` here, not `cache.graph`, + // because that is the graph that the calling code will be using. + var graph = context.graph(); + var selectID; + var focusCenter; // Try to focus the map at the center of the issue.. + + var issueExtent = issue.extent(graph); + + if (issueExtent) { + focusCenter = issueExtent.center(); + } // Try to select the first entity in the issue.. + if (issue.entityIds && issue.entityIds.length) { + selectID = issue.entityIds[0]; // If a relation, focus on one of its members instead. + // Otherwise we might be focusing on a part of map where the relation is not visible. + + if (selectID && selectID.charAt(0) === 'r') { + // relation + var ids = utilEntityAndDeepMemberIDs([selectID], graph); + var nodeID = ids.find(function (id) { + return id.charAt(0) === 'n' && graph.hasEntity(id); + }); + + if (!nodeID) { + // relation has no downloaded nodes to focus on + var wayID = ids.find(function (id) { + return id.charAt(0) === 'w' && graph.hasEntity(id); + }); + + if (wayID) { + nodeID = graph.entity(wayID).first(); // focus on the first node of this way + } + } + + if (nodeID) { + focusCenter = graph.entity(nodeID).loc; + } + } + } + + if (focusCenter) { + // Adjust the view + var setZoom = Math.max(context.map().zoom(), 19); + context.map().unobscuredCenterZoomEase(focusCenter, setZoom); + } + + if (selectID) { + // Enter select mode window.setTimeout(function () { - var ids = issue.entityIds; - context.enter(modeSelect(context, [ids[0]])); + context.enter(modeSelect(context, [selectID])); dispatch.call('focusedIssue', _this, issue); }, 250); // after ease } @@ -58426,12 +58471,12 @@ validator.getSharedEntityIssues = function (entityIDs, options) { - // show some issue types in a particular order - var orderedIssueTypes = [// flag missing data first - 'missing_tag', 'missing_role', // then flag identity issues - 'outdated_tags', 'mismatched_geometry', // flag geometry issues where fixing them might solve connectivity issues - 'crossing_ways', 'almost_junction', // then flag connectivity issues - 'disconnected_way', 'impossible_oneway']; + var orderedIssueTypes = [// Show some issue types in a particular order: + 'missing_tag', 'missing_role', // - missing data first + 'outdated_tags', 'mismatched_geometry', // - identity issues + 'crossing_ways', 'almost_junction', // - geometry issues where fixing them might solve connectivity issues + 'disconnected_way', 'impossible_oneway' // - finally connectivity issues + ]; var allIssues = validator.getIssues(options); var forEntityIDs = new Set(entityIDs); return allIssues.filter(function (issue) { @@ -58547,12 +58592,16 @@ validator.validate = function () { + // Make sure the caches have graphs assigned to them. + // (we don't do this in `reset` because context is still resetting things and `history.base()` is unstable then) + var baseGraph = context.history().base(); + if (!_headCache.graph) _headCache.graph = baseGraph; + if (!_baseCache.graph) _baseCache.graph = baseGraph; + var prevGraph = _headCache.graph; var currGraph = context.graph(); - var prevGraph = _headGraph || context.history().base(); - if (currGraph === prevGraph) { - // _headGraph is current - we are caught up + // _headCache.graph is current - we are caught up _headIsCurrent = true; dispatch.call('validated'); return Promise.resolve(); @@ -58563,30 +58612,21 @@ _headIsCurrent = false; // We will need to catch up after the validation promise fulfills return _headPromise; - } - - _headGraph = currGraph; // take snapshot + } // If we get here, its time to start validating stuff. - var difference = coreDifference(prevGraph, _headGraph); // Gather all entities related to this difference.. - // For created/modified, use the head graph - var entityIDs = difference.extantIDs(true); // created/modified (true = w/relation members) + _headCache.graph = currGraph; // take snapshot - entityIDs = entityIDsToValidate(entityIDs, _headGraph); // For modified/deleted, use the previous graph - // (e.g. deleting the only highway connected to a road should create a disconnected highway issue) + _completeDiff = context.history().difference().complete(); + var incrementalDiff = coreDifference(prevGraph, currGraph); + var entityIDs = Object.keys(incrementalDiff.complete()); // if (!entityIDs.size) { - var previousEntityIDs = difference.deleted().concat(difference.modified()).map(function (entity) { - return entity.id; - }); - previousEntityIDs = entityIDsToValidate(previousEntityIDs, prevGraph); - previousEntityIDs.forEach(entityIDs.add, entityIDs); // concat the sets - - if (!entityIDs.size) { + if (!entityIDs.length) { dispatch.call('validated'); return Promise.resolve(); } - _headPromise = validateEntitiesAsync(entityIDs, _headGraph, _headCache).then(function () { + _headPromise = validateEntitiesAsync(entityIDs, _headCache).then(function () { return updateResolvedIssues(entityIDs); }).then(function () { return dispatch.call('validated'); @@ -58619,13 +58659,17 @@ context.on('exit.validator', validator.validate); // When merging fetched data, validate base graph: context.history().on('merge.validator', function (entities) { - if (!entities) return; + if (!entities) return; // Make sure the caches have graphs assigned to them. + // (we don't do this in `reset` because context is still resetting things and `history.base()` is unstable then) + var baseGraph = context.history().base(); + if (!_headCache.graph) _headCache.graph = baseGraph; + if (!_baseCache.graph) _baseCache.graph = baseGraph; var entityIDs = entities.map(function (entity) { return entity.id; - }); - entityIDs = entityIDsToValidate(entityIDs, baseGraph); - validateEntitiesAsync(entityIDs, baseGraph, _baseCache); + }); // entityIDs = entityIDsToValidate(entityIDs, baseGraph); // expand set + + validateEntitiesAsync(entityIDs, _baseCache); }); // `validateEntity()` (private) // Runs all validation rules on a single entity. // Some things to note: @@ -58651,7 +58695,10 @@ var result = { issues: [], provisional: false - }; // runs validation and appends resulting issues + }; + Object.keys(_rules).forEach(runValidation); // run all rules + + return result; // runs validation and appends resulting issues function runValidation(key) { var fn = _rules[key]; @@ -58662,128 +58709,78 @@ return; } - var detected = fn(entity, graph).filter(applySeverityOverrides); + var detected = fn(entity, graph); if (detected.provisional) { // this validation should be run again later result.provisional = true; } - result.issues = result.issues.concat(detected); - } // run all rules + detected = detected.filter(applySeverityOverrides); + result.issues = result.issues.concat(detected); // If there are any override rules that match the issue type/subtype, + // adjust severity (or disable it) and keep/discard as quickly as possible. + function applySeverityOverrides(issue) { + var type = issue.type; + var subtype = issue.subtype || ''; + var i; - Object.keys(_rules).forEach(runValidation); - return result; - } // If there are any override rules that match the issue type/subtype, - // adjust severity (or disable it) and keep/discard as quickly as possible. - + for (i = 0; i < _errorOverrides.length; i++) { + if (_errorOverrides[i].type.test(type) && _errorOverrides[i].subtype.test(subtype)) { + issue.severity = 'error'; + return true; + } + } - function applySeverityOverrides(issue) { - var type = issue.type; - var subtype = issue.subtype || ''; - var i; + for (i = 0; i < _warningOverrides.length; i++) { + if (_warningOverrides[i].type.test(type) && _warningOverrides[i].subtype.test(subtype)) { + issue.severity = 'warning'; + return true; + } + } - for (i = 0; i < _errorOverrides.length; i++) { - if (_errorOverrides[i].type.test(type) && _errorOverrides[i].subtype.test(subtype)) { - issue.severity = 'error'; - return true; - } - } + for (i = 0; i < _disableOverrides.length; i++) { + if (_disableOverrides[i].type.test(type) && _disableOverrides[i].subtype.test(subtype)) { + return false; + } + } - for (i = 0; i < _warningOverrides.length; i++) { - if (_warningOverrides[i].type.test(type) && _warningOverrides[i].subtype.test(subtype)) { - issue.severity = 'warning'; return true; } } - - for (i = 0; i < _disableOverrides.length; i++) { - if (_disableOverrides[i].type.test(type) && _disableOverrides[i].subtype.test(subtype)) { - return false; - } - } - - return true; - } // `entityIDsToValidate()` (private) - // Collects the complete list of entityIDs related to the input entityIDs. - // - // Arguments - // `entityIDs` - Set or Array containing entityIDs. - // `graph` - graph containing the entities - // - // Returns - // Set containing entityIDs - // - - - function entityIDsToValidate(entityIDs, graph) { - var seen = new Set(); - var collected = new Set(); - entityIDs.forEach(function (entityID) { - // keep `seen` separate from `collected` because an `entityID` - // could have been added to `collected` as a related entity through an earlier pass - if (seen.has(entityID)) return; - seen.add(entityID); - var entity = graph.hasEntity(entityID); - if (!entity) return; - collected.add(entityID); // collect self - - var checkParentRels = [entity]; - - if (entity.type === 'node') { - graph.parentWays(entity).forEach(function (parentWay) { - collected.add(parentWay.id); // collect parent ways - - checkParentRels.push(parentWay); - }); - } else if (entity.type === 'relation') { - entity.members.forEach(function (member) { - return collected.add(member.id); - }); // collect members - } else if (entity.type === 'way') { - entity.nodes.forEach(function (nodeID) { - collected.add(nodeID); // collect child nodes - - graph._parentWays[nodeID].forEach(function (wayID) { - return collected.add(wayID); - }); // collect connected ways - - }); - } - - checkParentRels.forEach(function (entity) { - // collect parent relations - if (entity.type !== 'relation') { - // but not super-relations - graph.parentRelations(entity).forEach(function (parentRelation) { - return collected.add(parentRelation.id); - }); - } - }); - }); - return collected; } // `updateResolvedIssues()` (private) // Determine if any issues were resolved for the given entities. // This is called by `validate()` after validation of the head graph // + // Give the user credit for fixing an issue if: + // - the issue is in the base cache + // - the issue is not in the head cache + // - the user did something to one of the entities involved in the issue + // // Arguments - // `entityIDs` - Set containing entity IDs. + // `entityIDs` - Array containing entity IDs. // function updateResolvedIssues(entityIDs) { entityIDs.forEach(function (entityID) { - var headIssues = _headCache.issuesByEntityID[entityID]; var baseIssues = _baseCache.issuesByEntityID[entityID]; if (!baseIssues) return; baseIssues.forEach(function (issueID) { - if (headIssues && headIssues.has(issueID)) { + // Check if the user did something to one of the entities involved in this issue. + // (This issue could involve multiple entities, e.g. disconnected routable features) + var issue = _baseCache.issuesByIssueID[issueID]; + var userModified = (issue.entityIds || []).some(function (id) { + return _completeDiff.hasOwnProperty(id); + }); + + if (userModified && !_headCache.issuesByIssueID[issueID]) { + // issue seems fixed + _resolvedIssueIDs.add(issueID); + } else { // issue still not resolved _resolvedIssueIDs["delete"](issueID); // (did undo, or possibly fixed and then re-caused the issue) - } else { - _resolvedIssueIDs.add(issueID); } }); }); @@ -58791,7 +58788,7 @@ // Schedule validation for many entities. // // Arguments - // `entityIDs` - Set containing entity IDs. + // `entityIDs` - Array containing entity IDs. // `graph` - the graph to validate that contains those entities // `cache` - the cache to store results in (_headCache or _baseCache) // @@ -58801,29 +58798,35 @@ // - function validateEntitiesAsync(entityIDs, graph, cache) { + function validateEntitiesAsync(entityIDs, cache) { // Enqueue the work - var jobs = Array.from(entityIDs).map(function (entityID) { + var jobs = entityIDs.map(function (entityID) { if (cache.queuedEntityIDs.has(entityID)) return null; // queued already cache.queuedEntityIDs.add(entityID); return function () { - // clear caches for existing issues related to this entity + // Clear caches for existing issues related to this entity cache.uncacheEntityID(entityID); - cache.queuedEntityIDs["delete"](entityID); // detect new issues and update caches + cache.queuedEntityIDs["delete"](entityID); + var graph = cache.graph; + if (!graph) return; // was reset? var entity = graph.hasEntity(entityID); // Sanity check: don't validate deleted entities - if (entity) { - var result = validateEntity(entity, graph); + if (!entity) return; // In the head cache, only validate features that the user is responsible for - #8632 + // For example, a user can undo some work and an issue will still present in the + // head graph, but we don't want to credit the user for causing that issue. - if (result.provisional) { - // provisional result - cache.provisionalEntityIDs.add(entityID); // we'll need to revalidate this entity again later - } + if (cache.which === 'head' && !_completeDiff.hasOwnProperty(entityID)) return; // detect new issues and update caches - cache.cacheIssues(result.issues); // update cache + var result = validateEntity(entity, graph); + + if (result.provisional) { + // provisional result + cache.provisionalEntityIDs.add(entityID); // we'll need to revalidate this entity again later } + + cache.cacheIssues(result.issues); // update cache }; }).filter(Boolean); // Perform the work in chunks. // Because this will happen during idle callbacks, we want to choose a chunk size @@ -58858,8 +58861,7 @@ if (!cache.provisionalEntityIDs.size) return; // nothing to do - var graph = cache === _headCache ? _headGraph : context.history().base(); - validateEntitiesAsync(cache.provisionalEntityIDs, graph, cache); + validateEntitiesAsync(Array.from(cache.provisionalEntityIDs), cache); }, RETRY); _deferredST.add(handle); @@ -58876,8 +58878,7 @@ function processQueue(cache) { - // const which = (cache === _headCache) ? 'head' : 'base'; - // console.log(`${which} queue length ${cache.queue.length}`); + // console.log(`${cache.which} queue length ${cache.queue.length}`); if (!cache.queue.length) return Promise.resolve(); // we're done var chunk = cache.queue.pop(); @@ -58910,16 +58911,21 @@ // `_baseCache` for validation on the base graph (unedited) // `_headCache` for validation on the head graph (user edits applied) // + // Arguments + // `which` - just a String 'base' or 'head' to keep track of it + // - function validationCache() { + function validationCache(which) { var cache = { + which: which, + graph: null, queue: [], queuePromise: null, queuedEntityIDs: new Set(), provisionalEntityIDs: new Set(), issuesByIssueID: {}, // issue.id -> issue - issuesByEntityID: {} // entity.id -> set(issue.id) + issuesByEntityID: {} // entity.id -> Set(issue.id) }; @@ -59622,7 +59628,7 @@ // https://docs.microsoft.com/en-us/bingmaps/rest-services/imagery/get-imagery-metadata // https://docs.microsoft.com/en-us/bingmaps/rest-services/directly-accessing-the-bing-maps-tiles //fallback url template - data.template = 'https://ecn.t{switch:0,1,2,3}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=10555&n=z'; + data.template = 'https://ecn.t{switch:0,1,2,3}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&n=z'; var bing = rendererBackgroundSource(data); //var key = 'Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU'; // P2, JOSM, etc var key = 'Ak5oTE46TUbjRp08OFVcGpkARErDobfpuyNKa-W2mQ8wbt1K1KL8p1bIRwWwcF-Q'; // iD @@ -62145,3126 +62151,798 @@ }(data); }; - //[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF] - //[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040] - //[5] Name ::= NameStartChar (NameChar)* - var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/; //\u10000-\uEFFFF - - var nameChar = new RegExp("[\\-\\.0-9" + nameStartChar.source.slice(1, -1) + "\\u00B7\\u0300-\\u036F\\u203F-\\u2040]"); - var tagNamePattern = new RegExp('^' + nameStartChar.source + nameChar.source + '*(?:\:' + nameStartChar.source + nameChar.source + '*)?$'); //var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/ - //var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',') - //S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE - //S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE - - var S_TAG = 0; //tag name offerring + var $entries = objectToArray.entries; - var S_ATTR = 1; //attr name offerring - - var S_ATTR_SPACE = 2; //attr name end and space offer - - var S_EQ = 3; //=space? - - var S_ATTR_NOQUOT_VALUE = 4; //attr value(no quot value only) + // `Object.entries` method + // https://tc39.es/ecma262/#sec-object.entries + _export({ target: 'Object', stat: true }, { + entries: function entries(O) { + return $entries(O); + } + }); - var S_ATTR_END = 5; //attr value end and no space(quot end) + var _marked = /*#__PURE__*/regeneratorRuntime.mark(gpxGen), + _marked3 = /*#__PURE__*/regeneratorRuntime.mark(kmlGen); - var S_TAG_SPACE = 6; //(attr value end || tag end ) && (space offer) + // cast array x into numbers + // get the content of a text node, if any + function nodeVal(x) { + if (x && x.normalize) { + x.normalize(); + } - var S_TAG_CLOSE = 7; //closed el + return x && x.textContent || ""; + } // one Y child of X, if any, otherwise null - function XMLReader() {} - XMLReader.prototype = { - parse: function parse(source, defaultNSMap, entityMap) { - var domBuilder = this.domBuilder; - domBuilder.startDocument(); + function get1(x, y) { + var n = x.getElementsByTagName(y); + return n.length ? n[0] : null; + } - _copy(defaultNSMap, defaultNSMap = {}); + function getLineStyle(extensions) { + var style = {}; - _parse(source, defaultNSMap, entityMap, domBuilder, this.errorHandler); + if (extensions) { + var lineStyle = get1(extensions, "line"); - domBuilder.endDocument(); - } - }; + if (lineStyle) { + var color = nodeVal(get1(lineStyle, "color")), + opacity = parseFloat(nodeVal(get1(lineStyle, "opacity"))), + width = parseFloat(nodeVal(get1(lineStyle, "width"))); + if (color) style.stroke = color; + if (!isNaN(opacity)) style["stroke-opacity"] = opacity; // GPX width is in mm, convert to px with 96 px per inch - function _parse(source, defaultNSMapCopy, entityMap, domBuilder, errorHandler) { - function fixedFromCharCode(code) { - // String.prototype.fromCharCode does not supports - // > 2 bytes unicode chars directly - if (code > 0xffff) { - code -= 0x10000; - var surrogate1 = 0xd800 + (code >> 10), - surrogate2 = 0xdc00 + (code & 0x3ff); - return String.fromCharCode(surrogate1, surrogate2); - } else { - return String.fromCharCode(code); + if (!isNaN(width)) style["stroke-width"] = width * 96 / 25.4; } } - function entityReplacer(a) { - var k = a.slice(1, -1); - - if (k in entityMap) { - return entityMap[k]; - } else if (k.charAt(0) === '#') { - return fixedFromCharCode(parseInt(k.substr(1).replace('x', '0x'))); - } else { - errorHandler.error('entity not found:' + a); - return a; - } - } + return style; + } // get the contents of multiple text nodes, if present - function appendText(end) { - //has some bugs - if (end > start) { - var xt = source.substring(start, end).replace(/&#?\w+;/g, entityReplacer); - locator && position(start); - domBuilder.characters(xt, 0, end - start); - start = end; - } - } - function position(p, m) { - while (p >= lineEnd && (m = linePattern.exec(source))) { - lineStart = m.index; - lineEnd = lineStart + m[0].length; - locator.lineNumber++; //console.log('line++:',locator,startPos,endPos) - } + function getMulti(x, ys) { + var o = {}; + var n; + var k; - locator.columnNumber = p - lineStart + 1; + for (k = 0; k < ys.length; k++) { + n = get1(x, ys[k]); + if (n) o[ys[k]] = nodeVal(n); } - var lineStart = 0; - var lineEnd = 0; - var linePattern = /.*(?:\r\n?|\n)|.*$/g; - var locator = domBuilder.locator; - var parseStack = [{ - currentNSMap: defaultNSMapCopy - }]; - var closeMap = {}; - var start = 0; - - while (true) { - try { - var tagStart = source.indexOf('<', start); - - if (tagStart < 0) { - if (!source.substr(start).match(/^\s*$/)) { - var doc = domBuilder.doc; - var text = doc.createTextNode(source.substr(start)); - doc.appendChild(text); - domBuilder.currentElement = text; - } - - return; - } + return o; + } - if (tagStart > start) { - appendText(tagStart); - } + function getProperties$1(node) { + var prop = getMulti(node, ["name", "cmt", "desc", "type", "time", "keywords"]); // Parse additional data from our Garmin extension(s) - switch (source.charAt(tagStart + 1)) { - case '/': - var end = source.indexOf('>', tagStart + 3); - var tagName = source.substring(tagStart + 2, end); - var config = parseStack.pop(); + var extensions = node.getElementsByTagNameNS("http://www.garmin.com/xmlschemas/GpxExtensions/v3", "*"); - if (end < 0) { - tagName = source.substring(tagStart + 2).replace(/[\s<].*/, ''); //console.error('#@@@@@@'+tagName) + for (var i = 0; i < extensions.length; i++) { + var extension = extensions[i]; // Ignore nested extensions, like those on routepoints or trackpoints - errorHandler.error("end tag name: " + tagName + ' is not complete:' + config.tagName); - end = tagStart + 1 + tagName.length; - } else if (tagName.match(/\s - locator && position(tagStart); - end = parseInstruction(source, tagStart, domBuilder); - break; + if (!isNaN(e)) { + ll.push(e); + } + } - case '!': - // start) { - start = end; - } else { - //TODO: 这里有可能sax回退,有位置错误风险 - appendText(Math.max(tagStart, start) + 1); + extendedValues[plural][i] = val; } } - } - function copyLocator(f, t) { - t.lineNumber = f.lineNumber; - t.columnNumber = f.columnNumber; - return t; + return { + line: line, + times: times, + extendedValues: extendedValues + }; } - /** - * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack); - * @return end of the elementStartPart(end of elementEndPart for selfClosed el) - */ - - function parseElementStartPart(source, start, el, currentNSMap, entityReplacer, errorHandler) { - var attrName; - var value; - var p = ++start; - var s = S_TAG; //status + function getTrack(node) { + var segments = node.getElementsByTagName("trkseg"); + var track = []; + var times = []; + var extractedLines = []; - while (true) { - var c = source.charAt(p); - - switch (c) { - case '=': - if (s === S_ATTR) { - //attrName - attrName = source.slice(start, p); - s = S_EQ; - } else if (s === S_ATTR_SPACE) { - s = S_EQ; - } else { - //fatalError: equal must after attrName or space after attrName - throw new Error('attribute equal must after attrName'); - } + for (var i = 0; i < segments.length; i++) { + var line = getPoints$1(segments[i], "trkpt"); - break; + if (line) { + extractedLines.push(line); + if (line.times && line.times.length) times.push(line.times); + } + } - case '\'': - case '"': - if (s === S_EQ || s === S_ATTR //|| s == S_ATTR_SPACE - ) { - //equal - if (s === S_ATTR) { - errorHandler.warning('attribute value must after "="'); - attrName = source.slice(start, p); - } + if (extractedLines.length === 0) return; + var multi = extractedLines.length > 1; + var properties = Object.assign(getProperties$1(node), getLineStyle(get1(node, "extensions")), { + _gpxType: "trk" + }, times.length ? { + coordinateProperties: { + times: multi ? times : times[0] + } + } : {}); - start = p + 1; - p = source.indexOf(c, start); + for (var _i3 = 0; _i3 < extractedLines.length; _i3++) { + var _line = extractedLines[_i3]; + track.push(_line.line); - if (p > 0) { - value = source.slice(start, p).replace(/&#?\w+;/g, entityReplacer); - el.add(attrName, value, start - 1); - s = S_ATTR_END; - } else { - //fatalError: no end quot match - throw new Error('attribute value no end \'' + c + '\' match'); - } - } else if (s == S_ATTR_NOQUOT_VALUE) { - value = source.slice(start, p).replace(/&#?\w+;/g, entityReplacer); //console.log(attrName,value,start,p) + for (var _i4 = 0, _Object$entries = Object.entries(_line.extendedValues); _i4 < _Object$entries.length; _i4++) { + var _Object$entries$_i = _slicedToArray(_Object$entries[_i4], 2), + name = _Object$entries$_i[0], + val = _Object$entries$_i[1]; - el.add(attrName, value, start); //console.dir(el) + var props = properties; - errorHandler.warning('attribute "' + attrName + '" missed start quot(' + c + ')!!'); - start = p + 1; - s = S_ATTR_END; - } else { - //fatalError: no equal before - throw new Error('attribute value must after "="'); + if (name === "heart") { + if (!properties.coordinateProperties) { + properties.coordinateProperties = {}; } - break; - - case '/': - switch (s) { - case S_TAG: - el.setTagName(source.slice(start, p)); - - case S_ATTR_END: - case S_TAG_SPACE: - case S_TAG_CLOSE: - s = S_TAG_CLOSE; - el.closed = true; - - case S_ATTR_NOQUOT_VALUE: - case S_ATTR: - case S_ATTR_SPACE: - break; - //case S_EQ: - - default: - throw new Error("attribute invalid close char('/')"); - } + props = properties.coordinateProperties; + } - break; + if (multi) { + if (!props[name]) props[name] = extractedLines.map(function (line) { + return new Array(line.line.length).fill(null); + }); + props[name][_i3] = val; + } else { + props[name] = val; + } + } + } - case '': - //end document - //throw new Error('unexpected end of input') - errorHandler.error('unexpected end of input'); + return { + type: "Feature", + properties: properties, + geometry: multi ? { + type: "MultiLineString", + coordinates: track + } : { + type: "LineString", + coordinates: track[0] + } + }; + } - if (s == S_TAG) { - el.setTagName(source.slice(start, p)); - } + function getPoint(node) { + return { + type: "Feature", + properties: Object.assign(getProperties$1(node), getMulti(node, ["sym"])), + geometry: { + type: "Point", + coordinates: coordPair$1(node).coordinates + } + }; + } - return p; + function gpxGen(doc) { + var tracks, routes, waypoints, i, feature, _i5, _feature, _i6; - case '>': - switch (s) { - case S_TAG: - el.setTagName(source.slice(start, p)); + return regeneratorRuntime.wrap(function gpxGen$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + tracks = doc.getElementsByTagName("trk"); + routes = doc.getElementsByTagName("rte"); + waypoints = doc.getElementsByTagName("wpt"); + i = 0; - case S_ATTR_END: - case S_TAG_SPACE: - case S_TAG_CLOSE: + case 4: + if (!(i < tracks.length)) { + _context.next = 12; break; - //normal - - case S_ATTR_NOQUOT_VALUE: //Compatible state - - case S_ATTR: - value = source.slice(start, p); - - if (value.slice(-1) === '/') { - el.closed = true; - value = value.slice(0, -1); - } - - case S_ATTR_SPACE: - if (s === S_ATTR_SPACE) { - value = attrName; - } - - if (s == S_ATTR_NOQUOT_VALUE) { - errorHandler.warning('attribute "' + value + '" missed quot(")!!'); - el.add(attrName, value.replace(/&#?\w+;/g, entityReplacer), start); - } else { - if (currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !value.match(/^(?:disabled|checked|selected)$/i)) { - errorHandler.warning('attribute "' + value + '" missed value!! "' + value + '" instead!!'); - } + } - el.add(value, value, start); - } + feature = getTrack(tracks[i]); + if (!feature) { + _context.next = 9; break; + } - case S_EQ: - throw new Error('attribute value missed!!'); - } // console.log(tagName,tagNamePattern,tagNamePattern.test(tagName)) - - - return p; - - /*xml space '\x20' | #x9 | #xD | #xA; */ - - case "\x80": - c = ' '; + _context.next = 9; + return feature; - default: - if (c <= ' ') { - //space - switch (s) { - case S_TAG: - el.setTagName(source.slice(start, p)); //tagName + case 9: + i++; + _context.next = 4; + break; - s = S_TAG_SPACE; - break; + case 12: + _i5 = 0; - case S_ATTR: - attrName = source.slice(start, p); - s = S_ATTR_SPACE; - break; + case 13: + if (!(_i5 < routes.length)) { + _context.next = 21; + break; + } - case S_ATTR_NOQUOT_VALUE: - var value = source.slice(start, p).replace(/&#?\w+;/g, entityReplacer); - errorHandler.warning('attribute "' + value + '" missed quot(")!!'); - el.add(attrName, value, start); + _feature = getRoute(routes[_i5]); - case S_ATTR_END: - s = S_TAG_SPACE; - break; - //case S_TAG_SPACE: - //case S_EQ: - //case S_ATTR_SPACE: - // void();break; - //case S_TAG_CLOSE: - //ignore warning + if (!_feature) { + _context.next = 18; + break; } - } else { - //not space - //S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE - //S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE - switch (s) { - //case S_TAG:void();break; - //case S_ATTR:void();break; - //case S_ATTR_NOQUOT_VALUE:void();break; - case S_ATTR_SPACE: - el.tagName; - - if (currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !attrName.match(/^(?:disabled|checked|selected)$/i)) { - errorHandler.warning('attribute "' + attrName + '" missed value!! "' + attrName + '" instead2!!'); - } - el.add(attrName, attrName, start); - start = p; - s = S_ATTR; - break; - - case S_ATTR_END: - errorHandler.warning('attribute space is required"' + attrName + '"!!'); + _context.next = 18; + return _feature; - case S_TAG_SPACE: - s = S_ATTR; - start = p; - break; + case 18: + _i5++; + _context.next = 13; + break; - case S_EQ: - s = S_ATTR_NOQUOT_VALUE; - start = p; - break; + case 21: + _i6 = 0; - case S_TAG_CLOSE: - throw new Error("elements closed character '/' and '>' must be connected to"); + case 22: + if (!(_i6 < waypoints.length)) { + _context.next = 28; + break; } - } - } //end outer switch - //console.log('p++',p) + _context.next = 25; + return getPoint(waypoints[_i6]); + case 25: + _i6++; + _context.next = 22; + break; - p++; - } + case 28: + case "end": + return _context.stop(); + } + } + }, _marked); } - /** - * @return true if has new namespace define - */ - - function appendElement(el, domBuilder, currentNSMap) { - var tagName = el.tagName; - var localNSMap = null; //var currentNSMap = parseStack[parseStack.length-1].currentNSMap; + function gpx(doc) { + return { + type: "FeatureCollection", + features: Array.from(gpxGen(doc)) + }; + } - var i = el.length; + var removeSpace = /\s*/g; + var trimSpace = /^\s*|\s*$/g; + var splitSpace = /\s+/; // generate a short, numeric hash of a string - while (i--) { - var a = el[i]; - var qName = a.qName; - var value = a.value; - var nsp = qName.indexOf(':'); - - if (nsp > 0) { - var prefix = a.prefix = qName.slice(0, nsp); - var localName = qName.slice(nsp + 1); - var nsPrefix = prefix === 'xmlns' && localName; - } else { - localName = qName; - prefix = null; - nsPrefix = qName === 'xmlns' && ''; - } //can not set prefix,because prefix !== '' + function okhash(x) { + if (!x || !x.length) return 0; + var h = 0; + for (var i = 0; i < x.length; i++) { + h = (h << 5) - h + x.charCodeAt(i) | 0; + } - a.localName = localName; //prefix == null for no ns prefix attribute + return h; + } // get one coordinate from a coordinate array, if any - if (nsPrefix !== false) { - //hack!! - if (localNSMap == null) { - localNSMap = {}; //console.log(currentNSMap,0) - _copy(currentNSMap, currentNSMap = {}); //console.log(currentNSMap,1) + function coord1(v) { + return v.replace(removeSpace, "").split(",").map(parseFloat); + } // get all coordinates from a coordinate array as [[],[]] - } - currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value; - a.uri = 'http://www.w3.org/2000/xmlns/'; - domBuilder.startPrefixMapping(nsPrefix, value); - } - } + function coord(v) { + return v.replace(trimSpace, "").split(splitSpace).map(coord1); + } - var i = el.length; + function xml2str(node) { + if (node.xml !== undefined) return node.xml; - while (i--) { - a = el[i]; - var prefix = a.prefix; + if (node.tagName) { + var output = node.tagName; - if (prefix) { - //no prefix attribute has no namespace - if (prefix === 'xml') { - a.uri = 'http://www.w3.org/XML/1998/namespace'; - } + for (var i = 0; i < node.attributes.length; i++) { + output += node.attributes[i].name + node.attributes[i].value; + } - if (prefix !== 'xmlns') { - a.uri = currentNSMap[prefix || '']; //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)} - } + for (var _i9 = 0; _i9 < node.childNodes.length; _i9++) { + output += xml2str(node.childNodes[_i9]); } - } - var nsp = tagName.indexOf(':'); + return output; + } - if (nsp > 0) { - prefix = el.prefix = tagName.slice(0, nsp); - localName = el.localName = tagName.slice(nsp + 1); - } else { - prefix = null; //important!! + if (node.nodeName === "#text") { + return (node.nodeValue || node.value || "").trim(); + } - localName = el.localName = tagName; - } //no prefix element has default namespace + if (node.nodeName === "#cdata-section") { + return node.nodeValue; + } + return ""; + } - var ns = el.uri = currentNSMap[prefix || '']; - domBuilder.startElement(ns, localName, tagName, el); //endPrefixMapping and startPrefixMapping have not any help for dom builder - //localNSMap = null + var geotypes = ["Polygon", "LineString", "Point", "Track", "gx:Track"]; - if (el.closed) { - domBuilder.endElement(ns, localName, tagName); + function kmlColor(properties, elem, prefix) { + var v = nodeVal(get1(elem, "color")) || ""; + var colorProp = prefix == "stroke" || prefix === "fill" ? prefix : prefix + "-color"; - if (localNSMap) { - for (prefix in localNSMap) { - domBuilder.endPrefixMapping(prefix); - } - } - } else { - el.currentNSMap = currentNSMap; - el.localNSMap = localNSMap; //parseStack.push(el); + if (v.substr(0, 1) === "#") { + v = v.substr(1); + } - return true; + if (v.length === 6 || v.length === 3) { + properties[colorProp] = v; + } else if (v.length === 8) { + properties[prefix + "-opacity"] = parseInt(v.substr(0, 2), 16) / 255; + properties[colorProp] = "#" + v.substr(6, 2) + v.substr(4, 2) + v.substr(2, 2); } } - function parseHtmlSpecialContent(source, elStartEnd, tagName, entityReplacer, domBuilder) { - if (/^(?:script|textarea)$/i.test(tagName)) { - var elEndStart = source.indexOf('', elStartEnd); - var text = source.substring(elStartEnd + 1, elEndStart); + function numericProperty(properties, elem, source, target) { + var val = parseFloat(nodeVal(get1(elem, source))); + if (!isNaN(val)) properties[target] = val; + } - if (/[&<]/.test(text)) { - if (/^script$/i.test(tagName)) { - //if(!/\]\]>/.test(text)){ - //lexHandler.startCDATA(); - domBuilder.characters(text, 0, text.length); //lexHandler.endCDATA(); + function gxCoords(root) { + var elems = root.getElementsByTagName("coord"); + var coords = []; + var times = []; + if (elems.length === 0) elems = root.getElementsByTagName("gx:coord"); - return elEndStart; //} - } //}else{//text area + for (var i = 0; i < elems.length; i++) { + coords.push(nodeVal(elems[i]).split(" ").map(parseFloat)); + } + var timeElems = root.getElementsByTagName("when"); - text = text.replace(/&#?\w+;/g, entityReplacer); - domBuilder.characters(text, 0, text.length); - return elEndStart; //} - } + for (var j = 0; j < timeElems.length; j++) { + times.push(nodeVal(timeElems[j])); } - return elStartEnd + 1; + return { + coords: coords, + times: times + }; } - function fixSelfClosed(source, elStartEnd, tagName, closeMap) { - //if(tagName in closeMap){ - var pos = closeMap[tagName]; - - if (pos == null) { - //console.log(tagName) - pos = source.lastIndexOf(''); - - if (pos < elStartEnd) { - //忘记闭合 - pos = source.lastIndexOf('', start + 4); //append comment source.substring(4,end)//"); - - case DOCUMENT_TYPE_NODE: - var pubid = node.publicId; - var sysid = node.systemId; - buf.push(''); - } else if (sysid && sysid != '.') { - buf.push(' SYSTEM "', sysid, '">'); - } else { - var sub = node.internalSubset; - - if (sub) { - buf.push(" [", sub, "]"); - } - - buf.push(">"); - } - - return; - - case PROCESSING_INSTRUCTION_NODE: - return buf.push(""); - - case ENTITY_REFERENCE_NODE: - return buf.push('&', node.nodeName, ';'); - //case ENTITY_NODE: - //case NOTATION_NODE: - - default: - buf.push('??', node.nodeName); - } - } - - function _importNode(doc, node, deep) { - var node2; - - switch (node.nodeType) { - case ELEMENT_NODE: - node2 = node.cloneNode(false); - node2.ownerDocument = doc; - //var attrs = node2.attributes; - //var len = attrs.length; - //for(var i=0;i', - 'amp': '&', - 'quot': '"', - 'apos': "'" - }; - - if (locator) { - domBuilder.setDocumentLocator(locator); - } - - sax.errorHandler = buildErrorHandler(errorHandler, domBuilder, locator); - sax.domBuilder = options.domBuilder || domBuilder; - - if (/\/x?html?$/.test(mimeType)) { - entityMap.nbsp = '\xa0'; - entityMap.copy = '\xa9'; - defaultNSMap[''] = 'http://www.w3.org/1999/xhtml'; - } - - defaultNSMap.xml = defaultNSMap.xml || 'http://www.w3.org/XML/1998/namespace'; - - if (source) { - sax.parse(source, defaultNSMap, entityMap); - } else { - sax.errorHandler.error("invalid doc source"); - } - - return domBuilder.doc; - }; - - function buildErrorHandler(errorImpl, domBuilder, locator) { - if (!errorImpl) { - if (domBuilder instanceof DOMHandler) { - return domBuilder; - } - - errorImpl = domBuilder; - } - - var errorHandler = {}; - var isCallback = errorImpl instanceof Function; - locator = locator || {}; - - function build(key) { - var fn = errorImpl[key]; - - if (!fn && isCallback) { - fn = errorImpl.length == 2 ? function (msg) { - errorImpl(key, msg); - } : errorImpl; - } - - errorHandler[key] = fn && function (msg) { - fn('[xmldom ' + key + ']\t' + msg + _locator(locator)); - } || function () {}; - } - - build('warning'); - build('error'); - build('fatalError'); - return errorHandler; - } //console.log('#\n\n\n\n\n\n\n####') - - /** - * +ContentHandler+ErrorHandler - * +LexicalHandler+EntityResolver2 - * -DeclHandler-DTDHandler - * - * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler - * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2 - * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html - */ - - - function DOMHandler() { - this.cdata = false; - } - - function position(locator, node) { - node.lineNumber = locator.lineNumber; - node.columnNumber = locator.columnNumber; - } - /** - * @see org.xml.sax.ContentHandler#startDocument - * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html - */ - - - DOMHandler.prototype = { - startDocument: function startDocument() { - this.doc = new DOMImplementation().createDocument(null, null, null); - - if (this.locator) { - this.doc.documentURI = this.locator.systemId; - } - }, - startElement: function startElement(namespaceURI, localName, qName, attrs) { - var doc = this.doc; - var el = doc.createElementNS(namespaceURI, qName || localName); - var len = attrs.length; - appendElement(this, el); - this.currentElement = el; - this.locator && position(this.locator, el); - - for (var i = 0; i < len; i++) { - var namespaceURI = attrs.getURI(i); - var value = attrs.getValue(i); - var qName = attrs.getQName(i); - var attr = doc.createAttributeNS(namespaceURI, qName); - this.locator && position(attrs.getLocator(i), attr); - attr.value = attr.nodeValue = value; - el.setAttributeNode(attr); - } - }, - endElement: function endElement(namespaceURI, localName, qName) { - var current = this.currentElement; - current.tagName; - this.currentElement = current.parentNode; - }, - startPrefixMapping: function startPrefixMapping(prefix, uri) {}, - endPrefixMapping: function endPrefixMapping(prefix) {}, - processingInstruction: function processingInstruction(target, data) { - var ins = this.doc.createProcessingInstruction(target, data); - this.locator && position(this.locator, ins); - appendElement(this, ins); - }, - ignorableWhitespace: function ignorableWhitespace(ch, start, length) {}, - characters: function characters(chars, start, length) { - chars = _toString.apply(this, arguments); //console.log(chars) - - if (chars) { - if (this.cdata) { - var charNode = this.doc.createCDATASection(chars); - } else { - var charNode = this.doc.createTextNode(chars); - } - - if (this.currentElement) { - this.currentElement.appendChild(charNode); - } else if (/^\s*$/.test(chars)) { - this.doc.appendChild(charNode); //process xml - } - - this.locator && position(this.locator, charNode); - } - }, - skippedEntity: function skippedEntity(name) {}, - endDocument: function endDocument() { - this.doc.normalize(); - }, - setDocumentLocator: function setDocumentLocator(locator) { - if (this.locator = locator) { - // && !('lineNumber' in locator)){ - locator.lineNumber = 0; - } - }, - //LexicalHandler - comment: function comment(chars, start, length) { - chars = _toString.apply(this, arguments); - var comm = this.doc.createComment(chars); - this.locator && position(this.locator, comm); - appendElement(this, comm); - }, - startCDATA: function startCDATA() { - //used in characters() methods - this.cdata = true; - }, - endCDATA: function endCDATA() { - this.cdata = false; - }, - startDTD: function startDTD(name, publicId, systemId) { - var impl = this.doc.implementation; - - if (impl && impl.createDocumentType) { - var dt = impl.createDocumentType(name, publicId, systemId); - this.locator && position(this.locator, dt); - appendElement(this, dt); - } - }, - - /** - * @see org.xml.sax.ErrorHandler - * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html - */ - warning: function warning(error) { - console.warn('[xmldom warning]\t' + error, _locator(this.locator)); - }, - error: function error(_error) { - console.error('[xmldom error]\t' + _error, _locator(this.locator)); - }, - fatalError: function fatalError(error) { - console.error('[xmldom fatalError]\t' + error, _locator(this.locator)); - throw error; - } - }; - - function _locator(l) { - if (l) { - return '\n@' + (l.systemId || '') + '#[line:' + l.lineNumber + ',col:' + l.columnNumber + ']'; - } - } - - function _toString(chars, start, length) { - if (typeof chars == 'string') { - return chars.substr(start, length); - } else { - //java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)") - if (chars.length >= start + length || start) { - return new java.lang.String(chars, start, length) + ''; - } - - return chars; - } - } - /* - * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html - * used method of org.xml.sax.ext.LexicalHandler: - * #comment(chars, start, length) - * #startCDATA() - * #endCDATA() - * #startDTD(name, publicId, systemId) - * - * - * IGNORED method of org.xml.sax.ext.LexicalHandler: - * #endDTD() - * #startEntity(name) - * #endEntity(name) - * - * - * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html - * IGNORED method of org.xml.sax.ext.DeclHandler - * #attributeDecl(eName, aName, type, mode, value) - * #elementDecl(name, model) - * #externalEntityDecl(name, publicId, systemId) - * #internalEntityDecl(name, value) - * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html - * IGNORED method of org.xml.sax.EntityResolver2 - * #resolveEntity(String name,String publicId,String baseURI,String systemId) - * #resolveEntity(publicId, systemId) - * #getExternalSubset(name, baseURI) - * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html - * IGNORED method of org.xml.sax.DTDHandler - * #notationDecl(name, publicId, systemId) {}; - * #unparsedEntityDecl(name, publicId, systemId, notationName) {}; - */ - - - "endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g, function (key) { - DOMHandler.prototype[key] = function () { - return null; - }; - }); - /* Private static helpers treated below as private instance methods, so don't need to add these to the public API; we might use a Relator to also get rid of non-standard public properties */ - - function appendElement(hander, node) { - if (!hander.currentElement) { - hander.doc.appendChild(node); - } else { - hander.currentElement.appendChild(node); - } - } //appendChild and setAttributeNS are preformance key - //if(typeof require == 'function'){ - - - var XMLReader = sax.XMLReader; - var DOMImplementation = exports.DOMImplementation = dom.DOMImplementation; - exports.XMLSerializer = dom.XMLSerializer; - exports.DOMParser = DOMParser; //} - }); - - var togeojson = createCommonjsModule(function (module, exports) { - var toGeoJSON = function () { - - var removeSpace = /\s*/g, - trimSpace = /^\s*|\s*$/g, - splitSpace = /\s+/; // generate a short, numeric hash of a string - - function okhash(x) { - if (!x || !x.length) return 0; - - for (var i = 0, h = 0; i < x.length; i++) { - h = (h << 5) - h + x.charCodeAt(i) | 0; - } - - return h; - } // all Y children of X - - - function get(x, y) { - return x.getElementsByTagName(y); - } - - function attr(x, y) { - return x.getAttribute(y); - } - - function attrf(x, y) { - return parseFloat(attr(x, y)); - } // one Y child of X, if any, otherwise null - - - function get1(x, y) { - var n = get(x, y); - return n.length ? n[0] : null; - } // https://developer.mozilla.org/en-US/docs/Web/API/Node.normalize - - - function norm(el) { - if (el.normalize) { - el.normalize(); - } - - return el; - } // cast array x into numbers - - - function numarray(x) { - for (var j = 0, o = []; j < x.length; j++) { - o[j] = parseFloat(x[j]); - } - - return o; - } // get the content of a text node, if any - - - function nodeVal(x) { - if (x) { - norm(x); - } - - return x && x.textContent || ''; - } // get the contents of multiple text nodes, if present - - - function getMulti(x, ys) { - var o = {}, - n, - k; - - for (k = 0; k < ys.length; k++) { - n = get1(x, ys[k]); - if (n) o[ys[k]] = nodeVal(n); - } - - return o; - } // add properties of Y to X, overwriting if present in both - - - function extend(x, y) { - for (var k in y) { - x[k] = y[k]; - } - } // get one coordinate from a coordinate array, if any - - - function coord1(v) { - return numarray(v.replace(removeSpace, '').split(',')); - } // get all coordinates from a coordinate array as [[],[]] - - - function coord(v) { - var coords = v.replace(trimSpace, '').split(splitSpace), - o = []; - - for (var i = 0; i < coords.length; i++) { - o.push(coord1(coords[i])); - } - - return o; - } - - function coordPair(x) { - var ll = [attrf(x, 'lon'), attrf(x, 'lat')], - ele = get1(x, 'ele'), - // handle namespaced attribute in browser - heartRate = get1(x, 'gpxtpx:hr') || get1(x, 'hr'), - time = get1(x, 'time'), - e; - - if (ele) { - e = parseFloat(nodeVal(ele)); - - if (!isNaN(e)) { - ll.push(e); - } - } - - return { - coordinates: ll, - time: time ? nodeVal(time) : null, - heartRate: heartRate ? parseFloat(nodeVal(heartRate)) : null - }; - } // create a new feature collection parent object - - - function fc() { - return { - type: 'FeatureCollection', - features: [] - }; - } - - var serializer; - - if (typeof XMLSerializer !== 'undefined') { - /* istanbul ignore next */ - serializer = new XMLSerializer(); // only require xmldom in a node environment - } else if ((typeof process === "undefined" ? "undefined" : _typeof(process)) === 'object' && !process.browser) { - serializer = new domParser.XMLSerializer(); - } - - function xml2str(str) { - // IE9 will create a new XMLSerializer but it'll crash immediately. - // This line is ignored because we don't run coverage tests in IE9 - - /* istanbul ignore next */ - if (str.xml !== undefined) return str.xml; - return serializer.serializeToString(str); - } - - var t = { - kml: function kml(doc) { - var gj = fc(), - // styleindex keeps track of hashed styles in order to match features - styleIndex = {}, - styleByHash = {}, - // stylemapindex keeps track of style maps to expose in properties - styleMapIndex = {}, - // atomic geospatial types supported by KML - MultiGeometry is - // handled separately - geotypes = ['Polygon', 'LineString', 'Point', 'Track', 'gx:Track'], - // all root placemarks in the file - placemarks = get(doc, 'Placemark'), - styles = get(doc, 'Style'), - styleMaps = get(doc, 'StyleMap'); - - for (var k = 0; k < styles.length; k++) { - var hash = okhash(xml2str(styles[k])).toString(16); - styleIndex['#' + attr(styles[k], 'id')] = hash; - styleByHash[hash] = styles[k]; - } - - for (var l = 0; l < styleMaps.length; l++) { - styleIndex['#' + attr(styleMaps[l], 'id')] = okhash(xml2str(styleMaps[l])).toString(16); - var pairs = get(styleMaps[l], 'Pair'); - var pairsMap = {}; - - for (var m = 0; m < pairs.length; m++) { - pairsMap[nodeVal(get1(pairs[m], 'key'))] = nodeVal(get1(pairs[m], 'styleUrl')); - } - - styleMapIndex['#' + attr(styleMaps[l], 'id')] = pairsMap; - } - - for (var j = 0; j < placemarks.length; j++) { - gj.features = gj.features.concat(getPlacemark(placemarks[j])); - } - - function kmlColor(v) { - var color, opacity; - v = v || ''; - - if (v.substr(0, 1) === '#') { - v = v.substr(1); - } - - if (v.length === 6 || v.length === 3) { - color = v; - } - - if (v.length === 8) { - opacity = parseInt(v.substr(0, 2), 16) / 255; - color = '#' + v.substr(6, 2) + v.substr(4, 2) + v.substr(2, 2); - } - - return [color, isNaN(opacity) ? undefined : opacity]; - } - - function gxCoord(v) { - return numarray(v.split(' ')); - } - - function gxCoords(root) { - var elems = get(root, 'coord'), - coords = [], - times = []; - if (elems.length === 0) elems = get(root, 'gx:coord'); - - for (var i = 0; i < elems.length; i++) { - coords.push(gxCoord(nodeVal(elems[i]))); - } - - var timeElems = get(root, 'when'); - - for (var j = 0; j < timeElems.length; j++) { - times.push(nodeVal(timeElems[j])); - } - - return { - coords: coords, - times: times - }; - } - - function getGeometry(root) { - var geomNode, - geomNodes, - i, - j, - k, - geoms = [], - coordTimes = []; - - if (get1(root, 'MultiGeometry')) { - return getGeometry(get1(root, 'MultiGeometry')); - } - - if (get1(root, 'MultiTrack')) { - return getGeometry(get1(root, 'MultiTrack')); - } - - if (get1(root, 'gx:MultiTrack')) { - return getGeometry(get1(root, 'gx:MultiTrack')); - } - - for (i = 0; i < geotypes.length; i++) { - geomNodes = get(root, geotypes[i]); - - if (geomNodes) { - for (j = 0; j < geomNodes.length; j++) { - geomNode = geomNodes[j]; - - if (geotypes[i] === 'Point') { - geoms.push({ - type: 'Point', - coordinates: coord1(nodeVal(get1(geomNode, 'coordinates'))) - }); - } else if (geotypes[i] === 'LineString') { - geoms.push({ - type: 'LineString', - coordinates: coord(nodeVal(get1(geomNode, 'coordinates'))) - }); - } else if (geotypes[i] === 'Polygon') { - var rings = get(geomNode, 'LinearRing'), - coords = []; - - for (k = 0; k < rings.length; k++) { - coords.push(coord(nodeVal(get1(rings[k], 'coordinates')))); - } - - geoms.push({ - type: 'Polygon', - coordinates: coords - }); - } else if (geotypes[i] === 'Track' || geotypes[i] === 'gx:Track') { - var track = gxCoords(geomNode); - geoms.push({ - type: 'LineString', - coordinates: track.coords - }); - if (track.times.length) coordTimes.push(track.times); - } - } - } - } - - return { - geoms: geoms, - coordTimes: coordTimes - }; - } - - function getPlacemark(root) { - var geomsAndTimes = getGeometry(root), - i, - properties = {}, - name = nodeVal(get1(root, 'name')), - address = nodeVal(get1(root, 'address')), - styleUrl = nodeVal(get1(root, 'styleUrl')), - description = nodeVal(get1(root, 'description')), - timeSpan = get1(root, 'TimeSpan'), - timeStamp = get1(root, 'TimeStamp'), - extendedData = get1(root, 'ExtendedData'), - lineStyle = get1(root, 'LineStyle'), - polyStyle = get1(root, 'PolyStyle'), - visibility = get1(root, 'visibility'); - if (!geomsAndTimes.geoms.length) return []; - if (name) properties.name = name; - if (address) properties.address = address; - - if (styleUrl) { - if (styleUrl[0] !== '#') { - styleUrl = '#' + styleUrl; - } - - properties.styleUrl = styleUrl; - - if (styleIndex[styleUrl]) { - properties.styleHash = styleIndex[styleUrl]; - } - - if (styleMapIndex[styleUrl]) { - properties.styleMapHash = styleMapIndex[styleUrl]; - properties.styleHash = styleIndex[styleMapIndex[styleUrl].normal]; - } // Try to populate the lineStyle or polyStyle since we got the style hash - - - var style = styleByHash[properties.styleHash]; - - if (style) { - if (!lineStyle) lineStyle = get1(style, 'LineStyle'); - if (!polyStyle) polyStyle = get1(style, 'PolyStyle'); - } - } - - if (description) properties.description = description; - - if (timeSpan) { - var begin = nodeVal(get1(timeSpan, 'begin')); - var end = nodeVal(get1(timeSpan, 'end')); - properties.timespan = { - begin: begin, - end: end - }; - } - - if (timeStamp) { - properties.timestamp = nodeVal(get1(timeStamp, 'when')); - } - - if (lineStyle) { - var linestyles = kmlColor(nodeVal(get1(lineStyle, 'color'))), - color = linestyles[0], - opacity = linestyles[1], - width = parseFloat(nodeVal(get1(lineStyle, 'width'))); - if (color) properties.stroke = color; - if (!isNaN(opacity)) properties['stroke-opacity'] = opacity; - if (!isNaN(width)) properties['stroke-width'] = width; - } - - if (polyStyle) { - var polystyles = kmlColor(nodeVal(get1(polyStyle, 'color'))), - pcolor = polystyles[0], - popacity = polystyles[1], - fill = nodeVal(get1(polyStyle, 'fill')), - outline = nodeVal(get1(polyStyle, 'outline')); - if (pcolor) properties.fill = pcolor; - if (!isNaN(popacity)) properties['fill-opacity'] = popacity; - if (fill) properties['fill-opacity'] = fill === '1' ? properties['fill-opacity'] || 1 : 0; - if (outline) properties['stroke-opacity'] = outline === '1' ? properties['stroke-opacity'] || 1 : 0; - } - - if (extendedData) { - var datas = get(extendedData, 'Data'), - simpleDatas = get(extendedData, 'SimpleData'); - - for (i = 0; i < datas.length; i++) { - properties[datas[i].getAttribute('name')] = nodeVal(get1(datas[i], 'value')); - } - - for (i = 0; i < simpleDatas.length; i++) { - properties[simpleDatas[i].getAttribute('name')] = nodeVal(simpleDatas[i]); - } - } - - if (visibility) { - properties.visibility = nodeVal(visibility); - } - - if (geomsAndTimes.coordTimes.length) { - properties.coordTimes = geomsAndTimes.coordTimes.length === 1 ? geomsAndTimes.coordTimes[0] : geomsAndTimes.coordTimes; - } - - var feature = { - type: 'Feature', - geometry: geomsAndTimes.geoms.length === 1 ? geomsAndTimes.geoms[0] : { - type: 'GeometryCollection', - geometries: geomsAndTimes.geoms - }, - properties: properties - }; - if (attr(root, 'id')) feature.id = attr(root, 'id'); - return [feature]; - } - - return gj; - }, - gpx: function gpx(doc) { - var i, - tracks = get(doc, 'trk'), - routes = get(doc, 'rte'), - waypoints = get(doc, 'wpt'), - // a feature collection - gj = fc(), - feature; - - for (i = 0; i < tracks.length; i++) { - feature = getTrack(tracks[i]); - if (feature) gj.features.push(feature); - } - - for (i = 0; i < routes.length; i++) { - feature = getRoute(routes[i]); - if (feature) gj.features.push(feature); - } - - for (i = 0; i < waypoints.length; i++) { - gj.features.push(getPoint(waypoints[i])); - } - - function getPoints(node, pointname) { - var pts = get(node, pointname), - line = [], - times = [], - heartRates = [], - l = pts.length; - if (l < 2) return {}; // Invalid line in GeoJSON - - for (var i = 0; i < l; i++) { - var c = coordPair(pts[i]); - line.push(c.coordinates); - if (c.time) times.push(c.time); - if (c.heartRate) heartRates.push(c.heartRate); - } - - return { - line: line, - times: times, - heartRates: heartRates - }; - } - - function getTrack(node) { - var segments = get(node, 'trkseg'), - track = [], - times = [], - heartRates = [], - line; - - for (var i = 0; i < segments.length; i++) { - line = getPoints(segments[i], 'trkpt'); - - if (line) { - if (line.line) track.push(line.line); - if (line.times && line.times.length) times.push(line.times); - if (line.heartRates && line.heartRates.length) heartRates.push(line.heartRates); - } - } - - if (track.length === 0) return; - var properties = getProperties(node); - extend(properties, getLineStyle(get1(node, 'extensions'))); - if (times.length) properties.coordTimes = track.length === 1 ? times[0] : times; - if (heartRates.length) properties.heartRates = track.length === 1 ? heartRates[0] : heartRates; - return { - type: 'Feature', - properties: properties, - geometry: { - type: track.length === 1 ? 'LineString' : 'MultiLineString', - coordinates: track.length === 1 ? track[0] : track - } - }; - } - - function getRoute(node) { - var line = getPoints(node, 'rtept'); - if (!line.line) return; - var prop = getProperties(node); - extend(prop, getLineStyle(get1(node, 'extensions'))); - var routeObj = { - type: 'Feature', - properties: prop, - geometry: { - type: 'LineString', - coordinates: line.line - } - }; - return routeObj; - } - - function getPoint(node) { - var prop = getProperties(node); - extend(prop, getMulti(node, ['sym'])); - return { - type: 'Feature', - properties: prop, - geometry: { - type: 'Point', - coordinates: coordPair(node).coordinates - } - }; - } - - function getLineStyle(extensions) { - var style = {}; - - if (extensions) { - var lineStyle = get1(extensions, 'line'); - - if (lineStyle) { - var color = nodeVal(get1(lineStyle, 'color')), - opacity = parseFloat(nodeVal(get1(lineStyle, 'opacity'))), - width = parseFloat(nodeVal(get1(lineStyle, 'width'))); - if (color) style.stroke = color; - if (!isNaN(opacity)) style['stroke-opacity'] = opacity; // GPX width is in mm, convert to px with 96 px per inch - - if (!isNaN(width)) style['stroke-width'] = width * 96 / 25.4; - } - } - - return style; - } - - function getProperties(node) { - var prop = getMulti(node, ['name', 'cmt', 'desc', 'type', 'time', 'keywords']), - links = get(node, 'link'); - if (links.length) prop.links = []; - - for (var i = 0, link; i < links.length; i++) { - link = { - href: attr(links[i], 'href') - }; - extend(link, getMulti(links[i], ['text', 'type'])); - prop.links.push(link); - } - - return prop; - } - - return gj; - } - }; - return t; - }(); - - module.exports = toGeoJSON; - }); - - var _initialized = false; - var _enabled = false; - - var _geojson; - - function svgData(projection, context, dispatch) { - var throttledRedraw = throttle(function () { - dispatch.call('change'); - }, 1000); - - var _showLabels = true; - var detected = utilDetect(); - var layer = select(null); - - var _vtService; - - var _fileList; - - var _template; - - var _src; - - function init() { - if (_initialized) return; // run once - - _geojson = {}; - _enabled = true; - - function over(d3_event) { - d3_event.stopPropagation(); - d3_event.preventDefault(); - d3_event.dataTransfer.dropEffect = 'copy'; - } - - context.container().attr('dropzone', 'copy').on('drop.svgData', function (d3_event) { - d3_event.stopPropagation(); - d3_event.preventDefault(); - if (!detected.filedrop) return; - drawData.fileList(d3_event.dataTransfer.files); - }).on('dragenter.svgData', over).on('dragexit.svgData', over).on('dragover.svgData', over); - _initialized = true; - } - - function getService() { - if (services.vectorTile && !_vtService) { - _vtService = services.vectorTile; - - _vtService.event.on('loadedData', throttledRedraw); - } else if (!services.vectorTile && _vtService) { - _vtService = null; - } - - return _vtService; - } - - function showLayer() { - layerOn(); - layer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end', function () { - dispatch.call('change'); - }); - } - - function hideLayer() { - throttledRedraw.cancel(); - layer.transition().duration(250).style('opacity', 0).on('end', layerOff); - } - - function layerOn() { - layer.style('display', 'block'); - } + function layerOn() { + layer.style('display', 'block'); + } function layerOff() { layer.selectAll('.viewfield-group').remove(); @@ -65424,11 +63102,11 @@ switch (extension) { case '.gpx': - gj = togeojson.gpx(xmlToDom(data)); + gj = gpx(xmlToDom(data)); break; case '.kml': - gj = togeojson.kml(xmlToDom(data)); + gj = kml(xmlToDom(data)); break; case '.geojson': @@ -70224,7 +67902,8 @@ context.on('enter.map', function () { if (!map.editableDataEnabled(true /* skip zoom check */ - )) return; // redraw immediately any objects affected by a change in selectedIDs. + )) return; + if (_isTransformed) return; // redraw immediately any objects affected by a change in selectedIDs. var graph = context.graph(); var selectedAndParents = {}; @@ -70513,11 +68192,11 @@ k2 = t0.k * Math.pow(2, -dY / 500); k2 = clamp$1(k2, kMin, kMax); x2 = p0[0] - p1[0] * k2; - y2 = p0[1] - p1[1] * k2; // 2 finger map panning (Mac only, all browsers) - #5492, #5512 + y2 = p0[1] - p1[1] * k2; // 2 finger map panning (Mac only, all browsers except Firefox #8595) - #5492, #5512 // Panning via the `wheel` event will always have: // - `ctrlKey = false` // - `deltaX`,`deltaY` are round integer pixels - } else if (detected.os === 'mac' && !source.ctrlKey && isInteger(dX) && isInteger(dY)) { + } else if (detected.os === 'mac' && detected.browser !== 'Firefox' && !source.ctrlKey && isInteger(dX) && isInteger(dY)) { p1 = projection.translate(); x2 = p1[0] - dX; y2 = p1[1] - dY; @@ -87518,8 +85197,8 @@ var modalSection = introModal.append('div').attr('class', 'modal-section'); modalSection.append('p').html(_t.html('splash.text', { version: context.version, - website: 'ideditor.blog', - github: 'github.com' + website: 'changelog', + github: 'github.com' })); modalSection.append('p').html(_t.html('splash.privacy', { updateMessage: updateMessage, @@ -88576,6 +86255,14 @@ for (var severity in issuesBySeverity) { var issues = issuesBySeverity[severity]; + + if (severity !== 'error') { + // exclude 'fixme' and similar - #8603 + issues = issues.filter(function (issue) { + return issue.type !== 'help_request'; + }); + } + var section = severity + '-section'; var issueItem = severity + '-item'; var container = selection.selectAll('.' + section).data(issues.length ? [0] : []); @@ -88786,7 +86473,10 @@ where: 'all', includeIgnored: true, includeDisabledRules: true - }).warning; + }).warning.filter(function (issue) { + return issue.type !== 'help_request'; + }); // exclude 'fixme' and similar - #8603 + addIssueCounts(warnings, 'warnings'); // add counts of issues resolved by the user's edits var resolvedIssues = context.validator().getResolvedIssues(); @@ -92679,7 +90369,7 @@ var _deferred = new Set(); - context.version = '2.20.0'; + context.version = '2.20.1'; context.privacyVersion = '20201202'; // iD will alter the hash so cache the parameters intended to setup the session context.initialHashParams = window.location.hash ? utilStringQs(window.location.hash) : {}; @@ -93519,7 +91209,7 @@ // and fallbacks like // "amenity/yes" // excluding things like - // "highway", "surface", "ref", etc. + // "tiger:reviewed", "surface", "ref", etc. // // Arguments // `tags`: `Object` containing the feature's OSM tags @@ -93537,16 +91227,19 @@ var alternate = new Set(); Object.keys(tags).forEach(function (osmkey) { var osmvalue = tags[osmkey]; - if (!osmvalue) return; + if (!osmvalue) return; // Match a 'route_master' as if it were a 'route' - name-suggestion-index#5184 + + if (osmkey === 'route_master') osmkey = 'route'; var vmap = _nsi.kvt.get(osmkey); - if (!vmap) return; + if (!vmap) return; // not an interesting key - if (osmvalue !== 'yes') { - primary.add("".concat(osmkey, "/").concat(osmvalue)); - } else { - alternate.add("".concat(osmkey, "/").concat(osmvalue)); + if (vmap.get(osmvalue)) { + // Matched a category in NSI + primary.add("".concat(osmkey, "/").concat(osmvalue)); // interesting key/value + } else if (osmvalue === 'yes') { + alternate.add("".concat(osmkey, "/").concat(osmvalue)); // fallback key/yes } }); // Can we try a generic building fallback match? - See #6122, #7197 // Only try this if we do a preset match and find nothing else remarkable about that building. @@ -93585,7 +91278,9 @@ if (t) return; // found already var osmvalue = tags[osmkey]; - if (!osmvalue) return; + if (!osmvalue) return; // Match a 'route_master' as if it were a 'route' - name-suggestion-index#5184 + + if (osmkey === 'route_master') osmkey = 'route'; var vmap = _nsi.kvt.get(osmkey); @@ -93716,6 +91411,7 @@ } function isNamelike(osmkey, which) { + if (osmkey === 'old_name') return false; return patterns[which].test(osmkey) && !notNames.test(osmkey); } } // `gatherTuples()` @@ -93802,7 +91498,9 @@ } } } - }); // Gather key/value tag pairs to try to match + }); // Match a 'route_master' as if it were a 'route' - name-suggestion-index#5184 + + var isRouteMaster = tags.type === 'route_master'; // Gather key/value tag pairs to try to match var tryKVs = gatherKVs(tags); if (!tryKVs.primary.size && !tryKVs.alternate.size) return changed ? newTags : null; // Gather namelike tag values to try to match @@ -93868,11 +91566,15 @@ var category = _nsi.data[tkv]; var properties = category.properties || {}; // Preserve some tags that we specifically don't want NSI to overwrite. ('^name', sometimes) - var preserveTags = item.preserveTags || properties.preserveTags || []; + var preserveTags = item.preserveTags || properties.preserveTags || []; // These tags can be toplevel tags -or- attributes - so we generally want to preserve existing values - #8615 + // We'll only _replace_ the tag value if this tag is the toplevel/defining tag for the matched item (`k`) + + ['building', 'emergency', 'internet_access', 'takeaway'].forEach(function (osmkey) { + if (k !== osmkey) preserveTags.push("^".concat(osmkey, "$")); + }); var regexes = preserveTags.map(function (s) { return new RegExp(s, 'i'); }); - regexes.push(/^building$/i, /^takeaway$/i); var keepTags = {}; Object.keys(newTags).forEach(function (osmkey) { if (regexes.some(function (regex) { @@ -93880,8 +91582,8 @@ })) { keepTags[osmkey] = newTags[osmkey]; } - }); // Remove any primary tags ("amenity", "craft", "shop", "man_made", "route", etc) - // with a value like `amenity=yes` or `shop=yes` + }); // Remove any primary tags ("amenity", "craft", "shop", "man_made", "route", etc) that have a + // value like `amenity=yes` or `shop=yes` (exceptions have already been added to `keepTags` above) _nsi.kvt.forEach(function (vmap, k) { if (newTags[k] === 'yes') delete newTags[k]; @@ -93894,13 +91596,19 @@ } // Do the tag upgrade - Object.assign(newTags, item.tags, keepTags); // Special `branch` splitting rules - IF.. + Object.assign(newTags, item.tags, keepTags); // Swap `route` back to `route_master` - name-suggestion-index#5184 + + if (isRouteMaster) { + newTags.route_master = newTags.route; + delete newTags.route; + } // Special `branch` splitting rules - IF.. // - NSI is suggesting to replace `name`, AND // - `branch` doesn't already contain something, AND // - original name has not moved to an alternate name (e.g. "Dunkin' Donuts" -> "Dunkin'"), AND // - original name is "some name" + "some stuff", THEN // consider splitting `name` into `name`/`branch`.. + var origName = tags.name; var newName = newTags.name; @@ -104762,9 +102470,10 @@ utilDisplayLabel: utilDisplayLabel, utilEntityRoot: utilEntityRoot, utilEditDistance: utilEditDistance, - utilEntitySelector: utilEntitySelector, + utilEntityAndDeepMemberIDs: utilEntityAndDeepMemberIDs, utilEntityOrMemberSelector: utilEntityOrMemberSelector, utilEntityOrDeepMemberSelector: utilEntityOrDeepMemberSelector, + utilEntitySelector: utilEntitySelector, utilFastMouse: utilFastMouse, utilFetchJson: utilFetchJson, utilFunctor: utilFunctor,