123 lines
4.2 KiB
PHP
123 lines
4.2 KiB
PHP
<?php
|
|
|
|
final class ArticleParser
|
|
{
|
|
|
|
const PATTERN_DATE = "|\./data/articles/([0-9]+)/([0-9]+)/([0-9]+)/([0-9]+).txt|";
|
|
const PATTERN_TAGS = "/^\{(([a-zA-Z0-9]+,*)+)\}$/";
|
|
const PATTERN_IMG = "/^([a-zA-Z0-9\-_\.]+\.(jpg|png)) \((.*)\)$/";
|
|
const PATTERN_BOLD = "/\*([^*]*)\*/";
|
|
const PATTERN_ITALIC = "|/([^/]*)/|";
|
|
const PATTERN_UNDERLINE = "/_([^_]*)_/";
|
|
const REPLACE_DATE = "$1-$2-$3";
|
|
const REPLACE_REF = "$4";
|
|
const REPLACE_BOLD = "<strong>$1</strong>";
|
|
const REPLACE_ITALIC = "<em>$1</em>";
|
|
const REPLACE_UNDERLINE = "<u>$1</u>";
|
|
|
|
private bool $in_p = false;
|
|
private array $content = [];
|
|
private array $p = [];
|
|
|
|
public function parse(string $file_path): Article
|
|
{
|
|
$article = new Article();
|
|
$article->date = preg_replace(self::PATTERN_DATE, self::REPLACE_DATE, $file_path);
|
|
$article->ref = preg_replace(self::PATTERN_DATE, self::REPLACE_REF, $file_path);
|
|
$lines = file($file_path, FILE_IGNORE_NEW_LINES);
|
|
foreach ($lines as $line) {
|
|
if (substr($line, 0, 2) === "# ") {
|
|
$article->title = substr($line, 2);
|
|
continue;
|
|
}
|
|
if (substr($line, 0, 3) === "## ") {
|
|
$this->closeParagraph();
|
|
$this->content[] = "<h3>" . substr($line, 3) . "</h3>";
|
|
continue;
|
|
}
|
|
if (substr($line, 0, 4) === "### ") {
|
|
$this->closeParagraph();
|
|
$this->content[] = "<h4>" . substr($line, 4) . "</h4>";
|
|
continue;
|
|
}
|
|
if (substr($line, 0, 5) === "#### ") {
|
|
$this->closeParagraph();
|
|
$this->content[] = "<h5>" . substr($line, 5) . "</h5>";
|
|
continue;
|
|
}
|
|
if (preg_match(self::PATTERN_TAGS, $line, $matches)) {
|
|
$article->tags = explode(",", $matches[1]);
|
|
continue;
|
|
}
|
|
if (preg_match(self::PATTERN_IMG, $line, $matches)) {
|
|
$this->closeParagraph();
|
|
$this->content[] = "<figure>";
|
|
$this->content[] = " <img src=\"" . dirname($file_path) . "/$matches[1]\" alt=\"$matches[3]\">";
|
|
$this->content[] = " <figcaption>$matches[3]</figcaption>";
|
|
$this->content[] = "</figure>";
|
|
continue;
|
|
}
|
|
if ($line === "") {
|
|
$this->closeParagraph();
|
|
continue;
|
|
} else {
|
|
if (!$this->in_p) {
|
|
$this->content[] = "<p>";
|
|
$this->in_p = true;
|
|
}
|
|
$this->p[] = $this->parseLine($line);
|
|
}
|
|
}
|
|
$this->closeParagraph();
|
|
array_unshift($this->content,
|
|
"<header>",
|
|
" <h2>" . $article->title . "</h2>",
|
|
" <nav>" . $this->getHtmlTags($article->tags) . "</nav>",
|
|
"</header>"
|
|
);
|
|
$this->content[] = "<footer>" .
|
|
preg_replace("/([0-9]+)\-([0-9]+)-([0-9]+)/", "$3/$2/$1", $article->date) .
|
|
"</footer>";
|
|
$view_path = "./data/cache/{$article->date}_{$article->ref}.phtml";
|
|
file_put_contents($view_path, " " . implode("\n ", $this->content) . "\n");
|
|
$article->view = $view_path;
|
|
$this->content = [];
|
|
return $article;
|
|
}
|
|
|
|
private function closeParagraph()
|
|
{
|
|
if ($this->in_p) {
|
|
$this->content[] = " " . implode("<br>", $this->p);
|
|
$this->content[] = "</p>";
|
|
$this->in_p = false;
|
|
$this->p = [];
|
|
}
|
|
}
|
|
|
|
private function parseLine(string $line): string
|
|
{
|
|
$patterns = [
|
|
self::PATTERN_BOLD,
|
|
self::PATTERN_ITALIC,
|
|
self::PATTERN_UNDERLINE
|
|
];
|
|
$replacements = [
|
|
self::REPLACE_BOLD,
|
|
self::REPLACE_ITALIC,
|
|
self::REPLACE_UNDERLINE
|
|
];
|
|
return preg_replace($patterns, $replacements, htmlspecialchars($line, ENT_HTML5, UTF-8));
|
|
}
|
|
|
|
private function getHtmlTags(array $tags): string
|
|
{
|
|
$html = "";
|
|
foreach ($tags as $tag) {
|
|
$html .= "<a href=\"?view=tags&tag=$tag\" class=\"tag\">$tag</a>";
|
|
}
|
|
return $html;
|
|
}
|
|
|
|
}
|