TeaWeb/shared/js/text/chat.ts

120 lines
3.7 KiB
TypeScript
Raw Normal View History

2020-12-07 14:07:47 +00:00
import UrlKnife from 'url-knife';
import {Settings, settings} from "../settings";
import {renderMarkdownAsBBCode} from "../text/markdown";
import {escapeBBCode} from "../text/bbcode";
import {parseBBCode as parseBBCode} from "vendor/xbbcode/parser";
import {BBCodeTagElement} from "vendor/xbbcode/elements";
import {regexImage} from "tc-shared/text/bbcode/image";
2020-07-19 14:34:08 +00:00
2020-12-07 14:07:47 +00:00
interface UrlKnifeUrl {
value: {
url: string,
},
area: string,
index: {
start: number,
end: number
}
}
2020-07-19 14:34:08 +00:00
2020-12-07 14:22:39 +00:00
function bbcodeLinkUrls(message: string, ignore: { start: number, end: number }[]) : string {
2020-12-07 14:07:47 +00:00
const urls: UrlKnifeUrl[] = UrlKnife.TextArea.extractAllUrls(message, {
'ip_v4' : true,
'ip_v6' : false,
'localhost' : false,
'intranet' : true
});
2020-07-19 14:34:08 +00:00
2020-12-07 14:07:47 +00:00
/* we want to go through the urls from the back to the front */
urls.sort((a, b) => b.index.start - a.index.start);
outerLoop:
2020-12-07 14:07:47 +00:00
for(const url of urls) {
2020-12-07 14:22:39 +00:00
if(ignore.findIndex(range => range.start <= url.index.start && range.end >= url.index.end) !== -1) {
continue;
}
2020-12-07 14:07:47 +00:00
const prefix = message.substr(0, url.index.start);
const suffix = message.substr(url.index.end);
const urlPath = message.substring(url.index.start, url.index.end);
let bbcodeUrl;
regexImage.lastIndex = 0;
if (regexImage.test(urlPath)) {
for(const suffix of [
".jpeg", ".jpg",
".png", ".gif", ".tiff",
".bmp",
".webp",
".svg"
]) {
if(urlPath.endsWith(suffix)) {
/* It's an image. Images will be rendered by the client automatically. */
continue outerLoop;
}
}
}
2020-12-07 14:07:47 +00:00
let colonIndex = urlPath.indexOf(":");
2020-12-19 15:14:07 +00:00
if(colonIndex === -1 || colonIndex + 2 >= urlPath.length || urlPath[colonIndex + 1] !== "/" || urlPath[colonIndex + 2] !== "/") {
2020-12-07 14:07:47 +00:00
bbcodeUrl = "[url=https://" + urlPath + "]" + urlPath + "[/url]";
} else {
bbcodeUrl = "[url]" + urlPath + "[/url]";
2020-07-19 14:34:08 +00:00
}
2020-12-07 14:07:47 +00:00
message = prefix + bbcodeUrl + suffix;
2020-07-19 14:34:08 +00:00
}
2020-12-07 14:07:47 +00:00
return message;
2020-07-19 14:34:08 +00:00
}
export function preprocessChatMessageForSend(message: string) : string {
2021-01-10 15:13:15 +00:00
const parseMarkdown = settings.getValue(Settings.KEY_CHAT_ENABLE_MARKDOWN);
const escapeBBCodes = !settings.getValue(Settings.KEY_CHAT_ENABLE_BBCODE);
2020-07-19 14:34:08 +00:00
2020-12-07 14:07:47 +00:00
if(parseMarkdown) {
2020-12-07 14:22:39 +00:00
message = renderMarkdownAsBBCode(message, text => escapeBBCodes ? escapeBBCode(text) : text);
} else if(escapeBBCodes) {
message = escapeBBCode(message);
}
2021-01-10 15:13:15 +00:00
if(settings.getValue(Settings.KEY_CHAT_TAG_URLS)) {
2020-12-07 14:22:39 +00:00
const bbcodeElements = parseBBCode(message, {});
const noParseRanges: { start: number, end: number }[] = [];
while(true) {
const element = bbcodeElements.pop();
if(!element) {
break;
2020-12-07 14:07:47 +00:00
}
2020-07-19 14:34:08 +00:00
if(!(element instanceof BBCodeTagElement)) {
2020-12-07 14:22:39 +00:00
continue;
2020-12-07 14:07:47 +00:00
}
2020-07-19 14:34:08 +00:00
2020-12-07 14:22:39 +00:00
switch(element.tagType?.tag) {
case "code":
case "i-code":
case "url":
case "img":
case "no-parse":
case "youtube":
case "quote":
noParseRanges.push(element.textPosition);
break;
2020-07-19 14:34:08 +00:00
2020-12-07 14:22:39 +00:00
default:
bbcodeElements.push(...element.content);
break;
}
2020-12-07 14:07:47 +00:00
}
2020-07-19 14:34:08 +00:00
2020-12-07 14:22:39 +00:00
message = bbcodeLinkUrls(message, noParseRanges);
2020-12-07 14:07:47 +00:00
}
2020-12-07 14:22:39 +00:00
while(message.endsWith("\n")) {
message = message.substring(0, message.length - 1);
}
2020-12-07 14:22:39 +00:00
return message;
2020-07-19 14:34:08 +00:00
}