Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion 99.build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ echo
cat "${SRC_DIR}/meta/i18n-end.js" >> "${LOC_FILE}"

${COMPILER} \
--language_in ECMASCRIPT_2017 \
--language_in ECMASCRIPT_2020 \
--js "${SRC_DIR}/src/release.js" \
--js "${LOC_FILE}" \
--js "${SRC_DIR}/src/helpers.js" \
Expand Down
8 changes: 5 additions & 3 deletions meta/meta-begin.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
// ==UserScript==
// @name WME Validator
// @version 2025.02.26
// @version 2026.06.09
// @description This script validates a map area in Waze Map Editor, highlights issues and generates a very detailed report with wiki references and solutions
// @match https://beta.waze.com/*editor*
// @match https://www.waze.com/*editor*
// @exclude https://www.waze.com/*user/*editor/*
// @exclude https://www.waze.com/discuss/*
// @grant none
// @require https://cdn.jsdelivr.net/npm/@turf/turf@7/turf.min.js
// @icon https://raw.githubusercontent.com/WMEValidator/release/master/img/WV-icon96.png
// @namespace a
// @homepage https://www.waze.com/forum/viewtopic.php?f=819&t=76488
// @homepage https://www.waze.com/discuss/t/script-wme-validator-v2025-02-26-places-beta/44877
// @author Andriy Berestovskyy <[email protected]>
// @copyright 2013-2018 Andriy Berestovskyy
// @license GPLv3
Expand All @@ -19,6 +20,7 @@
// @contributor Glodenox
// @contributor DaveAcincy
// ==/UserScript==
/* global turf */
/*
* WME Validator uses Open Source GPLv3 license, i.e. you may copy,
* distribute and modify the software as long as you track changes/dates
Expand All @@ -30,7 +32,7 @@
* https://github.com/WMEValidator/
*
* For questions please use official forum:
* https://www.waze.com/forum/viewtopic.php?f=819&t=76488
* https://www.waze.com/discuss/t/script-wme-validator-v2025-02-26-places-beta/44877
*
* Report bugs on GitHub Issues Tracker:
* https://github.com/WMEValidator/validator/issues
Expand Down
34 changes: 34 additions & 0 deletions meta/wme-externs.js
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,9 @@ window.viewHelpers = {
formatRank: function (r) { }
};
window.require = {};
window.SDK_INITIALIZED = {};
var getWmeSdk = function(e) { };
var turf = {};

///////////////////////////////////////////////////////////////////////////
// Other externs
Expand All @@ -537,3 +540,34 @@ Error.prepareStackTrace = function (a, b) { };

var WME_Validator_I18n = {};
window.WME_Validator_I18n = {};

var wmeSDKref = {
DataModel: {
Cities: {
getById: function () { },
},
Countries: {
getById: function () { },
},
States: {
getById: function () { },
},
Streets: {
getById: function () { },
},
},
Editing: {
getSelection: function () { },
},
Events: {
on: function () { },
once: function () { },
},
Sidebar: {
registerScriptTab: function () { },
},
State: {
getUserInfo: function () { },
isLoggedIn: function () { },
},
}
137 changes: 109 additions & 28 deletions src/basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ function escRE(e) {
* @param {boolean=} newLine
*/
function getMsg(mType, msg, newLine) {
return "WME Validator v" + WV_VERSION
return "Validator"
+ (mType ? " " + mType : "")
+ (msg ? ":"
+ (newLine ? "\n" : " ")
Expand All @@ -94,6 +94,17 @@ function getMsg(mType, msg, newLine) {
function log(msg) {
window.console.log(getMsg("", msg));
}
function tlog(message, data = '') {
//if (!debug) return;

const t = new Date;
const h = t.getHours();
const m = t.getMinutes();
const s = t.getSeconds();
const ms = `${t.getMilliseconds()}`.padStart(3, '0');

console.log(`${h}:${m}:${s}.${ms} VAL: ${message}`, data);
}

/**
* Show error message
Expand Down Expand Up @@ -300,8 +311,12 @@ function ForceHLAllObjects() {
* This is used to wait for DOM to populate before filling in problem details in left panel.
*/
function delayForceHLAllObjects(e) {
const ldf = nW.app.layout.model.attributes.loadingFeatures;
if (ldf) {
const ldf = W.app.attributes.loadingFeatures;
const ae = document.getElementsByClassName("address-edit");
const selection = wmeSDK.Editing.getSelection();
let needLeftP = false;
if (ae.length == 0 && selection && selection.ids.length > 0 && ((selection.objectType == "segment") || (selection.objectType == "venue"))) { needLeftP = true; }
if (ldf || needLeftP) {
setTimeout(function () { delayForceHLAllObjects(e); }, 50);
}
else { ForceHLAllObjects(); }
Expand Down Expand Up @@ -476,23 +491,23 @@ function checkFilter(severity, objectCopy, seenObjects) {
&& _UI.pMain.pFilter.oExcludeNotes.CHECKED)
return false;

if (objectCopy.$userID !== _RT.$topUser.$userID
if (objectCopy.$userName !== _RT.$topUser.$userName
&& !_UI.pMain.pSearch.oIncludeYourEdits.NODISPLAY
&& _UI.pMain.pSearch.oIncludeYourEdits.CHECKED)
return false;

if (!_UI.pMain.pSearch.oIncludeUpdatedBy.NODISPLAY
&& _UI.pMain.pSearch.oIncludeUpdatedBy.VALUE) {
var cache = _RT.$includeUpdatedByCache;
var hash = objectCopy.$userID;
let cache = _RT.$includeUpdatedByCache;
let hash = objectCopy.$userID;

if (hash in cache) {
if (!cache[hash])
return false;
}
else {
var forUser = _UI.pMain.pSearch.oIncludeUpdatedBy.VALUE;
var curUser = _REP.$users[objectCopy.$userID];
let forUser = _UI.pMain.pSearch.oIncludeUpdatedBy.VALUE;
let curUser = _REP.$users[objectCopy.$userName];
try {
cache[hash] = false;
// check if the user tries to match another user
Expand Down Expand Up @@ -536,23 +551,23 @@ function checkFilter(severity, objectCopy, seenObjects) {
if (!objectCopy.$cityID)
return false;

var cache = _RT.$includeCityNameCache;
var hash = objectCopy.$cityID;
let cache = _RT.$includeCityNameCache;
let hash = objectCopy.$cityID;

if (hash in cache) {
if (!cache[hash])
return false;
}
else {
var forCity = _UI.pMain.pSearch.oIncludeCityName.VALUE;
var curCity = _REP.$cities[objectCopy.$cityID];
let forCity = _UI.pMain.pSearch.oIncludeCityName.VALUE;
let curCity = _REP.$cities[objectCopy.$cityID];
try {
cache[hash] = false;
if (!_WV.checkAccessFor(forCity,
function (e) {
// escape user input
e = escRE(e);
var r = new RegExp("^" + e + "$", "i");
let r = new RegExp("^" + e + "$", "i");
return r.test(curCity);
})
)
Expand Down Expand Up @@ -714,6 +729,14 @@ function onMoveEnd(e) {
else
delayForceHLAllObjects(e);
}
function onZoomEnd(e) {
//showTimes('onZoomEnd');
delayForceHLAllObjects(e);
}
function onSelChanged(e) {
//showTimes('onSelChanged');
delayForceHLAllObjects(e);
}

/**
* Load Start Handler
Expand All @@ -728,11 +751,65 @@ function onLoadStart() {
function onChangeLayer(e) {
sync(F_ONCHANGELAYER, e);
}
function onObjectsChanged(e) {
//const ln = e.objectIds.length;
//const tx = ln == 0 ? '' : ', id: ' + e.objectIds[0];
//tlog(e.dataModelName + ' objects changed, count: ' + ln + tx);
if (e.dataModelName == 'segments') {
_RT.$isMapChanged = true;
sync(F_ONSEGMENTSCHANGED, e.objectIds);
}
else if (e.dataModelName == 'venues') {
_RT.$isMapChanged = true;
sync(F_ONVENUESCHANGED, e.objectIds);
}
else if (e.dataModelName == 'nodes') {
_RT.$isMapChanged = true;
sync(F_ONNODESCHANGED, e.objectIds);
}
}
function onObjectsRemoved(e) {
//const ln = e.objectIds.length;
//const tx = ln == 0 ? '' : ', id: ' + e.objectIds[0];
//tlog(e.dataModelName + ' objects removed, count: ' + ln + tx);
if (e.dataModelName == 'segments') {
_RT.$isMapChanged = true;
if (1 === e.objectIds.length) {
if (RTStateIs(ST_STOP) || RTStateIs(ST_PAUSE)) {
sync(F_ONSEGMENTSCHANGED, e.objectIds);
}
}
}
else if (e.dataModelName == 'venues') {
_RT.$isMapChanged = true;
if (1 === e.objectIds.length) {
if (RTStateIs(ST_STOP) || RTStateIs(ST_PAUSE)) {
sync(F_ONVENUESCHANGED, e.objectIds);
}
}
}
else if (e.dataModelName == 'nodes') {
_RT.$isMapChanged = true;
if (1 === e.objectIds.length) {
if (RTStateIs(ST_STOP) || RTStateIs(ST_PAUSE)) {
sync(F_ONNODESCHANGED, e.objectIds);
}
}
}
}
function onObjectsAdded(e) {
//const ln = e.objectIds.length;
//const tx = ln == 0 ? '' : ', id: ' + e.objectIds[0];
//tlog(e.dataModelName + ' objects added, count: ' + ln + tx);
if (e.dataModelName == 'segments' || e.dataModelName == 'venues') {
_RT.$isMapChanged = true;
}
}

/**
* Segments Changed Handler
*/
/** @suppress {strictMissingProperties} */
/** @suppress {strictMissingProperties}
function onSegmentsChanged(e) {
_RT.$isMapChanged = true;
sync(F_ONSEGMENTSCHANGED, e);
Expand All @@ -741,7 +818,7 @@ function onSegmentsChanged(e) {
/**
* Segments Removed Handler
*/
/** @suppress {strictMissingProperties} */
/** @suppress {strictMissingProperties}
function onSegmentsRemoved(e) {
_RT.$isMapChanged = true;
if (1 === e.length)
Expand All @@ -752,15 +829,15 @@ function onSegmentsRemoved(e) {
/**
* Segments Added Handler
*/
/** @suppress {strictMissingProperties} */
/** @suppress {strictMissingProperties}
function onSegmentsAdded(e) {
_RT.$isMapChanged = true;
}

/**
* Nodes Changed Handler
*/
/** @suppress {strictMissingProperties} */
/** @suppress {strictMissingProperties}
function onNodesChanged(e) {
_RT.$isMapChanged = true;
sync(F_ONNODESCHANGED, e);
Expand All @@ -769,7 +846,7 @@ function onNodesChanged(e) {
/**
* Nodes Removed Handler
*/
/** @suppress {strictMissingProperties} */
/** @suppress {strictMissingProperties}
function onNodesRemoved(e) {
_RT.$isMapChanged = true;
if (1 === e.length)
Expand All @@ -781,36 +858,40 @@ function onNodesRemoved(e) {
* Recover from switching isImperial pref
*/
/** @suppress {strictMissingProperties} */
function onChangeIsImperial() {
clearReport();
_RT.$HLedObjects = {};
_RT.$HLlayer.destroyFeatures();
_RT.$isMapChanged = true;
async(F_LOGIN);
function onChangeUserSettings() {
const s = wmeSDK.Settings.getUserSettings();
if (_RT.$isImperial != s.isImperial) {
tlog('isImperial changed to: ' + s.isImperial);
clearReport();
_RT.$HLedObjects = {};
wmeSDK.Map.removeAllFeaturesFromLayer( { layerName: GL_LAYERNAME } );
_RT.$isMapChanged = true;
async(F_LOGIN);
}
}

/**
* Venues Added Handler
*/
/** @suppress {strictMissingProperties} */
/** @suppress {strictMissingProperties}
function onVenuesAdded(e) {
_RT.$isMapChanged = true;
}
/**
* Venues Changed Handler
*/
/** @suppress {strictMissingProperties} */
/** @suppress {strictMissingProperties}
function onVenuesChanged(e) {
_RT.$isMapChanged = true;
sync(F_ONVENUESCHANGED, e);
}
/**
* Venues Removed Handler
*/
/** @suppress {strictMissingProperties} */
/** @suppress {strictMissingProperties}
function onVenuesRemoved(e) {
_RT.$isMapChanged = true;
if (1 === e.length)
if (RTStateIs(ST_STOP) || RTStateIs(ST_PAUSE))
sync(F_ONVENUESCHANGED, e);
}
} */
Loading