diff options
author | Daniel Baumann <daniel@debian.org> | 2024-10-18 20:33:49 +0200 |
---|---|---|
committer | Daniel Baumann <daniel@debian.org> | 2024-12-12 23:57:56 +0100 |
commit | e68b9d00a6e05b3a941f63ffb696f91e554ac5ec (patch) | |
tree | 97775d6c13b0f416af55314eb6a89ef792474615 /web_src/js/utils.js | |
parent | Initial commit. (diff) | |
download | forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.tar.xz forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.zip |
Adding upstream version 9.0.3.
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to 'web_src/js/utils.js')
-rw-r--r-- | web_src/js/utils.js | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/web_src/js/utils.js b/web_src/js/utils.js new file mode 100644 index 0000000..ce0fb66 --- /dev/null +++ b/web_src/js/utils.js @@ -0,0 +1,144 @@ +import {encode, decode} from 'uint8-to-base64'; + +// transform /path/to/file.ext to file.ext +export function basename(path = '') { + const lastSlashIndex = path.lastIndexOf('/'); + return lastSlashIndex < 0 ? path : path.substring(lastSlashIndex + 1); +} + +// transform /path/to/file.ext to .ext +export function extname(path = '') { + const lastPointIndex = path.lastIndexOf('.'); + return lastPointIndex < 0 ? '' : path.substring(lastPointIndex); +} + +// test whether a variable is an object +export function isObject(obj) { + return Object.prototype.toString.call(obj) === '[object Object]'; +} + +// returns whether a dark theme is enabled +export function isDarkTheme() { + const style = window.getComputedStyle(document.documentElement); + return style.getPropertyValue('--is-dark-theme').trim().toLowerCase() === 'true'; +} + +// strip <tags> from a string +export function stripTags(text) { + return text.replace(/<[^>]*>?/g, ''); +} + +export function parseIssueHref(href) { + const path = (href || '').replace(/[#?].*$/, ''); + const [_, owner, repo, type, index] = /([^/]+)\/([^/]+)\/(issues|pulls)\/([0-9]+)/.exec(path) || []; + return {owner, repo, type, index}; +} + +// parse a URL, either relative '/path' or absolute 'https://localhost/path' +export function parseUrl(str) { + return new URL(str, str.startsWith('http') ? undefined : window.location.origin); +} + +// return current locale chosen by user +export function getCurrentLocale() { + return document.documentElement.lang; +} + +// given a month (0-11), returns it in the documents language +export function translateMonth(month) { + return new Date(Date.UTC(2022, month, 12)).toLocaleString(getCurrentLocale(), {month: 'short', timeZone: 'UTC'}); +} + +// given a weekday (0-6, Sunday to Saturday), returns it in the documents language +export function translateDay(day) { + return new Date(Date.UTC(2022, 7, day)).toLocaleString(getCurrentLocale(), {weekday: 'short', timeZone: 'UTC'}); +} + +// convert a Blob to a DataURI +export function blobToDataURI(blob) { + return new Promise((resolve, reject) => { + try { + const reader = new FileReader(); + reader.addEventListener('load', (e) => { + resolve(e.target.result); + }); + reader.addEventListener('error', () => { + reject(new Error('FileReader failed')); + }); + reader.readAsDataURL(blob); + } catch (err) { + reject(err); + } + }); +} + +// convert image Blob to another mime-type format. +export function convertImage(blob, mime) { + return new Promise(async (resolve, reject) => { + try { + const img = new Image(); + const canvas = document.createElement('canvas'); + img.addEventListener('load', () => { + try { + canvas.width = img.naturalWidth; + canvas.height = img.naturalHeight; + const context = canvas.getContext('2d'); + context.drawImage(img, 0, 0); + canvas.toBlob((blob) => { + if (!(blob instanceof Blob)) return reject(new Error('imageBlobToPng failed')); + resolve(blob); + }, mime); + } catch (err) { + reject(err); + } + }); + img.addEventListener('error', () => { + reject(new Error('imageBlobToPng failed')); + }); + img.src = await blobToDataURI(blob); + } catch (err) { + reject(err); + } + }); +} + +export function toAbsoluteUrl(url) { + if (url.startsWith('http://') || url.startsWith('https://')) { + return url; + } + if (url.startsWith('//')) { + return `${window.location.protocol}${url}`; // it's also a somewhat absolute URL (with the current scheme) + } + if (url && !url.startsWith('/')) { + throw new Error('unsupported url, it should either start with / or http(s)://'); + } + return `${window.location.origin}${url}`; +} + +// Encode an ArrayBuffer into a URLEncoded base64 string. +export function encodeURLEncodedBase64(arrayBuffer) { + return encode(arrayBuffer) + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=/g, ''); +} + +// Decode a URLEncoded base64 to an ArrayBuffer string. +export function decodeURLEncodedBase64(base64url) { + return decode(base64url + .replace(/_/g, '/') + .replace(/-/g, '+')); +} + +const domParser = new DOMParser(); +const xmlSerializer = new XMLSerializer(); + +export function parseDom(text, contentType) { + return domParser.parseFromString(text, contentType); +} + +export function serializeXml(node) { + return xmlSerializer.serializeToString(node); +} + +export const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); |