Преобразование формата HTML в формат BBCode из Mobile Legends

#javascript #html #css #algorithm #fonts

#javascript #HTML #css #алгоритм #шрифты

Вопрос:

В настоящее время я работаю над креативным текстовым приложением для игры Mobile Legends. Приложение может изменять цвет текста, который вы используете во время общения в игре. Есть также другие дополнения, такие как жирный шрифт, курсив, подчеркивание и зачеркивание, при этом конечным результатом является код для ввода. Приложение разработано так, чтобы быть удобным для пользователя и быстрым в использовании. Однако у меня возникли проблемы с творческими аспектами.

Сайт: https://mlcolor.netlify.app

Я создал свой собственный богатый редактор, который использует execcommand . Мне нужно решение, которое преобразует формат HTML (который создает rich editor) в текстовый формат 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 он использует шестнадцатеричный код.

Проблема

Как мне преобразовать этот код (пример вывода):

Привет, мир!

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

в к этому:

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

Мое решение

Я использовал метод с использованием .replace(/<b>/g,'[b]') . Однако, если формат становится слишком сложным, сложнее заменить теги. Код становится сложным и имеет много атрибутов.

Пример сложного формата:

remLo ipsum dolor sit amet.

 <span style="font-family: amp;quot;Open Sansamp;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>
  

Отказ от ответственности: я ни в коем случае не профессиональный программист, поэтому приношу свои извинения
за любые любительские ошибки. Кодирование — это просто мое хобби в свободное время, и я
решил сделать это приложение для сообщества Mobile Legends, так как я играю
игра тоже хотела украсить мою биографию и текст чата.

Комментарии:

1. Является ли список возможных форматов «Mobile Legends» полным? Этот вопрос предназначен для предотвращения того, чтобы в ответе был комментарий «хорошо, теперь мне также нужно преобразовать цвет фона следующим образом, а также пространство строк, а также выравнивание, а также …»

2. Спасибо за ответ. Список возможных форматов уже завершен. Больше никаких дополнений. Спасибо!

3. Как экранируется обычный текст, если в нем есть специальные символы типа [ ?

4. Привет! Спасибо за этот вопрос. Я действительно не рассматривал эту возможность до этого. Это будет отображаться в виде обычного текста, если они добавят специальные символы, потому что я еще не закодировал для этой части. На данный момент специальный текст в моем приложении не разрешен. Я добавлю в приложение знак, говорящий об этом. Еще раз спасибо. Это заставило меня увидеть дыру в моем приложении, которую я раньше не рассматривал.

5. Как долго настройка цвета остается действительной (поскольку нет соответствующего конечного тега)? Например [b][FF0000]This[/b] test . «Тест» все еще красный?

Ответ №1:

Вы должны проанализировать входные данные с помощью анализатора 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 amp;amp; node.nodeValue.trim()) {
                appliedColor = inheritedColor;
                return `[${appliedColor}]${node.nodeValue}`;
            }
            return node.nodeValue;
        }
        // Transfer color HTML attribute to style attribute:
        if (node.nodeName === "FONT" amp;amp; 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: amp;quot;Open Sansamp;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));  

Комментарии:

1. Эй, большое вам спасибо за ответ! Это действительно сработало. Я действительно ценю вашу помощь — мне было так сложно попробовать и написать код. Как новичок, я действительно в восторге от того, как вы решили эту проблему. Было здорово учиться у вас! Еще раз, спасибо вам тысячу раз.