diff --git a/www/mysql_adapter.php b/www/mysql_adapter.php
index 3d845b6..23904a7 100644
--- a/www/mysql_adapter.php
+++ b/www/mysql_adapter.php
@@ -268,7 +268,7 @@ class MySQLAdapter {
];
$qry = "
- SELECT post_path, post_metadata
+ SELECT *
FROM posts
WHERE MATCH(post_tags) AGAINST (? IN BOOLEAN MODE)
";
diff --git a/www/post.php b/www/post.php
new file mode 100644
index 0000000..94c0da2
--- /dev/null
+++ b/www/post.php
@@ -0,0 +1,166 @@
+
+ -1,
+ 'post_path' => '/404.md',
+ 'post_title' => '404 Page',
+ 'post_metadata' => [
+ 'type' => '404'
+ ]
+ ];
+ }
+
+ public static function _deduce_type($path) {
+ $ext = pathinfo($path, PATHINFO_EXTENSION);
+
+ if(preg_match("/\.(\w+)\.md$/", $path, $ext_match)) {
+ $ext = $ext_match[1];
+ }
+
+ $ext_mapping = [
+ '' => 'directory',
+ 'md' => 'text/markdown',
+ 'png' => 'image',
+ 'jpg' => 'image',
+ 'jpeg' => 'image'
+ ];
+
+ return $ext_mapping[$ext] ?? '?';
+ }
+
+ public static function _deduce_icon($type) {
+ $icon_mapping = [
+ '' => 'question',
+ 'text/markdown' => 'markdown',
+ 'directory' => 'folder',
+ 'gallery' => 'images',
+ 'image' => 'image'
+ ];
+
+ return $icon_mapping[$type] ?? 'unknown';
+ }
+
+ function __construct($post_handler, $sql_row) {
+ $this->post_handler = $post_handler;
+
+ $this->content_html = null;
+
+ $sql_meta = null;
+ if(!isset($sql_row) or !$sql_row['found']) {
+ $sql_row = $this->_generate_404($sql_row);
+ $sql_meta = $sql_row['post_metadata'];
+ }
+
+
+ $sql_meta = $sql_row['post_metadata'];
+ if(is_string($sql_meta)) {
+ $sql_meta = json_decode($sql_meta, true);
+ }
+
+ unset($sql_meta['settings']);
+
+ $this->sql_row = $sql_row;
+ $this->sql_meta = $sql_meta ?? [];
+ $sql_settings = json_decode($sql_row['post_settings_cache'], true) ?? [];
+
+ $data = [
+ 'id' => $sql_row['post_id'],
+ 'path' => $sql_row['post_path'],
+ 'url' => 'https://' . $sql_row['host'] . $sql_row['post_path'],
+ 'created_at' => $sql_row['post_create_time'] ?? '',
+ 'updated_at' => $sql_row['post_update_time'] ?? '',
+ 'view_count' => $sql_row['post_access_count'] ?? 0
+ ];
+
+ $data['title'] = $sql_meta['title'] ?? $sql_row['title'];
+ unset($sql_meta['title']);
+
+ $data['tags'] = $sql_meta['tags'] ?? [];
+ unset($sql_meta['tags']);
+
+ $data['type'] = $sql_meta['type']
+ ?? self::_deduce_type($sql_row['post_path']);
+ unset($sql_meta['type']);
+
+ $data['icon'] = $sql_meta['icon']
+ ?? self::_deduce_icon($data['type']);
+ unset($sql_meta['icon']);
+
+ if(isset($sql_meta['media_url'])) {
+ $data['media_url'] = $sql_meta['media_url'];
+ $data['thumb_url'] = $sql_meta['thumb_url'] ?? $data['media_url'];
+
+ unset($sql_meta['media_url']);
+ unset($sql_meta['thumb_url']);
+ }
+
+ $data['banners'] = $sql_meta['banners']
+ ?? $sql_settings['banners']
+ ?? self::$default_banners;
+
+ unset($sql_meta['banners']);
+ unset($sql_settings['banners']);
+
+ $data['preview_image'] = $sql_meta['preview_image'] ?? $data['banners'][0]['src'] ?? null;
+ unset($sql_meta['preview_image']);
+
+ $data['brief'] = $sql_meta['brief']
+ ?? $data['title'];
+ unset($sql_meta['brief']);
+
+ $data['excerpt'] = $sql_meta['excerpt']
+ ?? substr($sql_row['post_content'], 0, 256);
+
+ $data['metadata'] = $sql_meta;
+ $data['settings'] = $sql_settings;
+
+ $this->data = $data;
+ }
+
+ public function __get($name) {
+ if($name == 'html') {
+ return $this->get_html();
+ }
+ if($name == 'markdown') {
+ return $this->sql_row['post_content'];
+ }
+ if($name == 'json') {
+ return $this->to_json();
+ }
+
+ return $this->data[$name];
+ }
+
+ public function get_html() {
+ $fn = self::$markdown_engine;
+ $this->content_html ??= $fn($this);
+
+ return $this->content_html;
+ }
+
+ public function to_json($with_markdown = false, $with_html = false) {
+ $out_data = $this->data;
+
+ if($with_markdown) {
+ $out_data['markdown'] = $this->sql_row['post_content'];
+ }
+ if($with_html) {
+ $out_data['html'] = $this->get_html();
+ }
+
+ return json_encode($out_data);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/www/post_adapter.php b/www/post_adapter.php
index 09027cf..314f0d7 100644
--- a/www/post_adapter.php
+++ b/www/post_adapter.php
@@ -118,12 +118,14 @@ class PostHandler extends MySQLAdapter {
}
function handle_upload($post_path, $file_path) {
+ $post_path = $this->_sanitize_path($post_path);
$ext = pathinfo($post_path, PATHINFO_EXTENSION);
switch($ext) {
case "md":
$this->save_markdown_post($post_path, file_get_contents($file_path));
+ $this->make_post_directory(dirname($post_path));
move_uploaded_file($file_path, $this->data_directory . $post_path);
break;
default:
diff --git a/www/router.php b/www/router.php
index 18c4641..7994645 100644
--- a/www/router.php
+++ b/www/router.php
@@ -5,6 +5,9 @@ $data_time_start = microtime(true);
require_once 'vendor/autoload.php';
require_once 'post_adapter.php';
+
+require_once 'post.php';
+
require_once 'fontawesome.php';
require_once 'dergdown.php';
@@ -40,6 +43,10 @@ function dergdown_to_html($text) {
return $Parsedown->text($text);
}
+function post_to_html($post) {
+ return dergdown_to_html($post->markdown);
+}
+PostData::$markdown_engine = "post_to_html";
function deduce_user_agent() {
$real_agent=$_SERVER['HTTP_USER_AGENT'];
@@ -160,6 +167,7 @@ function try_render_post($SURI) {
break;
+ case 'blog':
case 'text/markdown':
echo render_twig('post_types/markdown.html', [
"post" => $post
@@ -185,6 +193,30 @@ function try_render_post($SURI) {
]);
break;
+ case 'blog_list':
+ if(preg_match('/^(.*[^\/])((?:#.*)?)$/', $SURI, $match)) {
+ header('Location: ' . $match[1] . '/' . $match[2]);
+
+ die();
+ }
+
+ $search_query = $post['post_metadata']['search_tags'] ??
+ ('+type:blog +path:' . $post['post_path'] . '/*');
+
+ $search_result = $adapter->perform_post_search($search_query);
+
+ $search_result = array_map(function($key) {
+ $post = new PostData(null, $key);
+ return $post->data;
+ }, $search_result['results']);
+
+ echo render_twig('post_types/blog_list.html', [
+ "post" => $post,
+ "subposts" => $adapter->get_subposts_by_path($SURI),
+ "blog_posts" => $search_result
+ ]);
+ break;
+
case 'image':
echo render_twig('post_types/image.html', [
"post" => $post,
@@ -233,7 +265,9 @@ function generate_website($SURI) {
} elseif(preg_match('/^\/api\/posts(.*)$/', $SURI, $match)) {
header('Content-Type: application/json');
- echo json_encode($adapter->get_post_by_path($match[1]));
+
+ $post = new PostData(null, $adapter->get_post_by_path($match[1]));
+ echo $post->to_json(with_markdown: true, with_html: true);
} elseif(preg_match('/^\/api\/subposts(.*)$/', $SURI, $match)) {
diff --git a/www/static/article_blop.css b/www/static/article_blop.css
new file mode 100644
index 0000000..1c46c37
--- /dev/null
+++ b/www/static/article_blop.css
@@ -0,0 +1,81 @@
+
+
+.article_blop {
+ position: relative;
+ overflow: clip;
+ z-index: 0;
+
+ background: var(--bg_2);
+
+ margin: 2rem;
+ padding: 0;
+
+ border-radius: 1rem;
+
+ box-shadow: 0px 5px 5px 0px #00000040;
+ transition: 0.3s;
+
+ min-height: 10rem;
+}
+
+.article_blop_bg {
+ position: absolute;
+ left: 0px;
+ right: 0;
+ top: 0;
+ bottom: 0;
+
+ background-repeat: no-repeat;
+ background-position: center;
+ background-size: cover;
+
+ opacity: 0.2;
+
+ z-index: -1;
+}
+
+.article_blop:hover {
+ box-shadow: 0px 8px 8px 0px #00000040;
+}
+
+.article_blop_content {
+ padding: 1rem;
+ padding-top: 5rem;
+}
+
+.article_blop_tags {
+ position: absolute;
+ top: 0.5rem;
+ right: 0.2rem;
+
+ width: 40%;
+ height: auto;
+
+ list-style: none;
+ display: flex;
+ flex-direction: row;
+ flex-flow: row wrap;
+
+ justify-content: right;
+}
+.article_blop_tags :first-child {
+ margin-left: auto;
+}
+.article_blop_tags li {
+ margin-right: 0.4rem;
+ margin-bottom: 0.4rem;
+
+ padding-left: 0.2rem;
+ padding-right: 0.2rem;
+
+ font-size: 0.8rem;
+
+ font-style: normal;
+ font-weight: bold;
+
+ background-color: var(--highlight_1);
+ border-radius: 0.3rem;
+ color: var(--bg_2);
+
+
+}
\ No newline at end of file
diff --git a/www/static/dergstyle.css b/www/static/dergstyle.css
index ccde5fa..8ee91c8 100644
--- a/www/static/dergstyle.css
+++ b/www/static/dergstyle.css
@@ -16,6 +16,7 @@ body {
--bg_2: #2c2943;
--bg_3: #3f4148;
+ --highlight_0: #ee9015b1;
--highlight_1: #ee9015;
--highlight_2: #edd29e;
@@ -185,6 +186,7 @@ a:hover {
z-index: 5;
}
+
#post_file_titles {
display: flex;
flex-direction: row;
@@ -194,13 +196,35 @@ a:hover {
padding: 0px;
}
-#post_file_titles * {
- padding: 0.5rem;
+#post_file_titles li {
+ padding: 0.2rem 0.8rem;
+
font-style: bold;
font-size: 1.3rem;
background: var(--highlight_1);
}
+#post_file_titles li:hover {
+ background: var(--highlight_0) !important;
+}
+
+#post_file_bar_dirbtn {
+ margin-left: 0.15rem;
+ background: var(--bg_2) !important;
+}
+#post_file_bar #dir_collapse {
+ display: none;
+}
+#post_file_bar #dir_collapse:checked + #post_file_bar_dirbtn {
+ background: var(--highlight_1) !important;
+}
+
+.directory {
+ display: none;
+}
+#dir_collapse:checked ~ .directory {
+ display: block;
+}
#post_file_path {
width: 100%;
@@ -223,7 +247,7 @@ a:hover {
padding-right: 0.2rem;
}
-#main_content_wrapper article {
+article {
background: var(--bg_3);
border-radius: 0rem 0rem 0.8rem 0.8rem;
@@ -232,7 +256,7 @@ a:hover {
padding: 0.75rem;
}
-#main_content_wrapper article img {
+article img {
display: block;
max-width: 100%;
diff --git a/www/templates/fragments/article_blop.html b/www/templates/fragments/article_blop.html
new file mode 100644
index 0000000..0000271
--- /dev/null
+++ b/www/templates/fragments/article_blop.html
@@ -0,0 +1,23 @@
+
+
+
+
+ {{post.title}}
+
+
+
+
+
+ {{post.excerpt}}
+
+
+ | Name | +Title | +Modified | +
---|---|---|---|
+ {{ fa[subpost.post_metadata.icon] | raw }} + | ++ {{subpost.post_basename}} + | ++ {{ subpost.post_metadata.title }} + | ++ {{ subpost.post_update_time }} + | +