Files
Radicale/radicale/web/internal_data/js/utils/misc.js
Max Berger 1f1e94340d Fix new JS verification errors and force specific TSC version
The new TSC compiler does stricter checking on the JS documentation
strings. All documentation strings have been updated to pass with
the current version (7.0.2)

In addition, the version of the TSC compiler used during the github
action will be fixed to 7.0.2, so that we don't get these type of
sudden errors again in the future. Unfortunately this means we need
to periodically update this manually.
2026-07-12 09:31:54 +02:00

166 lines
4.9 KiB
JavaScript

/**
* This file is part of Radicale Server - Calendar Server
* Copyright © 2017-2024 Unrud <unrud@outlook.com>
* Copyright © 2023-2024 Matthew Hana <matthew.hana@gmail.com>
* Copyright © 2024-2025 Peter Bieringer <pb@bieringer.de>
* Copyright © 2026-2026 Max Berger <max@berger.name>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { ROOT_PATH, SERVER } from "../constants.js";
/**
* Escape string for usage in XML
* @param {string} s
* @return {string}
*/
export function escape_xml(s) {
return (s
.replace(/&/g, "&amp;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&apos;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;"));
}
/**
* @return {string}
*/
export function random_uuid() {
return random_hex(8) + "-" + random_hex(4) + "-" + random_hex(4) + "-" + random_hex(4) + "-" + random_hex(12);
}
/**
* Generate random hex number.
* @param {number} length
* @return {string}
*/
export function random_hex(length) {
let bytes = new Uint8Array(Math.ceil(length / 2));
window.crypto.getRandomValues(bytes);
return bytes.reduce((s, b) => s + b.toString(16).padStart(2, "0"), "").substring(0, length);
}
/**
* Removed invalid HREF characters for a collection HREF.
* @param {HTMLInputElement} href_form A valid Input element or an onchange Event of an Input element.
*/
export function cleanHREFinput(href_form) {
let currentTxtVal = href_form.value.trim()
//Clean the HREF to remove not permitted chars
currentTxtVal = currentTxtVal.replace(/(?![0-9a-zA-Z\-\_\.\@])./g, '');
//Clean the HREF to remove leading . (would result in hidden directory)
currentTxtVal = currentTxtVal.replace(/^\./, '');
href_form.value = currentTxtVal;
}
/**
* Event listener for cleaning HREF input.
* @param {Event} event
*/
export function onCleanHREFinput(event) {
if (event.target instanceof HTMLInputElement) {
cleanHREFinput(event.target);
}
}
/**
* Make sure HREF is complete including server and prefix.
* @param {string} href
*/
export function completeHref(href) {
let full_href = href;
if (!href.includes("://")) {
if (!href.startsWith("/")) {
full_href = "/" + href;
}
// ROOT_PATH ends in / and href starts with /, so remove the duplicate /
full_href = SERVER + ROOT_PATH + full_href.substring(1);
}
return full_href;
}
/**
* Checks if a proposed HREF for a collection has a valid format and syntax.
* @param {string} href String of the proposed HREF.
* @return Boolean results if the HREF is valid.
*/
export function isValidHREF(href) {
if (href.length < 1) {
return false;
}
if (href.indexOf("/") != -1) {
return false;
}
return true;
}
/**
* Format bytes to human-readable text.
* @param {number} bytes Number of bytes.
* @return Formatted string.
*/
export function bytesToHumanReadable(bytes) {
if (isNaN(bytes - 0)) {
return "";
}
const units = ['b', 'kb', 'mb', 'gb', 'tb'];
let i = bytes == 0 ? 0 : Math.floor(Math.log(bytes) / Math.log(1024));
i = Math.min(i, units.length - 1);
return Math.round((bytes / Math.pow(1024, i)) * 100) / 100 + ' ' + units[i];
}
/**
* Get an element by its ID and throw an error if it's not found.
* @param {string} id The ID of the element to find.
* @return {HTMLElement} The found element.
*/
export function get_element_by_id(id) {
const element = document.getElementById(id);
if (!element) {
throw new Error("Element with ID '" + id + "' not found");
}
return element;
}
/**
* Get an element by a selector and throw an error if it's not found.
* @param {ParentNode} node The parent node to search within.
* @param {string} selector The CSS selector to use.
* @return {HTMLElement} The found element.
*/
export function get_element(node, selector) {
const element = node.querySelector(selector);
if (!element) {
throw new Error("Element with selector '" + selector + "' not found");
}
return /** @type {HTMLElement} */ (element);
}
/**
* Trim a string to the given maximum number of characters
*
* @param {string} str
* @param {number} max
* @returns {string}
*/
export function trim_to_max(str, max) {
if (str.length > max - 2) {
return str.substring(0, max) + "...";
}
return str;
}