fixes fixes...
This commit is contained in:
parent
24b3788493
commit
f093791c14
|
|
@ -249,6 +249,11 @@ article > header, article > footer {
|
||||||
color: #111;
|
color: #111;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
|
/* Добавляем эти свойства для правильного отображения переносов */
|
||||||
|
white-space: pre-wrap; /* Сохраняет пробелы и переносы строк, переносит текст */
|
||||||
|
word-wrap: break-word; /* Переносит длинные слова */
|
||||||
|
overflow-wrap: break-word; /* Альтернативное название word-wrap */
|
||||||
|
tab-size: 4; /* Размер табуляции */
|
||||||
}
|
}
|
||||||
|
|
||||||
#content:focus {
|
#content:focus {
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,21 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
let originalStyles = {};
|
let originalStyles = {};
|
||||||
let isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
let isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
||||||
|
|
||||||
|
|
||||||
|
function normalizeContent(text) {
|
||||||
|
// Заменяем множественные переносы на двойные
|
||||||
|
text = text.replace(/\n{3,}/g, '\n\n');
|
||||||
|
// Убираем пустые строки в начале и конце
|
||||||
|
return text.trim();
|
||||||
|
}
|
||||||
|
|
||||||
initEditor();
|
initEditor();
|
||||||
|
|
||||||
function initEditor() {
|
function initEditor() {
|
||||||
|
// Нормализуем контент при загрузке
|
||||||
|
if (contentTextarea.value) {
|
||||||
|
contentTextarea.value = normalizeContent(contentTextarea.value);
|
||||||
|
}
|
||||||
autoResize();
|
autoResize();
|
||||||
contentTextarea.addEventListener('input', autoResize);
|
contentTextarea.addEventListener('input', autoResize);
|
||||||
contentTextarea.addEventListener('input', processDialogues);
|
contentTextarea.addEventListener('input', processDialogues);
|
||||||
|
|
|
||||||
|
|
@ -174,26 +174,139 @@ class ChapterController extends BaseController {
|
||||||
|
|
||||||
public function preview() {
|
public function preview() {
|
||||||
$this->requireLogin();
|
$this->requireLogin();
|
||||||
|
|
||||||
require_once 'includes/parsedown/ParsedownExtra.php';
|
require_once 'includes/parsedown/ParsedownExtra.php';
|
||||||
$Parsedown = new ParsedownExtra();
|
$Parsedown = new ParsedownExtra();
|
||||||
|
|
||||||
$content = $_POST['content'] ?? '';
|
$content = $_POST['content'] ?? '';
|
||||||
$title = $_POST['title'] ?? 'Предпросмотр';
|
$title = $_POST['title'] ?? 'Предпросмотр';
|
||||||
$editor_type = $_POST['editor_type'] ?? 'markdown';
|
$editor_type = $_POST['editor_type'] ?? 'markdown';
|
||||||
|
|
||||||
// Обрабатываем контент в зависимости от типа редактора
|
// Обрабатываем контент в зависимости от типа редактора
|
||||||
if ($editor_type == 'markdown') {
|
if ($editor_type == 'markdown') {
|
||||||
$html_content = $Parsedown->text($content);
|
// Нормализуем Markdown перед преобразованием
|
||||||
|
$normalized_content = $this->normalizeMarkdownContent($content);
|
||||||
|
$html_content = $Parsedown->text($normalized_content);
|
||||||
} else {
|
} else {
|
||||||
$html_content = $content;
|
// Для HTML редактора нормализуем контент
|
||||||
|
$normalized_content = $this->normalizeHtmlContent($content);
|
||||||
|
$html_content = $normalized_content;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->render('chapters/preview', [
|
$this->render('chapters/preview', [
|
||||||
'content' => $html_content,
|
'content' => $html_content,
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'page_title' => "Предпросмотр: " . e($title)
|
'page_title' => "Предпросмотр: " . e($title)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function normalizeMarkdownContent($markdown) {
|
||||||
|
// Нормализация Markdown - убеждаемся, что есть пустые строки между абзацами
|
||||||
|
$lines = explode("\n", $markdown);
|
||||||
|
$normalized = [];
|
||||||
|
$inParagraph = false;
|
||||||
|
|
||||||
|
foreach ($lines as $line) {
|
||||||
|
$trimmed = trim($line);
|
||||||
|
|
||||||
|
if (empty($trimmed)) {
|
||||||
|
// Пустая строка - конец абзаца
|
||||||
|
if ($inParagraph) {
|
||||||
|
$normalized[] = '';
|
||||||
|
$inParagraph = false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем, не является ли строка началом списка
|
||||||
|
if (preg_match('/^[\*\-\+] /', $line) || preg_match('/^\d+\./', $line)) {
|
||||||
|
if ($inParagraph) {
|
||||||
|
$normalized[] = ''; // Завершаем предыдущий абзац
|
||||||
|
$inParagraph = false;
|
||||||
|
}
|
||||||
|
$normalized[] = $line;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем, не является ли строка началом цитаты
|
||||||
|
if (preg_match('/^> /', $line) || preg_match('/^— /', $line)) {
|
||||||
|
if ($inParagraph) {
|
||||||
|
$normalized[] = ''; // Завершаем предыдущий абзац
|
||||||
|
$inParagraph = false;
|
||||||
|
}
|
||||||
|
$normalized[] = $line;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем, не является ли строка заголовком
|
||||||
|
if (preg_match('/^#+ /', $line)) {
|
||||||
|
if ($inParagraph) {
|
||||||
|
$normalized[] = ''; // Завершаем предыдущий абзац
|
||||||
|
$inParagraph = false;
|
||||||
|
}
|
||||||
|
$normalized[] = $line;
|
||||||
|
$normalized[] = ''; // Пустая строка после заголовка
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Непустая строка - часть абзаца
|
||||||
|
if (!$inParagraph && !empty($normalized) && end($normalized) !== '') {
|
||||||
|
// Добавляем пустую строку перед новым абзацем
|
||||||
|
$normalized[] = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$normalized[] = $line;
|
||||||
|
$inParagraph = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode("\n", $normalized);
|
||||||
|
}
|
||||||
|
|
||||||
|
// И метод для нормализации HTML контента
|
||||||
|
private function normalizeHtmlContent($html) {
|
||||||
|
// Оборачиваем текст без тегов в <p>
|
||||||
|
if (!preg_match('/<[^>]+>/', $html) && trim($html) !== '') {
|
||||||
|
$lines = explode("\n", trim($html));
|
||||||
|
$wrapped = [];
|
||||||
|
$inParagraph = false;
|
||||||
|
|
||||||
|
foreach ($lines as $line) {
|
||||||
|
$trimmed = trim($line);
|
||||||
|
|
||||||
|
if (empty($trimmed)) {
|
||||||
|
if ($inParagraph) {
|
||||||
|
$wrapped[] = '</p>';
|
||||||
|
$inParagraph = false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем на начало списка
|
||||||
|
if (preg_match('/^[\*\-\+] /', $trimmed) || preg_match('/^\d+\./', $trimmed)) {
|
||||||
|
if ($inParagraph) {
|
||||||
|
$wrapped[] = '</p>';
|
||||||
|
$inParagraph = false;
|
||||||
|
}
|
||||||
|
// Обрабатываем списки отдельно
|
||||||
|
$wrapped[] = '<ul><li>' . htmlspecialchars($trimmed) . '</li></ul>';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$inParagraph) {
|
||||||
|
$wrapped[] = '<p>' . htmlspecialchars($trimmed);
|
||||||
|
$inParagraph = true;
|
||||||
|
} else {
|
||||||
|
$wrapped[] = htmlspecialchars($trimmed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($inParagraph) {
|
||||||
|
$wrapped[] = '</p>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode("\n", $wrapped);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
46
index.php
46
index.php
|
|
@ -2,6 +2,52 @@
|
||||||
// index.php - единая точка входа
|
// index.php - единая точка входа
|
||||||
require_once 'config/config.php';
|
require_once 'config/config.php';
|
||||||
|
|
||||||
|
// Получаем путь к запрашиваемому ресурсу
|
||||||
|
$requestUri = $_SERVER['REQUEST_URI'];
|
||||||
|
$requestPath = parse_url($requestUri, PHP_URL_PATH);
|
||||||
|
|
||||||
|
// Убираем базовый URL (SITE_URL) из пути
|
||||||
|
$basePath = parse_url(SITE_URL, PHP_URL_PATH) ?? '';
|
||||||
|
if ($basePath && strpos($requestPath, $basePath) === 0) {
|
||||||
|
$requestPath = substr($requestPath, strlen($basePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Убираем ведущий слеш
|
||||||
|
$requestPath = ltrim($requestPath, '/');
|
||||||
|
|
||||||
|
// Проверяем, существует ли запрашиваемый файл
|
||||||
|
$physicalPath = __DIR__ . '/' . $requestPath;
|
||||||
|
if (file_exists($physicalPath) && !is_dir($physicalPath) && !str_contains($physicalPath, '..')) {
|
||||||
|
// Определяем MIME-тип
|
||||||
|
$mimeTypes = [
|
||||||
|
'css' => 'text/css',
|
||||||
|
'js' => 'application/javascript',
|
||||||
|
'png' => 'image/png',
|
||||||
|
'jpg' => 'image/jpeg',
|
||||||
|
'jpeg' => 'image/jpeg',
|
||||||
|
'gif' => 'image/gif',
|
||||||
|
'webp' => 'image/webp',
|
||||||
|
'svg' => 'image/svg+xml',
|
||||||
|
'ico' => 'image/x-icon',
|
||||||
|
'json' => 'application/json',
|
||||||
|
'woff' => 'font/woff',
|
||||||
|
'woff2' => 'font/woff2',
|
||||||
|
'ttf' => 'font/ttf',
|
||||||
|
'eot' => 'application/vnd.ms-fontobject',
|
||||||
|
];
|
||||||
|
|
||||||
|
$extension = strtolower(pathinfo($physicalPath, PATHINFO_EXTENSION));
|
||||||
|
if (isset($mimeTypes[$extension])) {
|
||||||
|
header('Content-Type: ' . $mimeTypes[$extension]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запрещаем кэширование для разработки, в продакшене можно увеличить время
|
||||||
|
header('Cache-Control: public, max-age=3600');
|
||||||
|
|
||||||
|
// Отправляем файл
|
||||||
|
readfile($physicalPath);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
// Простой роутер
|
// Простой роутер
|
||||||
class Router {
|
class Router {
|
||||||
private $routes = [];
|
private $routes = [];
|
||||||
|
|
|
||||||
|
|
@ -363,14 +363,20 @@ private function convertContent($content, $from_editor, $to_editor) {
|
||||||
// Базовая конвертация HTML в Markdown
|
// Базовая конвертация HTML в Markdown
|
||||||
$markdown = $html;
|
$markdown = $html;
|
||||||
|
|
||||||
// Обрабатываем абзацы - заменяем на двойные переносы строк
|
// 1. Сначала обрабатываем абзацы - заменяем на двойные переносы строк
|
||||||
$markdown = preg_replace('/<p[^>]*>(.*?)<\/p>/is', "$1\n\n", $markdown);
|
$markdown = preg_replace_callback('/<p[^>]*>(.*?)<\/p>/is', function($matches) {
|
||||||
|
$content = trim($matches[1]);
|
||||||
|
if (!empty($content)) {
|
||||||
|
return $content . "\n\n";
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}, $markdown);
|
||||||
|
|
||||||
// Обрабатываем разрывы строк
|
// 2. Обрабатываем разрывы строк
|
||||||
$markdown = preg_replace('/<br[^>]*>\s*<\/br[^>]*>/i', "\n", $markdown);
|
$markdown = preg_replace('/<br[^>]*>\s*<\/br[^>]*>/i', "\n", $markdown);
|
||||||
$markdown = preg_replace('/<br[^>]*>/i', " \n", $markdown); // Два пробела для Markdown разрыва
|
$markdown = preg_replace('/<br[^>]*>/i', " \n", $markdown); // Два пробела для Markdown разрыва
|
||||||
|
|
||||||
// Заголовки
|
// 3. Заголовки
|
||||||
$markdown = preg_replace('/<h1[^>]*>(.*?)<\/h1>/is', "# $1\n\n", $markdown);
|
$markdown = preg_replace('/<h1[^>]*>(.*?)<\/h1>/is', "# $1\n\n", $markdown);
|
||||||
$markdown = preg_replace('/<h2[^>]*>(.*?)<\/h2>/is', "## $1\n\n", $markdown);
|
$markdown = preg_replace('/<h2[^>]*>(.*?)<\/h2>/is', "## $1\n\n", $markdown);
|
||||||
$markdown = preg_replace('/<h3[^>]*>(.*?)<\/h3>/is', "### $1\n\n", $markdown);
|
$markdown = preg_replace('/<h3[^>]*>(.*?)<\/h3>/is', "### $1\n\n", $markdown);
|
||||||
|
|
@ -378,49 +384,95 @@ private function convertContent($content, $from_editor, $to_editor) {
|
||||||
$markdown = preg_replace('/<h5[^>]*>(.*?)<\/h5>/is', "##### $1\n\n", $markdown);
|
$markdown = preg_replace('/<h5[^>]*>(.*?)<\/h5>/is', "##### $1\n\n", $markdown);
|
||||||
$markdown = preg_replace('/<h6[^>]*>(.*?)<\/h6>/is', "###### $1\n\n", $markdown);
|
$markdown = preg_replace('/<h6[^>]*>(.*?)<\/h6>/is', "###### $1\n\n", $markdown);
|
||||||
|
|
||||||
// Жирный текст
|
// 4. Жирный текст
|
||||||
$markdown = preg_replace('/<strong[^>]*>(.*?)<\/strong>/is', '**$1**', $markdown);
|
$markdown = preg_replace('/<strong[^>]*>(.*?)<\/strong>/is', '**$1**', $markdown);
|
||||||
$markdown = preg_replace('/<b[^>]*>(.*?)<\/b>/is', '**$1**', $markdown);
|
$markdown = preg_replace('/<b[^>]*>(.*?)<\/b>/is', '**$1**', $markdown);
|
||||||
|
|
||||||
// Курсив
|
// 5. Курсив
|
||||||
$markdown = preg_replace('/<em[^>]*>(.*?)<\/em>/is', '*$1*', $markdown);
|
$markdown = preg_replace('/<em[^>]*>(.*?)<\/em>/is', '*$1*', $markdown);
|
||||||
$markdown = preg_replace('/<i[^>]*>(.*?)<\/i>/is', '*$1*', $markdown);
|
$markdown = preg_replace('/<i[^>]*>(.*?)<\/i>/is', '*$1*', $markdown);
|
||||||
|
|
||||||
// Подчеркивание (не стандартно в Markdown, но обрабатываем)
|
// 6. Зачеркивание
|
||||||
$markdown = preg_replace('/<u[^>]*>(.*?)<\/u>/is', '<u>$1</u>', $markdown);
|
|
||||||
|
|
||||||
// Зачеркивание
|
|
||||||
$markdown = preg_replace('/<s[^>]*>(.*?)<\/s>/is', '~~$1~~', $markdown);
|
$markdown = preg_replace('/<s[^>]*>(.*?)<\/s>/is', '~~$1~~', $markdown);
|
||||||
$markdown = preg_replace('/<strike[^>]*>(.*?)<\/strike>/is', '~~$1~~', $markdown);
|
$markdown = preg_replace('/<strike[^>]*>(.*?)<\/strike>/is', '~~$1~~', $markdown);
|
||||||
$markdown = preg_replace('/<del[^>]*>(.*?)<\/del>/is', '~~$1~~', $markdown);
|
$markdown = preg_replace('/<del[^>]*>(.*?)<\/del>/is', '~~$1~~', $markdown);
|
||||||
|
|
||||||
// Списки
|
// 7. Списки
|
||||||
$markdown = preg_replace('/<li[^>]*>(.*?)<\/li>/is', '- $1', $markdown);
|
$markdown = preg_replace('/<li[^>]*>(.*?)<\/li>/is', "- $1\n", $markdown);
|
||||||
$markdown = preg_replace('/<ul[^>]*>(.*?)<\/ul>/is', "$1\n", $markdown);
|
|
||||||
$markdown = preg_replace('/<ol[^>]*>(.*?)<\/ol>/is', "$1\n", $markdown);
|
|
||||||
|
|
||||||
// Блочные цитаты
|
// Обработка вложенных списков
|
||||||
$markdown = preg_replace('/<blockquote[^>]*>(.*?)<\/blockquote>/is', "> $1\n", $markdown);
|
$markdown = preg_replace('/<ul[^>]*>(.*?)<\/ul>/is', "\n$1\n", $markdown);
|
||||||
|
$markdown = preg_replace('/<ol[^>]*>(.*?)<\/ol>/is', "\n$1\n", $markdown);
|
||||||
|
|
||||||
// Код
|
// 8. Блочные цитаты
|
||||||
|
$markdown = preg_replace('/<blockquote[^>]*>(.*?)<\/blockquote>/is', "> $1\n\n", $markdown);
|
||||||
|
|
||||||
|
// 9. Код
|
||||||
$markdown = preg_replace('/<code[^>]*>(.*?)<\/code>/is', '`$1`', $markdown);
|
$markdown = preg_replace('/<code[^>]*>(.*?)<\/code>/is', '`$1`', $markdown);
|
||||||
|
$markdown = preg_replace('/<pre[^>]*><code[^>]*>(.*?)<\/code><\/pre>/is', "```\n$1\n```", $markdown);
|
||||||
$markdown = preg_replace('/<pre[^>]*>(.*?)<\/pre>/is', "```\n$1\n```", $markdown);
|
$markdown = preg_replace('/<pre[^>]*>(.*?)<\/pre>/is', "```\n$1\n```", $markdown);
|
||||||
|
|
||||||
// Ссылки
|
// 10. Ссылки
|
||||||
$markdown = preg_replace('/<a[^>]*href="([^"]*)"[^>]*>(.*?)<\/a>/is', '[$2]($1)', $markdown);
|
$markdown = preg_replace('/<a[^>]*href="([^"]*)"[^>]*>(.*?)<\/a>/is', '[$2]($1)', $markdown);
|
||||||
|
|
||||||
// Изображения
|
// 11. Изображения
|
||||||
$markdown = preg_replace('/<img[^>]*src="([^"]*)"[^>]*alt="([^"]*)"[^>]*>/is', '', $markdown);
|
$markdown = preg_replace('/<img[^>]*src="([^"]*)"[^>]*alt="([^"]*)"[^>]*>/is', '', $markdown);
|
||||||
|
|
||||||
// Удаляем все остальные HTML-теги
|
// 12. Таблицы
|
||||||
|
$markdown = preg_replace_callback('/<table[^>]*>(.*?)<\/table>/is', function($matches) {
|
||||||
|
$tableContent = $matches[1];
|
||||||
|
// Простое преобразование таблицы в Markdown
|
||||||
|
$tableContent = preg_replace('/<th[^>]*>(.*?)<\/th>/i', "| **$1** ", $tableContent);
|
||||||
|
$tableContent = preg_replace('/<td[^>]*>(.*?)<\/td>/i', "| $1 ", $tableContent);
|
||||||
|
$tableContent = preg_replace('/<tr[^>]*>(.*?)<\/tr>/i', "$1|\n", $tableContent);
|
||||||
|
$tableContent = preg_replace('/<thead[^>]*>(.*?)<\/thead>/i', "$1", $tableContent);
|
||||||
|
$tableContent = preg_replace('/<tbody[^>]*>(.*?)<\/tbody>/i', "$1", $tableContent);
|
||||||
|
|
||||||
|
// Добавляем разделитель для заголовков таблицы
|
||||||
|
$tableContent = preg_replace('/\| \*\*[^\|]+\*\* [^\n]*?\|\n/', "$0| --- |\n", $tableContent, 1);
|
||||||
|
|
||||||
|
return "\n" . $tableContent . "\n";
|
||||||
|
}, $markdown);
|
||||||
|
|
||||||
|
// 13. Удаляем все остальные HTML-теги
|
||||||
$markdown = strip_tags($markdown);
|
$markdown = strip_tags($markdown);
|
||||||
|
|
||||||
// Чистим лишние пробелы и переносы
|
// 14. Чистим лишние пробелы и переносы
|
||||||
$markdown = preg_replace('/\n\s*\n\s*\n/', "\n\n", $markdown);
|
$markdown = preg_replace('/\n{3,}/', "\n\n", $markdown); // Более двух переносов заменяем на два
|
||||||
$markdown = preg_replace('/^\s+|\s+$/m', '', $markdown); // Trim каждой строки
|
$markdown = preg_replace('/^\s+|\s+$/m', '', $markdown); // Trim каждой строки
|
||||||
|
$markdown = preg_replace('/\n\s*\n/', "\n\n", $markdown); // Чистим пустые строки
|
||||||
|
$markdown = preg_replace('/^ +/m', '', $markdown); // Убираем отступы в начале строк
|
||||||
|
|
||||||
$markdown = trim($markdown);
|
$markdown = trim($markdown);
|
||||||
|
|
||||||
return $markdown;
|
// 15. Дополнительная нормализация - убеждаемся, что есть пустые строки между абзацами
|
||||||
|
$lines = explode("\n", $markdown);
|
||||||
|
$normalized = [];
|
||||||
|
$inParagraph = false;
|
||||||
|
|
||||||
|
foreach ($lines as $line) {
|
||||||
|
$trimmed = trim($line);
|
||||||
|
|
||||||
|
if (empty($trimmed)) {
|
||||||
|
// Пустая строка - конец абзаца
|
||||||
|
if ($inParagraph) {
|
||||||
|
$normalized[] = '';
|
||||||
|
$inParagraph = false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Непустая строка
|
||||||
|
if (!$inParagraph && !empty($normalized) && end($normalized) !== '') {
|
||||||
|
// Добавляем пустую строку перед новым абзацем
|
||||||
|
$normalized[] = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$normalized[] = $trimmed;
|
||||||
|
$inParagraph = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode("\n", $normalized);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function normalizeHtml($html) {
|
private function normalizeHtml($html) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,3 @@
|
||||||
<?php
|
|
||||||
// views/chapters/preview.php
|
|
||||||
include 'views/layouts/header.php';
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="ru">
|
<html lang="ru">
|
||||||
<head>
|
<head>
|
||||||
|
|
@ -29,6 +25,7 @@ include 'views/layouts/header.php';
|
||||||
h2 { border-bottom: 1px solid var(--border-color); padding-bottom: 0.3em; }
|
h2 { border-bottom: 1px solid var(--border-color); padding-bottom: 0.3em; }
|
||||||
p {
|
p {
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
|
text-align: justify;
|
||||||
}
|
}
|
||||||
code {
|
code {
|
||||||
background: var(--card-background-color);
|
background: var(--card-background-color);
|
||||||
|
|
@ -46,6 +43,7 @@ include 'views/layouts/header.php';
|
||||||
pre code {
|
pre code {
|
||||||
background: none;
|
background: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
blockquote {
|
blockquote {
|
||||||
border-left: 4px solid var(--border-color);
|
border-left: 4px solid var(--border-color);
|
||||||
|
|
@ -61,6 +59,7 @@ include 'views/layouts/header.php';
|
||||||
.dialogue {
|
.dialogue {
|
||||||
margin-left: 2rem;
|
margin-left: 2rem;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
|
color: #2c5aa0;
|
||||||
}
|
}
|
||||||
table {
|
table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
|
|
@ -77,6 +76,17 @@ include 'views/layouts/header.php';
|
||||||
th {
|
th {
|
||||||
background: var(--card-background-color);
|
background: var(--card-background-color);
|
||||||
}
|
}
|
||||||
|
ul, ol {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
padding-left: 2rem;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -84,13 +94,11 @@ include 'views/layouts/header.php';
|
||||||
<h1><?= e($title) ?></h1>
|
<h1><?= e($title) ?></h1>
|
||||||
<hr>
|
<hr>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main class="content">
|
<main class="content">
|
||||||
<?= $content ?>
|
<?= $content ?>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer style="margin-top: 3rem; padding-top: 1rem; border-top: 1px solid var(--border-color);">
|
<footer style="margin-top: 3rem; padding-top: 1rem; border-top: 1px solid var(--border-color);">
|
||||||
<small>Сгенерировано <?= date('d.m.Y H:i') ?> | Markdown Preview</small>
|
<small>Сгенерировано <?= date('d.m.Y H:i') ?> | Предпросмотр</small>
|
||||||
<br>
|
<br>
|
||||||
<a href="javascript:window.close()" class="button secondary">Закрыть</a>
|
<a href="javascript:window.close()" class="button secondary">Закрыть</a>
|
||||||
<a href="javascript:window.print()" class="button">Печать</a>
|
<a href="javascript:window.print()" class="button">Печать</a>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue