fixed quotes and made a safelink function

This commit is contained in:
MathMan05 2024-09-05 12:00:05 -05:00
parent e3185a06c6
commit 04779b6c6c
7 changed files with 156 additions and 14 deletions

View file

@ -225,7 +225,7 @@ class Dialog {
return table; return table;
} }
default: default:
console.error("can't find element:" + array[0], " full element:" + array); console.error("can't find element:" + array[0], " full element:", array);
} }
} }
show() { show() {

View file

@ -60,7 +60,7 @@ class Embed {
const a = document.createElement("a"); const a = document.createElement("a");
a.textContent = this.json.author.name; a.textContent = this.json.author.name;
if (this.json.author.url) { if (this.json.author.url) {
a.href = this.json.author.url; MarkDown.safeLink(a, this.json.author.url);
} }
a.classList.add("username"); a.classList.add("username");
authorline.append(a); authorline.append(a);
@ -70,7 +70,7 @@ class Embed {
const title = document.createElement("a"); const title = document.createElement("a");
title.append(new MarkDown(this.json.title, this.channel).makeHTML()); title.append(new MarkDown(this.json.title, this.channel).makeHTML());
if (this.json.url) { if (this.json.url) {
title.href = this.json.url; MarkDown.safeLink(title, this.json.url);
} }
title.classList.add("embedtitle"); title.classList.add("embedtitle");
embed.append(title); embed.append(title);
@ -155,7 +155,7 @@ class Embed {
if (this.json.url && this.json.title) { if (this.json.url && this.json.title) {
const td = document.createElement("td"); const td = document.createElement("td");
const a = document.createElement("a"); const a = document.createElement("a");
a.href = this.json.url; MarkDown.safeLink(a, this.json.url);
a.textContent = this.json.title; a.textContent = this.json.title;
td.append(a); td.append(a);
trtop.append(td); trtop.append(td);
@ -199,7 +199,7 @@ class Embed {
} }
const a = document.createElement("a"); const a = document.createElement("a");
if (this.json.url && this.json.url) { if (this.json.url && this.json.url) {
a.href = this.json.url; MarkDown.safeLink(a, this.json.url);
a.textContent = this.json.url; a.textContent = this.json.url;
div.append(a); div.append(a);
} }

View file

@ -1,4 +1,5 @@
import { Channel } from "./channel.js"; import { Channel } from "./channel.js";
import { Dialog } from "./dialog.js";
import { Emoji } from "./emoji.js"; import { Emoji } from "./emoji.js";
class MarkDown { class MarkDown {
txt; txt;
@ -102,6 +103,7 @@ class MarkDown {
} }
if (keep) { if (keep) {
element.append(keepys); element.append(keepys);
//span.appendChild(document.createElement("br"));
} }
element.appendChild(this.markdown(build, { keep, stdsize })); element.appendChild(this.markdown(build, { keep, stdsize }));
span.append(element); span.append(element);
@ -394,6 +396,29 @@ class MarkDown {
continue; continue;
} }
} }
if (txt[i] === "h" && txt[i + 1] === "t" && txt[i + 2] === "t" && txt[i + 3] === "p") {
let build = "http";
let j = i + 4;
const endchars = new Set(["\\", "<", ">", "|", "]", " "]);
for (; txt[j] !== undefined; j++) {
const char = txt[j];
if (endchars.has(char)) {
break;
}
build += char;
}
console.log("checking:" + build);
if (URL.canParse(build)) {
const a = document.createElement("a");
//a.href=build;
MarkDown.safeLink(a, build);
a.textContent = build;
a.target = "_blank";
i = j;
span.appendChild(a);
}
continue;
}
if (txt[i] === "<" && txt[i + 1] === "t" && txt[i + 2] === ":") { if (txt[i] === "<" && txt[i + 1] === "t" && txt[i + 2] === ":") {
let found = false; let found = false;
const build = ["<", "t", ":"]; const build = ["<", "t", ":"];
@ -489,7 +514,7 @@ class MarkDown {
const parts = build.join("").match(/^\[(.+)\]\((https?:.+?)( ('|").+('|"))?\)$/); const parts = build.join("").match(/^\[(.+)\]\((https?:.+?)( ('|").+('|"))?\)$/);
if (parts) { if (parts) {
const linkElem = document.createElement("a"); const linkElem = document.createElement("a");
linkElem.href = parts[2]; MarkDown.safeLink(linkElem, parts[2]);
linkElem.textContent = parts[1]; linkElem.textContent = parts[1];
linkElem.target = "_blank"; linkElem.target = "_blank";
linkElem.rel = "noopener noreferrer"; linkElem.rel = "noopener noreferrer";
@ -562,6 +587,54 @@ class MarkDown {
} }
return build; return build;
} }
static trustedDomains = new Set([location.host]);
static safeLink(elm, url) {
if (URL.canParse(url)) {
const Url = new URL(url);
if (elm instanceof HTMLAnchorElement && this.trustedDomains.has(Url.host)) {
elm.href = url;
elm.target = "_blank";
return;
}
elm.onmouseup = _ => {
if (_.button === 2)
return;
console.log(":3");
function open() {
const proxy = window.open(url, '_blank');
if (proxy && _.button === 1) {
proxy.focus();
}
else if (proxy) {
window.focus();
}
}
if (this.trustedDomains.has(Url.host)) {
open();
}
else {
const full = new Dialog([
"vdiv",
["title", "You're leaving spacebar"],
["text", "You're going to " + Url.host + " are you sure you want to go there?"],
["hdiv",
["button", "", "Nevermind", _ => full.hide()],
["button", "", "Go there", _ => { open(); full.hide(); }],
["button", "", "Go there and trust in the future", _ => {
open();
full.hide();
this.trustedDomains.add(Url.host);
}]
]
]);
full.show();
}
};
}
else {
throw Error(url + " is not a valid URL");
}
}
} }
//solution from https://stackoverflow.com/questions/4576694/saving-and-restoring-caret-position-for-contenteditable-div //solution from https://stackoverflow.com/questions/4576694/saving-and-restoring-caret-position-for-contenteditable-div
function saveCaretPosition(context) { function saveCaretPosition(context) {

View file

@ -232,7 +232,7 @@ class Dialog{
return table; return table;
} }
default: default:
console.error("can't find element:"+array[0]," full element:"+array); console.error("can't find element:"+array[0]," full element:",array);
} }
} }
show(){ show(){

View file

@ -65,7 +65,7 @@ class Embed{
const a=document.createElement("a"); const a=document.createElement("a");
a.textContent=this.json.author.name as string; a.textContent=this.json.author.name as string;
if(this.json.author.url){ if(this.json.author.url){
a.href=this.json.author.url; MarkDown.safeLink(a,this.json.author.url);
} }
a.classList.add("username"); a.classList.add("username");
authorline.append(a); authorline.append(a);
@ -75,7 +75,7 @@ class Embed{
const title=document.createElement("a"); const title=document.createElement("a");
title.append(new MarkDown(this.json.title,this.channel).makeHTML()); title.append(new MarkDown(this.json.title,this.channel).makeHTML());
if(this.json.url){ if(this.json.url){
title.href=this.json.url; MarkDown.safeLink(title,this.json.url);
} }
title.classList.add("embedtitle"); title.classList.add("embedtitle");
embed.append(title); embed.append(title);
@ -162,7 +162,7 @@ class Embed{
if(this.json.url&&this.json.title){ if(this.json.url&&this.json.title){
const td=document.createElement("td"); const td=document.createElement("td");
const a=document.createElement("a"); const a=document.createElement("a");
a.href=this.json.url; MarkDown.safeLink(a,this.json.url);
a.textContent=this.json.title; a.textContent=this.json.title;
td.append(a); td.append(a);
trtop.append(td); trtop.append(td);
@ -207,7 +207,7 @@ class Embed{
} }
const a=document.createElement("a"); const a=document.createElement("a");
if(this.json.url&&this.json.url){ if(this.json.url&&this.json.url){
a.href=this.json.url; MarkDown.safeLink(a,this.json.url);
a.textContent=this.json.url; a.textContent=this.json.url;
div.append(a); div.append(a);
} }

View file

@ -1,4 +1,5 @@
import{ Channel }from"./channel.js"; import{ Channel }from"./channel.js";
import { Dialog } from "./dialog.js";
import{ Emoji }from"./emoji.js"; import{ Emoji }from"./emoji.js";
import{ Localuser }from"./localuser.js"; import{ Localuser }from"./localuser.js";
@ -101,6 +102,7 @@ class MarkDown{
} }
if(keep){ if(keep){
element.append(keepys); element.append(keepys);
//span.appendChild(document.createElement("br"));
} }
element.appendChild(this.markdown(build,{keep,stdsize})); element.appendChild(this.markdown(build,{keep,stdsize}));
span.append(element); span.append(element);
@ -386,7 +388,29 @@ class MarkDown{
continue; continue;
} }
} }
if(txt[i]==="h" && txt[i + 1]==="t" && txt[i + 2]==="t" && txt[i + 3]==="p"){
let build="http";
let j = i+4;
const endchars=new Set(["\\", "<", ">", "|", "]"," "]);
for(; txt[j] !== undefined; j++){
const char=txt[j];
if(endchars.has(char)){
break;
}
build+=char;
}
console.log("checking:"+build);
if(URL.canParse(build)){
const a=document.createElement("a");
//a.href=build;
MarkDown.safeLink(a,build);
a.textContent=build;
a.target="_blank";
i=j;
span.appendChild(a);
}
continue;
}
if(txt[i]==="<" && txt[i + 1]==="t" && txt[i + 2]===":"){ if(txt[i]==="<" && txt[i + 1]==="t" && txt[i + 2]===":"){
let found=false; let found=false;
const build=["<","t",":"]; const build=["<","t",":"];
@ -484,7 +508,7 @@ class MarkDown{
const parts=build.join("").match(/^\[(.+)\]\((https?:.+?)( ('|").+('|"))?\)$/); const parts=build.join("").match(/^\[(.+)\]\((https?:.+?)( ('|").+('|"))?\)$/);
if(parts){ if(parts){
const linkElem=document.createElement("a"); const linkElem=document.createElement("a");
linkElem.href=parts[2]; MarkDown.safeLink(linkElem,parts[2])
linkElem.textContent=parts[1]; linkElem.textContent=parts[1];
linkElem.target="_blank"; linkElem.target="_blank";
linkElem.rel="noopener noreferrer"; linkElem.rel="noopener noreferrer";
@ -559,6 +583,50 @@ class MarkDown{
} }
return build; return build;
} }
static readonly trustedDomains=new Set([location.host])
static safeLink(elm:HTMLElement,url:string){
if(URL.canParse(url)){
const Url=new URL(url);
if(elm instanceof HTMLAnchorElement&&this.trustedDomains.has(Url.host)){
elm.href=url;
elm.target="_blank";
return;
}
elm.onmouseup=_=>{
if(_.button===2) return;
console.log(":3")
function open(){
const proxy=window.open(url, '_blank')
if(proxy&&_.button===1){
proxy.focus();
}else if(proxy){
window.focus();
}
}
if(this.trustedDomains.has(Url.host)){
open();
}else{
const full=new Dialog([
"vdiv",
["title","You're leaving spacebar"],
["text","You're going to "+Url.host+" are you sure you want to go there?"],
["hdiv",
["button","","Nevermind",_=>full.hide()],
["button","","Go there",_=>{open();full.hide()}],
["button","","Go there and trust in the future",_=>{
open();
full.hide();
this.trustedDomains.add(Url.host);
}]
]
]);
full.show();
}
}
}else{
throw Error(url+" is not a valid URL")
}
}
} }
//solution from https://stackoverflow.com/questions/4576694/saving-and-restoring-caret-position-for-contenteditable-div //solution from https://stackoverflow.com/questions/4576694/saving-and-restoring-caret-position-for-contenteditable-div

View file

@ -168,6 +168,7 @@ samp {
a { a {
color: var(--link); color: var(--link);
text-decoration: none; text-decoration: none;
cursor: pointer;
} }
a:hover { a:hover {
@ -923,7 +924,7 @@ input[type="checkbox"] {
} }
.quote { .quote {
display: flex; display: inline-flex;
width: fit-content; width: fit-content;
position: relative; position: relative;
} }