diff --git a/src/document/index.html b/src/document/index.html index 153cdbd..f476e8b 100644 --- a/src/document/index.html +++ b/src/document/index.html @@ -7,6 +7,7 @@
+
+
diff --git a/src/script/main.js b/src/script/main.js index 6cfcde0..ab26a86 100644 --- a/src/script/main.js +++ b/src/script/main.js @@ -1,11 +1,11 @@ const themes = require('./theme.js'); -const stylize = require('./colorparser.js'); window.irc = { socketUp: false, primaryFrame: null, config: { colors: true, + channelify: true, sharedInput: false, timestamps: true, timestampFormat: 'HH:mm:ss', @@ -13,6 +13,7 @@ window.irc = { colorNicklist: false, scrollOnResize: true, scrollOnFocus: true, + emoji: true, theme: 'default' }, serverData: {}, @@ -35,7 +36,8 @@ const colorizer = { }, strip: function(message) { return message.replace(/(\x03\d{0,2}(,\d{0,2})?)/g, '').replace(/[\x0F\x02\x16\x1F]/g, ''); - } + }, + stylize: require('./colorparser.js') }; let urlParams = {}; @@ -150,6 +152,50 @@ Date.prototype.format = function (format, utc){ return format; }; +const processors = { + inline_color: function (text) { + // TODO: Figure out how to make hex colors behave + //const hexRegex = /(^|[^&])(\#[0-9a-f]{6};?)(?!\w)/gmi; + const rgbRegex = /(.?)(rgba?\((?:\s*\d+\s*,){2}\s*\d+\s*(?:,\s*[\d.]+\s*)?\);?)/gmi; + const substitute = '$1$2 '; + //text = text.replace(hexRegex, substitute); + text = text.replace(rgbRegex, substitute); + return text; + }, + linkify(text) { + const re = /\b((?:https?:\/\/|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:''.,<>?«»“”‘’]))/gi; + return text.replace(re, function(url) { + let href = url; + if (url.indexOf('http') !== 0) { + href = 'http://' + url; + } + return '' + url + ''; + }); + }, + channelify(text) { + if(!irc.config.channelify) return text; + + const channelRegex = /(^|[\s,.:;?!"'()+@-\~%])(#+[^\x00\x07\r\n\s,:]*[a-z][^\x00\x07\r\n\s,:]*)/gmi; + const substitute = '$1$2'; + + return text.replace(channelRegex, substitute); + }, + emojify(text) { + if (irc.config.emoji === true && window.emojione !== undefined) { + // Emoji live in the D800-DFFF surrogate plane; only bother passing + // this range to CPU-expensive unicodeToImage(); + const emojiRegex = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g; + if (emojiRegex.test(text)) { + return emojione.unicodeToImage(text); + } else { + return text; + } + } else { + return text; + } + } +}; + function whoisMessage(whoisData, buffer) { let messages = []; for(let key in whoisData) { @@ -239,20 +285,6 @@ function match(word, array) { ); } -function linkify(text) { - // see http://daringfireball.net/2010/07/improved_regex_for_matching_urls - let re = /\b((?:https?:\/\/|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:''.,<>?«»“”‘’]))/gi; - let parsed = text.replace(re, function(url) { - // turn into a link - let href = url; - if (url.indexOf('http') !== 0) { - href = 'http://' + url; - } - return '' + url + ''; - }); - return parsed; -} - function serialize(obj) { let str = []; for(let p in obj) @@ -300,7 +332,7 @@ function objectGetKey(obj, value) { let composer = { message: { - simple: function(time, sender, message, type) { + simple: function(time, sender, message, type, server) { let element = document.createElement('div'); element.className = 'message type_simple m_'+type; @@ -308,11 +340,14 @@ let composer = { element.innerHTML += ' '; if(irc.config.colors) - message = stylize(message); + message = colorizer.stylize(message); else message = colorizer.strip(message); - message = linkify(message); + message = processors.inline_color(message); + message = processors.channelify(message); + message = processors.linkify(message); + message = processors.emojify(message); switch(type) { case 'mode': @@ -436,6 +471,15 @@ let composer = { } }; +// onclick food +window.irc.joinChannel = (channel) => { + let buf = irc.chat.getActiveChatBuffer(); + if(!buf || !buf.server) return; + + irc.socket.emit('userinput', {command: 'join', server: buf.server, message: '', arguments: [channel]}); + return false; +}; + /*****************************\ |** **| |** CLIENT COMMANDS **| @@ -948,9 +992,9 @@ class ChatBuffer { if(this.topic != null && this.topic != '') { addClass(clientdom.chat, 'vtopic'); if(irc.config.colors) - clientdom.topicbar.innerHTML = linkify(stylize(this.topic)); + clientdom.topicbar.innerHTML = processors.linkify(processors.channelify(colorizer.stylize(this.topic))); else - clientdom.topicbar.innerHTML = linkify(colorizer.strip(this.topic)); + clientdom.topicbar.innerHTML = processors.linkify(processors.channelify(colorizer.strip(this.topic))); } this.renderMessages(); @@ -989,7 +1033,7 @@ class ChatBuffer { } appendMessage(meta) { - let mesgConstr = composer.message[irc.chatType](meta.time, meta.sender, meta.message, meta.type); + let mesgConstr = composer.message[irc.chatType](meta.time, meta.sender, meta.message, meta.type, this.server); if(irc.serverData[this.server]) { let mynick = irc.serverData[this.server].my_nick; @@ -1008,9 +1052,9 @@ class ChatBuffer { topicChange(topic) { if(this.active) { if(irc.config.colors) - clientdom.topicbar.innerHTML = linkify(stylize(topic)); + clientdom.topicbar.innerHTML = processors.linkify(colorizer.stylize(topic)); else - clientdom.topicbar.innerHTML = linkify(colorizer.strip(topic)); + clientdom.topicbar.innerHTML = processors.linkify(colorizer.strip(topic)); if(this.topic == null) addClass(clientdom.chat, 'vtopic'); diff --git a/src/script/meta.js b/src/script/meta.js new file mode 100644 index 0000000..249bd78 --- /dev/null +++ b/src/script/meta.js @@ -0,0 +1,12 @@ +const metafunctions = { + hexcolor: {regex: /#([A-F0-9]{3}([A-F0-9]{3})?)\b/gi, replacer: (function (line, regxp) { + return line.replace(regxp, (color) => { + return '' + color + + '