#javascript #arrays #reactjs #regex
#javascript #массивы #reactjs #регулярное выражение
Вопрос:
У меня есть строка, которую я извлек из api, которая выглядит следующим образом:
"If you <a href='https://example.com'>Click here</a> then <a href='https://example.net'>Click here</a>."
Я пытаюсь создать массив, который выглядит следующим образом:
[
"If you "
<a ... </a>
" then "
<a ... </a>
"."
]
По сути, я хочу отобразить его так, как это было задумано, без использования опасно установленного подхода innerHTML.
У меня уже есть совпадения регулярных выражений, я просто пытаюсь найти самый умный способ перебрать их и создать это. Я только что набрал это, но, увидев результат, понял, что он явно ошибочен, мне нужно знать, с чего начать мою подстроку на основе последнего совпадения, но, похоже, не могу разобраться, как к этому подойти. Приветствуется любое руководство
let noticeTextArr: (string | JSX.Element)[] = [];
if(notice.label !== undefined) {
const reg = /<a. ?href="(. ?)".*?>(. ?)</a>/g;
let resu<
while((result = reg.exec(notice.label)) !== null) {
if(result.index > 0) {
noticeTextArr.push(notice.label.substring(0, result.index))
}
noticeTextArr.push(<a href={result[1]}>{result[2]}</a>);
}
}
Комментарии:
1. вы можете разделить строку с помощью split, а затем выполнить цикл по массиву. если строка равна «<a>», то подождите, пока не получите </a>. вы можете создать переменную res для хранения данных. Как только вы обнаружите <a>, вставьте данные переменной res в массив. запустите цикл while, пока не получите </a>. Добавьте данные в массив.
2. Я не могу просто разделить строку, потому что я не могу доверять тому, что содержится в строке, поэтому я использую регулярное выражение для поиска совпадений и вручную создаю теги привязки.
3. если вы не доверяете источнику содержимого, то простое извлечение ссылки и их повторное создание не сделает ее более безопасной, если вы каким-то образом не подтвердите фактическое
href
содержимое.
Ответ №1:
Вот немного жутковатое, но довольно хорошо работающее регулярное выражение. Это в основном тот же подход, который вы использовали с улучшениями.
function convertToJSX(text: string) {
const regex = /<s*a[^>]*href=["']([^>]*)["'][^>]*>(.*?)<s*/s*a>/g;
const matches = text.matchAll(regex);
const noticeTextArr: (string | JSX.Element)[] = [];
let lastIndex = 0;
for (const match of matches) {
const [fullMatch, href, content] = match;
noticeTextArr.push(text.substring(lastIndex, match.index));
noticeTextArr.push(<a href={href}>{content}</a>);
lastIndex = match.index fullMatch.length;
}
if (lastIndex < text.length) {
noticeTextArr.push(text.substring(lastIndex));
}
return noticeTextArr;
}
Ответ №2:
Вы можете попробовать это:
const text = "If you <a href='https://example.com'>Click here</a> then <a href='https://example.net'>Click here</a>.";
const array = text.split(/(<a. ?href=["']. ?["'].*?>. ?</a>)/g);
Когда вы разделяете свое регулярное выражение на целую группу, js разбивает текст, возвращая также захваченные группы. Итак, я изменил регулярное выражение, чтобы удалить внутренние группы.
Ответ №3:
const data = "If you <a href='https://example.com'>Click here</a> then <a href='https://example.net'>Click here</a>."
const c = data.split(' ')
let i = 0
let res = ''
let arr = []
while(i< c.length){
if(c[i] === '<a') {
arr.push(res)
res = c[i]
i ;
while(!c[i].includes('</a>')) {
res = " " c[i]
i
}
res = " " c[i ]
arr.push(res)
res ='';
} else {
res =" " c[i ]
}
}
console.log(arr)
Ответ №4:
Используйте split
с регулярным выражением, имеющим группу захвата:
const text = "If you <a href='https://example.com'>Click here</a> then <a href='https://example.net'>Click here</a>.";
console.log(text.split(/(<as[^>]*>[^<]*</a>)/));
Посмотрите, как работает регулярное выражение
Объяснение
EXPLANATION
--------------------------------------------------------------------------------
( group and capture to 1:
--------------------------------------------------------------------------------
<a '<a'
--------------------------------------------------------------------------------
s whitespace (n, r, t, f, and " ")
--------------------------------------------------------------------------------
[^>]* any character except: '>' (0 or more
times (matching the most amount
possible))
--------------------------------------------------------------------------------
> '>'
--------------------------------------------------------------------------------
[^<]* any character except: '<' (0 or more
times (matching the most amount
possible))
--------------------------------------------------------------------------------
< '<'
--------------------------------------------------------------------------------
/ '/'
--------------------------------------------------------------------------------
a> 'a>'
--------------------------------------------------------------------------------
) end of 1
Ответ №5:
Поскольку html-элемент сложно разобрать, я бы предложил использовать Document.createElement(), чтобы браузер мог проанализировать и разделить ваш текст:
var txt = "If you <a href='https://example.com'>Click here</a> then <a href='https://example.net'>Click here</a>.";
var el = document.createElement( 'html' );
el.innerHTML = txt;
var result = Array.from(el.querySelector('body').childNodes).map(function(ele) {
return ele.nodeType == Node.TEXT_NODE ? ele.textContent : ele.outerHTML;
});
console.log(result);