"use strict"; const markdown = require("./markdown.js"); const uri = require("./uri.js"); const settings = require("../models/settings.js"); function decamelize(str, sep) { sep = sep === undefined ? "-" : sep; return str .replace(/([a-z\d])([A-Z])/g, "$1" + sep + "$2") .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, "$1" + sep + "$2") .toLowerCase(); } function* range(start = 0, end = null, step = 1) { if (end === null) { end = start; start = 0; } for (let i = start; i < end; i += step) { yield i; } } function _formatUnits(number, base, suffixes, callback) { if (!number && number !== 0) { return NaN; } number *= 1.0; let suffix = suffixes.shift(); while (number >= base && suffixes.length > 0) { suffix = suffixes.shift(); number /= base; } if (callback === undefined) { callback = (number, suffix) => { return suffix ? number.toFixed(1) + suffix : number; }; } return callback(number, suffix); } function formatFileSize(fileSize) { return _formatUnits( fileSize, 1024, ["B", "K", "M", "G"], (number, suffix) => { const decimalPlaces = number < 20 && suffix !== "B" ? 1 : 0; return number.toFixed(decimalPlaces) + suffix; } ); } function formatRelativeTime(timeString) { if (!timeString) { return "never"; } const then = Date.parse(timeString); const now = Date.now(); const difference = Math.abs(now - then) / 1000.0; const future = now < then; const descriptions = [ [60, "a few seconds", null], [60 * 2, "a minute", null], [60 * 60, "% minutes", 60], [60 * 60 * 2, "an hour", null], [60 * 60 * 24, "% hours", 60 * 60], [60 * 60 * 24 * 2, "a day", null], [60 * 60 * 24 * 30.42, "% days", 60 * 60 * 24], [60 * 60 * 24 * 30.42 * 2, "a month", null], [60 * 60 * 24 * 30.42 * 12, "% months", 60 * 60 * 24 * 30.42], [60 * 60 * 24 * 30.42 * 12 * 2, "a year", null], [8640000000000000 /* max*/, "% years", 60 * 60 * 24 * 30.42 * 12], ]; let text = null; for (let kv of descriptions) { const multiplier = kv[0]; const template = kv[1]; const divider = kv[2]; if (difference < multiplier) { text = template.replace(/%/, Math.round(difference / divider)); break; } } if (text === "a day") { return future ? "tomorrow" : "yesterday"; } return future ? "in " + text : text + " ago"; } function formatMarkdown(text) { return markdown.formatMarkdown(text); } function formatInlineMarkdown(text) { return markdown.formatInlineMarkdown(text); } function splitByWhitespace(str) { return str.split(/\s+/).filter((s) => s); } function unindent(callSite, ...args) { function format(str) { let size = -1; return str.replace(/\n(\s+)/g, (m, m1) => { if (size < 0) { size = m1.replace(/\t/g, " ").length; } return "\n" + m1.slice(Math.min(m1.length, size)); }); } if (typeof callSite === "string") { return format(callSite); } if (typeof callSite === "function") { return (...args) => format(callSite(...args)); } let output = callSite .slice(0, args.length + 1) .map((text, i) => (i === 0 ? "" : args[i - 1]) + text) .join(""); return format(output); } function enableExitConfirmation() { window.onbeforeunload = (e) => { return ( "Are you sure you want to leave? " + "Data you have entered may not be saved." ); }; } function disableExitConfirmation() { window.onbeforeunload = null; } function confirmPageExit() { if (!window.onbeforeunload) { return true; } if (window.confirm(window.onbeforeunload())) { disableExitConfirmation(); return true; } } function makeCssName(text, suffix) { return suffix + "-" + text.replace(/[^a-z0-9]/g, "_"); } function escapeHtml(unsafe) { return unsafe .toString() .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } function arraysDiffer(source1, source2, orderImportant) { source1 = [...source1]; source2 = [...source2]; if (orderImportant === true) { if (source1.length !== source2.length) { return true; } for (let i = 0; i < source1.length; i++) { if (source1[i] !== source2[i]) { return true; } } return false; } return ( source1.filter((value) => !source2.includes(value)).length > 0 || source2.filter((value) => !source1.includes(value)).length > 0 ); } function escapeSearchTerm(text) { return text.replace(/([a-z_-]):/g, "$1\\:"); } function dataURItoBlob(dataURI) { const chunks = dataURI.split(","); const byteString = chunks[0].indexOf("base64") >= 0 ? window.atob(chunks[1]) : unescape(chunks[1]); const mimeString = chunks[0].split(":")[1].split(";")[0]; const data = new Uint8Array(byteString.length); for (let i = 0; i < byteString.length; i++) { data[i] = byteString.charCodeAt(i); } return new Blob([data], { type: mimeString }); } function getPrettyTagName(tag) { if (settings.get().tagUnderscoresAsSpaces) { return tag.replace(/_/g, " "); } return tag; } module.exports = { range: range, formatRelativeTime: formatRelativeTime, formatFileSize: formatFileSize, formatMarkdown: formatMarkdown, formatInlineMarkdown: formatInlineMarkdown, unindent: unindent, enableExitConfirmation: enableExitConfirmation, disableExitConfirmation: disableExitConfirmation, confirmPageExit: confirmPageExit, escapeHtml: escapeHtml, makeCssName: makeCssName, splitByWhitespace: splitByWhitespace, arraysDiffer: arraysDiffer, decamelize: decamelize, escapeSearchTerm: escapeSearchTerm, dataURItoBlob: dataURItoBlob, getPrettyTagName: getPrettyTagName, };