function loadTemplateAsync(path) { const result = new Promise(resolve => { const xhttp = new XMLHttpRequest() xhttp.onreadystatechange = function () { if (this.readyState == 4) { if (this.status == 200) resolve(this.responseText) if (this.status == 404) resolve(`
Page not found: ${path}
`) } } xhttp.open('GET', path, true) xhttp.send() }) return result } function imgSizeFit(img, maxWidth = 1024, maxHeight = 768) { let ratio = Math.min( 1, maxWidth / img.naturalWidth, maxHeight / img.naturalHeight ) return {width: img.naturalWidth * ratio, height: img.naturalHeight * ratio} } async function hash(string) { const utf8 = new TextEncoder().encode(string) const hashBuffer = await crypto.subtle.digest('SHA-256', utf8) const hashArray = Array.from(new Uint8Array(hashBuffer)) const hashHex = hashArray .map(bytes => bytes.toString(16).padStart(2, '0')) .join('') return hashHex } function isJson(str) { if (typeof str !== 'string') { return false } try { JSON.parse(str) return true } catch (error) { return false } }