szurubooru/client/js/util/misc.js

233 lines
6.2 KiB
JavaScript
Raw Normal View History

"use strict";
2016-03-31 23:18:08 +02:00
const markdown = require("./markdown.js");
const uri = require("./uri.js");
const settings = require("../models/settings.js");
2016-07-22 13:27:52 +02:00
function decamelize(str, sep) {
sep = sep === undefined ? "-" : sep;
2016-07-22 13:27:52 +02:00
return str
.replace(/([a-z\d])([A-Z])/g, "$1" + sep + "$2")
.replace(/([A-Z]+)([A-Z][a-z\d]+)/g, "$1" + sep + "$2")
2016-07-22 13:27:52 +02:00
.toLowerCase();
}
function* range(start = 0, end = null, step = 1) {
2020-06-04 20:09:35 +02:00
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;
}
);
}
2016-03-31 23:18:08 +02:00
function formatRelativeTime(timeString) {
if (!timeString) {
return "never";
2016-03-31 23:18:08 +02:00
}
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],
2016-03-31 23:18:08 +02:00
];
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";
2016-03-31 23:18:08 +02:00
}
return future ? "in " + text : text + " ago";
2016-03-31 23:18:08 +02:00
}
2016-05-29 12:26:29 +02:00
function formatMarkdown(text) {
return markdown.formatMarkdown(text);
2016-05-29 12:26:29 +02:00
}
function formatInlineMarkdown(text) {
return markdown.formatInlineMarkdown(text);
}
2016-07-03 13:46:49 +02:00
function splitByWhitespace(str) {
return str.split(/\s+/).filter((s) => s);
2016-07-03 13:46:49 +02:00
}
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, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&apos;");
}
function arraysDiffer(source1, source2, orderImportant) {
2016-07-22 13:27:52 +02:00
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
);
}
2016-09-29 22:45:40 +02:00
function escapeSearchTerm(text) {
return text.replace(/([a-z_-]):/g, "$1\\:");
2016-09-29 22:45:40 +02:00
}
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);
2020-06-04 20:09:35 +02:00
for (let i = 0; i < byteString.length; i++) {
data[i] = byteString.charCodeAt(i);
}
return new Blob([data], { type: mimeString });
}
function getPrettyName(tag) {
if (settings.get().tagUnderscoresAsSpaces) {
return tag.replace(/_/g, " ");
}
return tag;
}
module.exports = {
2020-06-04 20:09:35 +02:00
range: range,
formatRelativeTime: formatRelativeTime,
formatFileSize: formatFileSize,
formatMarkdown: formatMarkdown,
formatInlineMarkdown: formatInlineMarkdown,
unindent: unindent,
enableExitConfirmation: enableExitConfirmation,
disableExitConfirmation: disableExitConfirmation,
2020-06-04 20:09:35 +02:00
confirmPageExit: confirmPageExit,
escapeHtml: escapeHtml,
makeCssName: makeCssName,
splitByWhitespace: splitByWhitespace,
arraysDiffer: arraysDiffer,
decamelize: decamelize,
escapeSearchTerm: escapeSearchTerm,
dataURItoBlob: dataURItoBlob,
getPrettyName: getPrettyName,
};