将 HTML 格式转换为 Mobile Legends 的 BBCode 格式

Converting HTML format to the BBCode format of Mobile Legends

我目前正在为游戏 Mobile Legends 开发一款富有创意的游戏内文本应用程序。该应用程序可以更改您在游戏中聊天时使用的文本颜色。还有其他添加,如粗体、斜体、下划线和删除线,最终输出为代码供您输入。该应用程序旨在用户友好且易于使用。但是,我在创意方面遇到了麻烦。

站点: https://mlcolor.netlify.app/

我使用 execcommand 制作了自己的富编辑器。我需要一个将 HTML 格式(富编辑器生成的)转换为 Mobile Legends 文本格式的解决方案。

Mobile Legends 格式

与HTML相同。它使用方括号 [b]Hello World[/b]

而不是 <b>Hello World</b>

这些是Mobile Legends中的格式,与HTML非常相似:

粗体:[b]Hello World[/b]

斜体:[i]Hello World[/i]

下划线:[u]Hello World[/u]

删除线:[s]Hello World[/s]

foreColor: [FF0000]Hello World 它使用十六进制代码。

问题

如何转换此代码(示例输出):

Hello World!

<b><i><u><strike>Hello World!</strike></u></i></b>

在此:

[b][i][u][s]Hello World![/b][/i][/s]

我的解决方案

我使用了一种使用.replace(/<b>/g,'[b]')的方法。但是,如果格式变得太复杂,替换标签就更难了。代码变得复杂并且有很多属性。

复杂格式示例:

Lorem ipsum dolor sit amet.

<span style="font-family: &quot;Open Sans&quot;, Arial, sans-serif; font-size: 14px; text-align: justify; background-color: rgb(255, 255, 255);"><span style="text-decoration: underline;"><font color="#a9fcd4"><i>Lo</i><b>rem</b></font></span> <i style="text-decoration: underline;"><font color="#0000cc">ipsu<b>m</b></font></i> <b style="text-decoration: underline;"><i><font color="#cc00cc">dolor</font></i></b> <u><font color="#cccc00">sit</font></u> <strike><font color="#cc00cc"><b>amet</b><i>.</i></font></strike></span><br>

Disclaimer: I’m not a professional coder by any means so I apologize for any amateur mistakes. Coding is just my spare time hobby and I decided to make this app for the Mobile Legends community since I play the game too and wanted to decorate my bio and chat text.

您应该使用 DOM 解析器解析输入。然后递归地遍历 DOM ,并检查每个访问节点的样式以确定应指定哪些标签和颜色。这是它的工作原理:

function parse(html) {
    let appliedColor = "000000";
    
    function parseNode(inheritedStyles, inheritedColor, node) {
        // Base case: a plain text node:
        if (node.nodeType === 3) {
            if (inheritedColor !== appliedColor && node.nodeValue.trim()) {
                appliedColor = inheritedColor;
                return `[${appliedColor}]${node.nodeValue}`;
            }
            return node.nodeValue;
        }
        // Transfer color HTML attribute to style attribute:
        if (node.nodeName === "FONT" && node.color) node.style.color = node.color;

        // Get relevant styles of this node
        let {color, textDecorationLine, fontWeight, fontStyle} = node.style;
        color = color || inheritedColor;

        // Determine U,S,B,I:
        let styles = {
            u: inheritedStyles.u || node.nodeName === "U" || textDecorationLine.includes("underline"),
            s: inheritedStyles.s || node.nodeName === "STRIKE" || textDecorationLine.includes("through"),
            b: inheritedStyles.b || node.nodeName === "B" || fontWeight.includes("bold") || +fontWeight >= 700,
            i: inheritedStyles.i || node.nodeName === "I" || fontStyle.includes("italic")
        };
        
        // Deal with color
        if (color.slice(0,4) === "rgb(") {
            color = color.match(/\d+/g).map(dec => (+dec).toString(16).padStart(2, "0")).join("").toUpperCase();
        }

        // Apply recursion to parse the child nodes
        let res = Array.from(node.childNodes, parseNode.bind(null, styles, color)).join("");

        // Wrap the content inside the necessary [] tags
        for (let prop in styles) {
            if (styles[prop] !== !!inheritedStyles[prop]) res = `[${prop}]${res}[\/${prop}]`;
        }
        return res;
    }
    
    return parseNode({}, "000000", new DOMParser().parseFromString(html, "text/html").body);
}

// Demo
let html = `<span style="font-family: &quot;Open Sans&quot;, Arial, sans-serif; font-size: 14px; text-align: justify; background-color: rgb(255, 255, 255);"><span style="text-decoration: underline;"><font color="#a9fcd4"><i>Lo<\/i><b>rem<\/b><\/font><\/span> <i style="text-decoration: underline;"><font color="#0000cc">ipsu<b>m<\/b><\/font><\/i> <b style="text-decoration: underline;"><i><font color="#cc00cc">dolor<\/font><\/i><\/b> <u><font color="#cccc00">sit<\/font><\/u> <strike><font color="#cc00cc"><b>amet<\/b><i>.<\/i><\/font><\/strike><\/span><br>`;

console.log(parse(html));