0xab178613…feaasent to0xd6878475…ab48·#21,069,913·0x32997748…45d393
// Initialization
const typingSpeed = typingSpeeds[poemId - 1];
const context = contexts[poemId - 1];
const upscalePrompt =
"black and white," +
upscalePrompts[talismanId - 1] +
",metallic grain surface"; // This prompt should be used to upscale the talisman
let animate = undefined;
let isAnimateLoaded = import(`${arweaveGatewayURL}${animateURL}`)
.then(() => {
animate = Motion.animate;
// Now you can use the animate function
console.log("Successfully imported animate");
})
.catch((error) => console.error("Failed to import animate:", error));
console.log(codem);
console.log("Is it a signed edition? " + isSignedEdition);
// Font loading and initialization
function initializeFonts() {
const fontFaces = `
@font-face {
font-family: "Font-Bold";
src: URL("${arweaveGatewayURL}${fontBoldURL}");
font-display: swap;
}
@font-face {
font-family: "Font-Light";
src: URL("${arweaveGatewayURL}${fontLightURL}");
font-display: swap;
}
@font-face {
font-family: "Braille";
src: URL("${arweaveGatewayURL}${fontBrailleURL}");
font-display: swap;
}
@font-face {
font-family: "Silver-LQ";
src: URL("${arweaveGatewayURL}${fontSilverLQURL}");
font-display: swap;
}
@font-face {
font-family: "Silver";
src: URL("${arweaveGatewayURL}${fontSilverURL}");
font-display: swap;
}
`;
const style = document.createElement("style");
style.textContent = fontFaces;
document.head.appendChild(style);
const fonts = [
{
name: "Silver",
class: "HQ-font-loaded",
url: `${arweaveGatewayURL}${fontSilverURL}`,
},
{
name: "Silver-LQ",
class: "LQ-font-loaded",
url: `${arweaveGatewayURL}${fontSilverLQURL}`,
},
{
name: "Font-Bold",
class: "default-font-loaded",
url: `${arweaveGatewayURL}${fontBoldURL}`,
},
];
// Start loading all fonts immediately
fonts.forEach((font) => {
new FontFace(font.name, `url(${font.url})`)
.load()
.then((loadedFont) => {
document.fonts.add(loadedFont);
console.log(`${font.name} loaded`);
})
.catch((err) => console.error(`Failed to load ${font.name}:`, err));
});
function applyFont() {
for (const font of fonts) {
if (document.fonts.check(`12px "${font.name}"`)) {
document.body.classList.add(font.class);
console.log(`Applied ${font.name}`);
return true;
}
}
return false;
}
function checkAndApplyFonts() {
if (applyFont()) return;
const checkInterval = setInterval(() => {
if (applyFont()) {
clearInterval(checkInterval);
}
}, 50);
document.fonts.ready.then(() => {
applyFont();
clearInterval(checkInterval);
});
}
// Start checking for font availability immediately
checkAndApplyFonts();
}
// Call the font initialization function
initializeFonts();
document.querySelector(".author").innerText = author;
document.querySelector(".coverAuthor").innerText = "codem by " + author;
document.querySelector(".context").innerText = context;
document.querySelector(".code").innerText = codem;
const talismanImg = new Image();
talismanImg.src = `${arweaveGatewayURL}${talismansURL}/${talismanId}.avif`; //`./images/talismans/avif/${talismanId}.avif`;
talismanImg.alt = upscalePrompt;
talismanImg.onload = () => {
const talisman = document.querySelector(".talisman");
talisman.style.backgroundImage = `URL("${talismanImg.src}")`;
talisman.setAttribute("aria-label", upscalePrompt);
const coverTalisman = document.querySelector(".coverTalisman");
coverTalisman.style.backgroundImage = `URL("${talismanImg.src}")`;
coverTalisman.setAttribute("aria-label", upscalePrompt);
setFavicon();
};
talismanImg.onerror = () => {
talismanImg.src = talismanLQURL; //`./images/talismans/lowres-avif/${talismanId}.avif`;
};
//
document.querySelector(".title").innerText = title;
document.querySelector(".coverTitle").innerText = title;
addSignature();
document.addEventListener("DOMContentLoaded", () => {
console.log("window loaded");
const URLParams = new URLSearchParams(location.hash.substring(1));
if (URLParams.has("poem")) {
toggleCover(0, false);
console.log("Poem Mode Activated");
} else if (
!URLParams.has("cover") &&
!(typeof hl !== "undefined" && hl?.context?.previewMode)
) {
setTimeout(() => toggleCover(1, true), 2000);
console.log("Regular Mode Activated");
} else {
console.log("Cover Mode Activated");
}
document.body.onclick = () => toggleCover(0.4, true);
});
function addSignature() {
if (!isSignedEdition) {
return;
}
const signature = document.createElement("div");
signature.classList.add("signature");
const signatureImg = new Image();
signatureImg.src = `${arweaveGatewayURL}${signatureImageURL}`;
signatureImg.onload = () => {
signature.style.backgroundImage = `URL("${signatureImg.src}")`;
document.body.appendChild(signature);
};
signatureImg.onerror = () => {
signatureImg.src = signatureImageLQURL;
document.body.appendChild(signature);
};
}
let worker;
const outputDiv = document.querySelector(".console");
outputDiv.scrollTo = function () {
var start = window.performance.now();
var from = outputDiv.scrollTop;
var to = outputDiv.scrollHeight;
var duration = 100; // adjust the duration to your liking
function animateScroll(timestamp) {
var progress = Math.min(1, (timestamp - start) / duration);
outputDiv.scrollTop = from + (to - from) * progress;
if (progress < 1) {
requestAnimationFrame(animateScroll);
}
}
requestAnimationFrame(animateScroll);
};
let typingInProgress = false;
let messageQueue = [];
let typeInterval;
function initWorker() {
const workerCode = `let resolveUserInput;
self.onmessage = async (event) => {
if (
event.data.type === "promptAnswer" ||
event.data.type === "confirmAnswer" ||
event.data.type === "storageAnswer"
) {
resolveUserInput(event.data.answer);
} else {
try {
const code = event.data.code;
const asyncFunction = new Function(
"return async function() {" + code + "}"
);
await asyncFunction()();
} catch (e) {
console.log(e);
}
}
};
console.log = (message) => {
self.postMessage({ type: "consoleLog", message: message });
};
console.error = (error) => {
console.log("ERROR: " + error.toString());
console.trace(error);
};
console.warn = (warning) => {
console.log("WARNING: " + warning);
};
console.clear = () => {
self.postMessage({ type: "consoleClear" });
};
prompt = (message) => {
return new Promise((resolve) => {
resolveUserInput = resolve;
self.postMessage({ type: "prompt", message: message });
});
};
confirm = (message) => {
return new Promise((resolve) => {
resolveUserInput = resolve;
self.postMessage({ type: "confirm", message: message });
});
};
Error = (error) => {
console.log("Error: " + error.toString());
console.trace(error);
};
localStorage = {
getItem: (key) => {
return new Promise((resolve) => {
self.postMessage({ type: "localStorage", method: "getItem", key });
resolveUserInput = resolve;
});
},
setItem: (key, value) => {
return new Promise((resolve) => {
self.postMessage({ type: "localStorage", method: "setItem", key, value });
});
},
};
`;
const blob = new Blob([workerCode], { type: "application/javascript" });
const workerURL = URL.createObjectURL(blob);
worker = new Worker(workerURL);
worker.onmessage = async (event) => {
if (event.data.type === "consoleLog") {
messageQueue.push(event.data.message + String.fromCharCode(10));
if (!typingInProgress) {
typeNextMessage();
}
} else if (event.data.type === "consoleClear") {
messageQueue = [];
clearInterval(typeInterval);
typingInProgress = false;
outputDiv.innerText = "";
} else if (event.data.type === "prompt") {
const answer = await customPrompt(event.data.message);
worker.postMessage({ type: "promptAnswer", answer: answer });
} else if (event.data.type === "confirm") {
const answer = await customConfirm(event.data.message);
worker.postMessage({ type: "confirmAnswer", answer: answer });
} else if (event.data.type === "localStorage") {
if (event.data.method === "getItem") {
try {
const value = localStorage.getItem(event.data.key);
worker.postMessage({ type: "storageAnswer", answer: value });
} catch {
worker.postMessage({ type: "storageAnswer", answer: "0" });
}
} else if (event.data.method === "setItem") {
localStorage.setItem(event.data.key, event.data.value);
}
}
};
function typeNextMessage() {
if (messageQueue.length === 0) return;
typingInProgress = true;
const message = messageQueue.shift();
if (typingSpeed) {
let charIndex = 0;
let previousScrollHeight = outputDiv.scrollHeight;
typeInterval = setInterval(() => {
outputDiv.innerHTML += message[charIndex];
charIndex++;
// Check if the scroll height has increased, indicating a new line
if (outputDiv.scrollHeight > previousScrollHeight) {
outputDiv.scrollTop = outputDiv.scrollHeight;
}
previousScrollHeight = outputDiv.scrollHeight;
if (charIndex >= message.length) {
clearInterval(typeInterval);
typingInProgress = false;
typeNextMessage();
}
}, typingSpeed);
} else {
outputDiv.innerHTML += message;
outputDiv.scrollTop = outputDiv.scrollHeight;
typingInProgress = false;
typeNextMessage();
}
}
}
async function runCode() {
messageQueue = [];
clearInterval(typeInterval);
typingInProgress = false;
outputDiv.innerText = "";
if (worker) {
worker.terminate();
}
initWorker();
worker.postMessage({ code: codem });
}
window.runCode = runCode;
document.addEventListener("keydown", (event) => {
if ((event.metaKey || event.ctrlKey) && event.keyCode === 13) {
// Cmd+Enter (or Ctrl+Enter on Windows) pressed, run the function
runCode();
}
});
let isCovered = true;
window.toggleCover = async function toggleCover(duration, waitAnimate) {
if (waitAnimate) {
await isAnimateLoaded;
}
if (
arguments.length > 0 &&
arguments[0] &&
arguments[0].target &&
typeof arguments[0].target.closest === "function"
) {
if (arguments[0].target.closest("dialog")) {
// Click occurred on dialog, do nothing
return;
}
}
if (
document.querySelector("dialog").open ||
window.getSelection().toString() !== ""
) {
// Dialog is open or user is selecting text, do nothing
return;
}
console.log("toggling cover mode...");
isCovered = !isCovered;
if (!isCovered) {
setTimeout(() => runCode(), 500);
}
if (typeof animate !== "undefined") {
animate(
".top, .bottom",
{
height: isCovered ? "0" : "50%",
opacity: isCovered ? "0" : "100%",
transform: isCovered ? "rotateX(-90deg)" : "rotateX(0)",
},
{
duration: duration,
}
);
animate(
".cover",
{
height: isCovered ? "100%" : "0",
transform: isCovered ? "rotateX(0)" : "rotateX(90deg)",
opacity: isCovered ? "100%" : "0",
},
{
duration: duration,
}
);
animate(
" .coverTitle",
{
opacity: isCovered ? "100%" : "0",
fontSize: isCovered ? "14dvmin" : "0",
},
{
duration: duration,
}
);
animate(
" .coverAuthor",
{
fontSize: isCovered ? "1.5dvmax" : "0",
opacity: isCovered ? "100%" : "0",
},
{
duration: duration,
}
);
animate(
".coverData",
{
opacity: isCovered ? "100%" : "0",
},
{
duration: duration,
}
);
} else {
// Fallback: toggle the "open" class on the cover element
console.log("animate library not available, moving to fallback");
document.body.classList.toggle("open");
}
};
function setFavicon() {
const link = document.createElement("link");
link.rel = "shortcut icon";
link.type = "image/avif";
link.href = talismanImg.src;
document.getElementsByTagName("head")[0].appendChild(link);
}
// MODAL UTILITIES
let modalResolve;
window.customConfirm = function customConfirm(message) {
document.getElementById("modalText").innerText = message;
const dialog = document.querySelector("dialog");
dialog.showModal();
return new Promise((resolve) => {
modalResolve = resolve;
dialog.onkeydown = (event) => {
if (event.key === "Enter") modalChoice(true);
if (event.key === "Escape") modalChoice(false);
};
});
};
window.customPrompt = function customPrompt(message) {
document.getElementById("modalText").innerText = message;
document.getElementById("modalInput").style.display = "block";
const dialog = document.querySelector("dialog");
dialog.showModal();
return new Promise((resolve) => {
modalResolve = resolve;
dialog.onkeydown = (event) => {
if (event.key === "Enter") modalChoice(true);
if (event.key === "Escape") modalChoice(false);
};
});
};
window.modalChoice = function modalChoice(choice) {
const dialog = document.querySelector("dialog");
dialog.onkeydown = null; // Remove the event listener
if (document.getElementById("modalInput").style.display === "block") {
modalResolve(document.getElementById("modalInput").value);
document.getElementById("modalInput").style.display = "none";
document.getElementById("modalInput").value = "";
} else {
modalResolve(choice);
}
dialog.close();
event.stopPropagation(); // Add this line
};