@trailstash/ultra
Version:
A web based tool for making MapLibre GL maps with data from sources such as Overpass, GeoJSON, GPX, KML, TCX, etc
160 lines (144 loc) • 3.9 kB
JavaScript
import {
compressToEncodedURIComponent,
decompressFromEncodedURIComponent,
} from "lz-string";
import { setSetting } from "./settings.js";
export const getModeFromQueryParams = () => {
const params = new URLSearchParams(window.location.hash.slice(1));
let mode;
if (params.has("map")) {
mode = "map";
}
if (params.has("app")) {
mode = "app";
}
return mode;
};
const fetchGist = async (query) => {
let [gistID, filename] = query.slice("gist:".length).split("/", 2);
let resp = await fetch(`https://api.github.com/gists/${gistID}`);
if (!resp.ok) {
throw new Error(
`Failed to fetch ${resp.url}: ${resp.status} ${await resp.text()}`,
);
}
const gist = await resp.json();
if (!filename) {
for (filename in gist.files) break;
}
if (!gist.files[filename].truncated) {
return gist.files[filename].content;
}
resp = await fetch(gist.files[filename].raw_url);
return resp.text();
};
const fetchURL = async (url) => {
const resp = await fetch(url);
if (!resp.ok) {
throw new Error(
`Failed to fetch ${resp.url}: ${resp.status} ${await resp.text()}`,
);
}
return await resp.text();
};
export const hasHash = (hashName) => {
let hash = window.location.hash.slice(1);
if (hashName) {
const params = new URLSearchParams(hash);
hash = params.get(hashName);
}
if (!hash) {
return false;
}
const loc = hash.split("/");
return loc.length >= 3 && !loc.some((v) => isNaN(v));
};
export const getQueryFromQueryParams = () => {
const params = new URLSearchParams(window.location.hash.slice(1));
let query;
// query
if (params.has("q")) {
query = decompressFromEncodedURIComponent(params.get("q"));
if (!query) {
alert("Invalid compressed query specified in URL");
}
} else if (params.has("query")) {
query = params.get("query");
if (query.startsWith("gist:")) {
query = fetchGist(query);
} else if (query.startsWith("url:")) {
const url = query.slice("url:".length);
query = fetchURL(url);
}
}
// override style & server if provided
// fetched configs can't be overwritten via style&server params
if (!query?.then) {
if (params.has("style")) {
query = setSetting(query || "", {
style: params.get("style"),
});
}
if (params.has("server")) {
query = setSetting(query || "", {
server: params.get("server"),
});
}
}
return query;
};
export const getOptionsFromQueryParams = () => {
const params = new URLSearchParams(window.location.hash.slice(1));
const options = {};
// mapview params
if (params.has("m")) {
const m = params.get("m");
if (m.includes(",")) {
options.bounds = m.split(",").map(parseFloat);
} else {
const [zoom, lat, lng] = m.split("/").map(parseFloat);
options.zoom = zoom;
options.center = [lng, lat];
}
}
return options;
};
export const getAutoRunFromQueryParams = () => {
// Don't autorun if provided query can't be decompressed
// TODO: other query load errors?
const params = new URLSearchParams(window.location.hash.slice(1));
if (params.has("q")) {
const query = decompressFromEncodedURIComponent(params.get("q"));
if (!query) {
return false;
}
}
return new URLSearchParams(window.location.hash.slice(1)).has("run");
};
export const toQueryParams = ({
query,
center,
zoom,
autoRun = false,
mode,
}) => {
const root = window.location.origin + window.location.pathname;
const q = compressToEncodedURIComponent(query);
let hash = "#";
if (autoRun) {
hash += "run&";
}
if (mode === "map") {
hash += "map&";
}
if (center && zoom) {
const zyx = [
zoom.toFixed(2),
center[1].toFixed(4),
center[0].toFixed(4),
].join("/");
hash += `m=${zyx}&`;
}
hash += `q=${q}`;
return `${root}${hash}`;
};