Преобразование HTML в обычный текст в PHP для электронной почты
Я использую TinyMCE для минимального форматирования текста на моем сайте. Из созданного HTML-кода я хотел бы преобразовать его в обычный текст для электронной почты. Я использовал класс с именем html2text, но ему действительно не хватает поддержки UTF-8, между прочим. Мне, однако, нравится, что он отображает определенные теги HTML на форматирование простого текста - например, подчеркивание текста, который ранее содержал теги в HTML.
Кто-нибудь использует аналогичный подход для преобразования HTML в обычный текст в PHP? И если это так: вы рекомендуете какие-либо сторонние классы, которые я могу использовать? Или как лучше всего решить эту проблему?
16 ответов
Используйте html2text (например, HTML в текст), лицензируемый в рамках Eclipse Public License. Он использует методы PHP DOM для загрузки из HTML, а затем перебирает полученный DOM для извлечения простого текста. Использование:
// when installed using the Composer package
$text = Html2Text\Html2Text::convert($html);
// usage when installed using html2text.php
require('html2text.php');
$text = convert_html_to_text($html);
Хотя он и неполный, он с открытым исходным кодом и приветствуется.
Проблемы с другими скриптами преобразования:
Вот другое решение:
$cleaner_input = strip_tags($text);
Для других вариантов функций очистки см.:
https://runforgithub.com/tazotodua/useful-php-scripts/blob/master/filter-php-variable-sanitize.php
Есть надежная функция strip_tags. Это не красиво, хотя. Это будет только дезинфицировать. Вы могли бы объединить это с заменой строки, чтобы получить Ваши модные подчеркивания.
<?php
// to strip all tags and wrap italics with underscore
strip_tags(str_replace(array("<i>", "</i>"), array("_", "_"), $text));
// to preserve anchors...
str_replace("|a", "<a", strip_tags(str_replace("<a", "|a", $text)));
?>
Преобразование HTML в текст с использованием DOMDocument является жизнеспособным решением. Рассмотрим HTML2Text, который требует PHP5:
- http://www.howtocreate.co.uk/php/html2texthowto.html
- http://www.howtocreate.co.uk/php/
- http://www.howtocreate.co.uk/jslibs/termsOfUse.html
Что касается UTF-8, описание на странице "Howto" гласит:
Собственная поддержка PHP для Unicode довольно плохая, и она не всегда правильно обрабатывает utf-8. Хотя в сценарии html2text используются безопасные для Unicode методы (без использования модуля mbstring), он не всегда может справиться с обработкой кодировок в PHP. PHP на самом деле не понимает юникод или кодировки, такие как utf-8, и использует базовую кодировку системы, которая, как правило, относится к семейству ISO-8859. В результате то, что может выглядеть для вас как действительный символ в текстовом редакторе, либо в utf-8, либо в однобайтовом формате, может быть неправильно интерпретировано PHP. Таким образом, даже если вы думаете, что вводите действительный символ в html2text, вполне возможно, что это не так.
Автор предлагает несколько подходов к решению этой проблемы и утверждает, что версия 2 HTML2Text (с использованием DOMDocument) имеет поддержку UTF-8.
Обратите внимание на ограничения для коммерческого использования.
Вы можете использовать lynx с опциями -stdin и -dump для достижения этого:
<?php
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("file", "/tmp/htmp2txt.log", "a") // stderr is a file to write to
);
$process = proc_open('lynx -stdin -dump 2>&1', $descriptorspec, $pipes, '/tmp', NULL);
if (is_resource($process)) {
// $pipes now looks like this:
// 0 => writeable handle connected to child stdin
// 1 => readable handle connected to child stdout
// Any error output will be appended to htmp2txt.log
$stdin = $pipes[0];
fwrite($stdin, <<<'EOT'
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>TEST</title>
</head>
<body>
<h1><span>Lorem Ipsum</span></h1>
<h4>"Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit..."</h4>
<h5>"There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain..."</h5>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque et sapien ut erat porttitor suscipit id nec dui. Nam rhoncus mauris ac dui tristique bibendum. Aliquam molestie placerat gravida. Duis vitae tortor gravida libero semper cursus eu ut tortor. Nunc id orci orci. Suspendisse potenti. Phasellus vehicula leo sed erat rutrum sed blandit purus convallis.
</p>
<p>
Aliquam feugiat, neque a tempus rhoncus, neque dolor vulputate eros, non pellentesque elit lacus ut nunc. Pellentesque vel purus libero, ultrices condimentum lorem. Nam dictum faucibus mollis. Praesent adipiscing nunc sed dui ultricies molestie. Quisque facilisis purus quis felis molestie ut accumsan felis ultricies. Curabitur euismod est id est pretium accumsan. Praesent a mi in dolor feugiat vehicula quis at elit. Mauris lacus mauris, laoreet non molestie nec, adipiscing a nulla. Nullam rutrum, libero id pellentesque tempus, erat nibh ornare dolor, id accumsan est risus at leo. In convallis felis at eros condimentum adipiscing aliquam nisi faucibus. Integer arcu ligula, porttitor in fermentum vitae, lacinia nec dui.
</p>
</body>
</html>
EOT
);
fclose($stdin);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
// It is important that you close any pipes before calling
// proc_close in order to avoid a deadlock
$return_value = proc_close($process);
echo "command returned $return_value\n";
}
Я не нашел ни одного из существующих решений, подходящих - простые электронные письма HTML к простым текстовым файлам.
Я открыл этот репозиторий, надеюсь, он кому-нибудь поможет. Лицензия MIT, кстати:)
https://github.com/RobQuistNL/SimpleHtmlToText
Пример:
$myHtml = '<b>This is HTML</b><h1>Header</h1><br/><br/>Newlines';
echo (new Parser())->parseString($myHtml);
возвращает:
**This is HTML**
### Header ###
Newlines
Вы можете проверить эту функцию
function html2text($Document) {
$Rules = array ('@<script[^>]*?>.*?</script>@si',
'@<[\/\!]*?[^<>]*?>@si',
'@([\r\n])[\s]+@',
'@&(quot|#34);@i',
'@&(amp|#38);@i',
'@&(lt|#60);@i',
'@&(gt|#62);@i',
'@&(nbsp|#160);@i',
'@&(iexcl|#161);@i',
'@&(cent|#162);@i',
'@&(pound|#163);@i',
'@&(copy|#169);@i',
'@&(reg|#174);@i',
'@&#(d+);@e'
);
$Replace = array ('',
'',
'',
'',
'&',
'<',
'>',
' ',
chr(161),
chr(162),
chr(163),
chr(169),
chr(174),
'chr()'
);
return preg_replace($Rules, $Replace, $Document);
}
public function plainText($text)
{
$text = strip_tags($text, '<br><p><li>');
$text = preg_replace ('/<[^>]*>/', PHP_EOL, $text);
return $text;
}
$text = "string 1<br>string 2<br/><ul><li>string 3</li><li>string 4</li></ul><p>string 5</p>";
echo planText($text);
выход
строка 1
строка 2
строка 3
строка 4
строка 5
Если вы хотите преобразовать специальные символы HTML, а не просто удалить их, а также вырезать их и подготовить к простому тексту, это было решением, которое сработало для меня...
function htmlToPlainText($str){
$str = str_replace(' ', ' ', $str);
$str = html_entity_decode($str, ENT_QUOTES | ENT_COMPAT , 'UTF-8');
$str = html_entity_decode($str, ENT_HTML5, 'UTF-8');
$str = html_entity_decode($str);
$str = htmlspecialchars_decode($str);
$str = strip_tags($str);
return $str;
}
$string = '<p>this is ( ) a test</p>
<div>Yes this is! & does it get "processed"? </div>'
htmlToPlainText($string);
// "this is ( ) a test. Yes this is! & does it get processed?"`
html_entity_decode w / ENT_QUOTES | ENT_XML1 преобразует такие вещи, как '
htmlspecialchars_decode преобразует такие вещи, как &
html_entity_decode преобразует такие вещи, как '<
и strip_tags удаляет все оставшиеся HTML-теги.
Markdownify преобразует HTML в Markdown, систему форматирования простого текста, используемую на этом сайте.
Я столкнулся с той же проблемой, что и ОП, и попытка некоторых решений из приведенных выше ответов не сработала для моих сценариев. Посмотрите, почему в конце.
Вместо этого я нашел этот полезный скрипт, чтобы избежать путаницы, давайте назовем его html2text_roundcube
, доступно под лицензией GPL:
Это на самом деле обновленная версия уже упомянутого скрипта - http://www.chuggnutt.com/html2text.php
- обновлено почтой RoundCube.
Использование:
$h2t = new \Html2Text\Html2Text('Hello, "<b>world</b>"');
echo $h2t->getText(); // prints Hello, "WORLD"
Зачем html2text_roundcube
оказался лучше других
скрипт
http://www.chuggnutt.com/html2text.php
не работает из коробки для случаев со специальными кодами / именами HTML (например,ä
) или непарные кавычки (например,<p>25" Monitor</p>
).скрипт
https://github.com/soundasleep/html2text
не имел возможности скрывать или группировать ссылки в конце текста, что делало обычную HTML-страницу раздутой со ссылками в текстовом формате; настройка кода для особой обработки того, как выполняется преобразование, не так проста, как простое редактирование массива вhtml2text_roundcube
,
Для текстов в utf-8 у меня работал mb_convert_encoding. Чтобы обрабатывать все, независимо от ошибок, обязательно используйте "@".
Я использую следующий базовый код:
$dom = new DOMDocument();
@$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
$body = $dom->getElementsByTagName('body')->item(0);
echo $body->textContent;
Если вам нужно что-то более продвинутое, вы можете итеративно анализировать узлы, но вы столкнетесь со многими проблемами с пробелами.
Я реализовал преобразователь, основанный на том, что я здесь говорю. Если вам интересно, вы можете скачать его с git https://github.com/kranemora/html2text
Это может послужить справкой, чтобы сделать ваш
Вы можете использовать это так:
$html = <<<EOF
<p>Welcome to <strong>html2text<strong></p>
<p>It's <em>works</em> for you?</p>
EOF;
$html2Text = new \kranemora\Html2Text\Html2Text;
$text = $html2Text->convert($html);
Если вы не хотите полностью удалять теги и хранить содержимое внутри тегов, вы можете использовать DOMDocument
и извлечь textContent
корневого узла, как это:
function html2text($html) {
$dom = new DOMDocument();
$dom->loadHTML("<body>" . strip_tags($html, '<b><a><i><div><span><p>') . "</body>");
$xpath = new DOMXPath($dom);
$node = $xpath->query('body')->item(0);
return $node->textContent; // text
}
$p = 'this is <b>test</b>. <p>how are <i>you?</i>. <a href="#">I\'m fine!</a></p>';
print html2text($p);
// this is test. how are you?. I'm fine!
Одним из преимуществ этого подхода является то, что он не требует каких-либо внешних пакетов.
Я только что нашел функцию PHP "strip_tags()" и она работает в моем случае.
Я пытался преобразовать следующий HTML:
<p><span style="font-family: 'Verdana','sans-serif'; color: black; font-size: 7.5pt;"> </span>Many practitioners are optimistic that the eyeglass and contact lens industry will recover from the recent economic storm. Did your practice feel its affects? Statistics show revenue notably declined in 2008 and 2009. But interestingly enough, those that monitor these trends state that despite the industry's lackluster performance during this time, revenue has grown at an average annual rate of 2.2% over the last five years, to $9.0 billion in 2010. So despite the downturn, how were we able to manage growth as an industry?</p>
После применения функции strip_tags () я получил следующий вывод:
&nbsp;Many practitioners are optimistic that the eyeglass and contact lens industry will recover from the recent economic storm. Did your practice feel its affects?&nbsp; Statistics show revenue notably declined in 2008 and 2009. But interestingly enough, those that monitor these trends state that despite the industry's lackluster performance during this time, revenue has grown at an average annual rate&nbsp;of 2.2% over the last five years, to $9.0 billion in 2010.&nbsp; So despite the downturn, how were we able to manage growth as an industry?
Markdownify работал замечательно для меня! что следует упомянуть об этом: он прекрасно поддерживает utf-8, что и было главной причиной, по которой я искал другое решение, кроме html2text (что упоминалось ранее в этой теме).
Вы можете попробовать это, весь скрипт и демо в одном файле.
$html ="<h1>Hi Sandeep!</h1>
<p>This is some e-mail content in html.
Even though it has whitespace and newlines, the e-mail converter
will handle it correctly.
<p>Even mismatched tags.</p>
<div>A div</div>
<div>Another div</div>
<div>A div<div>within a div</div></div>";
$Html2Text = new Html2Text();
$text = $Html2Text->convert($html);
echo '<pre>'; print_r($text); die();
class Html2Text {
/** @return array<string, bool | string> */
public static function defaultOptions(): array {
return [
'ignore_errors' => false,
'drop_links' => false,
'char_set' => 'auto'
];
}
/**
* Tries to convert the given HTML into a plain text format - best suited for
* e-mail display, etc.
*
* <p>In particular, it tries to maintain the following features:
* <ul>
* <li>Links are maintained, with the 'href' copied over
* <li>Information in the <head> is lost
* </ul>
*
* @param string $html the input HTML
* @param boolean|array<string, bool | string> $options if boolean, Ignore xml parsing errors, else ['ignore_errors' => false, 'drop_links' => false, 'char_set' => 'auto']
* @return string the HTML converted, as best as possible, to text
* @throws Html2TextException if the HTML could not be loaded as a {@link \DOMDocument}
*/
public static function convert(string $html, $options = []): string {
if ($options === false || $options === true) {
// Using old style (< 1.0) of passing in options
$options = ['ignore_errors' => $options];
}
$options = array_merge(static::defaultOptions(), $options);
// check all options are valid
foreach ($options as $key => $value) {
if (!in_array($key, array_keys(static::defaultOptions()))) {
throw new \InvalidArgumentException("Unknown html2text option '$key'. Valid options are " . implode(',', static::defaultOptions()));
}
}
$is_office_document = self::isOfficeDocument($html);
if ($is_office_document) {
// remove office namespace
$html = str_replace(["<o:p>", "</o:p>"], "", $html);
}
$html = self::fixNewlines($html);
// use mb_convert_encoding for legacy versions of php
if (PHP_MAJOR_VERSION * 10 + PHP_MINOR_VERSION < 81 && mb_detect_encoding($html, "UTF-8", true)) {
$html = mb_convert_encoding($html, "HTML-ENTITIES", "UTF-8");
}
$doc = self::getDocument($html, $options);
$output = self::iterateOverNode($doc, null, false, $is_office_document, $options);
// process output for whitespace/newlines
$output = self::processWhitespaceNewlines($output);
return $output;
}
/**
* Unify newlines; in particular, \r\n becomes \n, and
* then \r becomes \n. This means that all newlines (Unix, Windows, Mac)
* all become \ns.
*
* @param string $text text with any number of \r, \r\n and \n combinations
* @return string the fixed text
*/
public static function fixNewlines(string $text): string {
// replace \r\n to \n
$text = str_replace("\r\n", "\n", $text);
// remove \rs
$text = str_replace("\r", "\n", $text);
return $text;
}
/** @return array<string> */
public static function nbspCodes(): array {
return [
"\xc2\xa0",
"\u00a0",
];
}
/** @return array<string> */
public static function zwnjCodes(): array {
return [
"\xe2\x80\x8c",
"\u200c",
];
}
/**
* Remove leading or trailing spaces and excess empty lines from provided multiline text
*
* @param string $text multiline text any number of leading or trailing spaces or excess lines
* @return string the fixed text
*/
public static function processWhitespaceNewlines(string $text): string {
// remove excess spaces around tabs
$text = preg_replace("/ *\t */im", "\t", $text);
// remove leading whitespace
$text = ltrim($text);
// remove leading spaces on each line
$text = preg_replace("/\n[ \t]*/im", "\n", $text);
// convert non-breaking spaces to regular spaces to prevent output issues,
// do it here so they do NOT get removed with other leading spaces, as they
// are sometimes used for indentation
$text = self::renderText($text);
// remove trailing whitespace
$text = rtrim($text);
// remove trailing spaces on each line
$text = preg_replace("/[ \t]*\n/im", "\n", $text);
// unarmor pre blocks
$text = self::fixNewLines($text);
// remove unnecessary empty lines
$text = preg_replace("/\n\n\n*/im", "\n\n", $text);
return $text;
}
/**
* Can we guess that this HTML is generated by Microsoft Office?
*/
public static function isOfficeDocument(string $html): bool {
return strpos($html, "urn:schemas-microsoft-com:office") !== false;
}
public static function isWhitespace(string $text): bool {
return strlen(trim(self::renderText($text), "\n\r\t ")) === 0;
}
/**
* Parse HTML into a DOMDocument
*
* @param string $html the input HTML
* @param array<string, bool | string> $options
* @return \DOMDocument the parsed document tree
*/
private static function getDocument(string $html, array $options): \DOMDocument {
$doc = new \DOMDocument();
$html = trim($html);
if (!$html) {
// DOMDocument doesn't support empty value and throws an error
// Return empty document instead
return $doc;
}
if ($html[0] !== '<') {
// If HTML does not begin with a tag, we put a body tag around it.
// If we do not do this, PHP will insert a paragraph tag around
// the first block of text for some reason which can mess up
// the newlines. See pre.html test for an example.
$html = '<body>' . $html . '</body>';
}
$header = '';
// use char sets for modern versions of php
if (PHP_MAJOR_VERSION * 10 + PHP_MINOR_VERSION >= 81) {
// use specified char_set, or auto detect if not set
$char_set = ! empty($options['char_set']) ? $options['char_set'] : 'auto';
if ('auto' === $char_set) {
$char_set = mb_detect_encoding($html);
} else if (strpos($char_set, ',')) {
mb_detect_order($char_set);
$char_set = mb_detect_encoding($html);
}
// turn off error detection for Windows-1252 legacy html
if (strpos($char_set, '1252')) {
$options['ignore_errors'] = true;
}
$header = '<?xml version="1.0" encoding="' . $char_set . '">';
}
if (! empty($options['ignore_errors'])) {
$doc->strictErrorChecking = false;
$doc->recover = true;
$doc->xmlStandalone = true;
$old_internal_errors = libxml_use_internal_errors(true);
$load_result = $doc->loadHTML($header . $html, LIBXML_NOWARNING | LIBXML_NOERROR | LIBXML_NONET | LIBXML_PARSEHUGE);
libxml_use_internal_errors($old_internal_errors);
}
else {
$load_result = $doc->loadHTML($header . $html);
}
if (!$load_result) {
throw new Html2TextException("Could not load HTML - badly formed?", $html);
}
return $doc;
}
/**
* Replace any special characters with simple text versions, to prevent output issues:
* - Convert non-breaking spaces to regular spaces; and
* - Convert zero-width non-joiners to '' (nothing).
*
* This is to match our goal of rendering documents as they would be rendered
* by a browser.
*/
private static function renderText(string $text): string {
$text = str_replace(self::nbspCodes(), " ", $text);
$text = str_replace(self::zwnjCodes(), "", $text);
return $text;
}
private static function nextChildName(?\DOMNode $node): ?string {
// get the next child
$nextNode = $node->nextSibling;
while ($nextNode != null) {
if ($nextNode instanceof \DOMText) {
if (!self::isWhitespace($nextNode->wholeText)) {
break;
}
}
if ($nextNode instanceof \DOMElement) {
break;
}
$nextNode = $nextNode->nextSibling;
}
$nextName = null;
if (($nextNode instanceof \DOMElement || $nextNode instanceof \DOMText) && $nextNode != null) {
$nextName = strtolower($nextNode->nodeName);
}
return $nextName;
}
/** @param array<string, bool | string> $options */
private static function iterateOverNode(\DOMNode $node, ?string $prevName, bool $in_pre, bool $is_office_document, array $options): string {
if ($node instanceof \DOMText) {
// Replace whitespace characters with a space (equivilant to \s)
if ($in_pre) {
$text = "\n" . trim(self::renderText($node->wholeText), "\n\r\t ") . "\n";
// Remove trailing whitespace only
$text = preg_replace("/[ \t]*\n/im", "\n", $text);
// armor newlines with \r.
return str_replace("\n", "\r", $text);
}
$text = self::renderText($node->wholeText);
$text = preg_replace("/[\\t\\n\\f\\r ]+/im", " ", $text);
if (!self::isWhitespace($text) && ($prevName == 'p' || $prevName == 'div')) {
return "\n" . $text;
}
return $text;
}
if ($node instanceof \DOMDocumentType || $node instanceof \DOMProcessingInstruction) {
// ignore
return "";
}
$name = strtolower($node->nodeName);
$nextName = self::nextChildName($node);
// start whitespace
switch ($name) {
case "hr":
$prefix = '';
if ($prevName != null) {
$prefix = "\n";
}
return $prefix . "---------------------------------------------------------------\n";
case "style":
case "head":
case "title":
case "meta":
case "script":
// ignore these tags
return "";
case "h1":
case "h2":
case "h3":
case "h4":
case "h5":
case "h6":
case "ol":
case "ul":
case "pre":
// add two newlines
$output = "\n\n";
break;
case "td":
case "th":
// add tab char to separate table fields
$output = "\t";
break;
case "p":
// Microsoft exchange emails often include HTML which, when passed through
// html2text, results in lots of double line returns everywhere.
//
// To fix this, for any p element with a className of `MsoNormal` (the standard
// classname in any Microsoft export or outlook for a paragraph that behaves
// like a line return) we skip the first line returns and set the name to br.
// @phpstan-ignore-next-line
if ($is_office_document && $node->getAttribute('class') == 'MsoNormal') {
$output = "";
$name = 'br';
break;
}
// add two lines
$output = "\n\n";
break;
case "tr":
// add one line
$output = "\n";
break;
case "div":
$output = "";
if ($prevName !== null) {
// add one line
$output .= "\n";
}
break;
case "li":
$output = "- ";
break;
default:
// print out contents of unknown tags
$output = "";
break;
}
// debug
//$output .= "[$name,$nextName]";
if (isset($node->childNodes)) {
$n = $node->childNodes->item(0);
$previousSiblingNames = [];
$previousSiblingName = null;
$parts = [];
$trailing_whitespace = 0;
while ($n != null) {
$text = self::iterateOverNode($n, $previousSiblingName, $in_pre || $name == 'pre', $is_office_document, $options);
// Pass current node name to next child, as previousSibling does not appear to get populated
if ($n instanceof \DOMDocumentType
|| $n instanceof \DOMProcessingInstruction
|| ($n instanceof \DOMText && self::isWhitespace($text))) {
// Keep current previousSiblingName, these are invisible
$trailing_whitespace++;
}
else {
$previousSiblingName = strtolower($n->nodeName);
$previousSiblingNames[] = $previousSiblingName;
$trailing_whitespace = 0;
}
$node->removeChild($n);
$n = $node->childNodes->item(0);
$parts[] = $text;
}
// Remove trailing whitespace, important for the br check below
while ($trailing_whitespace-- > 0) {
array_pop($parts);
}
// suppress last br tag inside a node list if follows text
$last_name = array_pop($previousSiblingNames);
if ($last_name === 'br') {
$last_name = array_pop($previousSiblingNames);
if ($last_name === '#text') {
array_pop($parts);
}
}
$output .= implode('', $parts);
}
// end whitespace
switch ($name) {
case "h1":
case "h2":
case "h3":
case "h4":
case "h5":
case "h6":
case "pre":
case "p":
// add two lines
$output .= "\n\n";
break;
case "br":
// add one line
$output .= "\n";
break;
case "div":
break;
case "a":
// links are returned in [text](link) format
// @phpstan-ignore-next-line
$href = $node->getAttribute("href");
$output = trim($output);
// remove double [[ ]] s from linking images
if (substr($output, 0, 1) == "[" && substr($output, -1) == "]") {
$output = substr($output, 1, strlen($output) - 2);
// for linking images, the title of the <a> overrides the title of the <img>
// @phpstan-ignore-next-line
if ($node->getAttribute("title")) {
// @phpstan-ignore-next-line
$output = $node->getAttribute("title");
}
}
// if there is no link text, but a title attr
// @phpstan-ignore-next-line
if (!$output && $node->getAttribute("title")) {
// @phpstan-ignore-next-line
$output = $node->getAttribute("title");
}
if ($href == null) {
// it doesn't link anywhere
// @phpstan-ignore-next-line
if ($node->getAttribute("name") != null) {
if ($options['drop_links']) {
$output = "$output";
} else {
$output = "[$output]";
}
}
} else {
if ($href == $output || $href == "mailto:$output" || $href == "http://$output" || $href == "https://$output") {
// link to the same address: just use link
$output = "$output";
} else {
// replace it
if ($output) {
if ($options['drop_links']) {
$output = "$output";
} else {
$output = "[$output]($href)";
}
} else {
// empty string
$output = "$href";
}
}
}
// does the next node require additional whitespace?
switch ($nextName) {
case "h1": case "h2": case "h3": case "h4": case "h5": case "h6":
$output .= "\n";
break;
}
break;
case "img":
// @phpstan-ignore-next-line
if ($node->getAttribute("title")) {
// @phpstan-ignore-next-line
$output = "[" . $node->getAttribute("title") . "]";
// @phpstan-ignore-next-line
} elseif ($node->getAttribute("alt")) {
// @phpstan-ignore-next-line
$output = "[" . $node->getAttribute("alt") . "]";
} else {
$output = "";
}
break;
case "li":
$output .= "\n";
break;
case "blockquote":
// process quoted text for whitespace/newlines
$output = self::processWhitespaceNewlines($output);
// add leading newline
$output = "\n" . $output;
// prepend '> ' at the beginning of all lines
$output = preg_replace("/\n/im", "\n> ", $output);
// replace leading '> >' with '>>'
$output = preg_replace("/\n> >/im", "\n>>", $output);
// add another leading newline and trailing newlines
$output = "\n" . $output . "\n\n";
break;
default:
// do nothing
}
return $output;
}
}