mirror of
				https://github.com/brianshea2/meshmap.net.git
				synced 2025-03-05 21:00:01 -08:00 
			
		
		
		
	handle special characters (e.g., newlines) in node data (#31)
This commit is contained in:
		
							parent
							
								
									92dcb58981
								
							
						
					
					
						commit
						ca2b7b3dd1
					
				|  | @ -97,7 +97,9 @@ | ||||||
|   } |   } | ||||||
| </style> | </style> | ||||||
| <div id="header"> | <div id="header"> | ||||||
|   <div><a href="https://meshmap.net/" title="A nearly live map of Meshtastic nodes seen by the official Meshtastic MQTT server">MeshMap</a></div> |   <div> | ||||||
|  |     <a href="https://meshmap.net/" title="A nearly live map of Meshtastic nodes seen by the official Meshtastic MQTT server">MeshMap</a> | ||||||
|  |   </div> | ||||||
|   <div> |   <div> | ||||||
|     <a |     <a | ||||||
|       href="#" |       href="#" | ||||||
|  | @ -126,8 +128,10 @@ | ||||||
|     182, 91, 46, 23, 11, 6, 3, 1, |     182, 91, 46, 23, 11, 6, 3, 1, | ||||||
|     1, 0, 0, 0, 0, 0, 0, 0 |     1, 0, 0, 0, 0, 0, 0, 0 | ||||||
|   ] |   ] | ||||||
|   // encodes html reserved characters |   // encodes html reserved characters and ascii control characters | ||||||
|   const html = str => str?.replace(/["&<>]/g, match => `&#${match.charCodeAt(0)};`) |   const html = str => str | ||||||
|  |     ?.replace(/[\x00-\x1F]/g, c => `\\x${c.charCodeAt(0).toString(16).toUpperCase().padStart(2, '0')}`) | ||||||
|  |     .replace(/["&<>]/g, c => `&#${c.charCodeAt(0)};`) | ||||||
|   // makes more human-readable time duration strings |   // makes more human-readable time duration strings | ||||||
|   const duration = d => { |   const duration = d => { | ||||||
|     let s = '' |     let s = '' | ||||||
|  | @ -232,22 +236,23 @@ | ||||||
|       <div class="title">${html(longName)} (${html(shortName)})</div> |       <div class="title">${html(longName)} (${html(shortName)})</div> | ||||||
|       <div>${nodeLink(nodeNum, id)} | ${html(role)} | ${html(hwModel)}</div> |       <div>${nodeLink(nodeNum, id)} | ${html(role)} | ${html(hwModel)}</div> | ||||||
|       <table><tbody> |       <table><tbody> | ||||||
|       ${fwVersion ? `<tr><th>Firmware</th><td>${html(fwVersion)}</td></tr>` : ''} |       ${fwVersion          ? `<tr><th>Firmware</th><td>${html(fwVersion)}</td></tr>`                               : ''} | ||||||
|       ${region ? `<tr><th>Region</th><td>${html(region)}</td></tr>` : ''} |       ${region             ? `<tr><th>Region</th><td>${html(region)}</td></tr>`                                    : ''} | ||||||
|       ${modemPreset ? `<tr><th>Modem preset</th><td>${html(modemPreset)}</td></tr>` : ''} |       ${modemPreset        ? `<tr><th>Modem preset</th><td>${html(modemPreset)}</td></tr>`                         : ''} | ||||||
|       ${hasDefaultCh ? `<tr><th>Has default channel</th><td>True</td></tr>` : ''} |       ${hasDefaultCh       ? `<tr><th>Has default channel</th><td>True</td></tr>`                                  : ''} | ||||||
|       ${onlineLocalNodes ? `<tr><th>Online local nodes</th><td>${onlineLocalNodes}</td></tr>` : ''} |       ${onlineLocalNodes   ? `<tr><th>Online local nodes</th><td>${onlineLocalNodes}</td></tr>`                    : ''} | ||||||
|       ${batteryLevel ? `<tr><th>Power</th><td>${batteryLevel > 100 ? 'Plugged in' : `${batteryLevel}%`}${voltage ? ` (${voltage.toFixed(2)}V)` : ''}</td></tr>` : ''} |       ${batteryLevel       ? `<tr><th>Power</th><td>${batteryLevel > 100 ? 'Plugged in' : `${batteryLevel}%`}` + | ||||||
|       ${chUtil ? `<tr><th>ChUtil</th><td>${chUtil.toFixed(2)}%</td></tr>` : ''} |                              `${voltage ? ` (${voltage.toFixed(2)}V)` : ''}</td></tr>`                             : ''} | ||||||
|       ${airUtilTx ? `<tr><th>AirUtilTX</th><td>${airUtilTx.toFixed(2)}%</td></tr>` : ''} |       ${chUtil             ? `<tr><th>ChUtil</th><td>${chUtil.toFixed(2)}%</td></tr>`                              : ''} | ||||||
|       ${uptime ? `<tr><th>Uptime</th><td>${duration(uptime)}</td></tr>` : ''} |       ${airUtilTx          ? `<tr><th>AirUtilTX</th><td>${airUtilTx.toFixed(2)}%</td></tr>`                        : ''} | ||||||
|       ${temperature ? `<tr><th>Temperature</th><td>${temperature.toFixed(1)}℃ / ${(temperature * 1.8 + 32).toFixed(1)}℉</td></tr>` : ''} |       ${uptime             ? `<tr><th>Uptime</th><td>${duration(uptime)}</td></tr>`                                : ''} | ||||||
|       ${relativeHumidity ? `<tr><th>Relative Humidity</th><td>${Math.round(relativeHumidity)}%</td></tr>` : ''} |       ${temperature        ? `<tr><th>Temperature</th><td>${temperature.toFixed(1)}℃ / ` + | ||||||
|  |                              `${(temperature * 1.8 + 32).toFixed(1)}℉</td></tr>`                             : ''} | ||||||
|  |       ${relativeHumidity   ? `<tr><th>Relative Humidity</th><td>${Math.round(relativeHumidity)}%</td></tr>`        : ''} | ||||||
|       ${barometricPressure ? `<tr><th>Barometric Pressure</th><td>${Math.round(barometricPressure)} hPa</td></tr>` : ''} |       ${barometricPressure ? `<tr><th>Barometric Pressure</th><td>${Math.round(barometricPressure)} hPa</td></tr>` : ''} | ||||||
|       ${altitude ? `<tr><th>Altitude</th><td>${altitude.toLocaleString()} m above MSL</td></tr>` : ''} |       ${altitude           ? `<tr><th>Altitude</th><td>${altitude.toLocaleString()} m above MSL</td></tr>`         : ''} | ||||||
|       ${precision && precisionMargins[precision-1] ? |       ${precision && precisionMargins[precision-1] ? "<tr><th>Location precision</th><td>±" + | ||||||
|         `<tr><th>Location precision</th><td>± ${precisionMargins[precision-1].toLocaleString()} m (orange circle)</td></tr>` : '' |                              `${precisionMargins[precision-1].toLocaleString()} m (orange circle)</td></tr>`       : ''} | ||||||
|       } |  | ||||||
|       </tbody></table> |       </tbody></table> | ||||||
|       <table><thead> |       <table><thead> | ||||||
|       <tr><th>Last seen</th><th>via</th><th>root topic</th><th>channel</th></tr> |       <tr><th>Last seen</th><th>via</th><th>root topic</th><th>channel</th></tr> | ||||||
|  | @ -255,7 +260,9 @@ | ||||||
|       ${Array.from( |       ${Array.from( | ||||||
|         new Map( |         new Map( | ||||||
|           Object.entries(seenBy) |           Object.entries(seenBy) | ||||||
|             .map(([topic, seen]) => (m => ({seen, via: m[3] ?? id, root: m[1], chan: m[2]}))(topic.match(/^(.*)(?:\/2\/e\/(.*)\/(![0-9a-f]+)|\/2\/map\/)$/))) |             .map(([topic, seen]) => (m => ({seen, via: m[3] ?? id, root: m[1], chan: m[2]}))( | ||||||
|  |               topic.match(/^(.*)(?:\/2\/e\/(.*)\/(![0-9a-f]+)|\/2\/map\/)$/s) | ||||||
|  |             )) | ||||||
|             .sort((a, b) => a.seen - b.seen) |             .sort((a, b) => a.seen - b.seen) | ||||||
|             .map(v => [v.via, v]) |             .map(v => [v.via, v]) | ||||||
|         ).values(), |         ).values(), | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue