private static function listToText(string $text) : string { static $symbols = ['#', '*', 'o', '+']; preg_match_all('~(?:<[a-z][a-z0-9]*[^>]*(?: /)?>)|(?:</[a-z][a-z0-9]*>)|(?:<![^>]+>)|(?:[^<]+)~i', $text, $matches); $text = ''; $ulLevel = 0; $olLevel = 0; $olLiCount = []; $path = []; foreach ($matches[0] as $textPart) { if (0 === stripos($textPart, '<ol')) { array_push($path, 'ol'); $olLevel++; $olLiCount[$olLevel] = 1; $textPart = "\n\n"; } elseif ('</ol>' === strtolower($textPart)) { array_pop($path); $olLevel--; $textPart = "\n\n"; } elseif (0 === stripos($textPart, '<ul')) { array_push($path, 'ul'); $ulLevel++; $textPart = "\n\n"; } elseif ('</ul>' === strtolower($textPart)) { array_pop($path); $ulLevel--; $textPart = "\n\n"; } elseif (0 === stripos($textPart, '<li')) { $textPart = str_repeat("\t", $olLevel + $ulLevel); if ('ul' === end($path)) { $textPart .= $symbols[$ulLevel % 4] . ' '; } elseif ('ol' === end($path)) { $textPart .= $olLiCount[$olLevel] . '. '; $olLiCount[$olLevel]++; } } elseif ('</li>' === strtolower($textPart)) { $textPart = "\n"; } $text .= $textPart; } return $text; }