Files
wanderer/web/src/lib/util/format_util.ts
slothful-vassal 44cd092065 Improve trail planning: option to re-order route anchors (#1007)
* trail anchor list added

* add search location card to extend route endpoint in drawing mode

* add POI popup endpoint action in route drawing mode

* fix anchor stats, improve anchor list entries and refine route marker behavior

* fix map marker spinner

* docs updated

* fix spinner when delete an anchor

* further improvements

* fix adding first anchor from POI

* optimize drag handle area

---------

Co-authored-by: Flomp <Flomp@users.noreply.github.com>
2026-06-06 11:56:12 +02:00

162 lines
4.2 KiB
TypeScript

import { browser } from "$app/environment";
import { page } from "$app/state";
export function formatTimeHHMM(seconds?: number) {
if (seconds == null || isNaN(seconds)) {
return "-";
}
const totalMinutes = Math.floor(seconds / 60);
const m = totalMinutes % 60;
const h = Math.floor(totalMinutes / 60);
return (h < 10 ? "0" : "") + h.toString() + "h " + (m < 10 ? "0" : "") + m.toString() + "m";
}
export function formatDistance(
meters?: number,
options: { compact?: boolean } = {},
) {
if (meters === undefined) {
return "-";
}
const unit = page.data.settings?.unit ?? "metric";
if (unit == "metric") {
if (meters >= 1000) {
const kilometers = meters / 1000;
if (options.compact && kilometers >= 100) {
return `${kilometers.toFixed(0)} km`;
}
if (options.compact && kilometers >= 10) {
return `${kilometers.toFixed(1)} km`;
}
return `${kilometers.toFixed(2)} km`
} else {
return meters % 1 == 0 ? `${meters} m` : `${Math.round(meters)} m`;
}
} else {
const miles = meters * 0.000621371;
const roundedMiles = miles.toFixed(2);
return `${roundedMiles} mi`;
}
}
export function formatElevation(meters?: number) {
if (meters === undefined) {
return "-";
}
const unit = page.data.settings?.unit ?? "metric";
if (unit == "metric") {
return `${Math.round(meters)} m`
} else {
const feet = meters * 3.28084;
return `${Math.round(feet)} ft`;
}
}
export function formatSpeed(speed?: number) {
if (speed === undefined) {
return "-";
}
const unit = page.data.settings?.unit ?? "metric";
if (unit == "metric") {
return `${(speed * 3.6).toFixed(2)} km/h`
} else {
const mph = speed * 3.6 * 0.621371;
return `${Math.round(mph)} mp/h`;
}
}
export function formatTimeSince(date: Date) {
const seconds = Math.floor((new Date().getTime() - date.getTime()) / 1000);
let interval = seconds / 31536000;
if (interval > 1) {
return { unit: "years", value: Math.floor(interval) };
}
interval = seconds / 2592000;
if (interval > 1) {
return { unit: "months", value: Math.floor(interval) };
}
interval = seconds / 86400;
if (interval > 1) {
return { unit: "days", value: Math.floor(interval) };
}
interval = seconds / 3600;
if (interval > 1) {
return { unit: "hours", value: Math.floor(interval) };
}
interval = seconds / 60;
if (interval > 1) {
return { unit: "minutes", value: Math.floor(interval) };
}
return { unit: "seconds", value: seconds };
}
export function formatHTMLAsText(html?: string) {
if(!html || !browser) {
return ""
}
// Create a temporary DOM element
const tempDiv = document.createElement("div");
tempDiv.innerHTML = html;
// Replace <br> with newlines to preserve line breaks
tempDiv.querySelectorAll("br").forEach((br) => br.replaceWith("\n"));
// Replace block-level elements with newlines before and after
const blockTags = new Set([
"DIV",
"P",
"LI",
"SECTION",
"ARTICLE",
"HEADER",
"FOOTER",
"ASIDE",
"MAIN",
"NAV",
"FIGURE",
"TABLE",
"TR",
"TD",
"TH",
"UL",
"OL",
"PRE",
]);
tempDiv.querySelectorAll("*").forEach((el) => {
if (blockTags.has(el.tagName)) {
el.insertAdjacentText("beforebegin", "\n");
el.insertAdjacentText("afterend", "\n");
}
});
// Extract the text content
let text = tempDiv.textContent;
if (!text) {
return "";
}
// Replace multiple spaces and newlines with a single one if needed
// Optional: collapse excessive blank lines to max two
text = text
.replace(/[ \t]+\n/g, "\n") // trailing spaces
.replace(/\n[ \t]+/g, "\n") // leading spaces
.replace(/\n{3,}/g, "\n\n") // collapse 3+ newlines
.replace(/[ \t]{2,}/g, " "); // collapse multiple spaces to two
// Trim the result
return text.trim();
}