showText.zip
showText.html
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="./showText.css"></head><body><script src="./marked.min.js"></script><script src="./showText.js" type="module"></script><script type="module"> import ShowText from "./showText.js"; // let input = "【文本-取文本左-->>文本1我是要反转的文本-->>反】" // let input = "【文本-取文本右-->>【文本-反转文本-->>文本1我是要反转的文本】-->>5】" // let input = "【文本-取中间-->>文本1我是要反转2的文本-->>1-->>1】" // let input = "【文本-反转文本-->>【文本-反转文本-->>4324【返回-->>返回】【当前时间】】】我是后缀" // let input = "【随机数-->>【随机数-->>af2f-->>a5g】-->>【随机数-->>5b-->>7】】" // let input = "【变量-->>a-->>3>2】【判断-->>【变量-->>a】-->>是-->>否】"; // let input = "【文本-替换-->>我是文本a字符-->>a-->>b】" // let input = "【权重随机数-->>a,b,c,d-->>4,2,2,1】" // let input = "【文本-反转文本-->>【当前时间】【文本-注音-->>汉字-->>hanzi】aaa】【当前时间】" // let input = `a【空格】【变量-->>日期-->>【当前时间-->>年-月-日】】 // 【变量-->>时间-->>【当前时间-->>时:分:秒】】 // 【文本-文字颜色-->>【变量-->>时间】-->>aqua】【换行】 // 【变量-->>日期】` // let input = "【文本-注音-->>fdsf【文本-反转文本-->>汉字】fdsfsd-->>【文本-反转文本-->>hanzi】】" // let input = " 【文本-文字颜色-->>【文本-注音-->>fdsf【文本-反转文本-->>汉字】fdsfsd-->>【文本-反转文本-->>hanzi】】-->>aqua】 __完了__" // let input = `【文本-文字颜色-->>【文本-黑幕-->>黑幕】-->>aqua】` let input = `【文本-黑幕-->>【文本-文字颜色-->>黑幕-->>aqua】】` const Show = new ShowText(); // const output = Show.showTextBrowser(input); const output = Show.showTextWithMarked(input); document.body.insertAdjacentHTML("beforeend", output);</script></body></html>
showText.js
import BrowserReplaceText from "./BrowserReplaceText.js";const ReplaceText = new BrowserReplaceText();class ShowText { errorOutput; #backText; constructor() { this.doTextList = Object.assign({ "文本-反转文本"(text) { const type = text.match(/-->>([\s\S]*)】/); return ReplaceText.getReverseText(this.doReplaceToText(type[1])); }, "文本-取文本左"(text) { const textState = this.doTextMatchList(text); return ReplaceText.getTextLeft(this.doReplaceToText(textState[0]), this.doReplaceToText(textState[1])); }, "文本-取文本右"(text) { const textState = this.doTextMatchList(text); return ReplaceText.getTextRight(this.doReplaceToText(textState[0]), this.doReplaceToText(textState[1])); }, "文本-取中间"(text) { const textState = this.doTextMatchList(text); return ReplaceText.getTextCenter(this.doReplaceToText(textState[0]), this.doReplaceToText(textState[1]), this.doReplaceToText(textState[2])); }, "文本-替换"(text) { const textState = this.doTextMatchList(text); return this.doReplaceToText(textState[0]).replace(this.doReplaceToText(textState[1]), this.doReplaceToText(textState[2])); }, "文本-取出数字"(text) { const textState = this.doTextMatchList(text); return ReplaceText.getTextNum(this.doReplaceToText(textState[0])); }, "当前时间"(text) { const type = text.match(/-->>([\s\S]*)】/); return ReplaceText.getDate(+new Date(), type && this.doReplaceToText(type[1])); }, "返回"(text) { const type = text.match(/-->>([\s\S]*)】/); this.#backText = this.doReplaceToText(type[1]); return '' }, "选择"(text) { const choiceList = this.doTextMatchList(text); return this.doReplaceToText(choiceList[ReplaceText.getTextNum(this.doReplaceToText(choiceList[0]))]); }, "判断"(text) { const choiceList = this.doTextMatchList(text); return Function("return " + this.doReplaceToText(choiceList[0]))() ? this.doReplaceToText(choiceList[1]) : this.doReplaceToText(choiceList[2]); }, "随机数"(text) { const minMax = this.doTextMatchList(text); return ReplaceText.getRandom(this.doReplaceToText(minMax[0]), this.doReplaceToText(minMax[1])); }, "权重随机数"(text) { const type = this.doTextMatchList(text); return ReplaceText.getWeightedRandom(this.doReplaceToText(type[0]).split(/[,,]/), this.doReplaceToText(type[1]).split(/[,,]/)); }, "变量"(text) { const type = this.doTextMatchList(text); return type.length === 1 ? ReplaceText.getVariable(this.doReplaceToText(type[0])) : ReplaceText.setVariable(this.doReplaceToText(type[0]), this.doReplaceToText(type[1])); } }, { "文本-注音"(text) { const textState = this.doTextMatchList(text); return `{{{注音-${this.doReplaceToText(textState[0])}-${this.doReplaceToText(textState[1])}}}}`; }, "文本-文字颜色"(text) { const textState = this.doTextMatchList(text); return `{{{文字颜色-${this.doReplaceToText(textState[0])}-${this.doReplaceToText(textState[1])}}}}`; }, "文本-黑幕"(text) { const textState = this.doTextMatchList(text); return `{{{黑幕-${this.doReplaceToText(textState[0])}}}}`; }, "换行"() { return "{{{换行}}}" }, "空格"() { return "{{{空格}}}" }, }); this.doHTMLList = { "注音"(text) { const type = this.doHTMLMatchList(text); return ReplaceText.getRubyHTML(this.doReplaceToHTML(type[0]), type[1]); }, "文字颜色"(text) { const type = this.doHTMLMatchList(text); return ReplaceText.setTextColor(this.doReplaceToHTML(type[0]), type[1]); }, "黑幕"(text) { const type = this.doHTMLMatchList(text); return ReplaceText.getHeimuHTML(this.doReplaceToHTML(type[0])); }, "换行"() { return "<br />" }, "空格"() { return " " }, }; } showTextBrowser(text) { let resText = text; if (/【[\s\S]*】/.test(text)) { text = text.replace(/\s+(?=【)/g, "").replace(/(?<=】)\s+/g, ""); resText = this.doReplaceToText(text); resText = this.doReplaceToHTML(resText) } return this.errorOutput || resText; } showTextWithMarked(text) { return marked.parse(this.showTextBrowser(text)); } doReplaceToText(text) { if (/【[\s\S]*】/.test(text)) { let parts = text.match(/[【】]|[^【】]+/g), matches = [], balance = 0, index = 0; for (let i = 0; i < parts.length; i++) { if (parts[i] === "【") { if (balance === 0) { index = i; } balance++; } else if (parts[i] === "】") { if (balance === 1) { matches.push(parts.slice(index, i + 1).join("")); } balance--; if (balance < 0) { this.errorOutput = 'missing "【"'; return text; } } } if (balance > 0) { this.errorOutput = 'missing "】"'; return text; } matches?.forEach(matchText => { text = text.replace(matchText, match => this.doTextMatch(match)); if (this.#backText) { text = this.#backText; this.#backText = ''; } }); } return text; } doReplaceToHTML(text) { if (/{{{[\s\S]*}}}/.test(text)) { let parts = text.match(/[\{\}]{3}|[^\{\}]+/g), matches = [], balance = 0, index = 0; for (let i = 0; i < parts.length; i++) { if (parts[i] === "{{{") { if (balance === 0) { index = i; } balance++; } else if (parts[i] === "}}}") { if (balance === 1) { matches.push(parts.slice(index, i + 1).join("")); } balance--; } } matches?.forEach(matchText => text = text.replace(matchText, match => this.doHTMLMatch(match)) ); } return text; } doTextMatch(match) { const type = match.match(/【([\s\S]*?)(?:-->>|】)/); if (type && this.doTextList[type[1]]) { return this.doTextList[type[1]].call(this, type.input); } else { return type.input; } } doHTMLMatch(match) { const type = match.match(/{{{([\s\S]*?)[-|(?:}}})]/); if (type && this.doHTMLList[type[1]]) { return this.doHTMLList[type[1]].call(this, type.input); } else { return type.input; } } #getMatchList(type, divide, left, right) { let list = [], balance = 0, cacheList = []; type.forEach(item => { if (item.match(new RegExp(left + "|" + right))) { balance += (item.match(new RegExp(left, "g")) || []).length; balance -= (item.match(new RegExp(right, "g")) || []).length; cacheList.push(item); if (balance === 0) { list.push(cacheList.join(divide)); cacheList = []; } } else if (balance) { cacheList.push(item); } else { list.push(item); } }); return list; } doTextMatchList(text) { const type = text.match(/(?<=-->>)[\s\S]*?(?=-->>|】$)/g); if (!type) { return [text] } return this.#getMatchList(type, "-->>", "【", "】"); } doHTMLMatchList(text) { const type = text.match(/(?<=-)[\s\S]*?(?=-|(?:}}})$)/g); if (!type) { return [text] } return this.#getMatchList(type, "-", "{{{", "}}}"); }}export default ShowText;
BrowserReplaceText.js
import ReplaceText from "./ReplaceText.js";class BrowserReplaceText extends ReplaceText { constructor() { super(); } getReverseText(text) { let resText = ''; text.split(/({{{[\s\S]*?}}})/).forEach(text => resText += /{{{[\s\S]*}}}/.test(text) ? text : text.split("").reverse().join("")); return resText; } getRubyHTML(text, rt) { return `<ruby>${text}<rp>(</rp><rt>${rt}</rt><rp>)</rp></ruby>`; } setTextColor(text, color) { if (/^<[\s\S]+>$/.test(text)) { return text.replace(/^<([\s\S]+?)>/, `<$1 style="color: ${color}">`); } else { return `<span style="color: ${color}" >${text}</span>`; } } getHeimuHTML(text) { if (/^<[\s\S]+>$/.test(text)) { return text.includes("class=") ? text.replace(/class="([\s\S]+?)"/, "class='$1 heimu'") : text.replace(/^<([\s\S]+?)>/, "<$1 class='heimu'>"); } else { return `<span class="heimu">${text}</span>`; } }}export default BrowserReplaceText;
ReplaceText.js
class ReplaceText { #variableMap; constructor() { this.#variableMap = {}; } getReverseText(text) { let resText = ""; for (let i = text.length - 1; i >= 0; i--) { resText += text[i]; } return resText; } getTextLeft(text, stamp) { return text.split(stamp)[0]; } getTextRight(text, stamp) { return text.substring(text.indexOf(stamp) + 1); } getTextCenter(text, leftStamp, rightStamp) { let matchType = text.match(new RegExp(`${leftStamp}([\\s\\S]*?)${rightStamp}`)); if (matchType) { return matchType[1]; } else { matchType = text.match(new RegExp(`${rightStamp}([\\s\\S]*?)${leftStamp}`)); return matchType ? matchType[1] : text; } } getTextNum(text) { if (typeof text === "number") { return text; } return text.replace(/\D/g, ''); } getRandom(min, max) { return Math.floor(Math.random() * (parseInt(this.getTextNum(max)) - (min = parseInt(this.getTextNum(min))) + 1) + min); } getWeightedRandom(randomList, weightedList) { let sum = 0; weightedList = weightedList.map(v => parseInt(this.getTextNum(v))); const r = this.getRandom(1, weightedList.reduce((a,b) => a + b)); for (let i = 0; i < randomList.length; i++) { sum += weightedList[i]; if (r <= sum) { return randomList[i]; } } } getDate(newDate = Date.now(), type) { const date = new Date(newDate), year = date.getFullYear(), month = date.getMonth() + 1 + "", day = date.getDate().toString().padStart(2, '0'), hour = date.getHours().toString().padStart(2, '0'), minutes = date.getMinutes().toString().padStart(2, '0'), seconds = date.getSeconds().toString().padStart(2, '0'), week = date.getDay(), weekList = ["星期一", "星期二","星期三", "星期四","星期五", "星期六","星期日"]; if (type) { if (type === "all") { return `${year}-${month}-${day} ${hour}:${minutes}:${seconds} ${weekList[week - 1]}`; } return type.replace("年", year).replace("月", month).replace("日", day) .replace("时", hour).replace("分", minutes).replace("秒", seconds) .replace("星期", weekList[week - 1]); } return `${year}-${month}-${day} ${hour}:${minutes}:${seconds}`; } getVariable(key) { return this.#variableMap[key]; } setVariable(key, value) { this.#variableMap[key] = value; return "" }}export default ReplaceText;
showText.css
.heimu { background-color: currentColor; transition: background-color .2s;}.heimu:hover { background-color: transparent;}ruby,rp,rt { background-color: inherit;}