diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..f4bb0304 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,279 @@ +{ + "parserOptions": { + "ecmaVersion": 2022, + "sourceType": "script" + }, + "env": { + "browser": true, + "es2022": true + }, + "globals": { + "AreaFilter": "readonly", + "CACHE_INVALIDATE_MS": "readonly", + "CLIENT_CONFIG": "readonly", + "CLIENT_TTL": "readonly", + "ChannelColorPicker": "readonly", + "ChannelColors": "readonly", + "ChannelDecrypt": "readonly", + "ChannelQR": "readonly", + "Chart": "readonly", + "DIST_THRESHOLDS": "readonly", + "DragManager": "readonly", + "EXTERNAL_URLS": "readonly", + "FAV_KEY": "readonly", + "FilterUX": "readonly", + "GestureHints": "readonly", + "HEALTH_THRESHOLDS": "readonly", + "HashColor": "readonly", + "HopDisplay": "readonly", + "HopResolver": "readonly", + "IATA_CITIES": "readonly", + "IATA_COORDS_GEO": "readonly", + "L": "readonly", + "LIMITS": "readonly", + "Logo": "readonly", + "MAX_HOP_DIST": "readonly", + "MeshAudio": "readonly", + "MeshConfigReady": "readonly", + "PAYLOAD_COLORS": "readonly", + "PAYLOAD_TYPES": "readonly", + "PERF_SLOW_MS": "readonly", + "PROPAGATION_BUFFER_MS": "readonly", + "PULL_THRESHOLD_PX": "readonly", + "PacketFilter": "readonly", + "PathInspector": "readonly", + "QRCode": "readonly", + "ROLE_COLORS": "readonly", + "ROLE_EMOJI": "readonly", + "ROLE_LABELS": "readonly", + "ROLE_SHAPES": "readonly", + "ROLE_SORT": "readonly", + "ROLE_STYLE": "readonly", + "ROUTE_TYPES": "readonly", + "RegionFilter": "readonly", + "SITE_CONFIG": "readonly", + "SKEW_SEVERITY_COLORS": "readonly", + "SKEW_SEVERITY_LABELS": "readonly", + "SKEW_SEVERITY_ORDER": "readonly", + "SNR_THRESHOLDS": "readonly", + "SlideOver": "readonly", + "TILE_DARK": "readonly", + "TILE_LIGHT": "readonly", + "TYPE_COLORS": "readonly", + "TableResponsive": "readonly", + "TableSort": "readonly", + "TouchGestures": "readonly", + "TracesHelpers": "readonly", + "URLState": "readonly", + "WS_RECONNECT_MS": "readonly", + "_SITE_CONFIG_ORIGINAL_HOME": "readonly", + "__PERF_LOG_RENDER": "readonly", + "__bottomNavInitDone": "readonly", + "__corescopeLogo": "readonly", + "__dirname": "readonly", + "__filename": "readonly", + "__gestureHints1065Init": "readonly", + "__liveMQLBindCount": "readonly", + "__meshcoreMapInternals": "readonly", + "__navDrawer": "readonly", + "__navDrawerPointerBindCount": "readonly", + "__pathOverflowWired": "readonly", + "__scrollLock": "readonly", + "__touchGestures1062InitCount": "readonly", + "_analyticsChannelTbodyHtml": "readonly", + "_analyticsChannelTheadHtml": "readonly", + "_analyticsDecorateChannels": "readonly", + "_analyticsHashStatCardsHtml": "readonly", + "_analyticsLoadChannelSort": "readonly", + "_analyticsRenderCollisionsFromServer": "readonly", + "_analyticsRenderMultiByteAdopters": "readonly", + "_analyticsRenderMultiByteCapability": "readonly", + "_analyticsRfNFColumnChart": "readonly", + "_analyticsSaveChannelSort": "readonly", + "_analyticsSortChannels": "readonly", + "_apiCache": "readonly", + "_apiPerf": "readonly", + "_channelsBeginMessageRequestForTest": "readonly", + "_channelsGetStateForTest": "readonly", + "_channelsHandleWSBatchForTest": "readonly", + "_channelsIsStaleMessageRequestForTest": "readonly", + "_channelsLoadChannelsForTest": "readonly", + "_channelsProcessWSBatchForTest": "readonly", + "_channelsReconcileSelectionForTest": "readonly", + "_channelsRefreshMessagesForTest": "readonly", + "_channelsSelectChannelForTest": "readonly", + "_channelsSetObserverRegionsForTest": "readonly", + "_channelsSetStateForTest": "readonly", + "_channelsShouldProcessWSMessageForRegion": "readonly", + "_customizerV2": "readonly", + "_ensurePullIndicator": "readonly", + "_inflight": "readonly", + "_isTouchDevice": "readonly", + "_liveAddFeedItem": "readonly", + "_liveBufferPacket": "readonly", + "_liveBuildClickablePathPopupHtml": "readonly", + "_liveBuildObserverIataMap": "readonly", + "_liveClickablePaths": "readonly", + "_liveDbPacketToLive": "readonly", + "_liveExpandToBufferEntries": "readonly", + "_liveExpandToBufferEntriesAsync": "readonly", + "_liveFormatLiveTimestampHtml": "readonly", + "_liveGetFavoritePubkeys": "readonly", + "_liveGetNodeFilterKeys": "readonly", + "_liveGetObserverIataMap": "readonly", + "_liveIsNodeFavorited": "readonly", + "_liveNodeActivity": "readonly", + "_liveNodeData": "readonly", + "_liveNodeMarkers": "readonly", + "_livePacketInvolvesFavorite": "readonly", + "_livePacketInvolvesFilterNode": "readonly", + "_livePacketMatchesRegion": "readonly", + "_livePruneClickablePaths": "readonly", + "_livePruneStaleNodes": "readonly", + "_liveRebuildFeedList": "readonly", + "_liveResolveHopPositions": "readonly", + "_liveSEG_MAP": "readonly", + "_liveSetMarkerColor": "readonly", + "_liveSetMarkerSize": "readonly", + "_liveSetNodeFilter": "readonly", + "_liveSetObserverIataMap": "readonly", + "_liveSpeedLabel": "readonly", + "_liveVCR": "readonly", + "_liveVcrPause": "readonly", + "_liveVcrResumeLive": "readonly", + "_liveVcrSetMode": "readonly", + "_liveVcrSpeedCycle": "readonly", + "_live_packetTimestamp": "readonly", + "_mapGetNeighborPubkeys": "readonly", + "_mapSelectRefNode": "readonly", + "_meshAudioVoices": "readonly", + "_meshcoreHeatLayer": "readonly", + "_meshcoreLiveHeatLayer": "readonly", + "_nodesGetAllNodes": "readonly", + "_nodesGetSortState": "readonly", + "_nodesGetStatusInfo": "readonly", + "_nodesGetStatusTooltip": "readonly", + "_nodesIsAdvertMessage": "readonly", + "_nodesMatchesSearch": "readonly", + "_nodesRenderNodeTimestampHtml": "readonly", + "_nodesRenderNodeTimestampText": "readonly", + "_nodesSetAllNodes": "readonly", + "_nodesSetSortState": "readonly", + "_nodesSortArrow": "readonly", + "_nodesSortNodes": "readonly", + "_nodesSyncClaimedToFavorites": "readonly", + "_nodesToggleSort": "readonly", + "_packetsTestAPI": "readonly", + "_panelCorner": "readonly", + "_pendingPathInspectorRoute": "readonly", + "_perfWriteSourcesPrev": "readonly", + "_pullIndicator": "readonly", + "_pullToast": "readonly", + "_pullToastTimer": "readonly", + "_reducedMotionMQL": "readonly", + "_showPullToast": "readonly", + "_themeRefreshTimer": "readonly", + "_vcrFormatTime": "readonly", + "addEventListener": "readonly", + "api": "readonly", + "apiPerf": "readonly", + "bindFavStars": "readonly", + "buildHexLegend": "readonly", + "buildNodesQuery": "readonly", + "buildPacketsQuery": "readonly", + "clearParsedCache": "readonly", + "closeMoreMenu": "readonly", + "closeNav": "readonly", + "comparePacketSets": "readonly", + "computeBreakdownRanges": "readonly", + "computeOverlapStats": "readonly", + "connectWS": "readonly", + "copyToClipboard": "readonly", + "createColoredHexDump": "readonly", + "currentPage": "readonly", + "currentSkewValue": "readonly", + "debounce": "readonly", + "debouncedOnWS": "readonly", + "destroy": "readonly", + "devicePixelRatio": "readonly", + "dispatchEvent": "readonly", + "drawPacketRoute": "readonly", + "escapeHtml": "readonly", + "exports": "readonly", + "favStar": "readonly", + "filterPacketsByRoute": "readonly", + "formatAbsoluteTimestamp": "readonly", + "formatChartAxisLabel": "readonly", + "formatDistance": "readonly", + "formatDistanceRound": "readonly", + "formatDrift": "readonly", + "formatEngineBadge": "readonly", + "formatHex": "readonly", + "formatIsoLike": "readonly", + "formatSkew": "readonly", + "formatTimestamp": "readonly", + "formatTimestampCustom": "readonly", + "formatTimestampWithTooltip": "readonly", + "formatVersionBadge": "readonly", + "getDistanceUnit": "readonly", + "getFavorites": "readonly", + "getHashParams": "readonly", + "getHealthThresholds": "readonly", + "getNodeStatus": "readonly", + "getParsedDecoded": "readonly", + "getParsedPath": "readonly", + "getPathLenOffset": "readonly", + "getResolvedPath": "readonly", + "getTileUrl": "readonly", + "getTimestampCustomFormat": "readonly", + "getTimestampFormatPreset": "readonly", + "getTimestampMode": "readonly", + "getTimestampTimezone": "readonly", + "global": "readonly", + "initGeoFilterOverlay": "readonly", + "initTabBar": "readonly", + "invalidateApiCache": "readonly", + "isFavorite": "readonly", + "isTransportRoute": "readonly", + "makeColumnsResizable": "readonly", + "makeRoleMarkerSVG": "readonly", + "miniMarkdown": "readonly", + "module": "readonly", + "navigate": "readonly", + "observerSkewSeverity": "readonly", + "offWS": "readonly", + "onWS": "readonly", + "pad2": "readonly", + "pad3": "readonly", + "pages": "readonly", + "payloadTypeColor": "readonly", + "payloadTypeName": "readonly", + "process": "readonly", + "pullReconnect": "readonly", + "qrcode": "readonly", + "registerPage": "readonly", + "renderSkewBadge": "readonly", + "renderSkewSparkline": "readonly", + "require": "readonly", + "routeLayer": "readonly", + "routeTypeName": "readonly", + "setupPullToReconnect": "readonly", + "syncBadgeColors": "readonly", + "timeAgo": "readonly", + "toggleFavorite": "readonly", + "transportBadge": "readonly", + "truncate": "readonly", + "ws": "readonly", + "wsListeners": "readonly" + }, + "rules": { + "no-undef": "error", + "no-unused-vars": [ + "warn", + { + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_" + } + ] + } +} \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index d7050edf..0e016dcf 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -107,6 +107,14 @@ jobs: node test-area-filter.js node test-issue-1293-marker-shapes.js + - name: ๐Ÿงน Frontend lint (eslint no-undef) โ€” issue #1342 + run: | + set -e + # Use eslint@8 (legacy .eslintrc.json). Don't migrate to flat-config / eslint@9. + # --no-save: avoid touching package.json / no committed node_modules. + npm install --no-save --no-audit --no-fund eslint@8 + npx eslint public/*.js + - name: Verify proto syntax run: | set -e diff --git a/public/map.js b/public/map.js index 54fb9504..301489f7 100644 --- a/public/map.js +++ b/public/map.js @@ -20,8 +20,10 @@ let userHasMoved = false; let controlsCollapsed = false; - // Safe escape โ€” falls back to identity if app.js hasn't loaded yet - const safeEsc = (typeof esc === 'function') ? esc : function (s) { return s; }; + // Safe escape โ€” falls back to identity if app.js hasn't loaded yet. + // Note: `esc` is not a true global; some IIFEs define it locally. Reference + // through globalThis so the optional lookup is safe under `no-undef`. + const safeEsc = (typeof globalThis.esc === 'function') ? globalThis.esc : function (s) { return s; }; // Roles loaded from shared roles.js (ROLE_STYLE, ROLE_LABELS, ROLE_COLORS globals)