/** * Asserts that the given string is valid HTML document. * * @since 1.23 * * @note Will mark the test as skipped if the "tidy" module is not installed. * @note This ignores $wgUseTidy, so we can check for valid HTML even (and especially) * when automatic tidying is disabled. * * @param string $html A complete HTML document */ protected function assertValidHtmlDocument($html) { // Note: we only validate if the tidy PHP extension is available. // In case wgTidyInternal is false, MWTidy would fall back to the command line version // of tidy. In that case however, we can not reliably detect whether a failing validation // is due to malformed HTML, or caused by tidy not being installed as a command line tool. // That would cause all HTML assertions to fail on a system that has no tidy installed. if (!$GLOBALS['wgTidyInternal'] || !MWTidy::isEnabled()) { $this->markTestSkipped('Tidy extension not installed'); } $errorBuffer = ''; MWTidy::checkErrors($html, $errorBuffer); $allErrors = preg_split('/[\\r\\n]+/', $errorBuffer); // Filter Tidy warnings which aren't useful for us. // Tidy eg. often cries about parameters missing which have actually // been deprecated since HTML4, thus we should not care about them. $errors = preg_grep('/^(.*Warning: (trimming empty|.* lacks ".*?" attribute).*|\\s*)$/m', $allErrors, PREG_GREP_INVERT); $this->assertEmpty($errors, implode("\n", $errors)); }
/** * Replace the output with an error if the HTML is not valid * * @param $s string * * @return string */ function wfHtmlValidationHandler($s) { $errors = ''; if (MWTidy::checkErrors($s, $errors)) { return $s; } header('Cache-Control: no-cache'); $out = Html::element('h1', null, 'HTML validation error'); $out .= Html::openElement('ul'); $error = strtok($errors, "\n"); $badLines = array(); while ($error !== false) { if (preg_match('/^line (\\d+)/', $error, $m)) { $lineNum = intval($m[1]); $badLines[$lineNum] = true; $out .= Html::rawElement('li', null, Html::element('a', array('href' => "#line-{$lineNum}"), $error)) . "\n"; } $error = strtok("\n"); } $out .= Html::closeElement('ul'); $out .= Html::element('pre', null, $errors); $out .= Html::openElement('ol') . "\n"; $line = strtok($s, "\n"); $i = 1; while ($line !== false) { $attrs = array(); if (isset($badLines[$i])) { $attrs['class'] = 'highlight'; $attrs['id'] = "line-{$i}"; } $out .= Html::element('li', $attrs, $line) . "\n"; $line = strtok("\n"); $i++; } $out .= Html::closeElement('ol'); $style = <<<CSS .highlight { background-color: #ffc } li { white-space: pre } CSS; $out = Html::htmlHeader(array('lang' => 'en', 'dir' => 'ltr')) . Html::rawElement('head', null, Html::element('title', null, 'HTML validation error') . Html::inlineStyle($style)) . Html::rawElement('body', null, $out) . Html::closeElement('html'); return $out; }
/** * Replace the output with an error if the HTML is not valid * * @param $s string * * @return string */ function wfHtmlValidationHandler($s) { $errors = ''; if (MWTidy::checkErrors($s, $errors)) { return $s; } header('Cache-Control: no-cache'); $out = <<<EOT <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en" dir="ltr"> <head> <title>HTML validation error</title> <style> .highlight { background-color: #ffc } li { white-space: pre } </style> </head> <body> <h1>HTML validation error</h1> <ul> EOT; $error = strtok($errors, "\n"); $badLines = array(); while ($error !== false) { if (preg_match('/^line (\\d+)/', $error, $m)) { $lineNum = intval($m[1]); $badLines[$lineNum] = true; $out .= "<li><a href=\"#line-{$lineNum}\">" . htmlspecialchars($error) . "</a></li>\n"; } $error = strtok("\n"); } $out .= '</ul>'; $out .= '<pre>' . htmlspecialchars($errors) . '</pre>'; $out .= "<ol>\n"; $line = strtok($s, "\n"); $i = 1; while ($line !== false) { if (isset($badLines[$i])) { $out .= "<li class=\"highlight\" id=\"line-{$i}\">"; } else { $out .= '<li>'; } $out .= htmlspecialchars($line) . "</li>\n"; $line = strtok("\n"); $i++; } $out .= '</ol></body></html>'; return $out; }