Захват сообщений об ошибках на html-странице с помощью nodejs

#javascript #html #node.js #regex

#javascript #HTML #node.js #регулярное выражение

Вопрос:

Я использую Nodejs, чтобы проверить, есть ли какие-либо ошибки / предупреждения / уведомления, сгенерированные php в html-файле.

Первое, что я делаю, это фиксирую эти ошибки, используя это регулярное выражение в теге body:

const warningAndError = /(?:(?:.*n){0,0}).*?<b>(Warning|Error|Notice)</b>.*(?:(?:n.*))/gm;

Это вернет список, подобный этому :

 ["Error:  Here goes the err message on line 571",
 "Warning:  Here goes the warn message on line 700"]
  

Что я хочу сделать дальше, так это создать такой массив :

 [chalk.red.bold("Error: ")   "Here goes the err message on line 571",
 chalk.yellow.bold("Warning: ")   "Here goes the warn message on line 700"]
  

Итак, мой код выглядит так:

 const warningAndError = /(?:(?:.*n){0,0}).*?<b>(Warning|Error|Notice)</b>.*(?:(?:n.*){0,0})/gm;
const errList = [];
(body.match(warningAndError) || []).forEach((err) => {
  let strippedString = err.replace(/(<([^>] )>)/gi, "");

  if (strippedString.startsWith("Error:")) {
    errList.push(
      chalk.red.bold("Error: ")   strippedString.replace("Error:", "").trim()
    );
  }
  if (strippedString.startsWith("Warning:")) {
    errList.push(
      chalk.yellow.bold("Warning: ")   strippedString.replace("Warning:", "").trim()
    );
  }
  if (strippedString.startsWith("Notice:")) {
    errList.push(
      chalk.green.bold("Notice: ")   strippedString.replace("Notice:", "").trim()
    );
  }
});
  

Проблема, с которой я сталкиваюсь, заключается в том, что это не чисто, поэтому мне было интересно, есть ли более чистый способ сделать это, и другое дело, что для выполнения требуется много времени, более 2 секунд.

Если это поможет, вот как ошибки выглядят на HTML-странице:

     <br />
<b>Error</b>:  Here goes the err message on line <b>571</b><br />
<br />
<b>Warning</b>:  Here goes the warn message on line <b>700</b><br />
  

Заранее спасибо.

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

1. Что {0,0} предполагается делать?

2. @xehpuk если я не сделаю первое {0,0} , это вернет мне <br /> so, чтобы не захватывать строку перед строкой ошибки

3. x{0,0} означает «повторить x ноль раз», так что это то же самое, что и пустая строка. Ваше текущее регулярное выражение может быть упрощено до /.*?<b>(Warning|Error|Notice)</b>.*/gm .

Ответ №1:

Использование RegExp.prototype.exec(String) должно сделать свое дело:

 const levels = {
  Error: 'red',
  Warning: 'yellow',
  Notice: 'green'
}

const regex = new RegExp(`<b>(${Object.keys(levels).join('|')})</b>:  ([^<]*)<b>([^<]*)`, 'g')

function chalkify(html) {
  const matches = []

  let match
  while ((match = regex.exec(html)) !== null) {
    const [ , level, message, line ] = match
    matches.push(chalk[levels[level]].bold(`${level}: `)   message   line)
  }

  regex.lastIndex = 0 // reset for next invocation

  return matches
}

// "Polyfill" and test in the browser:

const chalk = {
  red: { bold: _ => `<font color="red"><b>${_}</b></font>` },
  yellow: { bold: _ => `<font color="yellow"><b>${_}</b></font>` },
  green: { bold: _ => `<font color="green"><b>${_}</b></font>` }
}

document.body.innerHTML = chalkify(document.body.innerHTML).join('<br>')  
     <br />
<b>Error</b>:  Here goes the err message on line <b>571</b><br />
<br />
<b>Warning</b>:  Here goes the warn message on line <b>700</b><br />  

Вы также можете использовать String.prototype.matchAll(RegExp) , если вы хотя бы на Node.js 12.