БлогNot. PHP: ещё одна небольшая авторасстановка тегов

PHP: ещё одна небольшая авторасстановка тегов

В очередной раз было лень расставлять теги "руками", то есть, нажимая кнопочки, вспомнил об этом простом решении, его оказалось легко адаптировать и к тому, что понадобилось сейчас.

На входе - текстовый файл в кодировке Юникода UTF-8, более-менее вычитанный, конечно. Формат для разметки должен быть максимально простым, я свой описал прямо в файле "теста", который приведу "как есть" с разрывами строк:

Если первым непустым символом строки "+" и за ним хотя бы один пробел - строка будет заголовком
и выделится капсом.
  + Заголовок, е, ё!
Строка текста, если последним словом в ней URL, станет ссылкой на этот URL.  http://blog.kislenko.net/ 
Bторой абзац, просто следом за первым...



Хотя бы одна пустая строка до и после - блок станет цитатой, а если приведён  
одинокий URL в строке, то он станет ссылкой в своём отдельном абзаце, как вот этот:
  https://www.php.net/manual/ru/function.array-push.php  
Неважно, происходит это в цитате или нет, одинокий URL останется URL, 
а абзац - абзацам, здесь делаем это в цитате

Символы "больше", "меньше" и некоторые другие неудобные, автозаменятся,
абзацы необязательно вытягивать в одну строку, началом нового абзаца 
  будет Большая буква в начале строки...
Любой не-буквенный символ, например, > в первой непустой позиции тоже откроет новый абзац, 
потому что так всегда обозначают цитирование, а также абзац может открыться двойной кавычкой, дефисом и т.д.
   Пустые строки в начале и конце файла не мешают
Тег <p> не закрываем сознательно, может быть, где-то придётся менять на <br>
 Hello, world - абзацы работают и для
английского.
https://ya.ru/ Если URL находится не последним и не единственным https://google.ru/ в строке и отделён 
хотя бы одним разделителем, он попытается "вписаться" 
в абзац, сделав якорем предыдущее или следующее слово.


 открыли новую цитатку для автозакрытия, будет ли она абзацем, 
зависит от первого непустого символа.

Вот что получилось в браузере:

вид полученной разметки в браузере
вид полученной разметки в браузере

Чтобы не использовать страшную разметку по умолчанию, проверял вот с этим небольшим стилем (файл 2021.css):

* {
 font-family: sans-serif;
}
h5 {
 margin: 5px 0; 
 font-size: 120%; 
 line-height: 120%; 
}
p {
 margin: 5px 0;
 line-height: 140%;
}
blockquote {
 margin: 5px 0;
 color: #333333;
 background-color: #F0F0F0; 
 border: 1px solid #D1D7DC;
 padding: 2px;
 line-height: 120%;
}
a[target="_blank"] { 
 background-color: #FFFFCC;
}

Вот исходник на момент написания, проверялся в актуальной сборке XAMPP с PHP 8, думаю, сюда несложно прикрутить интерфейс с загрузкой файлов, мне быстрее вставить контент в текстовый файл 1.txt из папки скрипта, который, напомню, тоже должен быть в кодировке UTF-8.

<link rel="stylesheet" type="text/css" href="2021.css">
<?php
 define ('FILENAME','1.txt');
 $file = file_get_contents (FILENAME); //Получить весь файл строкой
 if ($file === false) {
  echo '<p>Файл '.FILENAME.' не найден!</p>';
  exit;
 }
 $file = preg_replace("/^(\s*\r?\n){3,}/mu","\r\n\r\n",trim($file)); //Убрать лишние пустые строки (кроме двух)
 $file = explode ("\n", $file); //Преобразовать в массив строк
 $quoted = true;
 foreach ($file as $str) { //Для каждой строки
  $str = trim($str); //Убрать лишние разделители в начале и конце
  $str = str_replace ( //Выполнить глобальные замены
   ['<',    '>',    '\'\'', '«', '»', '…'  , '—' ],
   ['&lt;', '&gt;', '"',    '"', '"', '...', '-' ],
   $str);
  $words = preg_split ('/[\s]+/', $str); //Получить массив лексем
  $len = count($words);
  if ($words[0] == '+') { //Символ "+" в первой позиции - заголовок, делаем его КАПСом
   array_shift ($words);
   if (!count($words)) array_push ($words, 'Заголовок');
   echo '<h5>'.mb_strtoupper (implode(' ',$words),'UTF-8').'</h5>'."\n";
  }
  else if ($len == 1) {
   if (empty($str)) { //Пустая строка - открываем или закрываем цитату
    echo ($quoted ? '<blockquote>' : '</blockquote>')."\n";
    $quoted = !$quoted;
   }
   else if (filter_var($words[0], FILTER_VALIDATE_URL)) { //Отдельный URL в строке
    echo '<p><a href="'.$words[0].'" target="_blank">'.$words[0].'</a></p>'."\n";
   }
   else { //Просто отдельное слово
    echo start_delim($str).$words[0]."\n";
   }
  }
  else if ($len > 1) {
   if (filter_var($words[$len-1], FILTER_VALIDATE_URL)) { //Последнее слово в строке = URL
    echo '<p><a href="'.$words[$len-1].'" target="_blank">'.implode(' ',array_slice($words,0,$len-1)).
     '</a></p>'."\n";
   }
   else { 
    for ($i = 0; $i < $len; $i++) { //Смотрим все слова
     if (filter_var($words[$i], FILTER_VALIDATE_URL)) { //Если URL
      if ($i == 0) { //Первым в строке
       if (filter_var($words[1], FILTER_VALIDATE_URL)) {
        echo '<p>Ошибка в строке "'.$str.'", 2 URL подряд</p>';
        exit;
       }
       $words[1] = '<a href="'.$words[0].'" target="_blank">'.$words[1].'</a>';
       array_shift ($words);
       $len = count ($words);
      }
      else { //Не первым в строке
       if (filter_var($words[$i-1], FILTER_VALIDATE_URL)) {
        echo '<p>Ошибка в строке "'.$str.'", 2 URL подряд</p>';
        exit;
       }
       $words[$i-1] = '<a href="'.$words[$i].'" target="_blank">'.$words[$i-1].'</a>';
       array_splice ($words, $i, 1);
       $len = count ($words);
      }
     }
    }
    echo start_delim($words[0]).implode(' ',$words)."\n"; //Выводим слова
   }   
  }
 }
 if (!$quoted) echo '</blockquote>';

 function start_delim ($w) { //Надо ли начинать новый абзац
  $c = mb_substr ($w,0,1,'UTF-8');
  if (mb_strtoupper($c,'UTF-8')==$c) return '<p>';
  return ' ';
 }
?>

P.S. Если нужно две цитаты подряд, оставляем между ними две пустых строки:

Текст

Цитата 1,
возможно, многострочная


Цитата2

Снова текст

01.05.2021, 13:44 [215 просмотров]


теги: php css textprocessing ссылки html форматы