hnOsmium0001

irccloud-sws with strikethrough support (userscript)

Feb 1st, 2021
850
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name        Send with Style
  3. // @namespace   dogancelik.com
  4. // @description Enables font styles in IRCCloud
  5. // @include     https://www.irccloud.com/*
  6. // @version     4.4.0
  7. // @grant       none
  8. // @updateURL   https://github.com/dogancelik/irccloud-sws/raw/master/build/send_with_style.meta.js
  9. // @downloadURL https://github.com/dogancelik/irccloud-sws/raw/master/build/send_with_style.user.js
  10. // ==/UserScript==
  11.  
  12. (function () {
  13.  
  14. 'use strict';
  15.  
  16. var Settings = {
  17.   keyPrefix: 'sws.',
  18.   get: function(key, def) {
  19.     var getVal = localStorage.getItem(this.keyPrefix + key);
  20.     if (typeof def !== 'undefined' && getVal == null) {
  21.       this.set(key, def);
  22.       return def;
  23.     }
  24.     return getVal;
  25.   },
  26.   set: function(key, value) {
  27.     localStorage.setItem(this.keyPrefix + key, value);
  28.   },
  29.   remove: function (keys) {
  30.     var keys = [].concat(keys);
  31.     keys.forEach((function (key) {
  32.       localStorage.removeItem(this.keyPrefix + key);
  33.     }).bind(this));
  34.   }
  35. };
  36.  
  37. function upgradeOldSettings() {
  38.   var settingsTable = {
  39.     'swsEnabled': 'sws.enabled',
  40.     'swsAlias': 'sws.alias',
  41.     'swsKeyboard': 'sws.key.enabled',
  42.     'swsKeyCtrl': 'sws.key.ctrl',
  43.     'swsKeyAlt': 'sws.key.alt',
  44.     'swsKeyShift': 'sws.key.shift',
  45.     'swsKeyChar': 'sws.key.char',
  46.     'swsMarkdown': 'sws.markdown',
  47.     'swsColorsTable': 'sws.colorsTable'
  48.   };
  49.   for (var oldKey in settingsTable) {
  50.     var newKey = settingsTable[oldKey];
  51.     var oldVal = localStorage[oldKey];
  52.     var newVal = localStorage[newKey];
  53.     if (typeof oldVal !== 'undefined') {
  54.       localStorage.setItem(newKey, oldVal);
  55.       localStorage.removeItem(oldKey);
  56.     }
  57.   }
  58. }
  59.  
  60. var isChrome = /chrome/.test(navigator.userAgent.toLowerCase());
  61.  
  62. var swsEnabled, swsAlias, swsMarkdown, swsKeyboard, swsKeyCtrl, swsKeyAlt, swsKeyShift, swsKeyChar, shortcutWaiting, swsColorsTable, swsSpecialFuncs, colorsTable, last2Keys;
  63.  
  64. var fontStyles = {
  65.   color: '\u0003',
  66.   bold: '\u0002',
  67.   reset: '\u000f',
  68.   italic: '\u001d',
  69.   underline: '\u001f',
  70.   strikethrough: '\u001e',
  71. };
  72.  
  73. function replaceFontStyles (str) {
  74.   return str.replace(/%B/g, fontStyles.bold)
  75.     .replace(/%R/g, fontStyles.reset)
  76.     .replace(/%I/g, fontStyles.italic)
  77.     .replace(/%U/g, fontStyles.underline)
  78.     .replace(/%X/g, fontStyles.strikethrough)
  79.     .replace(/%C/g, fontStyles.color);
  80. }
  81.  
  82. function replaceMarkdown (str) {
  83.   if (/^\/mode/.test(str)) return str;
  84.   if (/^\\/.test(str)) return str.substr(1);
  85.  
  86.   return str.replace(/\*{3}([^\*]+)\*{3}/g, fontStyles.bold + fontStyles.italic + '$1' + fontStyles.italic + fontStyles.bold)
  87.     .replace(/\*{2}([^\*]+)\*{2}/g, fontStyles.bold + '$1' + fontStyles.bold)
  88.     .replace(/\*{1}([^\*]+)\*{1}/g, fontStyles.italic + '$1' + fontStyles.italic)
  89.     .replace(/\_{2}([^\_]+)\_{2}/g, fontStyles.underline + '$1' + fontStyles.underline)
  90.     .replace(/\_{1}([^\_]+)\_{1}/g, fontStyles.italic + '$1' + fontStyles.italic)
  91.     .replace(/\~{2}([^\~]+)\~{2}/g, fontStyles.strikethrough + '$1' + fontStyles.strikethrough);
  92. }
  93.  
  94. function replaceAliases (str) {
  95.   if (swsAlias.val().trim() === "") {
  96.     return str;
  97.   } else {
  98.     swsAlias.val().split('\n').forEach(function (i) {
  99.       var keyval = i.split(/,(.*)/g);
  100.       str = str.split(keyval[0]).join(keyval[1]);
  101.     });
  102.     return str;
  103.   }
  104. }
  105.  
  106. function toggleShortcutProgress (input, toggle) {
  107.   if (toggle) {
  108.     input.css('outline', '1px solid blue');
  109.     shortcutWaiting = true;
  110.   } else {
  111.     input.css('outline', '');
  112.     shortcutWaiting = false;
  113.   }
  114. }
  115.  
  116. function insertTo(input, text) {
  117.   var cursorPos = input.prop('selectionStart');
  118.   var val = input.val();
  119.   var before = val.substring(0, cursorPos);
  120.   var after  = val.substring(cursorPos, val.length);
  121.   input.val(before + text + after);
  122.   input.prop('selectionStart', cursorPos + 1);
  123.   input.prop('selectionEnd', cursorPos + 1);
  124. }
  125.  
  126. // colorsTable start
  127. var currentInput, currentColorsTable, origColorsTable; // required for colorsTable click
  128.  
  129. function toggleColorsTable(input, toggle) {
  130.   var offset = input.offset();
  131.  
  132.   if (currentColorsTable.data('sws') !== '1') {
  133.     currentColorsTable.find('td').on('click', function() {
  134.       var number = $(this).children().first().text();
  135.       var text = currentInput.val();
  136.       currentInput.val(text + number);
  137.       toggleColorsTable(currentInput, false);
  138.     });
  139.     currentColorsTable.data('sws', '1');
  140.   }
  141.  
  142.   currentColorsTable.css({
  143.     display: (toggle ? 'block' : 'none'),
  144.     left: offset.left + 'px',
  145.     top: (offset.top - 40) + 'px'
  146.   });
  147. }
  148.  
  149. // required for showing colorsTable in normal mode
  150. function trackLast2Keys(key) {
  151.   last2Keys += key;
  152.   if (last2Keys.length > 2) {
  153.     last2Keys = last2Keys.substring(1,3);
  154.   }
  155. }
  156.  
  157. function createColorsTable() {
  158.   var scroll = currentInput.parents('.buffermain').find('.scroll');
  159.   var colorsTable = $('#sws-current-colors-table');
  160.  
  161.   if (colorsTable.length === 0) {
  162.     colorsTable = origColorsTable.clone();
  163.     colorsTable.attr('id', 'sws-current-colors-table');
  164.     scroll.append(colorsTable);
  165.     colorsTable.css({
  166.       position: 'fixed',
  167.       display: 'none'
  168.     });
  169.   }
  170.  
  171.   return colorsTable.detach().appendTo(scroll);
  172. }
  173. // colorsTable end
  174.  
  175. // specialFunctions start
  176. function rainbow(text, match) {
  177.   var output = '';
  178.   var colors = ['05', '04', '07', '08', '09', '03', '11', '10', '12', '02', '06', '13', '15', '14'];
  179.   var startIndex = Math.floor(Math.random() * colors.length);
  180.  
  181.   for (var i = 0; i < match.length; i++) {
  182.     var char = match[i];
  183.     if (char !== ' ') {
  184.       output += fontStyles.color + colors[startIndex++] + char + fontStyles.color;
  185.     } else {
  186.       output += char;
  187.     }
  188.     if (startIndex >= colors.length) {
  189.       startIndex = 0;
  190.     }
  191.   }
  192.  
  193.   return output;
  194. }
  195.  
  196. var specialFunctions = [
  197.   {
  198.     regex: /<rainbow>(.*)<\/rainbow>/g,
  199.     func: rainbow
  200.   }
  201. ];
  202.  
  203. function replaceSpecials(text) {
  204.   var oldText = text;
  205.   var newText = oldText;
  206.   for (var i = 0; i < specialFunctions.length; i++) {
  207.     var item = specialFunctions[i];
  208.     newText = oldText.replace(item.regex, item.func);
  209.   }
  210.   return newText;
  211. }
  212. // specialFunctions end
  213.  
  214. function bindTextarea () {
  215.   if (cb() == null) {
  216.     return false;
  217.   }
  218.  
  219.   var input = $('#bufferInputView' + cb().bid());
  220.   currentInput = input;
  221.   currentColorsTable = createColorsTable();
  222.  
  223.   if (input.data('sws') !== '1') {
  224.     input.on('keypress', function (e) {
  225.       var lowerKey = String.fromCharCode(e.which).toLowerCase();
  226.       if (e.which > 31) {
  227.         trackLast2Keys(lowerKey);
  228.       }
  229.     });
  230.  
  231.     input.on('keyup', function (e) {
  232.       var keyboardEnabled = swsKeyboard.prop('checked');
  233.       var colorsEnabled = swsColorsTable.prop('checked');
  234.       if (colorsEnabled && !keyboardEnabled && last2Keys === '%c') {
  235.         toggleColorsTable(input, true);
  236.       }
  237.     });
  238.  
  239.     input.on('keydown', function (e) {
  240.       var mainEnabled = swsEnabled.prop('checked');
  241.       var keyboardEnabled = swsKeyboard.prop('checked');
  242.       var markdownEnabled = swsMarkdown.prop('checked');
  243.       var colorsEnabled = swsColorsTable.prop('checked');
  244.       var specialEnabled = swsSpecialFuncs.prop('checked');
  245.       var lowerKey = (isChrome ? String.fromCharCode(e.which) : e.key).toLowerCase();
  246.  
  247.       if (colorsEnabled) {
  248.         toggleColorsTable(input, false);
  249.       }
  250.  
  251.       if (keyboardEnabled) {
  252.         var enabledCtrl = swsKeyCtrl.prop('checked');
  253.         var enabledAlt = swsKeyAlt.prop('checked');
  254.         var enabledShift = swsKeyShift.prop('checked');
  255.         var activateChar = swsKeyChar.val().trim().substr(0, 1).toLowerCase();
  256.  
  257.         if (e.ctrlKey === enabledCtrl && e.altKey === enabledAlt && e.shiftKey === enabledShift && lowerKey == activateChar) {
  258.           toggleShortcutProgress(input, true);
  259.           return;
  260.         }
  261.       }
  262.  
  263.       if (e.keyCode === 13 && mainEnabled) {
  264.         var val = input.val();
  265.         val = replaceAliases(val);
  266.         input.val(val);
  267.  
  268.         if (specialEnabled) {
  269.           var val = input.val();
  270.           val = replaceSpecials(val);
  271.           input.val(val);
  272.         }
  273.  
  274.         if (!keyboardEnabled) {
  275.           var val = input.val();
  276.           val = replaceFontStyles(val);
  277.           input.val(val);
  278.         }
  279.  
  280.         if (markdownEnabled) {
  281.           var val = input.val();
  282.           val = replaceMarkdown(val);
  283.           input.val(val);
  284.         }
  285.       }
  286.  
  287.       if (shortcutWaiting && keyboardEnabled) {
  288.         var noInput = false;
  289.         switch (lowerKey) {
  290.           case "c":
  291.             insertTo(input, fontStyles.color);
  292.             if (colorsEnabled) {
  293.               toggleColorsTable(input, true);
  294.             }
  295.             noInput = true;
  296.             break;
  297.           case "b":
  298.             insertTo(input, fontStyles.bold);
  299.             noInput = true;
  300.             break;
  301.           case "i":
  302.             insertTo(input, fontStyles.italic);
  303.             noInput = true;
  304.             break;
  305.           case "u":
  306.             insertTo(input, fontStyles.underline);
  307.             noInput = true;
  308.             break;
  309.           case 'x':
  310.             insertTo(input, fontStyles.strikethrough);
  311.             noInput = true;
  312.             break;
  313.           case "r":
  314.             insertTo(input, fontStyles.reset);
  315.             noInput = true;
  316.             break;
  317.         }
  318.         toggleShortcutProgress(input, false);
  319.         if (noInput) return false;
  320.       }
  321.     });
  322.     input.data('sws', '1');
  323.   }
  324. }
  325.  
  326. function embedStyle() {
  327.   return $('<style>').prop('type', 'text/css').html('#sws-container{font-size:18px}.sws-bold{font-weight:bold}.sws-info-table{border:1px solid rgba(0,0,0,0.1);border-radius:.2em;}.sws-info-table th,.sws-info-table td{padding:.2em .4em}.sws-colors-table td{background-color:#fff;height:20px;width:20px;line-height:20px;font-size:12px;border:1px solid #000;border-left:0;text-align:center;padding:1px;cursor:pointer}.sws-colors-table td:first-child{border-left:1px solid #000}.sws-colors-table span{display:inline-block;height:20px;width:20px}#sws-colors-box{display:none}#sws-colors-anchor{cursor:pointer}.sws-key-box{display:inline-block;background-color:rgba(0,0,0,0.1);border-radius:.25em;padding:.25em .5em;margin-right:.25em}#sws-key-char{width:30px}#sws-custom-alias{height:60px;width:100%}#sws-enabled-label{font-weight:normal}#sws-enabled-check:not(:checked) ~ #sws-enabled-label{color:#f00;}#sws-enabled-check:not(:checked) ~ #sws-enabled-label::after{content:"Not enabled"}#sws-enabled-check:checked ~ #sws-enabled-label{color:#008000;}#sws-enabled-check:checked ~ #sws-enabled-label::after{content:"Enabled"}').appendTo('head:first');
  328. }
  329.  
  330. function createMenu() {
  331.   return $('<div id="sws-bar" class="settingsMenu__item settingsMenu__item__sendwithstyle"><a class="settingsMenu__link" href="/?/settings=sendwithstyle">Send with Style</a></div>').insertAfter('.settingsContainer .settingsMenu .settingsMenu__item:last');
  332. }
  333.  
  334. function createContainer() {
  335.   return $('<div id="sws-container" data-section="sendwithstyle" class="settingsContents settingsContents__sendwithstyle"><h2 class="settingsTitle"><span>Send with Style&nbsp;</span><input id="sws-enabled-check" type="checkbox"/>&nbsp;<label id="sws-enabled-label" for="sws-enabled-check"></label></h2><p class="explanation">Type your text as you normally would, use the codes to style your text.</p><p class="explanation sws-bold">If your settings are lost, please&nbsp;<a href="https://github.com/dogancelik/irccloud-sws/wiki/Help#my-custom-settings-have-disappeared-in-new-version-what-do-i-do" target="_blank">read this page</a>&nbsp;to learn how to recover it.</p><table class="sws-info-table"><tr><th>Code</th><th>Example</th></tr><tr><td><code>%C</code>&nbsp;for&nbsp;<a id="sws-colors-anchor" title="Click here to show color numbers" style="border-bottom: 1px dashed black;"><font color="#ff0000">c</font><font color="#cc8f33">o</font><font color="#99ed66">l</font><font color="#66f899">o</font><font color="#33accc">r</font></a></td><td><code>%C2This is blue</code>&nbsp;→&nbsp;<code><span style="color: blue">This is blue</span></code></td></tr><tr id="sws-colors-box"><td colspan="2"><table class="sws-colors-table"><tr><td><span class="bg-white black">0</span></td><td><span class="bg-black white">1</span></td><td><span class="bg-navy white">2</span></td><td><span class="bg-green white">3</span></td><td><span class="bg-red black">4</span></td><td><span class="bg-maroon white">5</span></td><td><span class="bg-purple white">6</span></td><td><span class="bg-orange black">7</span></td><td><span class="bg-yellow black">8</span></td><td><span class="bg-lime black">9</span></td><td><span class="bg-teal white">10</span></td><td><span class="bg-cyan black">11</span></td><td><span class="bg-blue white">12</span></td><td><span class="bg-magenta black">13</span></td><td><span class="bg-grey black">14</span></td><td><span class="bg-silver black">15</span></td></tr></table></td></tr><tr><td><code>%B</code>&nbsp;for&nbsp;<b>bold</b></td><td><code>%BVery bold</code>&nbsp;→&nbsp;<code><b>Very bold</b></code></td></tr><tr><td><code>%I</code>&nbsp;for&nbsp;<i>italic</i></td><td><code>%IPizza</code>&nbsp;→&nbsp;<code><i>Pizza</i></code></td></tr><tr><td><code>%U</code>&nbsp;for&nbsp;<u>underline</u></td><td><code>%UBeep</code>&nbsp;→&nbsp;<code><u>Beep</u></code></td></tr><tr><td><code>%R</code>&nbsp;for reset</td><td><code>%C4Wo%Rrd</code>&nbsp;→&nbsp;<code><span style="color: red">Wo</span>rd</code></td></tr></table><p class="explanation"><input id="sws-keyboard-mode" type="checkbox"/><label for="sws-keyboard-mode">&nbsp;Keyboard Mode (Disables %C, %B etc.)&nbsp;</label><span class="sws-key-box"><label for="sws-key-ctrl">Ctrl:&nbsp;</label><input id="sws-key-ctrl" type="checkbox"/></span><span class="sws-key-box"><label for="sws-key-alt">Alt:&nbsp;</label><input id="sws-key-alt" type="checkbox"/></span><span class="sws-key-box"><label for="sws-key-alt">Shift:&nbsp;</label><input id="sws-key-shift" type="checkbox"/></span><span class="sws-key-box"><label for="sws-key-char">Key:&nbsp;</label><input id="sws-key-char" type="text"/></span></p><p class="explanation"><input id="sws-colors-table" type="checkbox"/><label for="sws-colors-table">&nbsp;Show Colors Table (when you are about to type color numbers)</label></p><p class="explanation"><input id="sws-markdown-mode" type="checkbox"/><label for="sws-markdown-mode">&nbsp;Markdown Mode (Enables <code>*</code> and <code>_</code> for <i>italic text</i>, <code>**</code> for <b>bold text</b>, and <code>__</code> for <u>underlined text</u>.)</label></p><p class="explanation"><input id="sws-special-funcs" type="checkbox"/><label for="sws-special-funcs">&nbsp;Special Functions (Enables <code>&lt;rainbow&gt;</code> tag)</label></p><h3>Custom aliases</h3><textarea id="sws-custom-alias"></textarea><hr/><p id="sws-donate" class="explanation sws-bold">If you like this script, please&nbsp;<a href="http://dogancelik.com/donate.html" target="_blank">consider a donation</a></p><p class="explanation"><a href="https://github.com/dogancelik/irccloud-sws" target="_blank">Source code</a>&nbsp;-&nbsp;<a href="https://github.com/dogancelik/irccloud-sws/issues" target="_blank">Report bug / Request feature</a>&nbsp;-&nbsp;<a href="https://github.com/dogancelik/irccloud-sws/wiki/Help" target="_blank">Help</a></p></div>').insertAfter('.settingsContentsWrapper .settingsContents:last');
  336. }
  337.  
  338. function init() {
  339.   embedStyle();
  340.   upgradeOldSettings(); // for version 4.0.3 and below
  341.  
  342.   var menu = createMenu();
  343.   var container = createContainer();
  344.  
  345.   var hashName = 'sendwithstyle';
  346.   if (window.location.search === '?/settings=' + hashName) {
  347.     SESSIONVIEW.showSettings(hashName);
  348.   }
  349.  
  350.   swsEnabled = container.find('#sws-enabled-check').change(function () {
  351.     Settings.set('enabled', this.checked);
  352.   }).prop('checked', JSON.parse(Settings.get('enabled', true)));
  353.  
  354.   var colorsBox = container.find('#sws-colors-box');
  355.   container.find('#sws-colors-anchor').click(function () {
  356.     colorsBox.toggle();
  357.   });
  358.  
  359.   swsAlias = container.find("#sws-custom-alias");
  360.   swsAlias.val(Settings.get('alias'))
  361.   .on('change', function () {
  362.     Settings.set('alias', swsAlias.val());
  363.   });
  364.  
  365.   swsKeyboard = container.find('#sws-keyboard-mode').change(function () {
  366.     Settings.set('key.enabled', this.checked);
  367.   }).prop('checked', JSON.parse(Settings.get('key.enabled')) || false);
  368.  
  369.   swsKeyCtrl = container.find('#sws-key-ctrl').change(function () {
  370.     Settings.set('key.ctrl', this.checked);
  371.   }).prop('checked', JSON.parse(Settings.get('key.ctrl')) || true);
  372.  
  373.   swsKeyAlt = container.find('#sws-key-alt').change(function () {
  374.     Settings.set('key.alt', this.checked);
  375.   }).prop('checked', JSON.parse(Settings.get('key.alt')) || false);
  376.  
  377.   swsKeyShift = container.find('#sws-key-shift').change(function () {
  378.     Settings.set('key.shift', this.checked);
  379.   }).prop('checked', JSON.parse(Settings.get('key.shift')) || true);
  380.  
  381.   swsKeyChar = container.find('#sws-key-char').change(function () {
  382.     Settings.set('key.char', this.value);
  383.   }).val(Settings.get('key.char', 'z'));
  384.  
  385.   swsMarkdown = container.find('#sws-markdown-mode').change(function () {
  386.     Settings.set('markdown', this.checked);
  387.   }).prop('checked', JSON.parse(Settings.get('markdown', false)));
  388.  
  389.   swsColorsTable = container.find('#sws-colors-table').change(function () {
  390.     Settings.set('colorsTable', this.checked);
  391.     if (!this.checked) {
  392.       colorsTable.css('display', 'none');
  393.     }
  394.   }).prop('checked', JSON.parse(Settings.get('colorsTable', false)));
  395.  
  396.   origColorsTable = container.find('.sws-colors-table');
  397.  
  398.   swsSpecialFuncs = container.find('#sws-special-funcs').change(function () {
  399.     Settings.set('specialFuncs', this.checked);
  400.   }).prop('checked', JSON.parse(Settings.get('specialFuncs', false)));
  401.  
  402.   bindTextarea();
  403. }
  404.  
  405. (function checkSession () {
  406.   if (window.hasOwnProperty('SESSION')) {
  407.     window.SESSION.bind('init', function () {
  408.       init();
  409.  
  410.       window.SESSION.buffers.on('doneSelected', function () {
  411.         bindTextarea();
  412.       });
  413.     });
  414.   } else {
  415.     setTimeout(checkSession, 100);
  416.   }
  417. })();
  418.  
  419. })();
  420.  
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×