/** * @name BetterFormattingRedux * @description Enables different types of formatting in standard Discord chat. * @version 2.3.15 * @author Zerebos * @authorId 249746236008169473 * @website https://github.com/zerebos/BetterDiscordAddons/tree/master/Plugins/BetterFormattingRedux * @source https://raw.githubusercontent.com/zerebos/BetterDiscordAddons/master/Plugins/BetterFormattingRedux/BetterFormattingRedux.plugin.js */ /*@cc_on @if (@_jscript) // Offer to self-install for clueless users that try to run this directly. var shell = WScript.CreateObject("WScript.Shell"); var fs = new ActiveXObject("Scripting.FileSystemObject"); var pathPlugins = shell.ExpandEnvironmentStrings("%APPDATA%\\BetterDiscord\\plugins"); var pathSelf = WScript.ScriptFullName; // Put the user at ease by addressing them in the first person shell.Popup("It looks like you've mistakenly tried to run me directly. \n(Don't do that!)", 0, "I'm a plugin for BetterDiscord", 0x30); if (fs.GetParentFolderName(pathSelf) === fs.GetAbsolutePathName(pathPlugins)) { shell.Popup("I'm in the correct folder already.", 0, "I'm already installed", 0x40); } else if (!fs.FolderExists(pathPlugins)) { shell.Popup("I can't find the BetterDiscord plugins folder.\nAre you sure it's even installed?", 0, "Can't install myself", 0x10); } else if (shell.Popup("Should I copy myself to BetterDiscord's plugins folder for you?", 0, "Do you need some help?", 0x34) === 6) { fs.CopyFile(pathSelf, fs.BuildPath(pathPlugins, fs.GetFileName(pathSelf)), true); // Show the user where to put plugins in the future shell.Exec("explorer " + pathPlugins); shell.Popup("I'm installed!", 0, "Successfully installed", 0x40); } WScript.Quit(); @else@*/ var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/plugins/BetterFormattingRedux/index.ts var index_exports = {}; __export(index_exports, { default: () => BetterFormattingRedux }); module.exports = __toCommonJS(index_exports); // src/common/plugin.ts var Plugin = class { meta; manifest; settings; defaultSettings; LocaleManager; get strings() { if (!this.manifest.strings) return {}; const locale = this.LocaleManager?.locale.split("-")[0] ?? "en"; if (this.manifest.strings.hasOwnProperty(locale)) return this.manifest.strings[locale]; if (this.manifest.strings.hasOwnProperty("en")) return this.manifest.strings.en; return this.manifest.strings; } constructor(meta, zplConfig) { this.meta = meta; this.manifest = zplConfig; if (typeof this.manifest.config !== "undefined") { this.defaultSettings = {}; for (let s = 0; s < this.manifest.config.length; s++) { const current = this.manifest.config[s]; if (current.type != "category") { this.defaultSettings[current.id] = current.value; } else { for (let si = 0; si < current.settings.length; si++) { const subCurrent = current.settings[si]; this.defaultSettings[subCurrent.id] = subCurrent.value; } } } this.settings = BdApi.Utils.extend({}, this.defaultSettings); } const currentVersionInfo = BdApi.Data.load(this.meta.name, "version"); if (currentVersionInfo !== this.meta.version) { this.#showChangelog(); BdApi.Data.save(this.meta.name, "version", this.meta.version); } if (this.manifest.strings) this.LocaleManager = BdApi.Webpack.getByKeys("locale", "initialize"); if (this.manifest.config && !this.getSettingsPanel) { this.getSettingsPanel = () => { this.#updateConfig(); return BdApi.UI.buildSettingsPanel({ onChange: (_, id, value) => { this.settings[id] = value; this.saveSettings(); }, settings: this.manifest.config }); }; } } async start() { BdApi.Logger.info(this.meta.name, `version ${this.meta.version} has started.`); if (this.defaultSettings) this.settings = this.loadSettings(); if (typeof this.onStart == "function") this.onStart(); } stop() { BdApi.Logger.info(this.meta.name, `version ${this.meta.version} has stopped.`); if (typeof this.onStop == "function") this.onStop(); } #showChangelog() { if (typeof this.manifest.changelog == "undefined") return; const changelog = { title: this.meta.name + " Changelog", subtitle: `v${this.meta.version}`, changes: [] }; if (!Array.isArray(this.manifest.changelog)) Object.assign(changelog, this.manifest.changelog); else changelog.changes = this.manifest.changelog; BdApi.UI.showChangelogModal(changelog); } saveSettings() { BdApi.Data.save(this.meta.name, "settings", this.settings); } loadSettings() { return BdApi.Utils.extend({}, this.defaultSettings ?? {}, BdApi.Data.load(this.meta.name, "settings")); } #updateConfig() { if (!this.manifest.config) return; for (const setting of this.manifest.config) { if (setting.type !== "category") { setting.value = this.settings[setting.id] ?? setting.value; } else { for (const subsetting of setting.settings) { subsetting.value = this.settings[subsetting.id] ?? subsetting.value; } } } } buildSettingsPanel(onChange) { this.#updateConfig(); return BdApi.UI.buildSettingsPanel({ onChange: (groupId, id, value) => { this.settings[id] = value; onChange?.(groupId, id, value); this.saveSettings(); }, settings: this.manifest.config }); } }; // src/plugins/BetterFormattingRedux/config.ts var manifest = { info: { name: "BetterFormattingRedux", authors: [{ name: "Zerebos", discord_id: "249746236008169473", github_username: "zerebos", twitter_username: "IAmZerebos" }], version: "2.3.15", description: "Enables different types of formatting in standard Discord chat.", github: "https://github.com/zerebos/BetterDiscordAddons/tree/master/Plugins/BetterFormattingRedux", github_raw: "https://raw.githubusercontent.com/zerebos/BetterDiscordAddons/master/Plugins/BetterFormattingRedux/BetterFormattingRedux.plugin.js" }, changelog: [ { title: "GUI Works Again", type: "fixed", items: [ "All basic formatting buttons are now working again.", "Settings appear and work as expected.", "Formatting should happen for messages with images." ] } ], main: "index.ts", config: [ { type: "category", id: "toolbar", name: "Toolbar Buttons", collapsible: true, shown: false, settings: [ { type: "switch", id: "boldButton", name: "Bold", value: true }, { type: "switch", id: "italicButton", name: "Italic", value: true }, { type: "switch", id: "underlineButton", name: "Underline", value: true }, { type: "switch", id: "strikethroughButton", name: "Strikethrough", value: true }, { type: "switch", id: "spoilerButton", name: "Spoiler", value: true }, { type: "switch", id: "codeButton", name: "Code", value: true }, { type: "switch", id: "codeblockButton", name: "Codeblock", value: true }, { type: "switch", id: "superscriptButton", name: "Superscript", value: true }, { type: "switch", id: "smallcapsButton", name: "Smallcaps", value: true }, { type: "switch", id: "fullwidthButton", name: "Full Width", value: true }, { type: "switch", id: "upsidedownButton", name: "Upsidedown", value: true }, { type: "switch", id: "variedButton", name: "Varied Caps", value: true }, { type: "switch", id: "leetButton", name: "Leet (1337)", value: false }, { type: "switch", id: "thiccButton", name: "Extra Thicc", value: false }, { type: "switch", id: "firstcapsButton", name: "First Caps", value: false }, { type: "switch", id: "uppercaseButton", name: "Uppercase", value: false }, { type: "switch", id: "lowercaseButton", name: "Lowercase", value: false } ] }, { type: "category", id: "formats", name: "Active Formats", collapsible: true, shown: false, settings: [ { type: "switch", id: "superscriptFormat", name: "Superscript", value: true }, { type: "switch", id: "smallcapsFormat", name: "Smallcaps", value: true }, { type: "switch", id: "fullwidthFormat", name: "Full Width", value: true }, { type: "switch", id: "upsidedownFormat", name: "Upsidedown", value: true }, { type: "switch", id: "variedFormat", name: "Varied Caps", value: true }, { type: "switch", id: "leetFormat", name: "Leet (1337)", value: false }, { type: "switch", id: "thiccFormat", name: "Extra Thicc", value: false }, { type: "switch", id: "firstcapsFormat", name: "First Caps", value: false }, { type: "switch", id: "uppercaseFormat", name: "Uppercase", value: false }, { type: "switch", id: "lowercaseFormat", name: "Lowercase", value: false } ] }, { type: "category", id: "wrappers", name: "Wrapper Options", collapsible: true, shown: false, settings: [ { type: "text", id: "superscriptWrapper", name: "Superscript", note: "The wrapper for superscripted text", value: "^^" }, { type: "text", id: "smallcapsWrapper", name: "Smallcaps", note: "The wrapper to make Smallcaps.", value: "%%" }, { type: "text", id: "fullwidthWrapper", name: "Full Width", note: "The wrapper for E X P A N D E D T E X T.", value: "##" }, { type: "text", id: "upsidedownWrapper", name: "Upsidedown", note: "The wrapper to flip the text upsidedown.", value: "&&" }, { type: "text", id: "variedWrapper", name: "Varied Caps", note: "The wrapper to VaRy the capitalization.", value: "==" }, { type: "text", id: "leetWrapper", name: "Leet (1337)", note: "The wrapper to talk in 13375p34k.", value: "++" }, { type: "text", id: "thiccWrapper", name: "Extra Thicc", note: "The wrapper to get \u4E47\u4E42\u4E0B\u5C3A\u5342 \u4E0B\u5344\u5DE5\u531A\u531A.", value: "$$" }, { type: "text", id: "firstcapsWrapper", name: "First Caps", note: "The wrapper to capitalize the first letter.", value: "--" }, { type: "text", id: "uppercaseWrapper", name: "Uppercase", note: "The wrapper to convert to uppercase.", value: ">>" }, { type: "text", id: "lowercaseWrapper", name: "Lowercase", note: "The wrapper to convert to lowercase.", value: "<<" } ] }, { type: "category", id: "formatting", name: "Formatting Options", collapsible: true, shown: false, settings: [ { type: "dropdown", id: "fullWidthMap", name: "Fullwidth Style", note: "Which style of fullwidth formatting should be used.", value: true, options: [ { label: "T H I S", value: false }, { label: "\uFF54\uFF48\uFF49\uFF53", value: true } ] }, { type: "switch", id: "reorderUpsidedown", name: "Reorder Upsidedown Text", note: "Having this enabled reorders the upside down text to make it in-order.", value: true }, { type: "switch", id: "startCaps", name: "Start VaRiEd Caps With Capital", note: "Enabling this starts a varied text string with a capital.", value: true } ] }, { type: "category", id: "plugin", name: "Functional Options", collapsible: true, shown: false, settings: [ { type: "dropdown", id: "hoverOpen", name: "Opening Toolbar", note: "Determines when to show the toolbar.", value: true, options: [ { label: "Click", value: false }, { label: "Hover", value: true } ] }, { type: "dropdown", id: "chainFormats", name: "Format Chaining", note: "Swaps priority of wrappers between inner first and outer first. Check the GitHub for more info.", value: true, options: [ { label: "Inner", value: false }, { label: "Outer", value: true } ] }, { type: "switch", id: "closeOnSend", name: "Close On Send", note: "This option will close the toolbar when a message is sent.", value: true } ] }, { type: "category", id: "style", name: "Style Options", collapsible: true, shown: false, settings: [ { type: "dropdown", id: "useIcons", name: "Toolbar Style", note: "Switches between icons and text as the toolbar buttons.", value: true, options: [ { label: "Text", value: false }, { label: "Icons", value: true } ] }, { type: "dropdown", id: "rightSide", name: "Toolbar Location", note: "This option enables swapping toolbar location.", value: true, options: [ { label: "Left", value: false }, { label: "Right", value: true } ] }, { type: "slider", id: "toolbarOpacity", name: "Opacity", note: "This allows the toolbar to be partially seethrough.", value: 1, min: 0, max: 1 }, { type: "slider", id: "fontSize", name: "Font Size", note: "Adjusts the font size between 0 and 100%.", value: 85, min: 0, max: 100 } ] } ] }; var config_default = manifest; // src/plugins/BetterFormattingRedux/toolbar.ts var toolbar_default = { bold: { type: "native-format", name: "Bold", displayName: "Bold", icon: `` }, italic: { type: "native-format", name: "Italic", displayName: "Italic", icon: `` }, underline: { type: "native-format", name: "Underline", displayName: "Underline", icon: `` }, strikethrough: { type: "native-format", name: "Strikethrough", displayName: "Strikethrough", icon: `` }, spoiler: { type: "native-format", name: "Spoiler", displayName: "Spoiler", icon: `` }, code: { type: "native-format", name: "Code", displayName: "Code", icon: `` }, codeblock: { type: "native-format", name: "Codeblock", displayName: "|Codeblock|", icon: `` }, superscript: { type: "bfr-format", name: "Superscript", displayName: "\u02E2\u1D58\u1D56\u1D49\u02B3\u02E2\u1D9C\u02B3\u1DA6\u1D56\u1D57", icon: "" }, smallcaps: { type: "bfr-format", name: "Smallcaps", displayName: "S\u1D0D\u1D00\u029F\u029FC\u1D00\u1D18s", icon: `` }, fullwidth: { type: "bfr-format", name: "Fullwidth", displayName: "\uFF26\uFF55\uFF4C\uFF4C\uFF57\uFF49\uFF44\uFF54\uFF48", icon: "" }, upsidedown: { type: "bfr-format", name: "Upsidedown", displayName: "u\u028Dop\u01DDp\u1D09sd\u2229", icon: `` }, varied: { type: "bfr-format", name: "Varied", displayName: "VaRiEd CaPs", icon: `` }, leet: { type: "bfr-format", name: "Leet", displayName: "1337", icon: "" }, thicc: { type: "bfr-format", name: "Extra Thicc", displayName: "\u4E47\u4E42\u4E0B\u5C3A\u5342 \u4E0B\u5344\u5DE5\u531A\u531A", icon: `` }, firstcaps: { type: "bfr-format", name: "First Caps", displayName: "First Caps", icon: `` }, uppercase: { type: "bfr-format", name: "Uppercase", displayName: "UPPERCASE", icon: `` }, lowercase: { type: "bfr-format", name: "Lowercase", displayName: "lowercase", icon: `` } }; // src/plugins/BetterFormattingRedux/languages.ts var languages_default = { A: { ada: "Ada", awk: "Awk" }, B: { bash: "Bash" }, C: { c: "c", clj: "Clojure", coffeescript: "CoffeeScript", cpp: "C++", crystal: "Crystal", csharp: "C#", css: "CSS" }, D: { d: "D", dart: "Dart", delphi: "Delphi", dockerfile: "Dockerfile" }, E: { elixir: "Elixir", elm: "Elm", erl: "Erlang" }, F: { fs: "F#" }, G: { go: "Go", graphql: "GraphQL", groovy: "Groovy" }, H: { hs: "Haskell", html: "HTML/XML" }, J: { java: "Java", js: "JavaScript", json: "JSON", julia: "Julia" }, K: { kt: "Kotlin" }, L: { latex: "LaTeX", less: "Less", lisp: "Lisp", lua: "Lua" }, O: { ml: "OCaml" }, M: { markdown: "Markdown", matlab: "Matlab", mk: "Makefile" }, N: { nginx: "Nginx", nim: "Nim" }, P: { perl: "Perl", php: "PHP", powershell: "Powershell", prolog: "Prolog", py: "Python" }, R: { pl: "Raku", r: "R", rs: "Rust", ruby: "Ruby" }, S: { sas: "SAS", scala: "Scala", scheme: "Scheme", scss: "SCSS", sql: "SQL", switf: "Swift" }, T: { tcl: "Tcl", ts: "TypeScript" }, V: { vbnet: "VB.NET", vhdl: "VHDL" }, Z: { zsh: "ZSH" } }; // src/plugins/BetterFormattingRedux/styles.css var styles_default = `.bf-toolbar { user-select: none; white-space: nowrap; font-size:85%; display:block; position: absolute; color: rgba(255, 255, 255, .5); width:auto!important; right:0; bottom:auto; border-radius:3px; height:27px!important; top:0px; transform:translate(0,-100%); opacity:1; overflow: hidden!important; pointer-events: none; padding:10px 30px 15px 5px; margin: 0 5px 0 0; } .bf-toolbar.bf-visible, .bf-toolbar.bf-hover:hover{ pointer-events: initial; } .bf-toolbar::before { content:""; display: block; width:100%; height:calc(100% - 15px); position: absolute; z-index: -1; background:#424549; pointer-events: initial; left:0px; top:5px; border-radius:3px; transform:translate(0,55px); transition:all 200ms ease; } .theme-light .bf-toolbar::before { background: #97A0AA; } .bf-toolbar.bf-visible:before, .bf-toolbar.bf-hover:hover:before { transform:translate(0,0px); transition:all 200ms cubic-bezier(0,0,0,1); } .bf-toolbar .format { display: inline; padding: 7px 5px; cursor: pointer; display : inline-flex; align-items : center; transform:translate(0,55px); transition:all 50ms,transform 200ms ease; position:relative; pointer-events: initial; border-radius:2px; max-height: 27px; box-sizing: border-box; vertical-align: middle; } .bf-toolbar .format > img, .bf-toolbar .format > svg { opacity: 0.6; vertical-align: middle; max-height: inherit; } .bf-toolbar .format .format-border { border: 1px solid rgba(255, 255, 255, .5); border-radius: inherit; } .bf-toolbar .format:hover{ background:rgba(255,255,255,.1); color:rgba(255,255,255,.9); } .bf-toolbar .format:active{ background:rgba(0,0,0,.1)!important; transition:all 0ms,transform 200ms ease; } .bf-toolbar.bf-visible .format, .bf-toolbar.bf-hover:hover .format{ transform:translate(0,0); transition:all 50ms,transform 200ms cubic-bezier(0,0,0,1); } .bf-toolbar .format.disabled { display: none; } .bf-toolbar .format.ghost { color: transparent; background: rgba(0,0,0,.1); } .bf-toolbar .format.ghost > img, .bf-toolbar .format.ghost > svg { opacity: 0; } .theme-light .bf-toolbar:hover .bf-arrow, .bf-toolbar .bf-arrow { content:""; display:block; background: url('data:image/svg+xml;utf8,'); height:30px; width:30px; right:5px; position: absolute; pointer-events: initial; bottom:0; background-repeat: no-repeat; background-position: 50%; transition:all 200ms ease; opacity: .3; cursor:pointer; } .theme-light .bf-toolbar .bf-arrow { background: url('data:image/svg+xml;utf8,'); } .bf-toolbar.bf-visible .bf-arrow, .bf-toolbar.bf-hover:hover .bf-arrow { transform:translate(0,-14px)rotate(-90deg); transition:all 200ms cubic-bezier(0,0,0,1); opacity: .9; } .message-group .bf-toolbar{ padding: 10px 5px 15px 5px; animation:slide-up 300ms cubic-bezier(0,0,0,1), opacity 300ms ease } .upload-modal .bf-toolbar { position: relative; transform: none; padding: 5px 0; margin-right: 0; border-radius: 2px; text-align: center; background: #424549; } .upload-modal .bf-toolbar::before { display: none; } .upload-modal .bf-toolbar .format:hover{ background:rgba(255,255,255,.1); } .upload-modal .bf-toolbar .format:active{ background:rgba(0,0,0,.1); } .upload-modal .bf-toolbar .format, .upload-modal .bf-toolbar:before, .message-group .bf-toolbar .format, .message-group .bf-toolbar:before{ transform:translate(0,0); } .upload-modal .bf-toolbar .bf-arrow, .message-group .bf-toolbar .bf-arrow{ display: none; } .bf-toolbar.bf-left { left: 0!important; right: auto!important; margin-right: 0!important; margin-left: 5px!important; padding: 10px 10px 15px 30px!important; } .bf-toolbar.bf-left .bf-arrow { left: 5px!important; right: auto!important; } .bf-toolbar.bf-left.bf-hover:hover .bf-arrow,.bf-toolbar.bf-left.bf-visible .bf-arrow { -webkit-transform: translate(0,-14px) rotate(90deg)!important; -ms-transform: translate(0,-14px) rotate(90deg)!important; transform: translate(0,-14px) rotate(90deg)!important; } .bf-languages { display: block; position: fixed !important; transform: scale(1,0); transform-origin: 100% 100%!important; background: #424549; border-radius: 3px; color: rgba(255,255,255,.5); padding: 3px; } .bf-languages.bf-visible { height: auto; transition: 200ms cubic-bezier(.2,0,0,1); transform: scale(1,1); transform-origin: 100% 100%!important; } .bf-languages div { display: block; cursor: pointer; padding: 5px 7px; border-radius: 2px; } .bf-languages div:hover { background: rgba(255,255,255,.1); color: rgba(255,255,255,.9); }`; // src/plugins/BetterFormattingRedux/toolbar.html var toolbar_default2 = '
'; // src/plugins/BetterFormattingRedux/index.ts var { ContextMenu, DOM, Patcher, UI, ReactUtils, Webpack, Logger } = BdApi; var MessageActions = Webpack.getByKeys("jumpToMessage", "_sendMessage"); var TextareaClasses = Webpack.getByKeys("channelTextArea", "textArea") ?? { textArea: "textArea_bdf0de" }; var BetterFormattingRedux = class extends Plugin { customWrappers; buttonOrder; discordWrappers = { bold: "**", italic: "*", underline: "__", strikethrough: "~~", code: "`", codeblock: "```", spoiler: "||" }; isOpen = false; replaceList = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}"; smallCapsList = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`\u1D00\u0299\u1D04\u1D05\u1D07\uA730\u0262\u029C\u026A\u1D0A\u1D0B\u029F\u1D0D\u0274\u1D0F\u1D18\u01EB\u0280\uA731\u1D1B\u1D1C\u1D20\u1D21x\u028F\u1D22{|}"; superscriptList = " !\"#$%&'\u207D\u207E*\u207A,\u207B./\u2070\xB9\xB2\xB3\u2074\u2075\u2076\u2077\u2078\u2079:;<\u207C>?@\u1D2C\u1D2E\u1D9C\u1D30\u1D31\u1DA0\u1D33\u1D34\u1D35\u1D36\u1D37\u1D38\u1D39\u1D3A\u1D3C\u1D3EQ\u1D3F\u02E2\u1D40\u1D41\u03BD\u1D42\u02E3\u02B8\u1DBB[\\]^_`\u1D43\u1D47\u1D9C\u1D48\u1D49\u1DA0\u1D4D\u02B0\u1DA6\u02B2\u1D4F\u02E1\u1D50\u207F\u1D52\u1D56\u146B\u02B3\u02E2\u1D57\u1D58\u1D5B\u02B7\u02E3\u02B8\u1DBB{|}"; upsideDownList = ` \xA1"#$%\u2118,)(*+'-\u02D9/0\u0196\u218A\u0190\u07C8\u03DB9\u312586:;>=<\xBF@\u2200\u15FA\u0186\u15E1\u018E\u2132\uA4E8HI\u0550\uA4D8\uA4F6WNO\u0500\uA779\uA4E4S\uA4D5\uA4F5\u039BMX\u2144Z]\\[^\u203E,\u0250q\u0254p\u01DD\u025F\u1D77\u0265\u1D09\u027E\u029E\uA781\u026Fuodb\u0279s\u0287n\u028C\u028Dx\u028Ez}|{`; fullwidthList = "\u3000\uFF01\uFF02\uFF03\uFF04\uFF05\uFF06\uFF07\uFF08\uFF09\uFF0A\uFF0B\uFF0C\uFF0D\uFF0E\uFF0F\uFF10\uFF11\uFF12\uFF13\uFF14\uFF15\uFF16\uFF17\uFF18\uFF19\uFF1A\uFF1B\uFF1C\uFF1D\uFF1E\uFF1F\uFF20\uFF21\uFF22\uFF23\uFF24\uFF25\uFF26\uFF27\uFF28\uFF29\uFF2A\uFF2B\uFF2C\uFF2D\uFF2E\uFF2F\uFF30\uFF31\uFF32\uFF33\uFF34\uFF35\uFF36\uFF37\uFF38\uFF39\uFF3A\uFF3B\uFF3C\uFF3D\uFF3E\uFF3F\uFF40\uFF41\uFF42\uFF43\uFF44\uFF45\uFF46\uFF47\uFF48\uFF49\uFF4A\uFF4B\uFF4C\uFF4D\uFF4E\uFF4F\uFF50\uFF51\uFF52\uFF53\uFF54\uFF55\uFF56\uFF57\uFF58\uFF59\uFF5A\uFF5B\uFF5C\uFF5D"; leetList = " !\"#$%&'()*+,-./0123456789:;<=>?@48CD3FG#IJK1MN0PQ\u042F57UVWXY2[\\]^_`48cd3fg#ijk1mn0pq\u042F57uvwxy2{|}"; thiccList = "\u3000!\"#$%&'()*+,-./0123456789:;<=>?@\u5342\u4E43\u531A\u5200\u4E47\u4E0B\u53B6\u5344\u5DE5\u4E01\u957F\u4E5A\u4ECE\u3093\u53E3\u5C38\u353F\u5C3A\u4E02\u4E05\u51F5\u30EA\u5C71\u4E42\u4E2B\u4E59[\\]^_`\u5342\u4E43\u531A\u5200\u4E47\u4E0B\u53B6\u5344\u5DE5\u4E01\u957F\u4E5A\u4ECE\u3093\u53E3\u5C38\u353F\u5C3A\u4E02\u4E05\u51F5\u30EA\u5C71\u4E42\u4E2B\u4E59{|}"; constructor(meta) { super(meta, config_default); this.customWrappers = (this.manifest.config?.find((g) => g.id === "wrappers")).settings.map((s) => s.id); this.buttonOrder = (this.manifest.config?.find((g) => g.id === "toolbar")).settings.map((s) => s.id); } async onStart() { DOM.addStyle(this.meta.name + "-style", styles_default); this.setupToolbar(); if (!MessageActions) return Logger.error(this.meta.name, "Could not find MessageActions module!"); Patcher.before(this.meta.name, MessageActions, "sendMessage", (_, [, msg]) => { msg.content = this.format(msg.content); }); } onStop() { Patcher.unpatchAll(this.meta.name); document.querySelector(".bf-toolbar")?.remove(); DOM.removeStyle(this.meta.name + "-style"); } observer(e) { if (!e.addedNodes.length || !(e.addedNodes[0] instanceof Element)) return; const elem = e.addedNodes[0]; const textarea = elem.matches(`.${TextareaClasses.textArea}`) ? elem : elem.querySelector(`.${TextareaClasses.textArea}`); if (textarea) this.addToolbar(textarea); } updateStyle() { this.updateSide(); this.updateOpacity(); this.updateFontSize(); } updateSide() { const toolbar = document.querySelector(".bf-toolbar"); if (!toolbar) return; if (this.settings.rightSide) toolbar.classList.remove("bf-left"); else toolbar.classList.add("bf-left"); } updateOpacity() { const toolbar = document.querySelector(".bf-toolbar"); if (!toolbar) return; toolbar.style.opacity = this.settings.toolbarOpacity; } updateFontSize() { const toolbar = document.querySelector(".bf-toolbar"); if (!toolbar) return; toolbar.style.fontSize = this.settings.fontSize + "%"; } openClose() { this.isOpen = !this.isOpen; const toolbar = document.querySelector(".bf-toolbar"); if (!toolbar) return; toolbar.classList.toggle("bf-visible"); } escape(s) { return s.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"); } doFormat(text, wrapper, offset) { if (text.substring(offset, offset + wrapper.length) != wrapper) return text; let returnText = text; const len = text.length; const begin = text.indexOf(wrapper, offset); if (text[begin - 1] == "\\") return text; let end = text.indexOf(wrapper, begin + wrapper.length); if (end != -1) end += wrapper.length - 1; if (this.settings.chainFormats) { for (let w = 0; w < this.customWrappers.length; w++) { const newText = this.doFormat(returnText, this.settings[this.customWrappers[w]], begin + wrapper.length); if (returnText != newText) { returnText = newText; end = end - this.settings[this.customWrappers[w]].length * 2; } } } returnText = returnText.replace(new RegExp(`([^]{${begin}})${this.escape(wrapper)}([^]*)${this.escape(wrapper)}([^]{${len - end - 1}})`), (match, before, middle, after) => { let letterNum = 0; middle = middle.replace(/./g, (letter) => { const index = this.replaceList.indexOf(letter); letterNum += 1; if (wrapper == this.settings.fullwidthWrapper) { if (this.settings.fullWidthMap) return index != -1 ? this.fullwidthList[index] : letter; return index != -1 ? letterNum == middle.length ? letter.toUpperCase() : letter.toUpperCase() + " " : letter; } else if (wrapper == this.settings.superscriptWrapper) { return index != -1 ? this.superscriptList[index] : letter; } else if (wrapper == this.settings.smallcapsWrapper) { return index != -1 ? this.smallCapsList[index] : letter; } else if (wrapper == this.settings.upsidedownWrapper) { return index != -1 ? this.upsideDownList[index] : letter; } else if (wrapper == this.settings.leetWrapper) { return index != -1 ? this.leetList[index] : letter; } else if (wrapper == this.settings.thiccWrapper) { return index != -1 ? this.thiccList[index] : letter; } else if (wrapper == this.settings.variedWrapper) { const compare = this.settings.startCaps ? 1 : 0; if (letter.toLowerCase() == letter.toUpperCase()) letterNum = letterNum - 1; return index != -1 ? letterNum % 2 == compare ? letter.toUpperCase() : letter.toLowerCase() : letter; } else if (wrapper == this.settings.firstcapsWrapper) { if (letterNum == 1 || middle[letterNum - 2] === " ") return letter.toUpperCase(); } else if (wrapper == this.settings.uppercaseWrapper) { return letter.toUpperCase(); } else if (wrapper == this.settings.lowercaseWrapper) { return letter.toLowerCase(); } return letter; }); if (wrapper == this.settings.upsidedownWrapper && this.settings.reorderUpsidedown) return before + middle.split("").reverse().join("") + after; return before + middle + after; }); return returnText; } format(string) { let text = string; for (let i = 0; i < text.length; i++) { if (text[i] == "`") { const next = text.indexOf("`", i + 1); if (next != -1) i = next; } else if (text[i] == "@") { const match = /@.*#[0-9]*/.exec(text.substring(i)); if (match && match.index == 0) i += match[0].length - 1; } else { for (let w = 0; w < this.customWrappers.length; w++) { if (!this.settings[this.customWrappers[w].replace("Wrapper", "Format")]) continue; const newText = this.doFormat(text, this.settings[this.customWrappers[w]], i); if (text != newText) { text = newText; i = i - this.settings[this.customWrappers[w]].length * 2; } } } } if (this.settings.closeOnSend) document.querySelector(".bf-toolbar")?.classList.remove("bf-visible"); return text; } async wrapSelection(leftWrapper, rightWrapper) { if (!rightWrapper) rightWrapper = leftWrapper; if (leftWrapper.startsWith("```")) leftWrapper = leftWrapper + "\n"; if (rightWrapper.startsWith("```")) rightWrapper = "\n" + rightWrapper; const textarea = document.querySelector(`.${TextareaClasses.textArea}`); if (!textarea) return; if (textarea.tagName === "TEXTAREA") return this.oldWrapSelection(textarea, leftWrapper, rightWrapper); const slateNode = ReactUtils.getOwnerInstance(textarea); const slate = slateNode?.ref?.current?.getSlateEditor(); if (!slate) return; let offset; if (slate.selection.anchor.offset <= slate.selection.focus.offset) { offset = slate.selection.focus.offset + leftWrapper.length; slate.apply({ type: "insert_text", text: leftWrapper, path: slate.selection.anchor.path, offset: slate.selection.anchor.offset }); slate.apply({ type: "insert_text", text: rightWrapper, path: slate.selection.focus.path, offset: slate.selection.focus.offset }); } else { offset = slate.selection.anchor.offset + leftWrapper.length; slate.apply({ type: "insert_text", text: rightWrapper, path: slate.selection.anchor.path, offset: slate.selection.anchor.offset }); slate.apply({ type: "insert_text", text: leftWrapper, path: slate.selection.focus.path, offset: slate.selection.focus.offset }); } const newSelection = { anchor: { path: slate.selection.anchor.path, offset }, focus: { path: slate.selection.focus.path, offset } }; slate.selection = newSelection; slate.apply({ type: "insert_text", text: "", path: slate.selection.anchor.path, offset }); slateNode.focus(); } oldWrapSelection(textarea, leftWrapper, rightWrapper) { let text = textarea.value; const start = textarea.selectionStart; const len = text.substring(textarea.selectionStart, textarea.selectionEnd).length; text = leftWrapper + text.substring(textarea.selectionStart, textarea.selectionEnd) + rightWrapper; textarea.focus(); document.execCommand("insertText", false, text); textarea.selectionStart = start + leftWrapper.length; textarea.selectionEnd = textarea.selectionStart + len; } getContextMenu() { return ContextMenu.buildMenu( Object.keys(languages_default).map((letter) => { return { type: "submenu", label: letter, items: Object.keys(languages_default[letter]).map((language) => { return { label: languages_default[letter][language], action: () => { this.wrapSelection("```" + language, "```"); } }; }) }; }) ); } buildToolbar() { const toolbar = DOM.parseHTML(toolbar_default2); const sorted = this.buttonOrder; for (let i = 0; i < sorted.length; i++) { const key = sorted[i].replace("Button", ""); const button = DOM.parseHTML("
"); if (!toolbar_default[key]) continue; button.classList.add(toolbar_default[key].type); UI.createTooltip(button, toolbar_default[key].name); if (!this.settings[key + "Button"]) button.classList.add("disabled"); if (key === "codeblock") { const contextMenu = this.getContextMenu(); button.addEventListener("contextmenu", (e) => { ContextMenu.open(e, contextMenu, { align: "bottom" }); }); } button.dataset.name = sorted[i].replace("Button", ""); if (this.settings.useIcons) button.innerHTML = toolbar_default[key].icon; else button.innerHTML = toolbar_default[key].displayName; toolbar.append(button); } if (!this.settings.useIcons) { toolbar.addEventListener("mousemove", (e) => { const target = e.currentTarget; const pos = e.pageX - (target.parentElement?.getBoundingClientRect()?.left ?? 0); const width = parseInt(getComputedStyle(target).width); let diff = -1 * width; Array.from(target.children).forEach((elem) => { diff += elem.offsetWidth; }); target.scrollLeft = pos / width * diff; }); } return toolbar; } setupToolbar() { document.querySelector(".bf-toolbar")?.remove(); document.querySelectorAll(`.${TextareaClasses.textArea}`).forEach((elem) => { this.addToolbar(elem.children[0]); }); } addToolbar(textarea) { const toolbarElement = this.buildToolbar(); if (this.settings.hoverOpen == true) toolbarElement.classList.add("bf-hover"); if (this.isOpen) toolbarElement.classList.add("bf-visible"); const inner = textarea.parentElement?.parentElement; if (!inner) return; inner.parentElement?.insertBefore(toolbarElement, inner.nextSibling); toolbarElement.addEventListener("click", (e) => { e.preventDefault(); e.stopPropagation(); const button = e.target.closest("div"); if (!button) return; if (button.classList.contains("bf-arrow")) { if (!this.settings.hoverOpen) this.openClose(); } else if (button.classList.contains("format")) { if (!button.dataset.name) return; let wrapper = ""; if (button.classList.contains("native-format")) wrapper = this.discordWrappers[button.dataset.name]; else wrapper = this.settings[button.dataset.name + "Wrapper"]; this.wrapSelection(wrapper); } }); this.updateStyle(); } getSettingsPanel() { return this.buildSettingsPanel(this.updateSettings.bind(this)); } updateSettings(group, id, value) { if (group == "toolbar") this.setupToolbar(); if (group == "plugin" && id == "hoverOpen") { const toolbar = document.querySelector(".bf-toolbar"); if (value) { toolbar?.classList.remove("bf-visible"); toolbar?.classList.add("bf-hover"); } else { toolbar?.classList.remove("bf-hover"); } } if (group == "style") { if (id == "icons") this.setupToolbar(); if (id == "rightSide") this.updateSide(); if (id == "toolbarOpacity") this.updateOpacity(); if (id == "fontSize") this.updateFontSize(); } } }; /*@end@*/