// ==UserScript== // @name U2实时预览BBCODE // @namespace https://u2.dmhy.org/ // @version 0.4.6 // @description 实时预览BBCODE // @author kysdm // @grant none // @match *://u2.dmhy.org/* // @exclude *://u2.dmhy.org/shoutbox.php* // @icon https://u2.dmhy.org/favicon.ico // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/localforage/1.10.0/localforage.min.js // @license Apache-2.0 // @downloadURL none // ==/UserScript== /* 本脚本基于 Bamboo Green 界面风格进行修改 为什么会有近似功能的函数呢,问就是历史原因 等不能跑的时候再动祖传代码 /* /* GreasyFork 地址 https://greasyfork.org/zh-CN/scripts/426268 */ /* 更新日志 https://github.com/kysdm/u2_share/commits/main/u2share_bbcode.user.js */ /* 无法显示的 Tag Flash 有关的 Tag 我不知道的特殊操作 */ /* 与U2娘显示不同的标签 (非标准操作) U2允许未封闭标签,此脚本不接受此操作。 */ 'use strict'; // 声明全局变量 var lang = new lang_init($('#locale_selection').val());; // CSS $('body').append(``); // JS $('body').append(``); // 现存BBCODE元素 (async () => { if ($('.bbcode').length === 0) return; // 判断页面是否存在 bbcode 输入框 new init(); const url = location.href.match(/u2\.dmhy\.org\/(upload|forums|comment|contactstaff|sendmessage)\.php/i) || ['', '']; await syncScroll('#bbcodejs_tbody', url[1], '.bbcode', '#bbcode2'); if (url[1] === 'upload') { await autoSaveUpload(); } else { await autoSaveMessage('#bbcodejs_tbody', '.bbcode', '#qr', url[1], '#compose'); } $('.bbcode').parents("tr:eq(1)").after('' + lang['preview'] + '
' + '
' + '
' + await bbcode2html($('.bbcode').val()) + '
'); syncWindowChange('.bbcode', '#bbcode2'); $('.bbcode').bind('input propertychange', async function updateValue() { let html = await bbcode2html($(this).val()); $('#bbcode2').children('.child').html(html); }); $('.codebuttons').click(async function updateValue() { let html = await bbcode2html($('.bbcode').val()); $('#bbcode2').children('.child').html(html); }); $("td.embedded.smile-icon a").click(async function updateValue() { await sleep(0); let html = await bbcode2html($('.bbcode').val()); $('#bbcode2').children('.child').html(html); }); if (/u2\.dmhy\.org\/upload\.php/i.test(location.href)) { // 添加中括号 function add_brackets(txt) { if (txt === '') { return ''; } else { return '[' + txt + ']'; } }; // 检查重叠的中括号 function check_title(txt) { if (/\[{2,}|\]{2,}/g.test(txt)) { return '' + txt + ''; } else { return txt; } }; var main_title = '' + lang['select_type'] + ''; function add_main_title() { var type_id = $('#browsecat').val(); if (type_id === '0') { // console.log('请选择分类...'); main_title = '' + lang['select_type'] + ''; } else if (['9', '411', '413', '12', '13', '14', '15', '16', '17', '410', '412'].indexOf(type_id) !== -1) { // console.log('分类ID是: ' + type_id + ' anime'); main_title = '' + add_brackets($('#anime_chinese-input').val()) + add_brackets($('#anime_english-input').val()) + add_brackets($('#anime_original-input').val()) + add_brackets($('#anime_source-input').val()) + add_brackets($('#anime_resolution-input').val()) + add_brackets($('#anime_episode-input').val()) + add_brackets($('#anime_container-input').val()) + add_brackets($('#anime_extra-input').val()) + ''; } else if (['21', '22', '23'].indexOf(type_id) !== -1) { // console.log('分类ID是: ' + type_id + ' manga'); main_title = '' + add_brackets($('#manga_title-input').val()) + add_brackets($('#manga_author-input').val()) + add_brackets($('#manga_volume-input').val()) + add_brackets($('#manga_ended').find("select").val()) + add_brackets($('#manga_publisher-input').val()) + add_brackets($('#manga_remark-input').val()) + ''; } else if (type_id === '30') { // console.log('分类ID是: ' + type_id + ' music'); var prefix_1 = $('#music_prefix').find("select").val(); var prefix_2 = $('#music_collection').find("select").val(); if (['EAC', 'XLD'].indexOf(prefix_1) !== -1) { var music_quality = false; } else if (['Hi-Res', 'Web'].indexOf(prefix_1) !== -1) { var music_quality = true; }; switch (prefix_2) { case "0": // 单张 main_title = '' + add_brackets(prefix_1) + add_brackets($('#music_date-input').val()) + add_brackets($('#music_category-input').val()) + add_brackets($('#music_artist-input').val()) + add_brackets($('#music_title-input').val()) + add_brackets($('#music_serial_number-input').val()) + add_brackets((() => { if (music_quality) { return $('#music_quality-input').val(); } else { return ''; } })()) + add_brackets($('#music_format-input').val()) + ''; break; case "1": // 合集 main_title = '' + add_brackets(prefix_1) + add_brackets('合集') + add_brackets($('#music_category-input').val()) + add_brackets($('#music_title-input').val()) + add_brackets($('#music_quantity-input').val()) + add_brackets((() => { if (music_quality) { return $('#music_quality-input').val(); } else { return ''; } })()) + ''; break; } } else if (type_id === '40') { // console.log('分类ID是: ' + type_id + ' other'); main_title = '' + $('#other_title-input').val() + ''; } else { // console.log('分类ID是: ' + type_id); } $('#checktitle').html(check_title(main_title)); } $("#browsecat").change(() => { new add_main_title; }) $(".torrent-info-input").bind('input propertychange', () => { new add_main_title; }); $('#other_title').after('' + lang['main_title'] + '' + '' + main_title + '' ); }; function init() { var h1 = $('.codebuttons').eq(6).parent().html(); var h2 = $('.codebuttons').eq(7).parent().html(); var h3 = $('.codebuttons').eq(8).parent().html(); $('.codebuttons').eq(8).parent().remove(); $('.codebuttons').eq(7).parent().remove(); $('.codebuttons').eq(6).parent().remove(); $('.codebuttons').eq(2).parent().after(''); $('.codebuttons').eq(5).parent() .after('') .after('') .after('') .after(''); // $('.codebuttons').eq(10).attr("onclick", "onEditorActionS('descr','EDITOR_QUOTE')"); $('.codebuttons').eq(10).parent() .after('') .after('') .after('') .after('') .after(''); $('.codebuttons').eq(4) .attr("onclick", "onEditorActionS('descr','EDITOR_URL')") .parent().after('' ); $('.codebuttons').parents('table').eq(0).after('
'); $('#bbcodejs_tbody').append('
' + h1 + h2 + h3 + '
'); const margin = $('.codebuttons').parents('tbody').eq(0).width() - $("#bbcodejs_select").width() - 2.6; $("#bbcodejs_select").css("margin-left", margin + "px"); $('body').append( '' ); } })(); async function sleep(interval) { return new Promise(resolve => { setTimeout(resolve, interval); }) }; async function bbcode2html(bbcodestr) { const f_reg = new RegExp("^\"?\"?$|^(?:")?(?:")?$"); var tempCode = new Array(); var tempCodeCount = 0; function addTempCode(value) { tempCode[tempCodeCount] = value; let returnstr = ""; tempCodeCount++; return returnstr; } const escape_reg = new RegExp("[&\"\'<>]", "g"); bbcodestr = bbcodestr.replace(escape_reg, function (s, x) { switch (s) { case '&': return '&'; case '"': return '"'; case "'": return '''; case '<': return '<'; case '>': return '>'; default: return s; } }); bbcodestr = bbcodestr.replace(/\r\n/g, () => { return '
' }); bbcodestr = bbcodestr.replace(/\n/g, () => { return '
' }); bbcodestr = bbcodestr.replace(/\r/g, () => { return '
' }); // info/code 标签 const info_reg = new RegExp("\\[(mediainfo|info|code)\\](.+?)\\[\\/(\\1)\\]", "gis"); bbcodestr = bbcodestr.replace(info_reg, function (s, x, y) { switch (x) { case 'info': return addTempCode('
' + lang['info'] + '' + y + '
'); case 'mediainfo': return addTempCode('
' + lang['mediainfo'] + '' + y + '
'); case 'code': return addTempCode(`
${lang['code']}
${y}

`); default: return s; } }); // 超链接 (绝对) bbcodestr = bbcodestr.replace(/\[url=((?:https?|ftp|gopher|news|telnet|mms|rtsp):\/\/((?!<|>|\s|"|>|'|<|\(|\)|\[|\]).)+)\](.+?)\[\/url\]/gis, function (s, x, y, z) { return addTempCode('' + z + ''); }); bbcodestr = bbcodestr.replace(/\[url\]((?:https?|ftp|gopher|news|telnet|mms|rtsp):\/\/((?!<|>|\s|"|>|'|<|\(|\)|\[|\]).)+)\[\/url\]/gis, function (s, x) { return addTempCode('' + x + '') }); // 超链接 (相对) bbcodestr = bbcodestr.replace(/\[url=(((?!<|>|\s|"|>|'|<|\(|\)|\[|\]).)+)\](.+?)\[\/url\]/gis, function (s, x, y, z) { return addTempCode('' + z + ''); }); bbcodestr = bbcodestr.replace(/\[url\](((?!<|>|\s|"|>|'|<|\(|\)|\[|\]).)+)\[\/url\]/gis, function (s, x) { return addTempCode('' + x + '') }); // 单个标签 不带参 const o_reg = new RegExp("\\[(\\*|siteurl|site)\\]", "gi"); bbcodestr = bbcodestr.replace(o_reg, function (s, x, y) { switch (x) { case '*': return 'list'; case 'site': return 'U2分享園@動漫花園'; case 'siteurl': return 'https://u2.dmhy.org'; default: return s; } }); // 成对标签 带参 const d_reg = new RegExp("\\[(rt|font)=([^\\]]+)\\](.*?)\\[(/\\1)\\]", "gis"); while (d_reg.test(bbcodestr)) { bbcodestr = bbcodestr.replace(d_reg, function (s, w, x, y, z) { switch (w) { case 'rt': if (f_reg.test(x)) { return '[' + addTempCode('p3F#oW2@cEn_JHstp-&37DgD' + w) + '=' + x + ']' + y + '[' + addTempCode('p3F#oW2@cEn_JHstp-&37DgD' + z) + ']' } else { return addTempCode('' + y + '(' + x.replace(/^(?:")?(.*?)(?:")?$/, "$1") + ')'); } case 'font': if (f_reg.test(x)) { return '[' + addTempCode('p3F#oW2@cEn_JHstp-&37DgD' + w) + '=' + x + ']' + y + '[' + addTempCode('p3F#oW2@cEn_JHstp-&37DgD' + z) + ']'; } else { return '' + y + ''; } default: return s; } }) }; // 成对标签 不带参 const a_reg = new RegExp("\\[(pre|b|i|u|s)\\](.*?)\\[/(\\1)\\]", "gs"); while (a_reg.test(bbcodestr)) { bbcodestr = bbcodestr.replace(a_reg, function (s, x, y, z) { switch (x) { case 'b': return '' + y + ''; case 'i': return '' + y + ''; case 'u': return '' + y + ''; case 's': return '' + y + ''; case 'pre': return '
' + y + '
'; default: return s; } }) }; // 颜色 const color_reg = new RegExp("\\[color=(?:")?([#0-9a-z]{1,15}|[a-z]+?)(?:")?\\](.*?)\\[/color\\]", "gis"); while (color_reg.test(bbcodestr)) { bbcodestr = bbcodestr.replace(color_reg, function (s, x, y) { return '' + y + ''; }) }; // 文字大小 const size_reg = new RegExp("\\[size=(?:")?([1-7])(?:")?\\](.*?)\\[/size\\]", "gis"); while (size_reg.test(bbcodestr)) { bbcodestr = bbcodestr.replace(size_reg, function (s, x, y) { return '' + y + ''; }) }; // 图片 bbcodestr = bbcodestr.replace(/\[(img|imglnk)\]([^\]]+)\[\/(?:\1)\]/gi, function (s, x, y) { if (/^https?:\/\/((?!<|>|"|>|'|<|;|\(|\)|\[|\]).)+$/i.test(y)) { switch (x) { case 'img': return addTempCode('image'); case 'imglnk': return addTempCode('image'); } } else { return addTempCode(s); } }); bbcodestr = bbcodestr.replace(/\[img=([^\]]+)\]/gi, function (s, x) { if (/^https?:\/\/((?!<|>|"|>|'|<|;|\(|\)|\[|\]).)+$/i.test(x)) { return addTempCode('image'); } else { return addTempCode(s); } }); // 没有bbcode包裹的超链接 bbcodestr = bbcodestr.replace(/((?:https?|ftp|gopher|news|telnet|mms|rtsp):\/\/((?!<|>|\s|"|>|'|<|\(|\)|\[|\]).)+)/gi, function (s, x) { return '' + s + ''; }); // 引用 const quote_reg1 = new RegExp("\\[quote\\](.*?)\\[/quote\\]", "gsi"); while (quote_reg1.test(bbcodestr)) { bbcodestr = bbcodestr.replace(quote_reg1, function (s, x) { return '
' + lang['quote'] + '' + x + '
'; }); }; const quote_reg2 = new RegExp("\\[quote=([^\\[\\]]*)\\](.*?)\\[/quote\\]", "gsi"); while (quote_reg2.test(bbcodestr)) { bbcodestr = bbcodestr.replace(quote_reg2, function (s, x, y) { if (f_reg.test(x)) { return '
' + lang['quote'] + '' + y + '
'; } else { return '
' + lang['quote'] + ': ' + x.replace(/^(?:")?(.*?)(?:")?$/, "$1") + '' + y + '
'; } }); }; // spoiler const spoiler_reg1 = new RegExp("\\[spoiler\\](.*?)\\[/spoiler\\]", "gsi"); const spoiler_reg2 = new RegExp("\\[spoiler=([^\\]]+)\\](.*?)\\[/spoiler\\]", "gsi"); while (spoiler_reg1.test(bbcodestr)) { bbcodestr = bbcodestr.replace(spoiler_reg1, function (s, x) { return '
' + lang['spoiler'] + '  ' + '' + '' + '
' + x + '
'; }); }; while (spoiler_reg2.test(bbcodestr)) { bbcodestr = bbcodestr.replace(spoiler_reg2, function (s, x, y) { if (f_reg.test(x)) { return '
' + lang['spoiler'] + '  ' + '' + '' + '
' + y + '
'; } else { return '
' + x.replace(/^(?:")?(.*?)(?:")?$/, "$1") + '  ' + '' + '' + '
' + y + '
'; } }); }; // 表情 const em_reg = new RegExp("\\[(em[1-9][0-9]*)\\]", "gi"); bbcodestr = bbcodestr.replace(em_reg, function (s, x) { switch (x) { case (x.match(/^em[1-9][0-9]*/i) || {}).input: return '[' + x + ']'; default: return s; }; }); // 附件 let db = localforage.createInstance({ name: "attachmap" }); bbcodestr = await replaceAsync(bbcodestr, /\[attach\](?\w{32})\[\/attach\]/gi, async (...args) => { const { hash } = args.slice(-1)[0]; return await db.getItem(hash).then(async (value) => { if (value !== null) { // console.log('数据已存在'); if (value.attach_type === 'img') { return `${value.attach_name}` } else if (value.attach_type === 'other') { return '
' + `other  ` + `${value.attach_name}` + '  ' + `(${value.attach_size})` + '
' } else if (value.attach_type === 'invalid') { // 会不会发生碰撞呢 xd return `
附件 ${args[1]} 无效。
`; }; } else { // console.log('数据不存在'); return await new Promise((resolve, reject) => { $.ajax({ type: 'post', url: 'https://u2.dmhy.org/preview.php', contentType: "application/x-www-form-urlencoded", data: ({ "body": `[attach]${hash}[/attach]` }), success: async function (d) { // console.log('成功'); let htmlobj = $.parseHTML(d); let span = $(htmlobj).find('span'); let attach_normal = $(span).children('bdo').children('div.attach'); // 普通附件 let attach_image = $(span).children('bdo').children('img'); // 图片附件 if (attach_normal.length !== 0 && attach_image.length === 0) { // console.log('普通附件'); // console.log(attach_normal); let attach_info_obj = /(?