canopy/www/js/channel/chatPostprocessor.js

140 lines
5.3 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class chatPostprocessor{
constructor(){
}
preprocess(chatEntry, rawData){
this.rawData = rawData;
//Set current chat nodes
this.chatEntry = chatEntry;
this.chatBody = this.chatEntry.querySelector(".chat-entry-body");
//Split the chat body into an array of objects representing each word
//We could pass this through arguments but these functions wont be very interoperable anyways since they expect a purpose-made hashtable
this.splitBody();
//Inject links into un-processed placeholders
this.processLinks();
//Inject whitespace into un-processed words
this.addWhitespace();
//Handle non-standard chat types
this.handleChatType();
//Inject the pre-processed chat into the chatEntry node
this.injectBody();
//Return the pre-processed node
return this.chatEntry;
}
splitBody(){
//Create an empty array to hold the body
this.bodyArray = [];
//Split string by words (except for file seperator to keep link placeholders in-tact)
const splitString = this.chatBody.innerHTML.split(/(?<!␜)\b(?!␜)/g); //Group words together
//for each word in the splitstring
splitString.forEach((string) => {
//create a word object
const wordObj = {
string: string,
type: "word"
}
//Add it to our body array
this.bodyArray.push(wordObj);
});
}
injectBody(){
//Create empty array to hold strings
var stringArray = [];
//Extract strings into the empty array
this.bodyArray.forEach((wordObj) => {
if(wordObj.type == 'word'){
stringArray.push(wordObj.string);
}else if(wordObj.type == 'link'){
//Create a link node from our link
const link = document.createElement('a');
link.classList.add('chat-link');
link.href = wordObj.link;
link.innerHTML = wordObj.link;
//Inject it into the original string, and add it to string array
stringArray.push(wordObj.string.replace('␜',link.outerHTML));
}
});
//Join the strings to fill the chat entry
this.chatBody.innerHTML = stringArray.join("");
}
addWhitespace(){
//for each word object in the body
this.bodyArray.forEach((wordObj, wordIndex) => {
//if the word object hasn't been pre-processed elsewhere
if(wordObj.type == "word"){
var wordArray = [];
//Add invisible whitespace in-between characters to keep it from breaking page layout
this.bodyArray[wordIndex].string.split("").forEach((char, charIndex) => {
wordArray.push(char);
//After eight characters
if(charIndex > 8){
//Push an invisible line-break character between every character
wordArray.push("");
}
});
this.bodyArray[wordIndex].string = wordArray.join("");
}
});
}
processLinks(){
this.rawData.links.forEach((link, linkIndex) => {
this.bodyArray.forEach((wordObj, wordIndex) => {
//Check current wordobj for link (placeholder may contain whitespace with it)
if(wordObj.string.match(`${linkIndex}`)){
//Set current word object in the body array to the new link object
this.bodyArray[wordIndex] = {
//Don't want to use a numbered placeholder to make this easier during body injection
//but we also don't want to clobber any surrounding whitespace
string: wordObj.string.replace(`${linkIndex}`, '␜'),
link: link.link,
type: "link"
}
}
})
});
}
handleChatType(){
if(this.rawData.type == "whisper"){
//add whisper class
this.chatBody.classList.add('whisper');
}else if(this.rawData.type == "announcement"){
//Squash the high-level
this.chatEntry.querySelector('.high-level').remove();
//Get the username and make it into an announcement title (little hacky but this *IS* postprocessing)
const userNode = this.chatEntry.querySelector('.chat-entry-username');
userNode.innerHTML = `${userNode.innerHTML.slice(0,-2)} Announcement`;
//Add/remove relevant classes
userNode.classList.remove('chat-entry-username');
userNode.classList.add('announcement-title');
this.chatBody.classList.add('announcement-body');
this.chatEntry.classList.add('announcement');
}else if(this.rawData.type == "toke" || this.rawData.type == "tokewhisper"){
//Squash the high-level
this.chatEntry.querySelector('.high-level').remove();
//remove the username
this.chatEntry.querySelector('.chat-entry-username').remove();
//Add toke/tokewhisper class
this.chatBody.classList.add(this.rawData.type);
}
}
}