@ -0,0 +1,307 @@ // MSPFA JS window.MSPFA = { BBC: [ [/ /g, "  "], [/\t/g, "    "], [/\r?\n/g, "
"], [/\[b\]((?:(?!\[b\]).)*?)\[\/b\]/gi, "$1"], [/\[i\]((?:(?!\[i\]).)*?)\[\/i\]/gi, "$1"], [/\[u\]((?:(?!\[u\]).)*?)\[\/u\]/gi, "$1"], [/\[s\]((?:(?!\[s\]).)*?)\[\/s\]/gi, "$1"], [/\[size=(\d*?)\]((?:(?!\[size=(?:\d*?)\]).)*?)\[\/size\]/gi, "$2"], [/\[color=("?)#?([a-f0-9]{3}(?:[a-f0-9]{3})?)\1\]((?:(?!\[color(?:=[^;]*?)\]).)*?)\[\/color\]/gi, "$3"], [/\[color=("?)([^";]+?)\1\]((?:(?!\[color(?:=[^;]*?)\]).)*?)\[\/color\]/gi, "$3"], [/\[background=("?)#?([a-f0-9]{3}(?:[a-f0-9]{3})?)\1\]((?:(?!\[background(?:=[^;]*?)\]).)*?)\[\/background\]/gi, "$3"], [/\[background=("?)([^";]+?)\1\]((?:(?!\[background(?:=[^;]*?)\]).)*?)\[\/background\]/gi, "$3"], [/\[font=("?)([^";]*?)\1\]((?:(?!\[size(?:=[^;]*?)\]).)*?)\[\/font\]/gi, "$3"], [/\[(center|left|right|justify)\]((?:(?!\[\1\]).)*?)\[\/\1\]/gi, "
$2
"], [/\[url\]([^"]*?)\[\/url\]/gi, "$1"], [/\[url=("?)([^"]*?)\1\]((?:(?!\[url(?:=.*?)\]).)*?)\[\/url\]/gi, "$3"], [/\[alt=("?)([^"]*?)\1\]((?:(?!\[alt(?:=.*?)\]).)*?)\[\/alt\]/gi, "$3"], [/\[img\]([^"]*?)\[\/img\]/gi, ""], [/\[img=(\d*?)x(\d*?)\]([^"]*?)\[\/img\]/gi, ""], [/\[spoiler\]((?:(?!\[spoiler(?: .*?)?\]).)*?)\[\/spoiler\]/gi, "
$1
"], [/\[spoiler open=("?)([^"]*?)\1 close=("?)([^"]*?)\3\]((?:(?!\[spoiler(?: .*?)?\]).)*?)\[\/spoiler\]/gi, "
$5
"], [/\[spoiler close=("?)([^"]*?)\1 open=("?)([^"]*?)\3\]((?:(?!\[spoiler(?: .*?)?\]).)*?)\[\/spoiler\]/gi, "
$5
"], [/\[flash=(\d*?)x(\d*?)\](.*?)\[\/flash\]/gi, ""], [/\[user\](.+?)\[\/user\]/gi, "@..."] ], toggleSpoiler: function() { if(this.parentNode.parentNode.classList.contains("closed")) { this.value = this.getAttribute("data-close"); this.parentNode.parentNode.classList.remove("closed"); this.parentNode.parentNode.classList.add("open"); } else if(this.parentNode.parentNode.classList.contains("open")) { this.value = this.getAttribute("data-open"); this.parentNode.parentNode.classList.remove("open"); this.parentNode.parentNode.classList.add("closed"); } }, parseBBCode: function(code, noHTML) { if(noHTML) { code = [code.replace(//g, ">")]; } else { code = code.split(/\<(textarea|style)(?:(?: |\n)(?:.|\n)*?)?\>(?:.|\n)*?\<\/\2\>/gi); for(var i = 2; i < code.length; i += 2) { code.splice(i, 1); } } for(var i = 0; i < code.length; i += 2) { var prevCode; while(prevCode != code[i]) { prevCode = code[i]; for(var j = 0; j < MSPFA.BBC.length; j++) { code[i] = code[i].replace(MSPFA.BBC[j][0], MSPFA.BBC[j][1]); } } } code = code.join(""); var e = document.createElement("span"); e.innerHTML = code; var es = e.querySelectorAll("*"); for(var i = es.length-1; i >= 0; i--) { if(es[i].tagName == "SCRIPT") { es[i].parentNode.removeChild(es[i]); } else if(es[i].tagName == "PARAM") { if(es[i].name.trim() == "allowScriptAccess") { es[i].parentNode.removeChild(es[i]); } } else { // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet for(var j = 0; j < es[i].attributes.length; j++) { if(es[i].attributes[j].name.toLowerCase().indexOf("on") == 0 || (typeof es[i][es[i].attributes[j].name.toLowerCase()] == "string" && /^(?:javascript|data):/.test(es[i][es[i].attributes[j].name.toLowerCase()])) || /^(?:javascript|data):/.test(es[i].attributes[j].value) || es[i].attributes[j].name.toLowerCase() == "allowscriptaccess") { es[i].removeAttribute(es[i].attributes[j].name); } } } } try { var sins = e.querySelectorAll(".spoiler > div:first-child > input"); for(var i = 0; i < sins.length; i++) { sins[i].addEventListener("click", MSPFA.toggleSpoiler); } var sdivs = e.querySelectorAll(".spoiler > div:last-child"); for(var i = 0; i < sdivs.length; i++) { var rembrc = true; while(rembrc) { rembrc = false; var rembr = sdivs[i]; while(rembr = rembr.firstChild) { if(rembr.tagName == "BR") { rembr.parentNode.removeChild(rembr); rembrc = true; break; } } rembr = sdivs[i]; while(rembr = rembr.lastChild) { if(rembr.tagName == "BR") { rembr.parentNode.removeChild(rembr); rembrc = true; break; } } } } } catch (err) { } var usertags = e.querySelectorAll("a.usertag"); // for (var i = 0; i < usertags.length; i++) { // (function (usertag) { // MSPFA.request(0, { // do: "user", // u: usertag.getAttribute("data-userid") // }, function (user) { // usertag.innerText = "@" + user.n; // }, function (status) { // if (status == 404) { // usertag.innerText = ""; // } // }, true); // })(usertags[i]); // } // if (MSPFA.ruffleEnabled === undefined && e.querySelector("object")) { // var content = document.createElement('span'); // content.appendChild(document.createTextNode('This page tried to load Flash content, which is not supported. Would you like to automatically use ')); // var ruffleLink = document.createElement('a'); // ruffleLink.textContent = 'Ruffle'; // ruffleLink.href = 'https://ruffle.rs/'; // ruffleLink.target = '_blank'; // content.appendChild(ruffleLink); // content.appendChild(document.createTextNode(' to emulate all Flash content during this session?')); // content.appendChild(document.createElement('br')); // content.appendChild(document.createElement('br')); // var warning = document.createElement('span'); // warning.textContent = 'Warning: Ruffle is still in development and will not always work. You can always refresh the page to disable it again.'; // warning.style.color = '#ed5014'; // content.appendChild(warning); // MSPFA.dialog('Flash', content, ["Yes", "No"], function(output) { // if (output === 'Yes') { // MSPFA.ruffleEnabled = true; // var ruffleScript = document.createElement('script'); // ruffleScript.src = '/js/ruffle.js?cb=1'; // document.head.appendChild(ruffleScript); // } else { // MSPFA.ruffleEnabled = false; // } // }); // } return e; }, slide: [] } let adventureData // Get JSON window.addEventListener('DOMContentLoaded', (event) => { fetch("./adventure.json").then(response => response.json()).then(json => loadAdventure(json)); }); const clickLink = (event, link) => { console.log(link) event.preventDefault() history.pushState(null, '', link) loadPage() } const getUrlPage = () => { const urlParams = new URLSearchParams(window.location.search); const p = urlParams.get("p") return p ? p : "1" } const loadIntoElement = (id, element) => { console.log(id, element) document.getElementById(id).innerHTML = "" document.getElementById(id).append(element) } const loadAdventure = data => { adventureData = data document.title = adventureData.n document.getElementById("favicon").href = adventureData.o document.getElementById("goback").addEventListener("click", evt => clickLink(evt, document.getElementById("goback").href)) loadPage() } const genPageLinks = (pages, linkIndexs) => { const span = document.createElement("span") linkIndexs.forEach(pageIndex => { if (pages[pageIndex - 1]) { preloadImages(pageIndex) const a = document.createElement("a") a.href = `?p=${pageIndex}` a.append(MSPFA.parseBBCode(pages[pageIndex - 1].c)) a.addEventListener("click", evt => clickLink(evt, a.href)) const div = document.createElement("div") div.append(a) span.append(div) } }) return span } const loadPage = () => { const p = getUrlPage() document.body.className = "mspfa p" + p document.getElementById("gobackbar").style.display = "none" document.getElementById("goback").style.display = "none" document.getElementById("prelaod").innerHTML = "" // If Log, load log p if (p == "log" || isNaN(p)) { loadLog() return } // If page number too large if (p > adventureData.p.length) { loadIntoElement("command", MSPFA.parseBBCode("No page found")) loadIntoElement("content", MSPFA.parseBBCode("This page does not exist")) loadIntoElement("links", MSPFA.parseBBCode("")) return } // Load given page const pageData = adventureData.p[p - 1] loadIntoElement("command", MSPFA.parseBBCode(pageData.c)) loadIntoElement("content", MSPFA.parseBBCode(pageData.b)) loadIntoElement("links", genPageLinks(adventureData.p, pageData.n)) // Gen go back number var backid = 0; adventureData.p.forEach((e, i) => { if (e.n.includes(parseInt(p))) backid = i + 1 }) if (backid) { document.getElementById("gobackbar").style.display = "inline" document.getElementById("goback").style.display = "inline" document.getElementById("goback").href = "?p=" + backid preloadImages(backid) } // FINAL run all MSPFA slides MSPFA.slide.forEach(func => func()) } const loadLog = () => { // Generate Log link list let ul = document.createElement("ul") adventureData.p.forEach((pageData, index) => { const date = new Date(pageData.d).toLocaleDateString("en-US") const a = document.createElement("a") a.href = `?p=${index + 1}` a.append(MSPFA.parseBBCode(pageData.c)) a.addEventListener("click", evt => clickLink(evt, a.href)) const li = document.createElement("li") li.append(document.createTextNode(date + ": ")) li.append(a) ul.prepend(li) }) ul.style.textAlign = "left" ul.style.listStyleType = "none" ul.style.padding = "0" loadIntoElement("command", MSPFA.parseBBCode(adventureData.n + " LOG")) loadIntoElement("content", ul) loadIntoElement("links", MSPFA.parseBBCode("")) } const preloadImages = pageIndex => { if (adventureData.p[pageIndex - 1]) { const body = adventureData.p[pageIndex - 1].b const imgRegex = body.match(/\[img\](?[^"]*?)\[\/img\]|\[img=(\d*?)x(\d*?)\]([^"]*?)\[\/img\]/gi) document.getElementById("prelaod").append(MSPFA.parseBBCode(imgRegex.join(" "))) } } window.addEventListener("keydown", function(evt) { if (isNaN(getUrlPage())) { return } if (evt.key == "ArrowRight") { clickLink(evt, this.document.querySelector("#links a").href) } if (evt.key == "ArrowLeft") { clickLink(evt, this.document.querySelector("#goback").href) } if (evt.key == " ") { evt.preventDefault() this.document.querySelectorAll(".spoiler input").forEach(e => { e.click() }) } })