diff --git a/README.md b/README.md index 00ac779..5e58206 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,23 @@ # SAC Route Portal GPX Downloader +The [Swiss Alpine Club](https://www.sac-cas.ch/en/) has a great +[route portal](https://www.sac-cas.ch/en/huts-and-tours/sac-route-portal/) +for finding interesting hiking routes. -The [Swiss Alpine Club](https://www.sac-cas.ch/en/) has a great -[route portal](https://www.sac-cas.ch/en/huts-and-tours/sac-route-portal/) for -finding interesting hiking routes. +However you can not download the tracks as gpx files, as they argue that the exact +paths are subject to change and it could be dangerous to adhere too closely to them. -However you can not download the tracks as gpx files, as they argue that the -exact paths are subject to change and it could be dangerous to adhere too -closely to them. +I do agree with that, but you can draw your own routes +and download those, mainly taking some time to draw after the route they are +already showing on the map. -I do agree with that, but you can draw your own routes and download those, -mainly taking some time to draw after the route they are already showing on the -map. - -With this extension you can select any track and then download it as a gpx file +With this extension you can select any track and then download it as a gpx file (an active subscription is needed). ## Be Cautious! +Heed their warning and do not blindly follow the gps track! Use your brain and +plan your route beforehand to be aware of dangerous parts and alternatives. -Heed their warning and do not blindly follow the gps track! Use your brain and -plan your route beforehand to be aware of dangerous parts and alternatives. - -Take a look at their -[safety instructions](https://www.sac-cas.ch/en/training-and-safety/safety/). +Take a look at their [safety instructions](https://www.sac-cas.ch/en/training-and-safety/safety/). ## Contributors - - wizche -- [Michal Bryxí](mailto:michal.bryxi@gmail.com) - -## Contact - -For issue reporting contact me at [shu+gpx@vanwa.ch](mailto:shu+gpx@vanwa.ch) diff --git a/background.js b/background.js index e69a4e3..95ccd76 100644 --- a/background.js +++ b/background.js @@ -17,28 +17,26 @@ let gpxTrack = null; */ function toWGS84(point) { // convert LV95 into the civilian system - const y_aux = (point[0] - 2600000) / 1000000; - const x_aux = (point[1] - 1200000) / 1000000; + let y_aux = (point[0] - 2600000) / 1000000; + let x_aux = (point[1] - 1200000) / 1000000; // calculate longitude and latitude in the unit 10000" - let lat = - 16.9023892 + + let lat = 16.9023892 + 3.238272 * x_aux - 0.270978 * Math.pow(y_aux, 2) - 0.002528 * Math.pow(x_aux, 2) - 0.0447 * Math.pow(y_aux, 2) * x_aux - - 0.014 * Math.pow(x_aux, 3); + 0.0140 * Math.pow(x_aux, 3); - let lon = - 2.6779094 + + let lon = 2.6779094 + 4.728982 * y_aux + 0.791484 * y_aux * x_aux + 0.1306 * y_aux * Math.pow(x_aux, 2) - 0.0436 * Math.pow(y_aux, 3); // unit 10000" to 1" and seconds to degrees (dec) - lat = (lat * 100) / 36; - lon = (lon * 100) / 36; + lat = lat * 100 / 36; + lon = lon * 100 / 36; return { lat: lat, lon: lon }; } @@ -50,7 +48,7 @@ function toWGS84(point) { * @returns Track point xml node for gpx. */ function toTrackPoint(point) { - const wgs84Point = toWGS84(point); + let wgs84Point = toWGS84(point); return ``; } @@ -60,7 +58,7 @@ function toTrackPoint(point) { * @returns Way point xml node for gpx. */ function toWayPoint(point) { - const wgs84Point = toWGS84(point.geom.coordinates); + let wgs84Point = toWGS84(point.geom.coordinates); return ` ${point.altitude} @@ -75,6 +73,7 @@ function toWayPoint(point) { * @returns Combined route number, id and route title. */ function trackTitle(geoJson) { + const route = geoJson.segments[0]; const book = geoJson.book_route_number ? `${geoJson.book_route_number} - ` : ""; @@ -89,25 +88,18 @@ function trackTitle(geoJson) { * @returns Simple gpx string. */ function toGpx(geoJson) { - const trackSegments = geoJson.segments - .map((segment) => { - if (segment.geom == null) return ""; - return ` + let trackSegments = geoJson.segments.map((segment) => { + if (segment.geom == null) return ""; + return ` ${segment.geom.coordinates.map(toTrackPoint).join("")} `; - }) - .join(""); + }).join(""); - const departurePoint = geoJson.departure_point - ? toWayPoint(geoJson.departure_point) - : ""; - const endPoint = geoJson.end_point ? toWayPoint(geoJson.end_point) : ""; - const waypoints = geoJson.waypoints - ? geoJson.waypoints - .map((wp) => { - return toWayPoint(wp.reference_poi); - }) - .join("") + let endPoint = geoJson.end_point ? toWayPoint(geoJson.end_point) : ""; + let waypoints = geoJson.waypoints + ? geoJson.waypoints.map((wp) => { + return toWayPoint(wp.reference_poi); + }).join("") : ""; const routeTitle = trackTitle(geoJson); @@ -119,7 +111,7 @@ function toGpx(geoJson) { xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd" version="1.0" creator="SAC-Tourenportal GPX Downloader"> - ${departurePoint} + ${toWayPoint(geoJson.departure_point)} ${toWayPoint(geoJson.destination_poi)} ${waypoints} ${endPoint} @@ -131,7 +123,7 @@ function toGpx(geoJson) { `; const parser = new DOMParser(); - const xmlDoc = parser.parseFromString(xmlString, "text/xml"); + let xmlDoc = parser.parseFromString(xmlString, "text/xml"); return new XMLSerializer().serializeToString(xmlDoc.documentElement); } @@ -140,26 +132,26 @@ function toGpx(geoJson) { * Intercept the download of GeoJSON data and save it for the background script. */ function listener(details) { - const filter = browser.webRequest.filterResponseData(details.requestId); - const decoder = new TextDecoder("utf-8"); - const encoder = new TextEncoder(); + let filter = browser.webRequest.filterResponseData(details.requestId); + let decoder = new TextDecoder("utf-8"); + let encoder = new TextEncoder(); - const data = []; + let data = []; filter.ondata = (event) => { data.push(event.data); }; - filter.onstop = async (_event) => { - const blob = new Blob(data, { type: "text/html" }); - const buffer = await blob.arrayBuffer(); - const str = decoder.decode(buffer); + filter.onstop = async (event) => { + let blob = new Blob(data, { type: "text/html" }); + let buffer = await blob.arrayBuffer(); + let str = decoder.decode(buffer); updateActiveTab(browser.tabs); filter.write(encoder.encode(str)); filter.close(); - const geoJson = JSON.parse(str); + let geoJson = JSON.parse(str); const routeTitle = trackTitle(geoJson); gpxTrack = { title: routeTitle, data: toGpx(geoJson) }; }; @@ -181,41 +173,6 @@ function checkTrack(tab) { return tab.url.match("https://www.sac-cas.ch/.*") && gpxTrack; } -/** - * Remove characters that lead to problems in common filesystems. - * - * Windows (NTFS) seems to have the most restrictions, so it is mostly sourced from there. - * - * Reserved names on windows: https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file - * - * Code comes from https://github.com/parshap/node-sanitize-filename/blob/master/index.js - */ -function sanitizeFilename(input) { - const illegal = /[\/\?<>\\:\*\|"]/g; - // deno-lint-ignore no-control-regex - const control = /[\x00-\x1f\x80-\x9f]/g; - const reserved = /^\.+$/; - const windowsReserved = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$/i; - const windowsTrailing = /[\. ]+$/; - const replacement = "_"; - - const sanitized = input - .replace(illegal, replacement) - .replace(control, replacement) - .replace(reserved, replacement) - .replace(windowsReserved, replacement) - .replace(windowsTrailing, replacement); - - if (sanitized.length === 0) { - sanitized = "unnamed"; - } - - const maxLength = 250; - const uint8Array = new TextEncoder().encode(sanitized); - const truncated = uint8Array.slice(0, maxLength); - return new TextDecoder().decode(truncated); -} - /** * If a valid tack was selected, download it as a gpx file. */ @@ -225,13 +182,12 @@ function handleClick(tab) { return; } - const blob = new Blob([gpxTrack.data], { type: "application/gpx+xml" }); - const objectURL = URL.createObjectURL(blob); + let blob = new Blob([gpxTrack.data], { type: "application/gpx+xml" }); + let objectURL = URL.createObjectURL(blob); - const filename = sanitizeFilename(gpxTrack.title); - const downloading = browser.downloads.download({ + let downloading = browser.downloads.download({ url: objectURL, - filename: `${filename}.gpx`, + filename: `${gpxTrack.title}.gpx`, saveAs: true, conflictAction: "uniquify", }); @@ -246,14 +202,14 @@ function handleClick(tab) { /** * Update the download icon and text. */ -function updateActiveTab(_tabs) { +function updateActiveTab(tabs) { function updateTab(tabs) { if (tabs[0]) { updateIcon(tabs[0]); } } - const gettingActiveTab = browser.tabs.query({ + let gettingActiveTab = browser.tabs.query({ active: true, currentWindow: true, }); @@ -269,11 +225,11 @@ function updateIcon(tab) { browser.browserAction.setIcon({ path: hasTrack ? { - 48: "icons/map.png", - } + 48: "icons/map.png", + } : { - 48: "icons/map-disabled.png", - }, + 48: "icons/map-disabled.png", + }, tabId: tab.id, }); browser.browserAction.setTitle({ diff --git a/flake.lock b/flake.lock deleted file mode 100644 index f1b9252..0000000 --- a/flake.lock +++ /dev/null @@ -1,61 +0,0 @@ -{ - "nodes": { - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1719075281, - "narHash": "sha256-CyyxvOwFf12I91PBWz43iGT1kjsf5oi6ax7CrvaMyAo=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "a71e967ef3694799d0c418c98332f7ff4cc5f6af", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "root": { - "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/flake.nix b/flake.nix deleted file mode 100644 index 6c8eac7..0000000 --- a/flake.nix +++ /dev/null @@ -1,26 +0,0 @@ -{ - description = "little-hesinde project"; - inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - flake-utils.url = "github:numtide/flake-utils"; - }; - - outputs = - { nixpkgs, flake-utils, ... }: - flake-utils.lib.eachDefaultSystem ( - system: - let - pkgs = import nixpkgs { inherit system; }; - in - { - devShells.default = - with pkgs; - mkShell { - buildInputs = [ - deno - zip - ]; - }; - } - ); -} diff --git a/manifest.json b/manifest.json index 4f2230d..b738a29 100644 --- a/manifest.json +++ b/manifest.json @@ -1,15 +1,19 @@ { + "manifest_version": 2, "name": "SAC Route Portal GPX Downloader", - "version": "0.9", + "version": "0.7", "developer": { "name": "Sebastian Hugentobler", "url": "https://code.vanwa.ch/sebastian/sac-route-portal-gpx-fx" }, + "description": "Download gpx tracks from the sac route portal.", + "icons": { "48": "icons/map.png" }, + "permissions": [ "activeTab", "downloads", @@ -17,13 +21,13 @@ "webRequestBlocking", "https://www.sac-cas.ch/*" ], + "background": { - "scripts": [ - "background.js" - ] + "scripts": ["background.js"] }, + "browser_action": { "default_icon": "icons/map.png", "default_title": "To GPX" - } + } }