diff --git a/following.html b/following.html index aed4a8e..0122525 100644 --- a/following.html +++ b/following.html @@ -276,7 +276,7 @@ diff --git a/home.html b/home.html index f70c372..b9ac963 100644 --- a/home.html +++ b/home.html @@ -370,7 +370,7 @@ diff --git a/js/interface_common.js b/js/interface_common.js index 6f17f22..6d08428 100644 --- a/js/interface_common.js +++ b/js/interface_common.js @@ -1343,6 +1343,8 @@ function initInterfaceCommon() { closeModal(); }); + $('.modal-back').on('click', function() {history.back();}); + $('.prompt-close').on('click', function(e) { e.stopPropagation(); closeModalHandler('.prompt-wrapper'); @@ -1460,6 +1462,9 @@ $(document).ready(function() initInterfaceLogin(); } else if (page.indexOf("network.html") === 0) { initInterfaceNetwork(); + } else if (page.indexOf('options.html') === 0) { + initInterfaceCommon(); + $.Options.initControls(); } else if (page.indexOf("profile-edit.html") === 0) { initProfileEdit(); } diff --git a/js/interface_localization.js b/js/interface_localization.js index 6de0b34..3a75a49 100644 --- a/js/interface_localization.js +++ b/js/interface_localization.js @@ -40,6 +40,8 @@ if(preferredLanguage == "en"){ "Block chain information": "Block chain information", "Block chain is up-to-date, twister is ready to use!": "Block chain is up-to-date, twister is ready to use!", "Block generation": "Block generation ", + "busted_oh": "oh noes!", + "busted_avowal": "I\'m busted trying inject this suspicious stuff here", "Cancel": "Cancel", "Change user": "Change user", "Checking...": "Checking...", // checking if username is available @@ -329,6 +331,8 @@ if(preferredLanguage == "es"){ "Block chain information": "Información de la cadena de bloques", "Block chain is up-to-date, twister is ready to use!": "La cadena de bloques está puesta al día, twister está listo para usar!", "Block generation": "Generación de bloques ", + "busted_oh": "oh noes!", + "busted_avowal": "I\'m busted trying inject this suspicious stuff here", "Cancel": "Cancelar", "Change user": "Cambiar de usuario", "Checking...": "Comprobando ...", // checking if username is available @@ -602,6 +606,8 @@ if(preferredLanguage == "uk"){ "Block chain information": "Інформація про ланцюжок блоків", "Block chain is up-to-date, twister is ready to use!": "Ланцюг блоків оновлено, twister готовий до використання!", "Block generation": "Генерація блоку ", + "busted_oh": "oh noes!", + "busted_avowal": "I\'m busted trying inject this suspicious stuff here", "Cancel": "Відміна", "Change user": "Змінити користувача", "Checking...": "Перевірка...", // checking if username is available @@ -874,6 +880,8 @@ if(preferredLanguage == "zh-CN"){ "Block chain information": "区块链信息", "Block chain is up-to-date, twister is ready to use!": "区块链已经更新,Twister 已经可以使用!", "Block generation": "区块生成器", + "busted_oh": "噢,阻挡!", + "busted_avowal": "系统检测到此用户试图在这里注入恶意代码", "Cancel": "取消", "Change user": "切换用户", "Checking...": "检查中...", // checking if username is available @@ -1108,11 +1116,11 @@ if(preferredLanguage == "zh-CN"){ "Messages": "消息", "Edit profile": "编辑个人简介", "Top Trends": "热门趋势", - "Twistday Reminder": "Twistday Reminder", - "Show upcoming in near future": "Show upcoming in near future", - "Who's celebrating Twistday": "Who's celebrating Twistday", - "Today's luckies:": "Today's luckies:", - "Upcoming ones:": "Upcoming ones:", + "Twistday Reminder": "Twistday周年纪念日提醒", + "Show upcoming in near future": "显示Twistday周年纪念日预告", + "Who's celebrating Twistday": "谁在庆祝自己的Twistday周年纪念日", + "Today's luckies:": "今天的幸运用户:", + "Upcoming ones:": "即将到来的幸运用户:", "twisted again by": "转推由", "undo": "撤销", "Are you sure you want to exit the daemon?\nThe Twister client will stop working.": "你确定要退出后台进程?\nTwister 客户端将停止工作。", @@ -1163,6 +1171,8 @@ if(preferredLanguage == "nl"){ "Block chain information": "Block chain informatie", "Block chain is up-to-date, twister is ready to use!": "Block chain is up-to-date, twister is klaar voor gebruik!", "Block generation": "Block productie", + "busted_oh": "oh noes!", + "busted_avowal": "I\'m busted trying inject this suspicious stuff here", "Cancel": "Annuleren", "Change user": "Gebruiker wijzigen", "Checking...": "Controleren...", // checking if username is available @@ -1436,6 +1446,8 @@ if(preferredLanguage == "it"){ "Block chain information": "Informazioni sulla catena di blocchi", "Block chain is up-to-date, twister is ready to use!": "Catena di blocchi aggiornata, Twister è pronto per l'uso!", "Block generation": "Generatore di blocchi:", + "busted_oh": "oh noes!", + "busted_avowal": "I\'m busted trying inject this suspicious stuff here", "Cancel": "Cancella", "Change user": "Cambia utente", "Checking...": "Controllo in corso...", // checking if username is available @@ -1706,6 +1718,8 @@ if(preferredLanguage == "fr"){ "Block chain information": "Informations à propos de la chaîne de blocs", "Block chain is up-to-date, twister is ready to use!": "La chaîne de blocs est à jour, Twister est maintenant fonctionnel!", "Block generation": "Production de blocs", + "busted_oh": "oh noes!", + "busted_avowal": "I\'m busted trying inject this suspicious stuff here", "Cancel": "Annuler", "Change user": "Changer d'utilisateur", "Checking...": "Vérification...", // checking if username is available @@ -1981,6 +1995,8 @@ if(preferredLanguage == "ru"){ "Block chain information": "Информация цепочки блоков", "Block chain is up-to-date, twister is ready to use!": "Цепочка блоков обновлена, twister готов к использованию!", "Block generation": "Майнинг блоков ", + "busted_oh": "о нет!", + "busted_avowal": "я пойман на попытке вставить этот подозрительный код здесь", "Cancel": "Отмена", "Change user": "Сменить пользователя", "Checking...": "Проверка...", @@ -2259,6 +2275,8 @@ if(preferredLanguage == "de"){ "Block chain information": "Block-Chain Informationen", "Block chain is up-to-date, twister is ready to use!": "Block-Chain ist aktuell, twister ist benutzbar!", "Block generation": "Block-Generierung ", + "busted_oh": "Oh nein!", + "busted_avowal": "Ich bin ertappt, habe versucht, hier Schadcode einzugeben!", "Cancel": "Abbrechen", "Change user": "Benutzer wechseln", "Checking...": "Überprüfe...", // checking if username is available @@ -2533,6 +2551,8 @@ if(preferredLanguage == "ja"){ "Block chain information": "ブロックチェイン", "Block chain is up-to-date, twister is ready to use!": "ブロックチェインは最新の状態です。", "Block generation": "ブロック生成", + "busted_oh": "oh noes!", + "busted_avowal": "I\'m busted trying inject this suspicious stuff here", "Cancel": "キャンセル", "Change user": "ユーザーを変更", "Checking...": "チェック...", // checking if username is available @@ -2804,6 +2824,8 @@ if(preferredLanguage == "pt-BR"){ "Block chain information": "Informações da Cadeia de Blocos", "Block chain is up-to-date, twister is ready to use!": "A Cadeida de Blocos está sincronizada, Twister está pronto para uso!", "Block generation": "Geração de blocos ", + "busted_oh": "oh noes!", + "busted_avowal": "I\'m busted trying inject this suspicious stuff here", "Cancel": "Cancelar", "Change user": "Trocar usuário", "Checking...": "Verificando...", // checking if username is available @@ -3079,6 +3101,8 @@ if(preferredLanguage == "tr"){ "Block chain information": "Blok zincir bilgisi", "Block chain is up-to-date, twister is ready to use!": "Blok zinciri güncel, twister kullanıma hazır!", "Block generation": "Blok üretimi ", + "busted_oh": "oh noes!", + "busted_avowal": "I\'m busted trying inject this suspicious stuff here", "Cancel": "İptal", "Change user": "Kullanıcı değiştir", "Checking...": "Denetleniyor...", // checking if username is available @@ -3351,6 +3375,8 @@ if(preferredLanguage == "cs"){ "Block chain information": "Informace o blockchainu", "Block chain is up-to-date, twister is ready to use!": "Blockchain je aktuální, twister je připraven k použití!", "Block generation": "Generování bloků ", + "busted_oh": "oh noes!", + "busted_avowal": "I\'m busted trying inject this suspicious stuff here", "Cancel": "Zrušit", "Change user": "Změnit uživatele", "Checking...": "Ověřuji...", // checking if username is available diff --git a/js/twister_following.js b/js/twister_following.js index 674a7bd..46c5b90 100644 --- a/js/twister_following.js +++ b/js/twister_following.js @@ -777,7 +777,7 @@ function processSwarmProgressFinal(lastHaves, numPieces) } } } - window.setTimeout("requestSwarmProgress();",2000); + window.setTimeout(requestSwarmProgress, 2000); } function followingChangedUser() { diff --git a/js/twister_formatpost.js b/js/twister_formatpost.js index 24e5870..b7fba95 100644 --- a/js/twister_formatpost.js +++ b/js/twister_formatpost.js @@ -3,6 +3,28 @@ // // Format JSON posts and DMs to HTML. +var _htmlFormatMsgLinkTemplateExternal; +var _htmlFormatMsgLinkTemplateUser; +var _htmlFormatMsgLinkTemplateHashtag; + +$(document).ready(function() { + // we're setting it here for perfomance improvement purpose // to not search and prepare it for for every post every time + _htmlFormatMsgLinkTemplateExternal = $('#external-page-link-template') + if (_htmlFormatMsgLinkTemplateExternal.length) { + _htmlFormatMsgLinkTemplateExternal = _htmlFormatMsgLinkTemplateExternal[0].cloneNode(); + _htmlFormatMsgLinkTemplateExternal.removeAttribute('id'); + } + _htmlFormatMsgLinkTemplateUser = $('#msg-user-link-template') + if (_htmlFormatMsgLinkTemplateUser.length) { + _htmlFormatMsgLinkTemplateUser = _htmlFormatMsgLinkTemplateUser[0].cloneNode(); + _htmlFormatMsgLinkTemplateUser.removeAttribute('id'); + } + _htmlFormatMsgLinkTemplateHashtag = $('#hashtag-link-template') + if (_htmlFormatMsgLinkTemplateHashtag.length) { + _htmlFormatMsgLinkTemplateHashtag = _htmlFormatMsgLinkTemplateHashtag[0].cloneNode(); + _htmlFormatMsgLinkTemplateHashtag.removeAttribute('id'); + } +}); // format "userpost" to html element // kind = "original"/"ancestor"/"descendant" @@ -172,7 +194,7 @@ function dmDataToSnippetItem(dmData, remoteUser) { getGroupChatName( remoteUser, dmItem.find("a.post-info-name") ); else getFullname( remoteUser, dmItem.find("a.post-info-name") ); - dmItem.find(".post-text").html(escapeHtmlEntities(dmData.text)); + dmItem.find(".post-text").html(htmlFormatMsg(dmData.text)); dmItem.find(".post-info-time").text(timeGmtToText(dmData.time)).attr("title",timeSincePost(dmData.time)); return dmItem; @@ -198,7 +220,10 @@ function dmDataToConversationItem(dmData, localUser, remoteUser) { // convert message text to html, featuring @users and links formating. function htmlFormatMsg(msg, mentions) { - function getStrStart(str, startPoint, stopChars, isStopCharMustExist, stopCharsTrailing) { + // TODO: add options for emotions; msg = $.emotions(msg); + // TODO make markup optionally mutable ? + + function getSubStrStart(str, startPoint, stopChars, isStopCharMustExist, stopCharsTrailing) { for (var i = startPoint; i > -1; i--) { if (stopChars.indexOf(str[i]) > -1) break; @@ -215,7 +240,7 @@ function htmlFormatMsg(msg, mentions) { return i; } - function getStrEnd(str, startPoint, stopChars, isStopCharMustExist, stopCharsTrailing) { + function getSubStrEnd(str, startPoint, stopChars, isStopCharMustExist, stopCharsTrailing) { for (var i = startPoint; i < str.length; i++) { if (stopChars.indexOf(str[i]) > -1) break; @@ -232,8 +257,8 @@ function htmlFormatMsg(msg, mentions) { return i; } - function markdown(str, chr, tag) { - function whiteSpace(i, j) { + function markout(msg, chr, tag) { + function isWhiteSpacesBetween(i, j) { j++; for (i += 1; i < j; i++) { if (p[i].w) @@ -243,50 +268,50 @@ function htmlFormatMsg(msg, mentions) { return false; } - var i, j, t, l, r, strEncoded; + var i, j, t, l, r, htmlEntityEncoded; var w = false; var p = []; // collecting chars position data - for (i = 0; i < str.length; i++) { - if (str[i] === chr) { - for (j = i + 1; j < str.length; j++) { - if (str[j] !== chr) + for (i = 0; i < msg.str.length; i++) { + if (msg.str[i] === chr) { + for (j = i + 1; j < msg.str.length; j++) { + if (msg.str[j] !== chr) break; } if (i === 0) { p.push({i: i, k: j - i, t: -1, w: w, a: -1, p: -1}); w = false; - } else if (j === str.length) { + } else if (j === msg.str.length) { p.push({i: i, k: j - i, t: 1, w: w, a: -1, p: -1}); w = false; } else { - if (stopCharsMarkDown.indexOf(str[i - 1]) > -1) { + if (stopCharsMarkout.indexOf(msg.str[i - 1]) > -1) { l = 1; for (t = i - 2; t > -1; t--) { - if (str[t] === chr) { + if (msg.str[t] === chr) { l = -1; break; - } else if (stopCharsMarkDown.indexOf(str[t]) === -1) { - l = whiteSpaces.indexOf(str[t]); + } else if (stopCharsMarkout.indexOf(msg.str[t]) === -1) { + l = whiteSpaces.indexOf(msg.str[t]); break; } } } else - l = whiteSpaces.indexOf(str[i - 1]); - if (stopCharsMarkDown.indexOf(str[j]) > -1) { + l = whiteSpaces.indexOf(msg.str[i - 1]); + if (stopCharsMarkout.indexOf(msg.str[j]) > -1) { r = 1; - for (t = j + 1; t < str.length; t++) { - if (str[t] === chr) { + for (t = j + 1; t < msg.str.length; t++) { + if (msg.str[t] === chr) { r = -1; break; - } else if (stopCharsMarkDown.indexOf(str[t]) === -1) { - r = whiteSpaces.indexOf(str[t]); + } else if (stopCharsMarkout.indexOf(msg.str[t]) === -1) { + r = whiteSpaces.indexOf(msg.str[t]); break; } } } else - r = whiteSpaces.indexOf(str[j]); + r = whiteSpaces.indexOf(msg.str[j]); if (l > -1) { if (r > -1) { if (j - i > 2) { @@ -307,7 +332,7 @@ function htmlFormatMsg(msg, mentions) { w = false; } i = j - 1; - } else if (!w && whiteSpaces.indexOf(str[i]) > -1) { + } else if (!w && whiteSpaces.indexOf(msg.str[i]) > -1) { w = true; } } @@ -317,7 +342,7 @@ function htmlFormatMsg(msg, mentions) { if (p[i].t < 1 && p[i].a === -1) { t = i; for (j = i + 1; j < p.length; j++) { - if (p[i].t === 0 && whiteSpace(i, j)) { + if (p[i].t === 0 && isWhiteSpacesBetween(i, j)) { i = j - 1; break; } else if (p[j].t < 1 && p[j].a === -1) { @@ -335,11 +360,11 @@ function htmlFormatMsg(msg, mentions) { for (i = 0; i < p.length; i++) { if (p[i].t === -1 && p[i].a === -1) { for (j = p[i].p; j > -1; j = p[j].p) { - if (whiteSpace(i, j)) { + if (isWhiteSpacesBetween(i, j)) { i = j - 1; break; } else if (p[j].t === 0 - && !(p[j].p > -1 && p[p[j].p].t === 0 && !whiteSpace(j, p[j].p))) { + && !(p[j].p > -1 && p[p[j].p].t === 0 && !isWhiteSpacesBetween(j, p[j].p))) { p[j].a = i; p[i].a = j; i = j; @@ -359,15 +384,15 @@ function htmlFormatMsg(msg, mentions) { else t = '<' + tag + '>'; j = p[i].a; - t = t + str.slice(p[i].i + p[i].k, p[j].i); + t = t + msg.str.slice(p[i].i + p[i].k, p[j].i); if (p[j].k > 1) t = t + Array(p[i].k).join(chr) + ''; else t = t + ''; - html.push(t.replace(/&(?!lt;|gt;)/g, '&')); - strEncoded = '>' + (html.length - 1).toString() + '<'; - str = str.slice(0, p[i].i) + strEncoded + str.slice(p[j].i + p[j].k); - l = strEncoded.length - p[j].i - p[j].k + p[i].i; + msg.htmlEntities.push(t.replace(/&(?!lt;|gt;)/g, '&')); + htmlEntityEncoded = '>' + (msg.htmlEntities.length - 1).toString() + '<'; + msg.str = msg.str.slice(0, p[i].i) + htmlEntityEncoded + msg.str.slice(p[j].i + p[j].k); + l = htmlEntityEncoded.length - p[j].i - p[j].k + p[i].i; i = j; for (j += 1; j < p.length; j++) p[j].i += l; @@ -379,196 +404,228 @@ function htmlFormatMsg(msg, mentions) { if (p[i].a > -1) { if (p[i].t === -1 || (p[i].t === 0 && p[i].a > i)) { if (p[i].k > 1) - html.push('<' + tag + '>' + Array(p[i].k).join(chr)); + msg.htmlEntities.push('<' + tag + '>' + Array(p[i].k).join(chr)); else - html.push('<' + tag + '>'); + msg.htmlEntities.push('<' + tag + '>'); } else if (p[i].t === 1 || (p[i].t === 0 && p[i].a < i)) { if (p[i].k > 1) - html.push(Array(p[i].k).join(chr) + ''); + msg.htmlEntities.push(Array(p[i].k).join(chr) + ''); else - html.push(''); + msg.htmlEntities.push(''); } - strEncoded = '>' + (html.length - 1).toString() + '<'; - str = str.slice(0, p[i].i) + strEncoded + str.slice(p[i].i + p[i].k); - l = strEncoded.length - p[i].k; + htmlEntityEncoded = '>' + (msg.htmlEntities.length - 1).toString() + '<'; + msg.str = msg.str.slice(0, p[i].i) + htmlEntityEncoded + msg.str.slice(p[i].i + p[i].k); + l = htmlEntityEncoded.length - p[i].k; for (j = i + 1; j < p.length; j++) p[j].i += l; } } } - return str; + return msg; } - function htmlSplitCounter(str) { - html.push('' + str + ''); + function newHtmlEntityLink(template, urlTarget, urlName) { + template.href = urlTarget; + template.innerHTML = urlName; // .innerHTML instead .text to allow markup inside [] of [url name](target) - return '>' + (html.length - 1).toString() + '<'; + return template.outerHTML; } - function unpackHtml(str) { + function msgAddHtmlEntity(msg, strSliceLeft, strSliceRigth, htmlEntity) { + msg.htmlEntities.push(htmlEntity); + var htmlEntityEncoded = '>' + (msg.htmlEntities.length - 1).toString() + '<'; + msg.str = msg.str.slice(0, strSliceLeft) + htmlEntityEncoded + msg.str.slice(strSliceRigth); + msg.i = strSliceLeft + htmlEntityEncoded.length - 1; + + return msg; + } + + function applyHtml(msg) { var t; - for (var i = 0; i < str.length - 2; i++) { - if (str[i] === '>') { - for (var j = i + 2; j < str.length; j++) { - if (str[j] === '<') + for (var i = 0; i < msg.str.length - 2; i++) { + if (msg.str[i] === '>') { + for (var j = i + 2; j < msg.str.length; j++) { + if (msg.str[j] === '<') break; } - t = html[parseInt(str.slice(i + 1, j))]; - str = str.slice(0, i) + t + str.slice(j + 1); + t = msg.htmlEntities[parseInt(msg.str.slice(i + 1, j))]; + msg.str = msg.str.slice(0, i) + t + msg.str.slice(j + 1); i = i + t.length - 1; } } - return str; + return msg.str; } var mentionsChars = 'abcdefghijklmnopqrstuvwxyz_0123456789'; - var stopCharsTrailing = '/\\*~_-`.,:;?!%\'"[](){}^|«»…\u201C\u201D\u2026\u2014\u4E00\u3002\uFF0C\uFF1A\uFF1F\uFF01\u3010\u3011'; + var stopCharsTrailing = '/\\*~_-`.,:;?!%\'"[](){}^|«»…\u201C\u201D\u2026\u2014\u4E00\u3002\uFF0C\uFF1A\uFF1F\uFF01\u3010\u3011\u2047\u2048\u2049'; var stopCharsTrailingUrl = stopCharsTrailing.slice(1); var whiteSpaces = ' \f\n\r\t\v​\u00A0\u1680\u180E\u2000​\u2001\u2002​\u2003\u2004\u2005\u2006​\u2007\u2008​\u2009\u200A\u2028\u2029​\u202F\u205F\u3000'; + var whiteSpacesUrl = '\'\"' + whiteSpaces; var stopCharsLeft = '<' + whiteSpaces; var stopCharsRight = '>' + whiteSpaces; - var stopCharsRightHashtags = '>/\\.,:;?!%\'"[](){}^|«»…\u201C\u201D\u2026\u2014\u4E00\u3002\uFF0C\uFF1A\uFF1F\uFF01\u3010\u3011' // same as stopCharsTrailing but without '*~_-`' plus '>' + var stopCharsRightHashtags = '>/\\.,:;?!%\'"[](){}^|«»…\u201C\u201D\u2026\u2014\u4E00\u3002\uFF0C\uFF1A\uFF1F\uFF01\u3010\u3011\u2047\u2048\u2049' // same as stopCharsTrailing but without '*~_-`' plus '>' + whiteSpaces; - var stopCharsMarkDown = '/\\*~_-`.,:;?!%+=&\'"[](){}^|«»…\u201C\u201D\u2026\u2014\u4E00\u3002\uFF0C\uFF1A\uFF1F\uFF01\u3010\u3011'; - var i, j, k, str, strEncoded; - var html = []; - - msg = markdown(escapeHtmlEntities(msg), - '`', 'samp'); // kind of monospace, sequence of chars inside will be escaped from markup - for (i = 0; i < msg.length - 7; i++) { - var htmlPiece = undefined; - var msgSliceIdx; - if (msg.slice(i, i + 2) === '](') { - // FIXME there can be text with [] inside [] or links with () wee need to handle it too - j = getStrStart(msg, i - 1, '[', true, ''); - if (j < i) { - k = getStrEnd(msg, i + 2, ')', true, ''); - if (k > i + 1) { - var a = $('#external-page-link-template')[0].cloneNode(); - a.href = proxyURL(msg.slice(i + 2, k + 1)); - a.text = msg.slice(j, i); - htmlPiece = a.outerHTML; - msgSliceIdx = [j - 1, k + 2]; + var stopCharsMarkout = '/\\*~_-`.,:;?!%+=&\'"[](){}^|«»…\u201C\u201D\u2026\u2014\u4E00\u3002\uFF0C\uFF1A\uFF1F\uFF01\u3010\u3011\u2047\u2048\u2049'; + var i, j, k, str; + + msg = {str: escapeHtmlEntities(msg), htmlEntities: []}; + + msg = markout(msg, '`', 'samp'); // tag is kind of monospace, here sequence of chars inside it will be escaped from markup + + // handling links + for (i = 0; i < msg.str.length - 7; i++) { + if (msg.str.slice(i, i + 2) === '](') { + // FIXME there can be text with [] inside [] or links with () we need to handle it too + j = getSubStrStart(msg.str, i - 2, '[', true, ''); + if (j < i - 1) { + k = getSubStrEnd(msg.str, i + 3, ')', true, whiteSpaces); + if (k > i + 2) { + var linkName = msg.str.slice(j, i); // name of possiible link + for (i += 2; i < k; i++) { + if (whiteSpacesUrl.indexOf(msg.str[i]) === -1) // drop whitespaces and ' and " // apostrophes and quotes to prevent injection of js events + break; + } + if (i < k) { + var x = getSubStrEnd(msg.str, i, ':', false, '') + 1; + // following check is NOT for real protection (we have blocking CSP rule instead), it's just to aware people + if (msg.str[i] === '#' || (x > i && x < k && (msg.str.slice(x - 6, x).toLowerCase() === 'script' // other things would be added when W3C and all the people invent it + || msg.str.slice(x - 4, x).toLowerCase() === 'data'))) { + msg = msgAddHtmlEntity(msg, j - 1, getSubStrEnd(msg.str, k + 1, ')', true, '') + 2, + '…
' + polyglot.t('busted_oh') + ' ' + + polyglot.t('busted_avowal') + ':
' + + msg.str.slice(i, k + 1) + .replace(/&(?!lt;|gt;)/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + + '
' + ); + } else { + if (getSubStrEnd(msg.str, i + 1, whiteSpacesUrl, false, '') < k) // use only first word as href target, others drop silently + k = getSubStrEnd(msg.str, i + 1, whiteSpacesUrl, false, ''); + msg = msgAddHtmlEntity(msg, j - 1, getSubStrEnd(msg.str, k + 1, ')', true, '') + 2, + newHtmlEntityLink(_htmlFormatMsgLinkTemplateExternal, + proxyURL(msg.str.slice(i, k + 1)), + applyHtml( // we're trying markup inside [] of []() + markout(markout(markout(markout( + {str: linkName, htmlEntities: msg.htmlEntities}, + '*', 'b'), // bold + '~', 'i'), // italic + '_', 'u'), // underlined + '-', 's') // striketrough + ) + .replace(/&(?!lt;|gt;)/g, '&') + ) + ); + } + i = msg.i + 1; + } } } - } else if (msg.slice(i, i + 4).toLowerCase() === 'http') { - if (msg.slice(i + 4, i + 7) === '://' && stopCharsRight.indexOf(msg[i + 7]) === -1) { - j = getStrEnd(msg, i + 7, stopCharsRight, false, stopCharsTrailingUrl); + } else if (msg.str.slice(i, i + 4).toLowerCase() === 'http') { + if (msg.str.slice(i + 4, i + 7) === '://' && stopCharsRight.indexOf(msg.str[i + 7]) === -1) { + j = getSubStrEnd(msg.str, i + 7, stopCharsRight, false, stopCharsTrailingUrl); if (j > i + 6) { - str = msg.slice(i, j + 1); - // FIXME we're trying to not interact with DOM, coz' we want to run really fast [to hell of RegExps] - // FIXME actually we should avoid it by dropping a template idea and construct html right here - htmlPiece = $('#external-page-link-template')[0].outerHTML - .replace(/\bid\s*=\s*"[^]*?"+/ig, '') // $().removeAttr('id') - //.replace(/\bhref\s*=\s*"[^]*?"+/ig, '') // $().removeAttr('href') - .replace(/)[^]*?(<\/a>)/ig, '$1' + str + '$2') // $().closest('a').text(url) - ; - msgSliceIdx = [i, i + str.length]; + str = msg.str.slice(i, j + 1); + msg = msgAddHtmlEntity(msg, i, i + str.length, + newHtmlEntityLink(_htmlFormatMsgLinkTemplateExternal, + proxyURL(str), str) + ); + i = msg.i; } - } else if (msg.slice(i + 4, i + 8).toLowerCase() === 's://' && stopCharsRight.indexOf(msg[i + 8]) === -1) { - j = getStrEnd(msg, i + 8, stopCharsRight, false, stopCharsTrailingUrl); + } else if (msg.str.slice(i + 4, i + 8).toLowerCase() === 's://' && stopCharsRight.indexOf(msg.str[i + 8]) === -1) { + j = getSubStrEnd(msg.str, i + 8, stopCharsRight, false, stopCharsTrailingUrl); if (j > i + 7) { - str = msg.slice(i, j + 1); - htmlPiece = $('#external-page-link-template')[0].outerHTML - .replace(/\bid\s*=\s*"[^]*?"+/ig, '') // $().removeAttr('id') - //.replace(/\bhref\s*=\s*"[^]*?"+/ig, '') // $().removeAttr('href') - .replace(/)[^]*?(<\/a>)/ig, '$1' + str + '$2') // $().closest('a').text(url) - ; - msgSliceIdx = [i, i + str.length]; + str = msg.str.slice(i, j + 1); + msg = msgAddHtmlEntity(msg, i, i + str.length, + newHtmlEntityLink(_htmlFormatMsgLinkTemplateExternal, + proxyURL(str), str) + ); + i = msg.i; } } } - if (htmlPiece) { - html.push(htmlPiece) - strEncoded = '>' + (html.length - 1).toString() + '<'; - msg = msg.slice(0, msgSliceIdx[0]) + strEncoded + msg.slice(msgSliceIdx[1]); - i = i + strEncoded.length - 1; - } } - for (i = 1; i < msg.length - 1; i++) { - if (msg[i] === '@' && stopCharsLeft.indexOf(msg[i - 1]) === -1 - && stopCharsTrailing.indexOf(msg[i - 1]) === -1 && stopCharsRight.indexOf(msg[i + 1]) === -1) { - j = getStrStart(msg, i - 1, stopCharsLeft, false, stopCharsTrailing); + // handling mails + for (i = 1; i < msg.str.length - 1; i++) { + if (msg.str[i] === '@' && stopCharsLeft.indexOf(msg.str[i - 1]) === -1 + && stopCharsTrailing.indexOf(msg.str[i - 1]) === -1 && stopCharsRight.indexOf(msg.str[i + 1]) === -1) { + j = getSubStrStart(msg.str, i - 1, stopCharsLeft, false, stopCharsTrailing); if (j < i) { - k = getStrEnd(msg, i + 1, stopCharsRight, false, stopCharsTrailing); + k = getSubStrEnd(msg.str, i + 1, stopCharsRight, false, stopCharsTrailing); if (k > i) { - str = msg.slice(j, k + 1); - html.push($('#external-page-link-template')[0].outerHTML - .replace(/\bid\s*=\s*"[^]*?"+/ig, '') // $().removeAttr('id') - //.replace(/\bhref\s*=\s*"[^]*?"+/ig, '') // $().removeAttr('href') - .replace(/)[^]*?(<\/a>)/ig, '$1' + str + '$2') // $().closest('a').text(url) + str = msg.str.slice(j, k + 1); + msg = msgAddHtmlEntity(msg, j, j + str.length, + newHtmlEntityLink(_htmlFormatMsgLinkTemplateExternal, + 'mailto:' + str.toLowerCase(), str) ); - strEncoded = '>' + (html.length - 1).toString() + '<'; - msg = msg.slice(0, j) + strEncoded + msg.slice(j + str.length); - i = j + strEncoded.length - 1; + i = msg.i; } } } } - for (i = 0; i < msg.length - 1; i++) { - if (msg[i] === '@' && mentionsChars.indexOf(msg[i + 1].toLowerCase()) > -1) { - for (j = i + 2; j < msg.length; j++) { - if (mentionsChars.indexOf(msg[j].toLowerCase()) === -1) + // handling mentions + for (i = 0; i < msg.str.length - 1; i++) { + if (msg.str[i] === '@' && mentionsChars.indexOf(msg.str[i + 1].toLowerCase()) > -1) { + for (j = i + 2; j < msg.str.length; j++) { + if (mentionsChars.indexOf(msg.str[j].toLowerCase()) === -1) break; } - str = msg.slice(i + 1, j).toLowerCase(); + str = msg.str.slice(i + 1, j).toLowerCase(); mentions.push(str); // FIXME - html.push($('#msg-user-link-template')[0].outerHTML - .replace(/\bid\s*=\s*"[^]*?"+/ig, '') // $().removeAttr('id') - //.replace(/\bhref\s*=\s*"[^]*?"+/ig, '') // $().removeAttr('href') - .replace(/]*?\bclass\s*=\s*"(?=[^"]*?\bopen-profile-modal\b))/ig, ']*?\bclass\s*=\s*"(?=[^"]*?\bopen-profile-modal\b))[^]*?>)[^]*?(<\/a>)/ig, '$1@' + str + '$2') // $().closest('a.open-profile-modal').text('@'+username) + msg = msgAddHtmlEntity(msg, i, i + str.length + 1, + newHtmlEntityLink(_htmlFormatMsgLinkTemplateUser, + $.MAL.userUrl(str), '@' + str) ); - strEncoded = '>' + (html.length - 1).toString() + '<'; - msg = msg.slice(0, i) + strEncoded + msg.slice(i + str.length + 1); - i = i + strEncoded.length - 1; + i = msg.i; } } - for (i = 0; i < msg.length - 1; i++) { - if (msg[i] === '#' && msg[i + 1] !== '#' && stopCharsRight.indexOf(msg[i + 1]) === -1) { - j = getStrEnd(msg, i + 1, stopCharsRightHashtags, false, stopCharsTrailing); + // handling hashtags + for (i = 0; i < msg.str.length - 1; i++) { + if (msg.str[i] === '#' && msg.str[i + 1] !== '#' && stopCharsRight.indexOf(msg.str[i + 1]) === -1) { + j = getSubStrEnd(msg.str, i + 1, stopCharsRightHashtags, false, stopCharsTrailing); if (j > i) { - str = msg.slice(i + 1, j + 1); - html.push($('#hashtag-link-template')[0].outerHTML - .replace(/\bid\s*=\s*"[^]*?"+/ig, '') // $().removeAttr('id') - //.replace(/\bhref\s*=\s*"[^]*?"+/ig, '') // $().removeAttr('href') - .replace(/]*?\bclass\s*=\s*"(?=[^"]*?\bopen-hashtag-modal\b))/ig, ']*?\bclass\s*=\s*"(?=[^"]*?\bopen-hashtag-modal\b))[^]*?>)[^]*?(<\/a>)/ig, '$1#' + str.replace(/&/g, '&') + '$2') // $().closest('a.open-profile-modal').text('#'+hashtag) + str = msg.str.slice(i + 1, j + 1); + msg = msgAddHtmlEntity(msg, i, i + str.length + 1, + newHtmlEntityLink(_htmlFormatMsgLinkTemplateHashtag, + $.MAL.hashtagUrl(encodeURIComponent(str.toLowerCase())), '#' + str.replace(/&/g, '&')) ); - strEncoded = '>' + (html.length - 1).toString() + '<'; - msg = msg.slice(0, i) + strEncoded + msg.slice(i + str.length + 1); - i = i + strEncoded.length - 1; + i = msg.i; } } } - msg = unpackHtml( - markdown(markdown(markdown(markdown(msg, + // handling text style markup + msg = markout(markout(markout(markout(msg, '*', 'b'), // bold '~', 'i'), // italic '_', 'u'), // underlined '-', 's') // striketrough - .replace(/\(\d{1,2}\/\d{1,2}\)$/, htmlSplitCounter) + ; + + // handling splitted posts numbering and escaping ampersands, qoutes and apostrophes + msg.str = msg.str + .replace(/\(\d{1,2}\/\d{1,2}\)$/, function (str) { + msg.htmlEntities.push('' + str + ''); // FIXME + + return '>' + (msg.htmlEntities.length - 1).toString() + '<'; + }) .replace(/&(?!lt;|gt;)/g, '&') // FIXME in many cases there is no need to escape ampersand in HTML 5 .replace(/"/g, '"') .replace(/'/g, ''') - ); + // applying html entities to msg.str and converting msg to string back + msg = applyHtml(msg); + + // handling linebreaks if ($.Options.displayLineFeeds.val === 'enable') msg = msg.replace(/\n/g, '
'); - // TODO: add options for emotions; msg = $.emotions(msg); - // TODO make markdown optionally mutable ? - return msg; } @@ -604,4 +661,3 @@ function reverseHtmlEntities(str) { .replace(/'/g, "'") .replace(/&/g, '&'); } - diff --git a/options.html b/options.html index 13e8f92..494e0bb 100644 --- a/options.html +++ b/options.html @@ -20,14 +20,6 @@ - -