From 1a3ce1e3ff2b3d1c8e393760c422b866819ce2c0 Mon Sep 17 00:00:00 2001 From: TomatoCake <60300461+DEVTomatoCake@users.noreply.github.com> Date: Sat, 20 Jul 2024 19:19:23 +0200 Subject: [PATCH 01/10] implement very basic connections & applications --- webpage/index.html | 7 +- webpage/index.ts | 11 ++ webpage/localuser.ts | 260 ++++++++++++++++++++++++++++++++++++++++++- webpage/style.css | 39 +++++-- 4 files changed, 303 insertions(+), 14 deletions(-) diff --git a/webpage/index.html b/webpage/index.html index 07b70b1..c970952 100644 --- a/webpage/index.html +++ b/webpage/index.html @@ -37,7 +37,12 @@

STATUS

-

+ +
+

+

🔗

+

🤖

+
diff --git a/webpage/index.ts b/webpage/index.ts index a5d367e..3c21fa6 100644 --- a/webpage/index.ts +++ b/webpage/index.ts @@ -245,6 +245,17 @@ function userSettings(){ thisuser.usersettings.show(); } document.getElementById("settings").onclick=userSettings; + +function userConnections(){ + thisuser.userConnections.show(); +} +document.getElementById("connections").onclick=userConnections; + +function devPortal(){ + thisuser.devPortal.show(); +} +document.getElementById("dev-portal").onclick=devPortal; + let triggered=false; document.getElementById("messagecontainer").addEventListener("scroll",(e)=>{ const messagecontainer=document.getElementById("messagecontainer") diff --git a/webpage/localuser.ts b/webpage/localuser.ts index 9ca8b11..87cf0c5 100644 --- a/webpage/localuser.ts +++ b/webpage/localuser.ts @@ -19,6 +19,8 @@ class Localuser{ info; headers:{"Content-type":string,Authorization:string}; usersettings:Fullscreen; + userConnections:Fullscreen; + devPortal:Fullscreen; ready; guilds:Guild[]; guildids:{ [key: string]: Guild }; @@ -671,6 +673,262 @@ class Localuser{ newprouns=null; newbio=null; }.bind(this)) - } + + const connectionContainer=document.createElement("div"); + connectionContainer.id="connection-container"; + this.userConnections=new Fullscreen( + ["html", + connectionContainer + ], () => {}, async () => { + connectionContainer.innerHTML=""; + + const res=await fetch(this.info.api.toString()+"/v9/connections", { + headers: this.headers + }); + const json=await res.json(); + + Object.keys(json).sort(key => json[key].enabled ? -1 : 1).forEach(key => { + const connection=json[key]; + + const container=document.createElement("div"); + container.textContent=key.charAt(0).toUpperCase() + key.slice(1); + + if (connection.enabled) { + container.addEventListener("click", async () => { + const connectionRes=await fetch(this.info.api.toString()+"/v9/connections/" + key + "/authorize", { + headers: this.headers + }); + const connectionJSON=await connectionRes.json(); + window.open(connectionJSON.url, "_blank", "noopener noreferrer"); + }) + } else { + container.classList.add("disabled") + container.title="This connection has been disabled server-side." + } + + connectionContainer.appendChild(container); + }) + } + ); + + let appName=""; + const appListContainer=document.createElement("div"); + appListContainer.id="app-list-container"; + this.devPortal=new Fullscreen( + ["vdiv", + ["hdiv", + ["textbox", "Name:", appName, event => { + appName=event.target.value; + }], + ["button", + "", + "Create application", + async () => { + if (appName.trim().length == 0) return alert("Please enter a name for the application."); + + const res=await fetch(this.info.api.toString()+"/v9/applications", { + method: "POST", + headers: this.headers, + body: JSON.stringify({ + name: appName + }) + }); + const json=await res.json(); + this.manageApplication(json.id); + this.devPortal.hide(); + } + ] + ], + ["html", + appListContainer + ] + ], () => {}, async () => { + appListContainer.innerHTML=""; + + const res=await fetch(this.info.api.toString()+"/v9/applications", { + headers: this.headers + }); + const json=await res.json(); + + json.forEach(application => { + const container=document.createElement("div"); + + if (application.cover_image) { + const cover=document.createElement("img"); + cover.crossOrigin="anonymous"; + cover.src=this.info.cdn.toString()+"/app-icons/" + application.id + "/" + application.cover_image + ".png?size=256"; + cover.alt=""; + cover.loading="lazy"; + container.appendChild(cover); + } + + const name=document.createElement("h2"); + name.textContent=application.name + (application.bot ? " (Bot)" : ""); + container.appendChild(name); + + container.addEventListener("click", async () => { + this.devPortal.hide(); + this.manageApplication(application.id); + }); + appListContainer.appendChild(container); + }) + } + ) + } + async manageApplication(appId="") { + const res=await fetch(this.info.api.toString()+"/v9/applications/" + appId, { + headers: this.headers + }); + const json=await res.json(); + + const fields: any={}; + const appDialog=new Fullscreen( + ["vdiv", + ["title", + "Editing " + json.name + ], + ["hdiv", + ["textbox", "Application name:", json.name, event => { + fields.name=event.target.value; + }], + ["mdbox", "Description:", json.description, event => { + fields.description=event.target.value; + }], + ["vdiv", + json.icon ? ["img", this.info.cdn.toString()+"/app-icons/" + appId + "/" + json.icon + ".png?size=128", [128, 128]] : ["text", "No icon"], + ["fileupload", "Application icon:", event => { + const reader=new FileReader(); + reader.readAsDataURL(event.target.files[0]); + reader.onload=() => { + fields.icon=reader.result; + } + }] + ] + ], + ["hdiv", + ["textbox", "Privacy policy URL:", json.privacy_policy_url || "", event => { + fields.privacy_policy_url=event.target.value; + }], + ["textbox", "Terms of Service URL:", json.terms_of_service_url || "", event => { + fields.terms_of_service_url=event.target.value; + }] + ], + ["hdiv", + ["checkbox", "Make bot publicly inviteable?", json.bot_public, event => { + fields.bot_public=event.target.checked; + }], + ["checkbox", "Require code grant to invite the bot?", json.bot_require_code_grant, event => { + fields.bot_require_code_grant=event.target.checked; + }] + ], + ["hdiv", + ["button", + "", + "Save changes", + async () => { + const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId, { + method: "PATCH", + headers: this.headers, + body: JSON.stringify(fields) + }); + if (updateRes.ok) appDialog.hide(); + else { + const updateJSON=await updateRes.json(); + alert("An error occurred: " + updateJSON.message); + } + } + ], + ["button", + "", + (json.bot ? "Manage" : "Add") + " bot", + async () => { + if (!json.bot) { + if (!confirm("Are you sure you want to add a bot to this application? There's no going back.")) return; + + const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId + "/bot", { + method: "POST", + headers: this.headers + }); + const updateJSON=await updateRes.json(); + alert("Bot token:\n" + updateJSON.token); + } + + appDialog.hide(); + this.manageBot(appId); + } + ] + ] + ] + ) + appDialog.show(); + } + async manageBot(appId="") { + const res=await fetch(this.info.api.toString()+"/v9/applications/" + appId, { + headers: this.headers + }); + const json=await res.json(); + if (!json.bot) return alert("For some reason, this application doesn't have a bot (yet)."); + + const fields: any={ + username: json.bot.username, + avatar: json.bot.avatar ? (this.info.cdn.toString()+"/app-icons/" + appId + "/" + json.bot.avatar + ".png?size=256") : "" + }; + const botDialog=new Fullscreen( + ["vdiv", + ["title", + "Editing bot: " + json.bot.username + ], + ["hdiv", + ["textbox", "Bot username:", json.bot.username, event => { + fields.username=event.target.value + }], + ["vdiv", + fields.avatar ? ["img", fields.avatar, [128, 128]] : ["text", "No avatar"], + ["fileupload", "Bot avatar:", event => { + const reader=new FileReader(); + reader.readAsDataURL(event.target.files[0]); + reader.onload=() => { + fields.avatar=reader.result; + } + }] + ] + ], + ["hdiv", + ["button", + "", + "Save changes", + async () => { + const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId + "/bot", { + method: "PATCH", + headers: this.headers, + body: JSON.stringify(fields) + }); + if (updateRes.ok) botDialog.hide(); + else { + const updateJSON=await updateRes.json(); + alert("An error occurred: " + updateJSON.message); + } + } + ], + ["button", + "", + "Reset token", + async () => { + if (!confirm("Are you sure you want to reset the bot token? Your bot will stop working until you update it.")) return; + + const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId + "/bot/reset", { + method: "POST", + headers: this.headers + }); + const updateJSON=await updateRes.json(); + alert("New token:\n" + updateJSON.token); + botDialog.hide(); + } + ] + ] + ] + ); + botDialog.show(); + } } export {Localuser}; diff --git a/webpage/style.css b/webpage/style.css index b92af19..d3d03c7 100644 --- a/webpage/style.css +++ b/webpage/style.css @@ -699,22 +699,20 @@ textarea { flex-shrink: 1; } -#settings { +#user-actions { + display: flex; + flex-wrap: wrap; +} +#user-actions h2 { cursor: pointer; user-select: none; - border-radius: .3in; - transition: background 1s; + border-radius: .1in; + transition: color .5s; text-align: center; - font-size: .25in; - width: .3in; - height: .3in; overflow: visible; } - -#settings:hover { - background-color: var(--settings-hover); - cursor: pointer; - user-select: none; +#user-actions h2:hover, #user-actions h2:focus { + color: var(--timestamp-color); } #userinfo { @@ -1352,4 +1350,21 @@ span { width: 100%; flex-direction: row; max-height:100in; -} \ No newline at end of file +} + +#connection-container, #app-list-container { + display: flex; + flex-wrap: wrap; + gap: 10px; + max-width: 700px; +} +#connection-container div, #app-list-container div { + padding: 5px 10px; + border-radius: 5px; + background-color: var(--textarea-bg); + cursor: pointer; +} +#connection-container .disabled { + background-color: var(--embed-fallback); + cursor: not-allowed; +} From 36fc3fecc24b27f5acf1f1e60ad414ba9a5e667d Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Sat, 20 Jul 2024 18:31:12 -0500 Subject: [PATCH 02/10] fixed uploading pfps --- .dist/localuser.js | 6 +++--- webpage/localuser.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.dist/localuser.js b/.dist/localuser.js index 3df2641..d650a46 100644 --- a/.dist/localuser.js +++ b/.dist/localuser.js @@ -506,7 +506,7 @@ class Localuser { reader.readAsDataURL(file); console.log(this.headers); reader.onload = () => { - fetch(this.info.api.toString() + "/v9/users/@me", { + fetch(this.info.api.toString() + "/users/@me", { method: "PATCH", headers: this.headers, body: JSON.stringify({ @@ -517,7 +517,7 @@ class Localuser { }; } updatepronouns(pronouns) { - fetch(this.info.api.toString() + "/v9/users/@me/profile", { + fetch(this.info.api.toString() + "/users/@me/profile", { method: "PATCH", headers: this.headers, body: JSON.stringify({ @@ -600,7 +600,7 @@ class Localuser { newbio = this.value; regen(); }], - ["button", "update user content:", "submit", function () { + ["button", "update user content:", "submit", () => { if (file !== null) { this.updatepfp(file); } diff --git a/webpage/localuser.ts b/webpage/localuser.ts index 551a978..f3470cb 100644 --- a/webpage/localuser.ts +++ b/webpage/localuser.ts @@ -531,7 +531,7 @@ class Localuser{ reader.readAsDataURL(file); console.log(this.headers); reader.onload = ()=>{ - fetch(this.info.api.toString()+"/v9/users/@me",{ + fetch(this.info.api.toString()+"/users/@me",{ method:"PATCH", headers:this.headers, body:JSON.stringify({ @@ -543,7 +543,7 @@ class Localuser{ } updatepronouns(pronouns:string):void{ - fetch(this.info.api.toString()+"/v9/users/@me/profile",{ + fetch(this.info.api.toString()+"/users/@me/profile",{ method:"PATCH", headers:this.headers, body:JSON.stringify({ @@ -626,7 +626,7 @@ class Localuser{ newbio=this.value; regen(); }], - ["button","update user content:","submit",function(){ + ["button","update user content:","submit",()=>{ if(file!==null){ this.updatepfp(file); } From ec5b86b276343a3d57e7dfcf0bb3639693641b4c Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Sat, 20 Jul 2024 19:05:23 -0500 Subject: [PATCH 03/10] make MarkDown into a class and fixed emojis --- .dist/channel.js | 5 +- .dist/embed.js | 20 +- .dist/markdown.js | 882 ++++++++++++++++++++++--------------------- .dist/message.js | 12 +- .dist/user.js | 8 +- webpage/channel.ts | 6 +- webpage/embed.ts | 20 +- webpage/localuser.ts | 2 +- webpage/markdown.ts | 819 +++++++++++++++++++++------------------- webpage/message.ts | 13 +- webpage/style.css | 8 + webpage/user.ts | 10 +- 12 files changed, 957 insertions(+), 848 deletions(-) diff --git a/.dist/channel.js b/.dist/channel.js index 16635a2..3efee21 100644 --- a/.dist/channel.js +++ b/.dist/channel.js @@ -3,7 +3,6 @@ import { Message } from "./message.js"; import { Voice } from "./audio.js"; import { Contextmenu } from "./contextmenu.js"; import { Fullscreen } from "./fullscreen.js"; -import { markdown } from "./markdown.js"; import { Permissions } from "./permissions.js"; import { Settings, RoleList } from "./settings.js"; import { InfiniteScroller } from "./infiniteScroller.js"; @@ -745,10 +744,10 @@ class Channel { if (!("Notification" in window)) { } else if (Notification.permission === "granted") { - let noticontent = markdown(message.content).textContent; + let noticontent = message.content.textContent; if (message.embeds[0]) { noticontent ||= message.embeds[0].json.title; - noticontent ||= markdown(message.embeds[0].json.description).textContent; + noticontent ||= message.content.textContent; } noticontent ||= "Blank Message"; let imgurl = null; diff --git a/.dist/embed.js b/.dist/embed.js index 6a755cd..e617bdb 100644 --- a/.dist/embed.js +++ b/.dist/embed.js @@ -1,5 +1,5 @@ import { Fullscreen } from "./fullscreen.js"; -import { markdown } from "./markdown.js"; +import { MarkDown } from "./markdown.js"; class Embed { type; owner; @@ -27,6 +27,18 @@ class Embed { return document.createElement("div"); //prevent errors by giving blank div } } + get message() { + return this.owner; + } + get channel() { + return this.message.channel; + } + get guild() { + return this.channel.guild; + } + get localuser() { + return this.guild.localuser; + } generateRich() { console.log(this.json); const div = document.createElement("div"); @@ -55,7 +67,7 @@ class Embed { embed.append(authorline); } const title = document.createElement("a"); - title.append(markdown(this.json.title)); + title.append(new MarkDown(this.json.title, this.localuser).makeHTML()); if (this.json.url) { title.href = this.json.url; } @@ -63,7 +75,7 @@ class Embed { embed.append(title); if (this.json.description) { const p = document.createElement("p"); - p.append(markdown(this.json.description)); + p.append(new MarkDown(this.json.description, this.channel).makeHTML()); embed.append(p); } embed.append(document.createElement("br")); @@ -74,7 +86,7 @@ class Embed { b.textContent = thing.name; div.append(b); const p = document.createElement("p"); - p.append(markdown(thing.value)); + p.append(new MarkDown(thing.value, this.channel).makeHTML()); p.classList.add("embedp"); div.append(p); if (thing.inline) { diff --git a/.dist/markdown.js b/.dist/markdown.js index 0e1febb..8111f5f 100644 --- a/.dist/markdown.js +++ b/.dist/markdown.js @@ -1,446 +1,476 @@ -export { markdown }; -function markdown(text, { keep = false, stdsize = false } = {}) { - let txt; - if ((typeof text) === (typeof "")) { - txt = text.split(""); - } - else { - txt = text; - } - if (txt === undefined) { - txt = []; - } - const span = document.createElement("span"); - let current = document.createElement("span"); - function appendcurrent() { - if (current.innerHTML !== "") { - span.append(current); - current = document.createElement("span"); +export { MarkDown }; +class MarkDown { + txt; + keep; + stdsize; + owner; + info; + constructor(text, owner, { keep = false, stdsize = false } = {}) { + if ((typeof text) === (typeof "")) { + this.txt = text.split(""); } + else { + this.txt = text; + } + if (this.txt === undefined) { + this.txt = []; + } + this.info = owner.info; + this.keep = keep; + this.owner = owner; + this.stdsize = stdsize; } - for (let i = 0; i < txt.length; i++) { - if (txt[i] === "\n" || i === 0) { - const first = i === 0; - if (first) { - i--; + get rawString() { + return this.txt.concat(""); + } + get textContent() { + return this.makeHTML().textContent; + } + makeHTML({ keep = this.keep, stdsize = this.stdsize } = {}) { + return this.markdown(this.txt, { keep: keep, stdsize: stdsize }); + } + markdown(text, { keep = false, stdsize = false } = {}) { + let txt; + if ((typeof text) === (typeof "")) { + txt = text.split(""); + } + else { + txt = text; + } + if (txt === undefined) { + txt = []; + } + const span = document.createElement("span"); + let current = document.createElement("span"); + function appendcurrent() { + if (current.innerHTML !== "") { + span.append(current); + current = document.createElement("span"); } - let element = null; - let keepys = ""; - if (txt[i + 1] === "#") { - console.log("test"); - if (txt[i + 2] === "#") { - if (txt[i + 3] === "#" && txt[i + 4] === " ") { - element = document.createElement("h3"); - keepys = "### "; - i += 5; + } + for (let i = 0; i < txt.length; i++) { + if (txt[i] === "\n" || i === 0) { + const first = i === 0; + if (first) { + i--; + } + let element = null; + let keepys = ""; + if (txt[i + 1] === "#") { + console.log("test"); + if (txt[i + 2] === "#") { + if (txt[i + 3] === "#" && txt[i + 4] === " ") { + element = document.createElement("h3"); + keepys = "### "; + i += 5; + } + else if (txt[i + 3] === " ") { + element = document.createElement("h2"); + element.classList.add("h2md"); + keepys = "## "; + i += 4; + } } - else if (txt[i + 3] === " ") { - element = document.createElement("h2"); - element.classList.add("h2md"); - keepys = "## "; - i += 4; + else if (txt[i + 2] === " ") { + element = document.createElement("h1"); + keepys = "# "; + i += 3; } } - else if (txt[i + 2] === " ") { - element = document.createElement("h1"); - keepys = "# "; + else if (txt[i + 1] === ">" && txt[i + 2] === " ") { + element = document.createElement("div"); + const line = document.createElement("div"); + line.classList.add("quoteline"); + element.append(line); + element.classList.add("quote"); + keepys = "> "; i += 3; } - } - else if (txt[i + 1] === ">" && txt[i + 2] === " ") { - element = document.createElement("div"); - const line = document.createElement("div"); - line.classList.add("quoteline"); - element.append(line); - element.classList.add("quote"); - keepys = "> "; - i += 3; - } - if (keepys) { - appendcurrent(); - if (!first && !stdsize) { - span.appendChild(document.createElement("br")); + if (keepys) { + appendcurrent(); + if (!first && !stdsize) { + span.appendChild(document.createElement("br")); + } + const build = []; + for (; txt[i] !== "\n" && txt[i] !== undefined; i++) { + build.push(txt[i]); + } + if (stdsize) { + element = document.createElement("span"); + } + if (keep) { + element.append(keepys); + } + element.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize })); + span.append(element); + i--; + continue; } - const build = []; - for (; txt[i] !== "\n" && txt[i] !== undefined; i++) { - build.push(txt[i]); + if (first) { + i++; + } + } + if (txt[i] === "\n") { + if (!stdsize) { + appendcurrent(); + span.append(document.createElement("br")); + } + continue; + } + if (txt[i] === "`") { + let count = 1; + if (txt[i + 1] === "`") { + count++; + if (txt[i + 2] === "`") { + count++; + } + } + let build = ""; + if (keep) { + build += "`".repeat(count); + } + let find = 0; + let j = i + count; + let init = true; + for (; txt[j] !== undefined && (txt[j] !== "\n" || count === 3) && find !== count; j++) { + if (txt[j] === "`") { + find++; + } + else { + if (find !== 0) { + build += "`".repeat(find); + find = 0; + } + if (init && count === 3) { + if (txt[j] === " " || txt[j] === "\n") { + init = false; + } + if (keep) { + build += txt[j]; + } + continue; + } + build += txt[j]; + } } if (stdsize) { - element = document.createElement("span"); + console.log(build); + build = build.replaceAll("\n", ""); + console.log(build, JSON.stringify(build)); } - if (keep) { - element.append(keepys); - } - element.appendChild(markdown(build, { keep: keep, stdsize: stdsize })); - span.append(element); - i--; - continue; - } - if (first) { - i++; - } - } - if (txt[i] === "\n") { - if (!stdsize) { - appendcurrent(); - span.append(document.createElement("br")); - } - continue; - } - if (txt[i] === "`") { - let count = 1; - if (txt[i + 1] === "`") { - count++; - if (txt[i + 2] === "`") { - count++; - } - } - let build = ""; - if (keep) { - build += "`".repeat(count); - } - let find = 0; - let j = i + count; - let init = true; - for (; txt[j] !== undefined && (txt[j] !== "\n" || count === 3) && find !== count; j++) { - if (txt[j] === "`") { - find++; - } - else { - if (find !== 0) { - build += "`".repeat(find); - find = 0; - } - if (init && count === 3) { - if (txt[j] === " " || txt[j] === "\n") { - init = false; - } - if (keep) { - build += txt[j]; - } - continue; - } - build += txt[j]; - } - } - if (stdsize) { - console.log(build); - build = build.replaceAll("\n", ""); - console.log(build, JSON.stringify(build)); - } - if (find === count) { - appendcurrent(); - i = j; - if (keep) { - build += "`".repeat(find); - } - if (count !== 3 && !stdsize) { - const samp = document.createElement("samp"); - samp.textContent = build; - span.appendChild(samp); - } - else { - const pre = document.createElement("pre"); - if (build[build.length - 1] === "\n") { - build = build.substring(0, build.length - 1); - } - if (txt[i] === "\n") { - i++; - } - pre.textContent = build; - span.appendChild(pre); - } - i--; - continue; - } - } - if (txt[i] === "*") { - let count = 1; - if (txt[i + 1] === "*") { - count++; - if (txt[i + 2] === "*") { - count++; - } - } - let build = []; - let find = 0; - let j = i + count; - for (; txt[j] !== undefined && find !== count; j++) { - if (txt[j] === "*") { - find++; - } - else { - build.push(txt[j]); - if (find !== 0) { - build = build.concat(new Array(find).fill("*")); - find = 0; - } - } - } - if (find === count && (count != 1 || txt[i + 1] !== " ")) { - appendcurrent(); - i = j; - const stars = "*".repeat(count); - if (count === 1) { - const i = document.createElement("i"); - if (keep) { - i.append(stars); - } - i.appendChild(markdown(build, { keep: keep, stdsize: stdsize })); - if (keep) { - i.append(stars); - } - span.appendChild(i); - } - else if (count === 2) { - const b = document.createElement("b"); - if (keep) { - b.append(stars); - } - b.appendChild(markdown(build, { keep: keep, stdsize: stdsize })); - if (keep) { - b.append(stars); - } - span.appendChild(b); - } - else { - const b = document.createElement("b"); - const i = document.createElement("i"); - if (keep) { - b.append(stars); - } - b.appendChild(markdown(build, { keep: keep, stdsize: stdsize })); - if (keep) { - b.append(stars); - } - i.appendChild(b); - span.appendChild(i); - } - i--; - continue; - } - } - if (txt[i] === "_") { - let count = 1; - if (txt[i + 1] === "_") { - count++; - if (txt[i + 2] === "_") { - count++; - } - } - let build = []; - let find = 0; - let j = i + count; - for (; txt[j] !== undefined && find !== count; j++) { - if (txt[j] === "_") { - find++; - } - else { - build.push(txt[j]); - if (find !== 0) { - build = build.concat(new Array(find).fill("_")); - find = 0; - } - } - } - if (find === count && (count != 1 || (txt[j + 1] === " " || txt[j + 1] === "\n" || txt[j + 1] === undefined))) { - appendcurrent(); - i = j; - const underscores = "_".repeat(count); - if (count === 1) { - const i = document.createElement("i"); - if (keep) { - i.append(underscores); - } - i.appendChild(markdown(build, { keep: keep, stdsize: stdsize })); - if (keep) { - i.append(underscores); - } - span.appendChild(i); - } - else if (count === 2) { - const u = document.createElement("u"); - if (keep) { - u.append(underscores); - } - u.appendChild(markdown(build, { keep: keep, stdsize: stdsize })); - if (keep) { - u.append(underscores); - } - span.appendChild(u); - } - else { - const u = document.createElement("u"); - const i = document.createElement("i"); - if (keep) { - i.append(underscores); - } - i.appendChild(markdown(build, { keep: keep, stdsize: stdsize })); - if (keep) { - i.append(underscores); - } - u.appendChild(i); - span.appendChild(u); - } - i--; - continue; - } - } - if (txt[i] === "~" && txt[i + 1] === "~") { - let count = 2; - let build = []; - let find = 0; - let j = i + 2; - for (; txt[j] !== undefined && find !== count; j++) { - if (txt[j] === "~") { - find++; - } - else { - build.push(txt[j]); - if (find !== 0) { - build = build.concat(new Array(find).fill("~")); - find = 0; - } - } - } - if (find === count) { - appendcurrent(); - i = j; - const tildes = "~~"; - if (count === 2) { - const s = document.createElement("s"); - if (keep) { - s.append(tildes); - } - s.appendChild(markdown(build, { keep: keep, stdsize: stdsize })); - if (keep) { - s.append(tildes); - } - span.appendChild(s); - } - continue; - } - } - if (txt[i] === "|" && txt[i + 1] === "|") { - let count = 2; - let build = []; - let find = 0; - let j = i + 2; - for (; txt[j] !== undefined && find !== count; j++) { - if (txt[j] === "|") { - find++; - } - else { - build.push(txt[j]); - if (find !== 0) { - build = build.concat(new Array(find).fill("~")); - find = 0; - } - } - } - if (find === count) { - appendcurrent(); - i = j; - const pipes = "||"; - if (count === 2) { - const j = document.createElement("j"); - if (keep) { - j.append(pipes); - } - j.appendChild(markdown(build, { keep: keep, stdsize: stdsize })); - j.classList.add("spoiler"); - j.onclick = markdown.unspoil; - if (keep) { - j.append(pipes); - } - span.appendChild(j); - } - continue; - } - } - if (txt[i] === "<" && txt[i + 1] === "t" && txt[i + 2] === ":") { - let found = false; - const build = ["<", "t", ":"]; - let j = i + 3; - for (; txt[j] !== void 0; j++) { - build.push(txt[j]); - if (txt[j] === ">") { - found = true; - break; - } - } - if (found) { - appendcurrent(); - i = j; - const parts = build.join("").match(/^$/); - const dateInput = new Date(Number.parseInt(parts[1]) * 1000); - let time = ""; - if (Number.isNaN(dateInput.getTime())) - time = build.join(""); - else { - if (parts[3] === "d") - time = dateInput.toLocaleString(void 0, { day: "2-digit", month: "2-digit", year: "numeric" }); - else if (parts[3] === "D") - time = dateInput.toLocaleString(void 0, { day: "numeric", month: "long", year: "numeric" }); - else if (!parts[3] || parts[3] === "f") - time = dateInput.toLocaleString(void 0, { day: "numeric", month: "long", year: "numeric" }) + " " + - dateInput.toLocaleString(void 0, { hour: "2-digit", minute: "2-digit" }); - else if (parts[3] === "F") - time = dateInput.toLocaleString(void 0, { day: "numeric", month: "long", year: "numeric", weekday: "long" }) + " " + - dateInput.toLocaleString(void 0, { hour: "2-digit", minute: "2-digit" }); - else if (parts[3] === "t") - time = dateInput.toLocaleString(void 0, { hour: "2-digit", minute: "2-digit" }); - else if (parts[3] === "T") - time = dateInput.toLocaleString(void 0, { hour: "2-digit", minute: "2-digit", second: "2-digit" }); - else if (parts[3] === "R") - time = Math.round((Date.now() - (Number.parseInt(parts[1]) * 1000)) / 1000 / 60) + " minutes ago"; - } - const timeElem = document.createElement("span"); - timeElem.classList.add("markdown-timestamp"); - timeElem.textContent = time; - span.appendChild(timeElem); - continue; - } - } - if (txt[i] === "<" && (txt[i + 1] === ":" || (txt[i + 1] === "a" && txt[i + 2] === ":"))) { - let found = false; - const build = txt[i + 1] === "a" ? ["<", "a", ":"] : ["<", ":"]; - let j = i + build.length; - for (; txt[j] !== void 0; j++) { - build.push(txt[j]); - if (txt[j] === ">") { - found = true; - break; - } - } - if (found) { - const parts = build.join("").match(/^<(a)?:\w+:(\d{10,30})>$/); - if (parts && parts[2]) { + if (find === count) { appendcurrent(); i = j; - console.log(typeof txt, txt); - const isEmojiOnly = txt.join("").trim() === build.join("").trim(); - const emojiElem = document.createElement("img"); - emojiElem.classList.add("md-emoji"); - emojiElem.width = isEmojiOnly ? 48 : 22; - emojiElem.height = isEmojiOnly ? 48 : 22; - emojiElem.crossOrigin = "anonymous"; - //emojiElem.src=this.info.cdn.toString() + "/emojis/" + parts[2] + "." + (parts[1] ? "gif" : "png") + "?size=32"; - //must uncomment later - emojiElem.alt = ""; - emojiElem.loading = "lazy"; - span.appendChild(emojiElem); + if (keep) { + build += "`".repeat(find); + } + if (count !== 3 && !stdsize) { + const samp = document.createElement("samp"); + samp.textContent = build; + span.appendChild(samp); + } + else { + const pre = document.createElement("pre"); + if (build[build.length - 1] === "\n") { + build = build.substring(0, build.length - 1); + } + if (txt[i] === "\n") { + i++; + } + pre.textContent = build; + span.appendChild(pre); + } + i--; continue; } } + if (txt[i] === "*") { + let count = 1; + if (txt[i + 1] === "*") { + count++; + if (txt[i + 2] === "*") { + count++; + } + } + let build = []; + let find = 0; + let j = i + count; + for (; txt[j] !== undefined && find !== count; j++) { + if (txt[j] === "*") { + find++; + } + else { + build.push(txt[j]); + if (find !== 0) { + build = build.concat(new Array(find).fill("*")); + find = 0; + } + } + } + if (find === count && (count != 1 || txt[i + 1] !== " ")) { + appendcurrent(); + i = j; + const stars = "*".repeat(count); + if (count === 1) { + const i = document.createElement("i"); + if (keep) { + i.append(stars); + } + i.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize })); + if (keep) { + i.append(stars); + } + span.appendChild(i); + } + else if (count === 2) { + const b = document.createElement("b"); + if (keep) { + b.append(stars); + } + b.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize })); + if (keep) { + b.append(stars); + } + span.appendChild(b); + } + else { + const b = document.createElement("b"); + const i = document.createElement("i"); + if (keep) { + b.append(stars); + } + b.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize })); + if (keep) { + b.append(stars); + } + i.appendChild(b); + span.appendChild(i); + } + i--; + continue; + } + } + if (txt[i] === "_") { + let count = 1; + if (txt[i + 1] === "_") { + count++; + if (txt[i + 2] === "_") { + count++; + } + } + let build = []; + let find = 0; + let j = i + count; + for (; txt[j] !== undefined && find !== count; j++) { + if (txt[j] === "_") { + find++; + } + else { + build.push(txt[j]); + if (find !== 0) { + build = build.concat(new Array(find).fill("_")); + find = 0; + } + } + } + if (find === count && (count != 1 || (txt[j + 1] === " " || txt[j + 1] === "\n" || txt[j + 1] === undefined))) { + appendcurrent(); + i = j; + const underscores = "_".repeat(count); + if (count === 1) { + const i = document.createElement("i"); + if (keep) { + i.append(underscores); + } + i.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize })); + if (keep) { + i.append(underscores); + } + span.appendChild(i); + } + else if (count === 2) { + const u = document.createElement("u"); + if (keep) { + u.append(underscores); + } + u.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize })); + if (keep) { + u.append(underscores); + } + span.appendChild(u); + } + else { + const u = document.createElement("u"); + const i = document.createElement("i"); + if (keep) { + i.append(underscores); + } + i.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize })); + if (keep) { + i.append(underscores); + } + u.appendChild(i); + span.appendChild(u); + } + i--; + continue; + } + } + if (txt[i] === "~" && txt[i + 1] === "~") { + let count = 2; + let build = []; + let find = 0; + let j = i + 2; + for (; txt[j] !== undefined && find !== count; j++) { + if (txt[j] === "~") { + find++; + } + else { + build.push(txt[j]); + if (find !== 0) { + build = build.concat(new Array(find).fill("~")); + find = 0; + } + } + } + if (find === count) { + appendcurrent(); + i = j; + const tildes = "~~"; + if (count === 2) { + const s = document.createElement("s"); + if (keep) { + s.append(tildes); + } + s.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize })); + if (keep) { + s.append(tildes); + } + span.appendChild(s); + } + continue; + } + } + if (txt[i] === "|" && txt[i + 1] === "|") { + let count = 2; + let build = []; + let find = 0; + let j = i + 2; + for (; txt[j] !== undefined && find !== count; j++) { + if (txt[j] === "|") { + find++; + } + else { + build.push(txt[j]); + if (find !== 0) { + build = build.concat(new Array(find).fill("~")); + find = 0; + } + } + } + if (find === count) { + appendcurrent(); + i = j; + const pipes = "||"; + if (count === 2) { + const j = document.createElement("j"); + if (keep) { + j.append(pipes); + } + j.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize })); + j.classList.add("spoiler"); + j.onclick = MarkDown.unspoil; + if (keep) { + j.append(pipes); + } + span.appendChild(j); + } + continue; + } + } + if (txt[i] === "<" && txt[i + 1] === "t" && txt[i + 2] === ":") { + let found = false; + const build = ["<", "t", ":"]; + let j = i + 3; + for (; txt[j] !== void 0; j++) { + build.push(txt[j]); + if (txt[j] === ">") { + found = true; + break; + } + } + if (found) { + appendcurrent(); + i = j; + const parts = build.join("").match(/^$/); + const dateInput = new Date(Number.parseInt(parts[1]) * 1000); + let time = ""; + if (Number.isNaN(dateInput.getTime())) + time = build.join(""); + else { + if (parts[3] === "d") + time = dateInput.toLocaleString(void 0, { day: "2-digit", month: "2-digit", year: "numeric" }); + else if (parts[3] === "D") + time = dateInput.toLocaleString(void 0, { day: "numeric", month: "long", year: "numeric" }); + else if (!parts[3] || parts[3] === "f") + time = dateInput.toLocaleString(void 0, { day: "numeric", month: "long", year: "numeric" }) + " " + + dateInput.toLocaleString(void 0, { hour: "2-digit", minute: "2-digit" }); + else if (parts[3] === "F") + time = dateInput.toLocaleString(void 0, { day: "numeric", month: "long", year: "numeric", weekday: "long" }) + " " + + dateInput.toLocaleString(void 0, { hour: "2-digit", minute: "2-digit" }); + else if (parts[3] === "t") + time = dateInput.toLocaleString(void 0, { hour: "2-digit", minute: "2-digit" }); + else if (parts[3] === "T") + time = dateInput.toLocaleString(void 0, { hour: "2-digit", minute: "2-digit", second: "2-digit" }); + else if (parts[3] === "R") + time = Math.round((Date.now() - (Number.parseInt(parts[1]) * 1000)) / 1000 / 60) + " minutes ago"; + } + const timeElem = document.createElement("span"); + timeElem.classList.add("markdown-timestamp"); + timeElem.textContent = time; + span.appendChild(timeElem); + continue; + } + } + if (txt[i] === "<" && (txt[i + 1] === ":" || (txt[i + 1] === "a" && txt[i + 2] === ":"))) { + let found = false; + const build = txt[i + 1] === "a" ? ["<", "a", ":"] : ["<", ":"]; + let j = i + build.length; + for (; txt[j] !== void 0; j++) { + build.push(txt[j]); + if (txt[j] === ">") { + found = true; + break; + } + } + if (found) { + const buildjoin = build.join(""); + const parts = buildjoin.match(/^<(a)?:\w+:(\d{10,30})>$/); + if (parts && parts[2]) { + appendcurrent(); + i = j; + console.log(typeof txt, txt); + const isEmojiOnly = txt.join("").trim() === buildjoin.trim(); + console.log(isEmojiOnly, ":3"); + const emojiElem = document.createElement("img"); + emojiElem.classList.add("md-emoji"); + emojiElem.classList.add(isEmojiOnly ? "bigemoji" : "smallemoji"); + emojiElem.crossOrigin = "anonymous"; + emojiElem.src = this.info.cdn.toString() + "emojis/" + parts[2] + "." + (parts[1] ? "gif" : "png") + "?size=32"; + emojiElem.alt = buildjoin; + emojiElem.loading = "lazy"; + span.appendChild(emojiElem); + continue; + } + } + } + current.textContent += txt[i]; } - current.textContent += txt[i]; + appendcurrent(); + return span; + } + static unspoil(e) { + e.target.classList.remove("spoiler"); + e.target.classList.add("unspoiled"); } - appendcurrent(); - return span; } -markdown.unspoil = function (e) { - //console.log("undone") - e.target.classList.remove("spoiler"); - e.target.classList.add("unspoiled"); -}; diff --git a/.dist/message.js b/.dist/message.js index 799f605..6dcaafb 100644 --- a/.dist/message.js +++ b/.dist/message.js @@ -1,7 +1,7 @@ import { Contextmenu } from "./contextmenu.js"; import { User } from "./user.js"; import { Member } from "./member.js"; -import { markdown } from "./markdown.js"; +import { MarkDown } from "./markdown.js"; import { Embed } from "./embed.js"; import { File } from "./file.js"; class Message { @@ -33,7 +33,7 @@ class Message { } static setupcmenu() { Message.contextmenu.addbutton("Copy raw text", function () { - navigator.clipboard.writeText(this.content); + navigator.clipboard.writeText(this.content.rawString); }); Message.contextmenu.addbutton("Reply", function (div) { this.channel.setReplying(this); @@ -63,6 +63,10 @@ class Message { } continue; } + else if (thing === "content") { + this.content = new MarkDown(messagejson[thing], this.channel); + continue; + } this[thing] = messagejson[thing]; } for (const thing in this.embeds) { @@ -204,7 +208,7 @@ class Message { replyline.classList.add("replyflex"); this.channel.getmessage(this.message_reference.message_id).then(message => { const author = message.author; - reply.appendChild(markdown(message.content, { stdsize: true })); + reply.appendChild(message.content.makeHTML({ stdsize: true })); minipfp.src = author.getpfpsrc(); author.bind(minipfp); username.textContent = author.username; @@ -266,7 +270,7 @@ class Message { else { div.classList.remove("topMessage"); } - const messaged = markdown(this.content); + const messaged = this.content.makeHTML(); div["txt"] = messaged; const messagedwrap = document.createElement("div"); messagedwrap.classList.add("flexttb"); diff --git a/.dist/user.js b/.dist/user.js index 2323d78..401b8a9 100644 --- a/.dist/user.js +++ b/.dist/user.js @@ -1,6 +1,6 @@ //const usercache={}; import { Member } from "./member.js"; -import { markdown } from "./markdown.js"; +import { MarkDown } from "./markdown.js"; import { Contextmenu } from "./contextmenu.js"; class User { static userids = {}; @@ -48,6 +48,10 @@ class User { } if (dontclone) { for (const thing of Object.keys(userjson)) { + if (thing === "bio") { + this.bio = new MarkDown(userjson[thing], this.localuser); + continue; + } this[thing] = userjson[thing]; } this.hypotheticalpfp = false; @@ -146,7 +150,7 @@ class User { userbody.appendChild(pronounshtml); const rule = document.createElement("hr"); userbody.appendChild(rule); - const biohtml = markdown(this.bio); + const biohtml = this.bio.makeHTML(); userbody.appendChild(biohtml); } console.log(div); diff --git a/webpage/channel.ts b/webpage/channel.ts index ab9e615..1f1eca6 100644 --- a/webpage/channel.ts +++ b/webpage/channel.ts @@ -3,7 +3,7 @@ import { Message } from "./message.js"; import {Voice} from "./audio.js"; import {Contextmenu} from "./contextmenu.js"; import {Fullscreen} from "./fullscreen.js"; -import {markdown} from "./markdown.js"; +import {MarkDown} from "./markdown.js"; import {Guild} from "./guild.js"; import { Localuser } from "./localuser.js"; import { Permissions } from "./permissions.js"; @@ -744,10 +744,10 @@ class Channel{ if (!("Notification" in window)) { } else if (Notification.permission === "granted") { - let noticontent=markdown(message.content).textContent; + let noticontent=message.content.textContent; if(message.embeds[0]){ noticontent||=message.embeds[0].json.title; - noticontent||=markdown(message.embeds[0].json.description).textContent; + noticontent||=message.content.textContent; } noticontent||="Blank Message"; let imgurl=null; diff --git a/webpage/embed.ts b/webpage/embed.ts index a9c1494..ac5d60e 100644 --- a/webpage/embed.ts +++ b/webpage/embed.ts @@ -1,6 +1,6 @@ import {Fullscreen} from "./fullscreen.js"; import {Message} from "./message.js"; -import {markdown} from "./markdown.js"; +import {MarkDown} from "./markdown.js"; class Embed{ type:string; @@ -29,6 +29,18 @@ class Embed{ return document.createElement("div");//prevent errors by giving blank div } } + get message(){ + return this.owner; + } + get channel(){ + return this.message.channel; + } + get guild(){ + return this.channel.guild; + } + get localuser(){ + return this.guild.localuser; + } generateRich(){ console.log(this.json) const div=document.createElement("div"); @@ -59,7 +71,7 @@ class Embed{ embed.append(authorline); } const title=document.createElement("a"); - title.append(markdown(this.json.title)); + title.append(new MarkDown(this.json.title,this.localuser).makeHTML()); if(this.json.url){ title.href=this.json.url; } @@ -68,7 +80,7 @@ class Embed{ if(this.json.description){ const p=document.createElement("p"); - p.append(markdown(this.json.description)); + p.append(new MarkDown(this.json.description,this.channel).makeHTML()); embed.append(p); } @@ -80,7 +92,7 @@ class Embed{ b.textContent=thing.name; div.append(b); const p=document.createElement("p") - p.append(markdown(thing.value)); + p.append(new MarkDown(thing.value,this.channel).makeHTML()); p.classList.add("embedp"); div.append(p); diff --git a/webpage/localuser.ts b/webpage/localuser.ts index f3470cb..a363c8b 100644 --- a/webpage/localuser.ts +++ b/webpage/localuser.ts @@ -4,7 +4,7 @@ import {Direct} from "./direct.js"; import {Voice} from "./audio.js"; import {User} from "./user.js"; import {Member} from "./member.js"; -import {markdown} from "./markdown.js"; +import {MarkDown} from "./markdown.js"; import {Fullscreen} from "./fullscreen.js"; import {setTheme, Specialuser} from "./login.js"; diff --git a/webpage/markdown.ts b/webpage/markdown.ts index 128297d..3cf3a6e 100644 --- a/webpage/markdown.ts +++ b/webpage/markdown.ts @@ -1,413 +1,446 @@ -export {markdown}; -function markdown(text : string|string[],{keep=false,stdsize=false} = {}){ - let txt : string[]; - if((typeof text)===(typeof "")){ - txt=(text as string).split(""); - }else{ - txt=(text as string[]); - } - if(txt===undefined){ - txt=[]; - } - const span=document.createElement("span"); - let current=document.createElement("span"); - function appendcurrent(){ - if(current.innerHTML!==""){ - span.append(current); - current=document.createElement("span"); +import { Channel } from "./channel"; +import { Localuser } from "./localuser"; + +export {MarkDown}; +class MarkDown{ + txt : string[]; + keep:boolean; + stdsize:boolean; + owner:Localuser|Channel; + info:Localuser["info"]; + constructor(text : string|string[],owner:MarkDown["owner"],{keep=false,stdsize=false} = {}){ + if((typeof text)===(typeof "")){ + this.txt=(text as string).split(""); + }else{ + this.txt=(text as string[]); } - + if(this.txt===undefined){ + this.txt=[]; + } + this.info=owner.info; + this.keep=keep; + this.owner=owner; + this.stdsize=stdsize; } - for(let i=0;i"&&txt[i+2]===" "){ + element=document.createElement("div"); + const line=document.createElement("div"); + line.classList.add("quoteline"); + element.append(line); + element.classList.add("quote"); + keepys="> "; i+=3; } - }else if(txt[i+1]===">"&&txt[i+2]===" "){ - element=document.createElement("div"); - const line=document.createElement("div"); - line.classList.add("quoteline"); - element.append(line); - element.classList.add("quote"); - keepys="> "; - i+=3; - } - if(keepys){ - appendcurrent(); - if(!first&&!stdsize){ - span.appendChild(document.createElement("br")); + if(keepys){ + appendcurrent(); + if(!first&&!stdsize){ + span.appendChild(document.createElement("br")); + } + const build=[]; + for(;txt[i]!=="\n"&&txt[i]!==undefined;i++){ + build.push(txt[i]); + } + if(stdsize){ + element=document.createElement("span"); + } + if(keep){ + element.append(keepys); + } + element.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize})); + span.append(element); + i--; + continue; } - const build=[]; - for(;txt[i]!=="\n"&&txt[i]!==undefined;i++){ - build.push(txt[i]); + if(first){ + i++; + } + } + if(txt[i]==="\n"){ + + if(!stdsize){ + appendcurrent(); + span.append(document.createElement("br")); + } + continue; + } + if(txt[i]==="`"){ + let count=1; + if(txt[i+1]==="`"){ + count++; + if(txt[i+2]==="`"){ + count++; + } + } + let build=""; + if(keep){ + build+="`".repeat(count); + } + let find=0; + let j=i+count; + let init=true; + for(;txt[j]!==undefined&&(txt[j]!=="\n"||count===3)&&find!==count;j++){ + if(txt[j]==="`"){ + find++; + }else{ + if(find!==0){ + build+="`".repeat(find); + find=0; + } + if(init&&count===3){ + if(txt[j]===" "||txt[j]==="\n"){ + init=false; + } + if(keep){ + build+=txt[j]; + } + continue; + } + build+=txt[j]; + } } if(stdsize){ - element=document.createElement("span"); + console.log(build); + build=build.replaceAll("\n",""); + console.log(build,JSON.stringify(build)); } - if(keep){ - element.append(keepys); - } - element.appendChild(markdown(build,{keep:keep,stdsize:stdsize})); - span.append(element); - i--; - continue; - } - if(first){ - i++; - } - } - if(txt[i]==="\n"){ - - if(!stdsize){ - appendcurrent(); - span.append(document.createElement("br")); - } - continue; - } - if(txt[i]==="`"){ - let count=1; - if(txt[i+1]==="`"){ - count++; - if(txt[i+2]==="`"){ - count++; - } - } - let build=""; - if(keep){ - build+="`".repeat(count); - } - let find=0; - let j=i+count; - let init=true; - for(;txt[j]!==undefined&&(txt[j]!=="\n"||count===3)&&find!==count;j++){ - if(txt[j]==="`"){ - find++; - }else{ - if(find!==0){ - build+="`".repeat(find); - find=0; - } - if(init&&count===3){ - if(txt[j]===" "||txt[j]==="\n"){ - init=false; - } - if(keep){ - build+=txt[j]; - } - continue; - } - build+=txt[j]; - } - } - if(stdsize){ - console.log(build); - build=build.replaceAll("\n",""); - console.log(build,JSON.stringify(build)); - } - if(find===count){ - appendcurrent(); - i=j; - if(keep){ - build+="`".repeat(find); - } - if(count!==3&&!stdsize){ - const samp=document.createElement("samp"); - samp.textContent=build; - span.appendChild(samp); - }else{ - const pre=document.createElement("pre"); - if(build[build.length-1]==="\n"){ - build=build.substring(0,build.length-1); - } - if(txt[i]==="\n"){ - i++ - } - pre.textContent=build; - span.appendChild(pre); - } - i--; - continue; - } - } - - if(txt[i]==="*"){ - let count=1; - if(txt[i+1]==="*"){ - count++; - if(txt[i+2]==="*"){ - count++; - } - } - let build=[]; - let find=0; - let j=i+count; - for(;txt[j]!==undefined&&find!==count;j++){ - - if(txt[j]==="*"){ - find++; - }else{ - build.push(txt[j]); - if(find!==0){ - build=build.concat(new Array(find).fill("*")); - find=0; - } - } - } - if(find===count&&(count!=1||txt[i+1]!==" ")){ - appendcurrent(); - i=j; - - const stars="*".repeat(count); - if(count===1){ - const i=document.createElement("i"); - if(keep){i.append(stars)} - i.appendChild(markdown(build,{keep:keep,stdsize:stdsize})); - if(keep){i.append(stars)} - span.appendChild(i); - }else if(count===2){ - const b=document.createElement("b"); - if(keep){b.append(stars)} - b.appendChild(markdown(build,{keep:keep,stdsize:stdsize})); - if(keep){b.append(stars)} - span.appendChild(b); - }else{ - const b=document.createElement("b"); - const i=document.createElement("i"); - if(keep){b.append(stars)} - b.appendChild(markdown(build,{keep:keep,stdsize:stdsize})); - if(keep){b.append(stars)} - i.appendChild(b); - span.appendChild(i); - } - i-- - continue; - } - } - - if(txt[i]==="_"){ - let count=1; - if(txt[i+1]==="_"){ - count++; - if(txt[i+2]==="_"){ - count++; - } - } - let build=[]; - let find=0; - let j=i+count; - for(;txt[j]!==undefined&&find!==count;j++){ - - if(txt[j]==="_"){ - find++; - }else{ - build.push(txt[j]); - if(find!==0){ - build=build.concat(new Array(find).fill("_")); - find=0; - } - } - } - if(find===count&&(count!=1||(txt[j+1]===" "||txt[j+1]==="\n"||txt[j+1]===undefined))){ - appendcurrent(); - i=j; - const underscores="_".repeat(count); - if(count===1){ - const i=document.createElement("i"); - if(keep){i.append(underscores)} - i.appendChild(markdown(build,{keep:keep,stdsize:stdsize})); - if(keep){i.append(underscores)} - span.appendChild(i); - }else if(count===2){ - const u=document.createElement("u"); - if(keep){u.append(underscores)} - u.appendChild(markdown(build,{keep:keep,stdsize:stdsize})); - if(keep){u.append(underscores)} - span.appendChild(u); - }else{ - const u=document.createElement("u"); - const i=document.createElement("i"); - if(keep){i.append(underscores)} - i.appendChild(markdown(build,{keep:keep,stdsize:stdsize})); - if(keep){i.append(underscores)} - u.appendChild(i) - span.appendChild(u); - } - i--; - continue; - } - } - - if(txt[i]==="~"&&txt[i+1]==="~"){ - let count=2; - let build=[]; - let find=0; - let j=i+2; - for(;txt[j]!==undefined&&find!==count;j++){ - if(txt[j]==="~"){ - find++; - }else{ - build.push(txt[j]); - if(find!==0){ - build=build.concat(new Array(find).fill("~")); - find=0; - } - } - } - if(find===count){ - appendcurrent(); - i=j; - const tildes="~~"; - if(count===2){ - const s=document.createElement("s"); - if(keep){s.append(tildes)} - s.appendChild(markdown(build,{keep:keep,stdsize:stdsize})); - if(keep){s.append(tildes)} - span.appendChild(s); - } - continue; - } - } - if(txt[i]==="|"&&txt[i+1]==="|"){ - let count=2; - let build=[]; - let find=0; - let j=i+2; - for(;txt[j]!==undefined&&find!==count;j++){ - if(txt[j]==="|"){ - find++; - }else{ - build.push(txt[j]); - if(find!==0){ - build=build.concat(new Array(find).fill("~")); - find=0; - } - } - } - if(find===count){ - appendcurrent(); - i=j; - const pipes="||"; - if(count===2){ - const j=document.createElement("j"); - if(keep){j.append(pipes)} - j.appendChild(markdown(build,{keep:keep,stdsize:stdsize})); - j.classList.add("spoiler"); - j.onclick=markdown.unspoil; - if(keep){j.append(pipes)} - span.appendChild(j); - } - continue; - } - } - - if (txt[i]==="<" && txt[i + 1]==="t" && txt[i + 2]===":") { - let found=false; - const build=["<","t",":"]; - let j = i+3; - for (; txt[j] !== void 0; j++) { - build.push(txt[j]); - - if (txt[j]===">") { - found=true; - break; - } - } - - if (found) { - appendcurrent(); - i=j; - - const parts=build.join("").match(/^$/); - const dateInput=new Date(Number.parseInt(parts[1]) * 1000); - let time=""; - if (Number.isNaN(dateInput.getTime())) time=build.join(""); - else { - if (parts[3]==="d") time=dateInput.toLocaleString(void 0, {day: "2-digit", month: "2-digit", year: "numeric"}); - else if (parts[3]==="D") time=dateInput.toLocaleString(void 0, {day: "numeric", month: "long", year: "numeric"}); - else if (!parts[3] || parts[3]==="f") time=dateInput.toLocaleString(void 0, {day: "numeric", month: "long", year: "numeric"}) + " " + - dateInput.toLocaleString(void 0, {hour: "2-digit", minute: "2-digit"}); - else if (parts[3]==="F") time=dateInput.toLocaleString(void 0, {day: "numeric", month: "long", year: "numeric", weekday: "long"}) + " " + - dateInput.toLocaleString(void 0, {hour: "2-digit", minute: "2-digit"}); - else if (parts[3]==="t") time=dateInput.toLocaleString(void 0, {hour: "2-digit", minute: "2-digit"}); - else if (parts[3]==="T") time=dateInput.toLocaleString(void 0, {hour: "2-digit", minute: "2-digit", second: "2-digit"}); - else if (parts[3]==="R") time=Math.round((Date.now() - (Number.parseInt(parts[1]) * 1000))/1000/60) + " minutes ago"; - } - - const timeElem=document.createElement("span"); - timeElem.classList.add("markdown-timestamp"); - timeElem.textContent=time; - span.appendChild(timeElem); - continue; - } - } - - if (txt[i] === "<" && (txt[i + 1] === ":" || (txt[i + 1] === "a" && txt[i + 2] === ":"))) { - let found=false; - const build = txt[i + 1] === "a" ? ["<","a",":"] : ["<",":"]; - let j = i+build.length; - for (; txt[j] !== void 0; j++) { - build.push(txt[j]); - - if (txt[j]===">") { - found=true; - break; - } - } - - if (found) { - const parts=build.join("").match(/^<(a)?:\w+:(\d{10,30})>$/); - if (parts && parts[2]) { + if(find===count){ appendcurrent(); i=j; - console.log(typeof txt,txt); - const isEmojiOnly = txt.join("").trim()===build.join("").trim(); - - const emojiElem=document.createElement("img"); - emojiElem.classList.add("md-emoji"); - emojiElem.width=isEmojiOnly ? 48 : 22; - emojiElem.height=isEmojiOnly ? 48 : 22; - emojiElem.crossOrigin="anonymous"; - //emojiElem.src=this.info.cdn.toString() + "/emojis/" + parts[2] + "." + (parts[1] ? "gif" : "png") + "?size=32"; - //must uncomment later - emojiElem.alt=""; - emojiElem.loading="lazy"; - span.appendChild(emojiElem); - + if(keep){ + build+="`".repeat(find); + } + if(count!==3&&!stdsize){ + const samp=document.createElement("samp"); + samp.textContent=build; + span.appendChild(samp); + }else{ + const pre=document.createElement("pre"); + if(build[build.length-1]==="\n"){ + build=build.substring(0,build.length-1); + } + if(txt[i]==="\n"){ + i++ + } + pre.textContent=build; + span.appendChild(pre); + } + i--; continue; } } + + if(txt[i]==="*"){ + let count=1; + if(txt[i+1]==="*"){ + count++; + if(txt[i+2]==="*"){ + count++; + } + } + let build=[]; + let find=0; + let j=i+count; + for(;txt[j]!==undefined&&find!==count;j++){ + + if(txt[j]==="*"){ + find++; + }else{ + build.push(txt[j]); + if(find!==0){ + build=build.concat(new Array(find).fill("*")); + find=0; + } + } + } + if(find===count&&(count!=1||txt[i+1]!==" ")){ + appendcurrent(); + i=j; + + const stars="*".repeat(count); + if(count===1){ + const i=document.createElement("i"); + if(keep){i.append(stars)} + i.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize})); + if(keep){i.append(stars)} + span.appendChild(i); + }else if(count===2){ + const b=document.createElement("b"); + if(keep){b.append(stars)} + b.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize})); + if(keep){b.append(stars)} + span.appendChild(b); + }else{ + const b=document.createElement("b"); + const i=document.createElement("i"); + if(keep){b.append(stars)} + b.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize})); + if(keep){b.append(stars)} + i.appendChild(b); + span.appendChild(i); + } + i-- + continue; + } + } + + if(txt[i]==="_"){ + let count=1; + if(txt[i+1]==="_"){ + count++; + if(txt[i+2]==="_"){ + count++; + } + } + let build=[]; + let find=0; + let j=i+count; + for(;txt[j]!==undefined&&find!==count;j++){ + + if(txt[j]==="_"){ + find++; + }else{ + build.push(txt[j]); + if(find!==0){ + build=build.concat(new Array(find).fill("_")); + find=0; + } + } + } + if(find===count&&(count!=1||(txt[j+1]===" "||txt[j+1]==="\n"||txt[j+1]===undefined))){ + appendcurrent(); + i=j; + const underscores="_".repeat(count); + if(count===1){ + const i=document.createElement("i"); + if(keep){i.append(underscores)} + i.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize})); + if(keep){i.append(underscores)} + span.appendChild(i); + }else if(count===2){ + const u=document.createElement("u"); + if(keep){u.append(underscores)} + u.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize})); + if(keep){u.append(underscores)} + span.appendChild(u); + }else{ + const u=document.createElement("u"); + const i=document.createElement("i"); + if(keep){i.append(underscores)} + i.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize})); + if(keep){i.append(underscores)} + u.appendChild(i) + span.appendChild(u); + } + i--; + continue; + } + } + + if(txt[i]==="~"&&txt[i+1]==="~"){ + let count=2; + let build=[]; + let find=0; + let j=i+2; + for(;txt[j]!==undefined&&find!==count;j++){ + if(txt[j]==="~"){ + find++; + }else{ + build.push(txt[j]); + if(find!==0){ + build=build.concat(new Array(find).fill("~")); + find=0; + } + } + } + if(find===count){ + appendcurrent(); + i=j; + const tildes="~~"; + if(count===2){ + const s=document.createElement("s"); + if(keep){s.append(tildes)} + s.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize})); + if(keep){s.append(tildes)} + span.appendChild(s); + } + continue; + } + } + if(txt[i]==="|"&&txt[i+1]==="|"){ + let count=2; + let build=[]; + let find=0; + let j=i+2; + for(;txt[j]!==undefined&&find!==count;j++){ + if(txt[j]==="|"){ + find++; + }else{ + build.push(txt[j]); + if(find!==0){ + build=build.concat(new Array(find).fill("~")); + find=0; + } + } + } + if(find===count){ + appendcurrent(); + i=j; + const pipes="||"; + if(count===2){ + const j=document.createElement("j"); + if(keep){j.append(pipes)} + j.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize})); + j.classList.add("spoiler"); + j.onclick=MarkDown.unspoil; + if(keep){j.append(pipes)} + span.appendChild(j); + } + continue; + } + } + + if (txt[i]==="<" && txt[i + 1]==="t" && txt[i + 2]===":") { + let found=false; + const build=["<","t",":"]; + let j = i+3; + for (; txt[j] !== void 0; j++) { + build.push(txt[j]); + + if (txt[j]===">") { + found=true; + break; + } + } + + if (found) { + appendcurrent(); + i=j; + + const parts=build.join("").match(/^$/); + const dateInput=new Date(Number.parseInt(parts[1]) * 1000); + let time=""; + if (Number.isNaN(dateInput.getTime())) time=build.join(""); + else { + if (parts[3]==="d") time=dateInput.toLocaleString(void 0, {day: "2-digit", month: "2-digit", year: "numeric"}); + else if (parts[3]==="D") time=dateInput.toLocaleString(void 0, {day: "numeric", month: "long", year: "numeric"}); + else if (!parts[3] || parts[3]==="f") time=dateInput.toLocaleString(void 0, {day: "numeric", month: "long", year: "numeric"}) + " " + + dateInput.toLocaleString(void 0, {hour: "2-digit", minute: "2-digit"}); + else if (parts[3]==="F") time=dateInput.toLocaleString(void 0, {day: "numeric", month: "long", year: "numeric", weekday: "long"}) + " " + + dateInput.toLocaleString(void 0, {hour: "2-digit", minute: "2-digit"}); + else if (parts[3]==="t") time=dateInput.toLocaleString(void 0, {hour: "2-digit", minute: "2-digit"}); + else if (parts[3]==="T") time=dateInput.toLocaleString(void 0, {hour: "2-digit", minute: "2-digit", second: "2-digit"}); + else if (parts[3]==="R") time=Math.round((Date.now() - (Number.parseInt(parts[1]) * 1000))/1000/60) + " minutes ago"; + } + + const timeElem=document.createElement("span"); + timeElem.classList.add("markdown-timestamp"); + timeElem.textContent=time; + span.appendChild(timeElem); + continue; + } + } + + if (txt[i] === "<" && (txt[i + 1] === ":" || (txt[i + 1] === "a" && txt[i + 2] === ":"))) { + let found=false; + const build = txt[i + 1] === "a" ? ["<","a",":"] : ["<",":"]; + let j = i+build.length; + for (; txt[j] !== void 0; j++) { + build.push(txt[j]); + + if (txt[j]===">") { + found=true; + break; + } + } + + if (found) { + const buildjoin=build.join(""); + const parts=buildjoin.match(/^<(a)?:\w+:(\d{10,30})>$/); + if (parts && parts[2]) { + appendcurrent(); + i=j; + console.log(typeof txt,txt); + const isEmojiOnly = txt.join("").trim()===buildjoin.trim(); + console.log(isEmojiOnly,":3"); + + const emojiElem=document.createElement("img"); + emojiElem.classList.add("md-emoji"); + emojiElem.classList.add(isEmojiOnly ? "bigemoji" : "smallemoji"); + emojiElem.crossOrigin="anonymous"; + emojiElem.src=this.info.cdn.toString() + "emojis/" + parts[2] + "." + (parts[1] ? "gif" : "png") + "?size=32"; + + emojiElem.alt=buildjoin; + emojiElem.loading="lazy"; + span.appendChild(emojiElem); + + continue; + } + } + } + + current.textContent+=txt[i]; } - - current.textContent+=txt[i]; + appendcurrent(); + return span; + } + static unspoil(e:any) : void{ + e.target.classList.remove("spoiler") + e.target.classList.add("unspoiled") } - appendcurrent(); - return span; -} -markdown.unspoil=function(e:any) : void{ - //console.log("undone") - e.target.classList.remove("spoiler") - e.target.classList.add("unspoiled") } diff --git a/webpage/message.ts b/webpage/message.ts index 91eb35b..a16ac7b 100644 --- a/webpage/message.ts +++ b/webpage/message.ts @@ -1,7 +1,7 @@ import {Contextmenu} from "./contextmenu.js"; import {User} from "./user.js"; import {Member} from "./member.js"; -import {markdown} from "./markdown.js"; +import {MarkDown} from "./markdown.js"; import {Embed} from "./embed.js"; import { Channel } from "./channel.js"; import {Localuser} from "./localuser.js"; @@ -21,7 +21,7 @@ class Message{ message_reference; type:number; timestamp:number; - content:string; + content:MarkDown; static del:Promise; static resolve:Function; div:HTMLDivElement; @@ -37,7 +37,7 @@ class Message{ } static setupcmenu(){ Message.contextmenu.addbutton("Copy raw text",function(){ - navigator.clipboard.writeText(this.content); + navigator.clipboard.writeText(this.content.rawString); }); Message.contextmenu.addbutton("Reply",function(this:Message,div:HTMLDivElement){ this.channel.setReplying(this); @@ -67,6 +67,9 @@ class Message{ this.attachments.push(new File(thing,this)); } continue; + }else if(thing==="content"){ + this.content=new MarkDown(messagejson[thing],this.channel); + continue; } this[thing]=messagejson[thing]; } @@ -210,7 +213,7 @@ class Message{ replyline.classList.add("replyflex") this.channel.getmessage(this.message_reference.message_id).then(message=>{ const author=message.author; - reply.appendChild(markdown(message.content,{stdsize:true})); + reply.appendChild(message.content.makeHTML({stdsize:true})); minipfp.src=author.getpfpsrc() author.bind(minipfp); username.textContent=author.username; @@ -271,7 +274,7 @@ class Message{ }else{ div.classList.remove("topMessage"); } - const messaged=markdown(this.content); + const messaged=this.content.makeHTML(); div["txt"]=messaged; const messagedwrap=document.createElement("div"); messagedwrap.classList.add("flexttb") diff --git a/webpage/style.css b/webpage/style.css index 6f5fc92..31d8555 100644 --- a/webpage/style.css +++ b/webpage/style.css @@ -1359,3 +1359,11 @@ span { .sizeupdown{ height:4in; } +.bigemoji{ + width:48px; + height:48px; +} +.smallemoji{ + width:22px; + height:22px; +} \ No newline at end of file diff --git a/webpage/user.ts b/webpage/user.ts index dadf121..d62433b 100644 --- a/webpage/user.ts +++ b/webpage/user.ts @@ -1,6 +1,6 @@ //const usercache={}; import {Member} from "./member.js"; -import {markdown} from "./markdown.js"; +import {MarkDown} from "./markdown.js"; import {Contextmenu} from "./contextmenu.js"; import {Localuser} from "./localuser.js"; import {Guild} from "./guild.js"; @@ -12,7 +12,7 @@ class User{ id:string; avatar:string; username:string; - bio:string; + bio:MarkDown; discriminator:string; pronouns:string; bot:boolean; @@ -49,6 +49,10 @@ class User{ if(!owner){console.error("missing localuser")} if(dontclone){ for(const thing of Object.keys(userjson)){ + if(thing==="bio"){ + this.bio=new MarkDown(userjson[thing],this.localuser); + continue; + } this[thing]=userjson[thing]; } this.hypotheticalpfp=false; @@ -152,7 +156,7 @@ class User{ const rule=document.createElement("hr"); userbody.appendChild(rule); - const biohtml=markdown(this.bio); + const biohtml=this.bio.makeHTML(); userbody.appendChild(biohtml); } console.log(div); From 95a651396d8e4730b717a9330a778fc2f71e9d3a Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Sat, 20 Jul 2024 19:06:08 -0500 Subject: [PATCH 04/10] got rid of uneeded logs --- .dist/markdown.js | 2 -- webpage/markdown.ts | 2 -- 2 files changed, 4 deletions(-) diff --git a/.dist/markdown.js b/.dist/markdown.js index 8111f5f..c98a848 100644 --- a/.dist/markdown.js +++ b/.dist/markdown.js @@ -449,9 +449,7 @@ class MarkDown { if (parts && parts[2]) { appendcurrent(); i = j; - console.log(typeof txt, txt); const isEmojiOnly = txt.join("").trim() === buildjoin.trim(); - console.log(isEmojiOnly, ":3"); const emojiElem = document.createElement("img"); emojiElem.classList.add("md-emoji"); emojiElem.classList.add(isEmojiOnly ? "bigemoji" : "smallemoji"); diff --git a/webpage/markdown.ts b/webpage/markdown.ts index 3cf3a6e..8896749 100644 --- a/webpage/markdown.ts +++ b/webpage/markdown.ts @@ -414,9 +414,7 @@ class MarkDown{ if (parts && parts[2]) { appendcurrent(); i=j; - console.log(typeof txt,txt); const isEmojiOnly = txt.join("").trim()===buildjoin.trim(); - console.log(isEmojiOnly,":3"); const emojiElem=document.createElement("img"); emojiElem.classList.add("md-emoji"); From f2ce41d48aa671ca6a401b93ac024b9aeb40f1ba Mon Sep 17 00:00:00 2001 From: TomatoCake <60300461+DEVTomatoCake@users.noreply.github.com> Date: Sun, 21 Jul 2024 10:59:38 +0200 Subject: [PATCH 05/10] thanks git for yeeting my changes --- webpage/index.ts | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/webpage/index.ts b/webpage/index.ts index b3db4ee..6f37235 100644 --- a/webpage/index.ts +++ b/webpage/index.ts @@ -183,26 +183,15 @@ function userSettings(){ thisuser.usersettings.show(); } document.getElementById("settings").onclick=userSettings; -let triggered=false; -document.getElementById("messagecontainer").addEventListener("scroll",(e)=>{ - const messagecontainer=document.getElementById("messagecontainer") - if(messagecontainer.scrollTop<2000){ - if(!triggered){ - thisuser.lookingguild.prevchannel.grabmoremessages().then(()=>{ - triggered=false; - if(messagecontainer.scrollTop===0){ - messagecontainer.scrollTop=1; - } - }); - } - triggered=true; - }else{ - if(Math.abs(messagecontainer.scrollHeight-messagecontainer.scrollTop-messagecontainer.clientHeight) < 3){ - thisuser.lookingguild.prevchannel.readbottom(); - } - } - // -}) +function userConnections(){ + thisuser.userConnections.show(); +} +document.getElementById("connections").onclick=userConnections; +function devPortal(){ + thisuser.devPortal.show(); +} +document.getElementById("dev-portal").onclick=devPortal; + if(mobile){ document.getElementById("channelw").onclick=function(){ (document.getElementById("channels").parentNode as HTMLElement).classList.add("collapse"); From 02f53fb1e5384766b545a2df8cca2c7ed18f22a4 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Sun, 21 Jul 2024 15:55:44 -0500 Subject: [PATCH 06/10] Implements a markdown box --- .dist/embed.js | 2 +- .dist/index.js | 10 +++-- .dist/localuser.js | 6 ++- .dist/markdown.js | 89 +++++++++++++++++++++++++++++++++++++-- .dist/message.js | 4 +- webpage/embed.ts | 2 +- webpage/index.html | 2 +- webpage/index.ts | 12 ++++-- webpage/localuser.ts | 6 ++- webpage/markdown.ts | 99 +++++++++++++++++++++++++++++++++++++++++--- webpage/message.ts | 4 +- webpage/style.css | 15 +++++-- 12 files changed, 221 insertions(+), 30 deletions(-) diff --git a/.dist/embed.js b/.dist/embed.js index e617bdb..76fcbf3 100644 --- a/.dist/embed.js +++ b/.dist/embed.js @@ -67,7 +67,7 @@ class Embed { embed.append(authorline); } const title = document.createElement("a"); - title.append(new MarkDown(this.json.title, this.localuser).makeHTML()); + title.append(new MarkDown(this.json.title, this.channel).makeHTML()); if (this.json.url) { title.href = this.json.url; } diff --git a/.dist/index.js b/.dist/index.js index 7421acd..7894e2b 100644 --- a/.dist/index.js +++ b/.dist/index.js @@ -109,7 +109,7 @@ async function enter(event) { if (event.key === "Enter" && !event.shiftKey) { event.preventDefault(); if (channel.editing) { - channel.editing.edit((typebox).value); + channel.editing.edit(markdown.rawString); channel.editing = null; } else { @@ -119,7 +119,7 @@ async function enter(event) { replyingto.div.classList.remove("replying"); } thisuser.channelfocus.replyingto = null; - channel.sendMessage(typebox.value, { + channel.sendMessage(markdown.rawString, { attachments: images, replyingto: replying, }); @@ -129,11 +129,14 @@ async function enter(event) { images.pop(); pasteimage.removeChild(imageshtml.pop()); } - typebox.value = ""; + typebox.innerHTML = ""; return; } } const typebox = document.getElementById("typebox"); +const markdown = new MarkDown("", thisuser); +markdown.giveBox(typebox); +typebox["markdown"] = markdown; typebox.addEventListener("keyup", enter); typebox.addEventListener("keydown", event => { if (event.key === "Enter" && !event.shiftKey) @@ -149,6 +152,7 @@ function getguildinfo() { const images = []; const imageshtml = []; import { File } from "./file.js"; +import { MarkDown } from "./markdown.js"; document.addEventListener('paste', async (e) => { Array.from(e.clipboardData.files).forEach(async (f) => { const file = File.initFromBlob(f); diff --git a/.dist/localuser.js b/.dist/localuser.js index d650a46..dbb8daa 100644 --- a/.dist/localuser.js +++ b/.dist/localuser.js @@ -84,7 +84,9 @@ class Localuser { outoffocus() { document.getElementById("servers").textContent = ""; document.getElementById("channels").textContent = ""; - this.channelfocus.infinite.delete(); + if (this.channelfocus) { + this.channelfocus.infinite.delete(); + } this.lookingguild = null; this.channelfocus = null; } @@ -594,7 +596,7 @@ class Localuser { newprouns = this.value; regen(); }], - ["mdbox", "Bio:", this.user.bio, function (e) { + ["mdbox", "Bio:", this.user.bio.rawString, function (e) { console.log(this.value); hypouser.bio = this.value; newbio = this.value; diff --git a/.dist/markdown.js b/.dist/markdown.js index c98a848..1cd0b1e 100644 --- a/.dist/markdown.js +++ b/.dist/markdown.js @@ -21,7 +21,7 @@ class MarkDown { this.stdsize = stdsize; } get rawString() { - return this.txt.concat(""); + return this.txt.join(""); } get textContent() { return this.makeHTML().textContent; @@ -103,7 +103,8 @@ class MarkDown { } element.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize })); span.append(element); - i--; + i -= 1; + console.log(txt[i]); continue; } if (first) { @@ -335,7 +336,7 @@ class MarkDown { } if (find === count) { appendcurrent(); - i = j; + i = j - 1; const tildes = "~~"; if (count === 2) { const s = document.createElement("s"); @@ -370,7 +371,7 @@ class MarkDown { } if (find === count) { appendcurrent(); - i = j; + i = j - 1; const pipes = "||"; if (count === 2) { const j = document.createElement("j"); @@ -471,4 +472,84 @@ class MarkDown { e.target.classList.remove("spoiler"); e.target.classList.add("unspoiled"); } + giveBox(box) { + box.onkeydown = _ => { + //console.log(_); + }; + let prevcontent = ""; + box.onkeyup = _ => { + const content = MarkDown.gatherBoxText(box); + if (content !== prevcontent) { + prevcontent = content; + this.txt = content.split(""); + this.boxupdate(box); + } + }; + box.onpaste = _ => { + console.log(_.clipboardData.types); + const data = _.clipboardData.getData("text"); + document.execCommand('insertHTML', false, data); + _.preventDefault(); + box.onkeyup(new KeyboardEvent("_")); + }; + } + boxupdate(box) { + var restore = saveCaretPosition(box); + box.innerHTML = ""; + box.append(this.makeHTML({ keep: true })); + restore(); + } + static gatherBoxText(element) { + const children = element.childNodes; + if (element.tagName.toLowerCase() === "img") { + return element.alt; + } + if (element.tagName.toLowerCase() === "br") { + return "\n"; + } + if (children.length !== 0) { + let build = ""; + for (const thing of children) { + if (thing instanceof Text) { + const text = thing.textContent; + build += text; + continue; + } + const text = this.gatherBoxText(thing); + if (text) { + build += text; + } + } + return build; + } + } +} +//solution from https://stackoverflow.com/questions/4576694/saving-and-restoring-caret-position-for-contenteditable-div +function saveCaretPosition(context) { + var selection = window.getSelection(); + var range = selection.getRangeAt(0); + range.setStart(context, 0); + var len = range.toString().length; + return function restore() { + var pos = getTextNodeAtPosition(context, len); + selection.removeAllRanges(); + var range = new Range(); + range.setStart(pos.node, pos.position); + selection.addRange(range); + }; +} +function getTextNodeAtPosition(root, index) { + const NODE_TYPE = NodeFilter.SHOW_TEXT; + var treeWalker = document.createTreeWalker(root, NODE_TYPE, function next(elem) { + if (index > elem.textContent.length) { + index -= elem.textContent.length; + return NodeFilter.FILTER_REJECT; + } + return NodeFilter.FILTER_ACCEPT; + }); + var c = treeWalker.nextNode(); + return { + node: c ? c : root, + position: index + }; } diff --git a/.dist/message.js b/.dist/message.js index 6dcaafb..78c8519 100644 --- a/.dist/message.js +++ b/.dist/message.js @@ -43,7 +43,9 @@ class Message { }); Message.contextmenu.addbutton("Edit", function () { this.channel.editing = this; - document.getElementById("typebox").value = this.content; + const markdown = (document.getElementById("typebox"))["markdown"]; + markdown.txt = this.content.rawString; + markdown.boxupdate(document.getElementById("typebox")); }, null, _ => { return _.author.id === _.localuser.user.id; }); Message.contextmenu.addbutton("Delete message", function () { this.delete(); diff --git a/webpage/embed.ts b/webpage/embed.ts index ac5d60e..b17de58 100644 --- a/webpage/embed.ts +++ b/webpage/embed.ts @@ -71,7 +71,7 @@ class Embed{ embed.append(authorline); } const title=document.createElement("a"); - title.append(new MarkDown(this.json.title,this.localuser).makeHTML()); + title.append(new MarkDown(this.json.title,this.channel).makeHTML()); if(this.json.url){ title.href=this.json.url; } diff --git a/webpage/index.html b/webpage/index.html index 07b70b1..88f3c67 100644 --- a/webpage/index.html +++ b/webpage/index.html @@ -53,7 +53,7 @@
- +