您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Fix broken BBCode on the All Night Laundry comic
// ==UserScript== // @name All Night BBCode // @version 0.4 // @description Fix broken BBCode on the All Night Laundry comic // @author AjaxGb // @match http*://www.all-night-laundry.com/post/* // @icon http://www.all-night-laundry.com/static/favicon.ico // @grant GM_addStyle // @namespace https://greasyfork.org/users/85711 // ==/UserScript== (function() { 'use strict'; GM_addStyle('.ui-widget-content .quote { border-color: rgb(210, 210, 210); }'); const origMSPAFontSizePx = 13; const decoder = new TextDecoder('utf-8'); const u8arrays = { 2: new Uint8Array(2), 3: new Uint8Array(3), }; function walkNodes(walker, {addToNode, addToName}) { for (let node = walker.currentNode; node;) { let newAddTo = null; switch (node.nodeType) { case Node.ELEMENT_NODE: { if (walker.firstChild()) { walkNodes(walker, {}); walker.parentNode(); } break; } case Node.TEXT_NODE: { node.data = node.data.replace(/[\xc0-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}/g, text => { const array = u8arrays[text.length]; for (let i = text.length - 1; i >= 0; i--) { array[i] = text.codePointAt(i); } return decoder.decode(array); }); const tagMatch = node.data.match(/\[strike\]|\[size=(\d+)\]|\[quote=([^;\]]+);\d+\]|\[\/(strike|size|quote)\]/i); if (tagMatch) { const [tagTextI, sizePxText, quoteName, endTagI] = tagMatch; const tagTextNode = node.splitText(tagMatch.index); const nextTextNode = tagTextNode.splitText(tagTextI.length); // node tagTextNode nextTextNode // "blah" "[tag]" "blah" if (endTagI) { const endTag = endTagI.toLowerCase(); if (addToName !== endTag) { throw new Error(`Closed [${endTag}] tag when no such tag available`); } tagTextNode.replaceWith(nextTextNode); if (addToNode) { addToNode.append(node); } return; } else { const tagText = tagTextI.toLowerCase(); let walkArgs; if (tagText.startsWith('[strike')) { const strike = document.createElement('s'); tagTextNode.replaceWith(strike); walkArgs = {addToNode: strike, addToName: 'strike'}; } else if (tagText.startsWith('[size=')) { const sizePx = parseInt(sizePxText); const span = document.createElement('span'); const currFontSize = tagTextNode.parentElement.computedStyleMap().get('font-size'); if (currFontSize.unit !== 'px') { throw new Error('computedStyleMap() font-size was not px: '+currFontSize.unit); } span.style.fontSize = `${Math.round(currFontSize.value * sizePx / origMSPAFontSizePx)}px`; tagTextNode.replaceWith(span); walkArgs = {addToNode: span, addToName: 'size'}; } else if (tagText.startsWith('[quote=')) { const quoteBlock = document.createElement('div'); quoteBlock.className = 'quote'; const quoteTitle = document.createElement('span'); quoteTitle.className = 'quote_author'; const quoteStrong = document.createElement('strong'); quoteStrong.append(quoteName); quoteTitle.append(quoteStrong); quoteBlock.append(quoteTitle); quoteBlock.append(document.createElement('br')); tagTextNode.replaceWith(quoteBlock); walkArgs = {addToNode: quoteBlock, addToName: 'quote'}; } walker.currentNode = nextTextNode; walkNodes(walker, walkArgs); walker.currentNode = node; } } break; } } const oldNode = node; node = walker.nextSibling(); if (addToNode) { addToNode.append(oldNode); } } if (addToNode) { throw new Error(`Unclosed [${addToName}] tag`); } } const whatToWalk = NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_COMMENT; function fixBBCode(element) { const walker = document.createTreeWalker(element, whatToWalk); if (walker.firstChild()) { walkNodes(walker, {}); } } fixBBCode(document.getElementById('main_content')); const authorNotes = document.getElementById('notes'); if (authorNotes) { fixBBCode(authorNotes); } })();