Заменить определенные арабские слова в текстовой строке с помощью Javascript

У меня есть текстовая строка на арабском языке, и я хочу выделить несколько слов жирным шрифтом и добавить значки перед словом

метод, который я использую для этого текста на английском языке,

var wordsToBold = ["Properties", "How To Use"];

    function makeBold(input, wordsToBold) {
        return input.replace(new RegExp('(\\b)(' + wordsToBold.join('|') + ')(\\b)', 'ig'),
            '<br><br><i class="fas fa-ellipsis-h fa-xs mr-2"></i>$1<b>$2</b>$3');
    }

Когда я использую этот метод с арабскими словами, он не работает

var wordsToBold = ["الخصائص", "طريقة الاستعمال"];

Текст для тестирования:

فرانكوا اراب الخصائص: لوريم ايبسوم دولار سيت أميت ,كونسيكتيتور أدايبا يسكينج أليايت,سيت دو أيوسمود تيمبور

أنكايديديونتيوت لابوري ات دولار ماجنا أليكيوا . طريقة الاستعمال: وت انيم أد مينيم فينايم,كيواس نوستريد

أكسير سيتاشن يللأمكو لابورأس


person Nasser Hajlawi    schedule 17.03.2021    source источник
comment
Выдает ли какие-нибудь ошибки?   -  person Masood    schedule 17.03.2021
comment
@Masood Нет, регулярное выражение вообще не распознает слова в массиве   -  person Nasser    schedule 17.03.2021


Ответы (1)


Вы можете построить свои собственные границы слов в Юникоде:

  1. Левая (ведущая) граница слова может быть определена как позиция, которой непосредственно не предшествует буква + любые возможные диакритические знаки, цифра или подчеркивание: (?<!\p{L}\p{M}*|[\p{N}_])
  2. Правый (замыкающий) образец границы слова может быть определен как позиция, за которой сразу не следует буква, цифра или символ подчеркивания: (?![\p{L}\p{N}_]).

Таким образом, вы можете использовать

var wordsToBold = ["Properties", "How To Use"];

function makeBold(input, wordsToBold) {
    return input.replace(new RegExp('(?<!\\p{L}\\p{M}*|[\\p{N}_])(?:' + wordsToBold.join('|') + ')(?![\\p{L}\\p{N}_])', 'igu'),
        '<br><br><i class="fas fa-ellipsis-h fa-xs mr-2"></i><b>$&</b>');
}
console.log(makeBold("How To Use These Properties: 00How To Use These Properties00", wordsToBold));
// => <br><br><i class="fas fa-ellipsis-h fa-xs mr-2"></i><b>How To Use</b> These <br><br><i class="fas fa-ellipsis-h fa-xs mr-2"></i><b>Properties</b>: 00How To Use These Properties00
var wordsToBold = ["الخصائص", "طريقة الاستعمال"];
var arString = `فرانكوا اراب الخصائص: لوريم ايبسوم دولار سيت أميت ,كونسيكتيتور أدايبا يسكينج أليايت,سيت دو أيوسمود تيمبور

أنكايديديونتيوت لابوري ات دولار ماجنا أليكيوا . طريقة الاستعمال: وت انيم أد مينيم فينايم,كيواس نوستريد

أكسير سيتاشن يللأمكو لابورأس`;
console.log(makeBold(arString, wordsToBold));
// => فرانكوا اراب <br><br><i class="fas fa-ellipsis-h fa-xs mr-2"></i><b>الخصائص</b>: لوريم ايبسوم دولار سيت أميت ,كونسيكتيتور أدايبا يسكينج أليايت,سيت دو أيوسمود تيمبور أنكايديديونتيوت لابوري ات دولار ماجنا أليكيوا . <br><br><i class="fas fa-ellipsis-h fa-xs mr-2"></i><b>طريقة الاستعمال</b>: وت انيم أد مينيم فينايم,كيواس نوستريد أكسير سيتاشن يللأمكو لابورأس

Если вам нужен более общий \b, поддерживающий Unicode, вы должны помнить чему на самом деле соответствует \w, поддерживающий Unicode ([\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}] ), и учитывая, что \b можно записать как (?:(?<=^)(?=\w)|(?<=\w)(?=$)|(?<=\W)(?=\w)|(?<=\w)(?=\W)), вы можете использовать следующее:

const w = String.raw`[\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]`;
const nw = String.raw`[^\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]`;
const uwb = String.raw`(?:(?<=^)(?=${w})|(?<=${w})(?=$)|(?<=${nw})(?=${w})|(?<=${w})(?=${nw}))`;
console.log(uwb);

Функция makeBold будет выглядеть так

const w = String.raw`[\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]`;
const nw = String.raw`[^\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]`;
const uwb = String.raw`(?:(?<=^)(?=${w})|(?<=${w})(?=$)|(?<=${nw})(?=${w})|(?<=${w})(?=${nw}))`;

function makeBold(input, wordsToBold) {
    return input.replace(new RegExp(`${uwb}(?:${wordsToBold.join('|')})${uwb}`, 'gu'),
        '<br><br><i class="fas fa-ellipsis-h fa-xs mr-2"></i><b>$&</b>');
}

// Test
var wordsToBold = ["الخصائص", "طريقة الاستعمال"];
var arString = `فرانكوا اراب الخصائص: لوريم ايبسوم دولار سيت أميت ,كونسيكتيتور أدايبا يسكينج أليايت,سيت دو أيوسمود تيمبور     أنكايديديونتيوت لابوري ات دولار ماجنا أليكيوا . طريقة الاستعمال: وت انيم أد مينيم فينايم,كيواس نوستريد     أكسير سيتاشن يللأمكو لابورأس`;
console.log(makeBold(arString, wordsToBold));

Обратите внимание на флаг u, который позволяет использовать классы категорий Unicode внутри RegExp шаблонов, совместимых с ECMAScript 2018+.

person Wiktor Stribiżew    schedule 17.03.2021
comment
(Не могу поверить, что вы получили отрицательный голос за этого человека ++). У меня возник вопрос из любопытства, почему на левой границе слова есть \p{M}, а на правой - нет? - person The fourth bird; 18.03.2021
comment
@Thefourthbird Поскольку диакритические знаки не используются сами по себе, они всегда являются частью символа base, который обычно является буквой, но, вероятно, может быть и цифрой. Я пока видел только диакритические знаки после букв. - person Wiktor Stribiżew; 18.03.2021
comment
Ага, теперь имеет смысл, спасибо! Я добавлю это в закладки. - person The fourth bird; 18.03.2021