Last active
October 24, 2019 03:55
-
-
Save Pmmlabs/fe2b34d6a877719bdfca to your computer and use it in GitHub Desktop.
Плагин для VkOpt, добавляющий возможность форматирования текста в диалогах (жирный,курсив,зачеркнутый)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @id font@vkopt | |
// @name Font for VkOpt | |
// @version 1.0 | |
// @namespace https://greasyfork.org/users/23 | |
// @author Pmmlabs@github | |
// @description Плагин для VkOpt, добавляющий возможность форматирования текста в диалогах (жирный,курсив,зачеркнутый) | |
// @include *vk.com* | |
// @run-at document-end | |
// @noframes | |
// @grant none | |
// ==/UserScript== | |
if (!window.vkopt_plugins) vkopt_plugins = {}; | |
(function () { | |
var PLUGIN_ID = 'TextFormat'; | |
vkopt_plugins[PLUGIN_ID] = { | |
Name: 'Text Formatting', | |
css:'d:after {content: "́";}', | |
el_id: 'vk_format_panel', // id элемента с кнопками. Нужен только для предотвращения повторной вставки. | |
masks: { | |
U: 1, | |
B: 2, | |
I: 4, | |
D: 8, | |
S: 16 | |
}, | |
// ФУНКЦИИ | |
onLocation: function (nav_obj, cur_module_name) { // событие "при переходе в Диалоги" | |
if (cur_module_name == 'im' && !nav_obj.w && !ge(this.el_id)) | |
this.UI(); | |
}, | |
UI: function(){ // Добавление кнопок форматирования | |
var parent = ge('im_texts'); // контейнер, содержащий текстовое поле и кнопки; сюда будем вставлять (в начало) | |
var main=vkCe('div',{id:this.el_id}); // панелька с кнопками форматирования | |
var B = vkCe('input',{type:"button", value:'𝗕','class':'im_rc_emojibtn'}); // тег input обязателен, с другим получаем не то выделение | |
B.onclick = function(){vkopt_plugins[PLUGIN_ID].onclick('b');}; | |
var U = vkCe('input',{type:"button", value:'U̲','class':'im_rc_emojibtn'}); | |
U.onclick = function(){vkopt_plugins[PLUGIN_ID].onclick('u');}; | |
var I = vkCe('input',{type:"button", value:'𝘐','class':'im_rc_emojibtn'}); | |
I.onclick = function(){vkopt_plugins[PLUGIN_ID].onclick('i');}; | |
var D = vkCe('input',{type:"button", value:'у́','class':'im_rc_emojibtn'}); // ударение | |
D.onclick = function(){vkopt_plugins[PLUGIN_ID].onclick('d');}; | |
var S = vkCe('input',{type:"button", value:'S̶','class':'im_rc_emojibtn'}); | |
S.onclick = function(){vkopt_plugins[PLUGIN_ID].onclick('s');}; | |
main.appendChild(B); | |
main.appendChild(U); | |
main.appendChild(I); | |
main.appendChild(D); | |
main.appendChild(S); | |
parent.insertBefore(main, parent.firstChild); | |
}, | |
onclick: function(tag){ // обработчик нажатия на кнопку форматирования. tag - строка, тег, которым будем оборачивать выделенный текст | |
var selection = window.getSelection().getRangeAt(0); | |
selection.insertNode(vkCe(tag,{},selection.extractContents().textContent)); | |
}, | |
onLibFiles: function (file_name) { // событие "при подгрузке im.js" | |
if (file_name == 'im.js') | |
Inj.Before('IM.send', 'if (progressNode', "vkopt_plugins['" + PLUGIN_ID + "'].process(txt);"); | |
}, | |
process: function (content,parents) { // Замена HTML-разметки в контейнере content на соответствующие Unicode-последовательности | |
var russianBold = { // не хватает: Б,Ж,И,Ц,Ч,Ш,Щ,Ы,Ъ,Э,Ю,Я,г,д,ж,з,и,л,м,н,ц,ч,щ,ш,ь,ы,ъ,э,ю,я | |
'А': '𝚨', | |
'В': '𝚩', | |
'Г': '𝚪', | |
'Д': '𝚫', | |
'Е': '𝚬', | |
'Ё': '𝚬', | |
'З': '𝟯', | |
'К': '𝚱', | |
'Л': '𝚲', | |
'М': '𝚳', | |
'Н': '𝚮', | |
'О': '𝚶', | |
'П': '𝚷', | |
'Р': '𝚸', | |
'С': '𝗖', | |
'Т': '𝚻', | |
'У': 'Ꭹ', | |
'Ф': '𝚽', | |
'Х': '𝚾', | |
'Ь': 'Ꮟ', //// | |
'а': '𝗮', | |
'б': '𝛅', | |
'в': '𝛃', | |
'е': '𝗲', | |
'ё': '𝗲', | |
'к': '𝛋', | |
'о': '𝗼', | |
'п': '𝛑', | |
'р': '𝗽', | |
'с': '𝗰', | |
'т': '𝛕', | |
'у': '𝛄', | |
'ф': '𝛟', | |
'х': '𝘅' | |
}; | |
var russianItalic = {// не хватает: Б,Ж,И,Ц,Ч,Ш,Щ,Ы,Ъ,Э,Ю,Я,г,ж,з,л,м,н,ц,ч,щ,ь,ы,ъ,э,ю,я | |
'А': '𝛢', | |
'В': '𝛣', | |
'Г': '𝛤', | |
'Д': '𝛥', | |
'Е': '𝛦', | |
'Ё': '𝛦', | |
'К': '𝛫', | |
'Л': '𝛬', | |
'М': '𝛭', | |
'Н': '𝛨', | |
'О': '𝛰', | |
'П': '𝛱', | |
'Р': '𝛲', | |
'С': '𝘊', | |
'Т': '𝛵', | |
'У': 'Ꭹ', | |
'Ф': '𝛷', | |
'Х': '𝛸', | |
'а': '𝘢', | |
'б': '𝛿', | |
'в': '𝛽', | |
'д': '𝜕', | |
'е': '𝘦', | |
'ё': '𝘦', | |
'и': 'ⴎ', | |
'к': '𝜅', | |
'о': '𝘰', | |
'п': 'ⴖ', | |
'р': '𝘱', | |
'с': '𝘤', | |
'т': '𝜏', | |
'у': 'ⴘ', | |
'ф': '𝜙', | |
'х': '𝘹', | |
'ш': 'ⴍ' | |
}; | |
var accum = ''; | |
var el = content.firstChild; | |
while (el) { // цикл по всем дочерним элементам | |
switch (el.nodeType) { | |
case 3: // Text Node | |
var text = el.innerText; | |
if (parents & this.masks.U) // Подчеркнутый | |
text = text.replace(/(.)/g, '͟$1'); | |
if (parents & this.masks.S) // Зачеркнутый | |
text = text.replace(/(.)/g, '⃪$1̵'); | |
if (parents & this.masks.D) // Ударение. Ставим только на последний символ. | |
text = text.replace(/(.)$/, '$1́'); | |
// замена английских букв на буквы из блока Mathematical Alphanumeric Symbols | |
if (parents & this.masks.B && parents & this.masks.I) // жирный курсив | |
text = text.replace(/(.)/g, function (char) { | |
if (char >= 'A' && char <= 'Z') | |
return String.fromCodePoint(char.codePointAt(0) + 120315); | |
if (char >= 'a' && char <= 'z') | |
return String.fromCodePoint(char.codePointAt(0) + 120309); | |
if (char >= '0' && char <= '9') | |
return String.fromCodePoint(char.codePointAt(0) + 120734); // просто жирный с засечками | |
return char; | |
}); | |
else if (parents & this.masks.B) // просто жирный | |
text = text.replace(/(.)/g, function (char) { | |
if (char >= 'A' && char <= 'Z') | |
return String.fromCodePoint(char.codePointAt(0) + 120211); | |
if (char >= 'a' && char <= 'z') | |
return String.fromCodePoint(char.codePointAt(0) + 120205); | |
if (char >= '0' && char <= '9') | |
return String.fromCodePoint(char.codePointAt(0) + 120764); | |
if (char >= 'А' && char <= 'я' || char=='Ё' || char=='ё') | |
return russianBold[char] || char; | |
return char; | |
}); | |
else if (parents & this.masks.I) // просто курсив | |
text = text.replace(/(.)/g, function (char) { | |
if (char >= 'A' && char <= 'Z') | |
return String.fromCodePoint(char.codePointAt(0) + 120263); | |
if (char >= 'a' && char <= 'z') | |
return String.fromCodePoint(char.codePointAt(0) + 120257); | |
if (char >= '0' && char <= '9') | |
return String.fromCodePoint(char.codePointAt(0) + 65248); // моноширинный | |
if (char >= 'А' && char <= 'я' || char=='Ё' || char=='ё') | |
return russianItalic[char] || char; | |
return char; | |
}); | |
accum += text; | |
case 1: // Element Node | |
accum += this.process(el,(parents || 0) + this.masks[el.tagName]); // рекурсивная обработка вложенных тегов | |
break; | |
} | |
el = el.nextSibling; | |
} | |
if (content.tagName == 'DIV') // случай первого уровня рекурсии, когда content - поле ввода сообщения. | |
content.innerHTML = accum; // подменяем в нём текст на наш сгенерированный | |
else | |
return accum; // случай обработки внутри какого-то тега | |
} | |
}; | |
if (window.vkopt_ready) vkopt_plugin_run(PLUGIN_ID); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment