I’m currently working on a creative in-game text app for the game Mobile Legends. The app can change the text color you use while chatting in-game. There are also other additions like bold, italic, underline and strike through, with the final output being a code for you to input. The app is designed to be user friendly and quick to use. However, I’m having trouble with the creative aspects.
The site: https://mlcolor.netlify.app/
I made my own rich editor that uses execcommand
. I need a solution that converts HTML format (that the rich editor produces) into Mobile Legends text format.
It is the same as with HTML. Instead of <b>Hello World</b>
it uses brackets [b]Hello World[/b]
These are the formats in Mobile Legends which are very similar with HTML:
Bold: [b]Hello World[/b]
Italic: [i]Hello World[/i]
Underline: [u]Hello World[/u]
StrikeThrough: [s]Hello World[/s]
foreColor: [FF0000]Hello World
it uses hex code.
How do I convert this code (example output):
Hello World!
<b><i><u><strike>Hello World!</strike></u></i></b>
in to this:
[b][i][u][s]Hello World![/b][/i][/s]
I used a method using .replace(/<b>/g,'[b]')
. However if the format gets too complicated, the harder is to replace the tags. The code gets complicated and has many attributes.
Example of a complex format:
Lorem ipsum dolor sit
amet.
<span style="font-family: "Open Sans", 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.
You should parse the input with a DOM parser. Then walk through that DOM recursively, and check the style of each visited node to determine which tags and colour should be specified. Here is how that could work:
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: "Open Sans", 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));