diff --git a/res/css/_mirccolor.sass b/res/css/_mirccolor.sass index fe20c12d15c7241f30fe97cfa7a4081e8e2d30fc..6f56b360d031796b55fa564989e50aa6ab947249 100644 --- a/res/css/_mirccolor.sass +++ b/res/css/_mirccolor.sass @@ -7,98 +7,17 @@ .irc_underline text-decoration: underline -[data-irc_foreground="0"] - color: #ffffff +.irc_strikethrough + text-decoration: line-through -[data-irc_foreground="1"] - color: #000000 +.irc_monospace + font-family: 'Roboto Mono', 'Source Code Pro', monospace -[data-irc_foreground="2"] - color: #000080 +$mircColors: ("00": #ffffff, "01": #000000, "02": #000080, "03": #008000, "04": #ff0000, "05": #800000, "06": #800080, "07": #ffa500, "08": #ffff00, "09": #00ff00, "10": #008080, "11": #00ffff, "12": #4169e1, "13": #ff00ff, "14": #808080, "15": #c0c0c0, "16": #470000, "17": #472100, "18": #474700, "19": #324700, "20": #004700, "21": #00472c, "22": #004747, "23": #002747, "24": #000047, "25": #2e0047, "26": #470047, "27": #47002a, "28": #740000, "29": #743a00, "30": #747400, "31": #517400, "32": #007400, "33": #007449, "34": #007474, "35": #004074, "36": #000074, "37": #4b0074, "38": #740074, "39": #740045, "40": #b50000, "41": #b56300, "42": #b5b500, "43": #7db500, "44": #00b500, "45": #00b571, "46": #00b5b5, "47": #0063b5, "48": #0000b5, "49": #7500b5, "50": #b500b5, "51": #b5006b, "52": #ff0000, "53": #ff8c00, "54": #ffff00, "55": #b2ff00, "56": #00ff00, "57": #00ffa0, "58": #00ffff, "59": #008cff, "60": #0000ff, "61": #a500ff, "62": #ff00ff, "63": #ff0098, "64": #ff5959, "65": #ffb459, "66": #ffff71, "67": #cfff60, "68": #6fff6f, "69": #65ffc9, "70": #6dffff, "71": #59b4ff, "72": #5959ff, "73": #c459ff, "74": #ff66ff, "75": #ff59bc, "76": #ff9c9c, "77": #ffd39c, "78": #ffff9c, "79": #e2ff9c, "80": #9cff9c, "81": #9cffdb, "82": #9cffff, "83": #9cd3ff, "84": #9c9cff, "85": #dc9cff, "86": #ff9cff, "87": #ff94d3, "88": #000000, "89": #131313, "90": #282828, "91": #363636, "92": #4d4d4d, "93": #656565, "94": #818181, "95": #9f9f9f, "96": #bcbcbc, "97": #e2e2e2, "98": #ffffff) -[data-irc_foreground="3"] - color: #008000 +@each $i, $color in $mircColors + [data-irc_foreground="#{$i}"] + color: $color -[data-irc_foreground="4"] - color: #ff0000 - -[data-irc_foreground="5"] - color: #800000 - -[data-irc_foreground="6"] - color: #800080 - -[data-irc_foreground="7"] - color: #ffa500 - -[data-irc_foreground="8"] - color: #ffff00 - -[data-irc_foreground="9"] - color: #00ff00 - -[data-irc_foreground="10"] - color: #008080 - -[data-irc_foreground="11"] - color: #00ffff - -[data-irc_foreground="12"] - color: #4169e1 - -[data-irc_foreground="13"] - color: #ff00ff - -[data-irc_foreground="14"] - color: #808080 - -[data-irc_foreground="15"] - color: #c0c0c0 - -[data-irc_background="0"] - background-color: #ffffff - -[data-irc_background="1"] - background-color: #000000 - -[data-irc_background="2"] - background-color: #000080 - -[data-irc_background="3"] - background-color: #008000 - -[data-irc_background="4"] - background-color: #ff0000 - -[data-irc_background="5"] - background-color: #800000 - -[data-irc_background="6"] - background-color: #800080 - -[data-irc_background="7"] - background-color: #ffa500 - -[data-irc_background="8"] - background-color: #ffff00 - -[data-irc_background="9"] - background-color: #00ff00 - -[data-irc_background="10"] - background-color: #008080 - -[data-irc_background="11"] - background-color: #00ffff - -[data-irc_background="12"] - background-color: #4169e1 - -[data-irc_background="13"] - background-color: #ff00ff - -[data-irc_background="14"] - background-color: #808080 - -[data-irc_background="15"] - background-color: #c0c0c0 \ No newline at end of file + [data-irc_background="#{$i}"] + background-color: $color \ No newline at end of file diff --git a/res/js/util/mirccolorhandler.js b/res/js/util/mirccolorhandler.js index 86afb8451bbd28d817ec54731f8d190eba2a046b..3ae68857790fc9a61edccc39ce4980c2e2a48279 100644 --- a/res/js/util/mirccolorhandler.js +++ b/res/js/util/mirccolorhandler.js @@ -2,30 +2,23 @@ class MircColorHandler { static render(text) { const CODE_BOLD = '\x02'; const CODE_COLOR = '\x03'; + const CODE_HEXCOLOR = '\x04'; const CODE_ITALIC = '\x1D'; const CODE_UNDERLINE = '\x1F'; + const CODE_STRIKETHROUGH = '\x1E'; + const CODE_MONOSPACE = '\x11'; const CODE_SWAP = '\x16'; const CODE_RESET = '\x0F'; + const urlRegex = /\b((?:(?:mailto:|(?:[+.-]?\w)+:\/\/)|www(?=\.\S+\.))(?:(?:[,.;@:]?[-\w]+)+\.?|\[[0-9a-f:.]+])(?::\d+)?(?:\/(?:[,.;:]*[\w~@/?&=+$()!%#*-])*)?)(?:>|[,.;:"]*\b|$)/gi; const readNumber = function (str, start, end) { if (start >= end || start >= str.length) return -1; else - return parseInt(str.substr(start, end), 10); + return parseInt(str.substr(start, end - start), 10); }; const findEndOfNumber = function (str, start) { - const validCharCodes = [ - '0', - '1', - '2', - '3', - '4', - '5', - '6', - '7', - '8', - '9' - ]; + const validCharCodes = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; let i; let tmp = str.substr(start, 2); for (i = 0; i < 2 && i < tmp.length; i++) { @@ -34,6 +27,25 @@ class MircColorHandler { } return i + start; }; + const readHexNumber = function (str, start, end) { + if (start >= end || start >= str.length) + return -1; + else + return parseInt(str.substr(start, end - start), 16); + }; + const findEndOfHexNumber = function (str, start) { + const validCharCodes = [ + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F' + ]; + let i; + let tmp = str.substr(start, 6); + for (i = 0; i < 6 && i < tmp.length; i++) { + if (validCharCodes.indexOf(tmp.charAt(i)) === -1) + break; + } + return i + start; + }; const fromState = function (state) { const elem = document.createElement((state.url) ? 'a' : 'span'); if (state.bold) @@ -42,10 +54,16 @@ class MircColorHandler { elem.classList.add('irc_italic'); if (state.underline) elem.classList.add('irc_underline'); + if (state.strikethrough) + elem.classList.add('irc_strikethrough'); + if (state.monospace) + elem.classList.add('irc_monospace'); if (state.foreground !== null) elem.dataset['irc_foreground'] = state.foreground; if (state.background !== null) elem.dataset['irc_background'] = state.background; + if (state.hexforeground !== null) + elem.style.color = '#' + ("000000" + state.hexforeground.toString(16)).substr(-6); if (state.highlight) elem.classList.add('irc_highlight'); return elem; @@ -85,7 +103,10 @@ class MircColorHandler { bold: false, italic: false, underline: false, + strikethrough: false, + monospace: false, foreground: null, + hexforeground: null, background: null, highlight: false, url: false @@ -129,6 +150,20 @@ class MircColorHandler { lastTag = fromState(state); } break; + case CODE_STRIKETHROUGH: { + apply(lastTag, str, i, normalCount, nodes); + normalCount = 0; + state.strikethrough = !state.strikethrough; + lastTag = fromState(state); + } + break; + case CODE_MONOSPACE: { + apply(lastTag, str, i, normalCount, nodes); + normalCount = 0; + state.monospace = !state.monospace; + lastTag = fromState(state); + } + break; case CODE_COLOR: { apply(lastTag, str, i, normalCount, nodes); normalCount = 0; @@ -147,7 +182,13 @@ class MircColorHandler { if (background === -1) background = state.background; } - state.foreground = foreground === -1 ? null : foreground; + if (foreground === -1) { + state.foreground = null; + state.hexforeground = null; + } else { + state.foreground = foreground; + state.hexforeground = null; + } state.background = background === -1 ? null : background; lastTag = fromState(state); i = (backgroundEnd === -1 ? foregroundEnd : backgroundEnd) - 1; @@ -158,6 +199,28 @@ class MircColorHandler { } } break; + case CODE_HEXCOLOR: { + apply(lastTag, str, i, normalCount, nodes); + normalCount = 0; + let foregroundStart = i + 1; + let foregroundEnd = findEndOfHexNumber(str, foregroundStart); + if (foregroundEnd > foregroundStart) { + let foreground = readHexNumber(str, foregroundStart, foregroundEnd); + if (foreground === -1) { + state.hexforeground = null; + state.foreground = null; + } else { + state.hexforeground = foreground; + state.foreground = null; + } + lastTag = fromState(state); + i = foregroundEnd - 1; + } else if (state.hexforeground !== null) { + state.hexforeground = null; + lastTag = fromState(state); + } + } + break; case CODE_SWAP: { apply(lastTag, str, i, normalCount, nodes); normalCount = 0;