diff --git a/engine/skin.php b/engine/skin.php index bbb9f3e..149d85e 100644 --- a/engine/skin.php +++ b/engine/skin.php @@ -95,9 +95,48 @@ function add_static(string ...$files): void { $SkinState->static[] = $file; } -function add_meta(array ...$data) { +function add_meta(array $data) { global $SkinState; - $SkinState->meta = array_merge($SkinState->meta, $data); + static $twitter_limits = [ + 'title' => 70, + 'description' => 200 + ]; + $real_meta = []; + $add_og_twitter = function($key, $value) use (&$real_meta, $twitter_limits) { + foreach (['og', 'twitter'] as $social) { + if ($social == 'twitter' && isset($twitter_limits[$key])) { + if (mb_strlen($value) > $twitter_limits[$key]) + $value = mb_substr($value, 0, $twitter_limits[$key]-3).'...'; + } + $real_meta[] = [ + $social == 'twitter' ? 'name' : 'property' => $social.':'.$key, + 'content' => $value + ]; + } + }; + foreach ($data as $key => $value) { + switch ($key) { + case '$url': + case '$title': + case '$image': + $add_og_twitter(substr($key, 1), $value); + break; + + case '$description': + $add_og_twitter(substr($key, 1), $value); + $real_meta[] = ['name' => 'description', 'content' => $value]; + break; + + default: + if (str_starts_with($key, 'og:')) { + $real_meta[] = ['property' => $key, 'content' => $value]; + } else { + logWarning("unsupported meta: $key => $value"); + } + break; + } + } + $SkinState->meta = array_merge($SkinState->meta, $real_meta); } diff --git a/handler/MainHandler.php b/handler/MainHandler.php index 8c6f259..78af66c 100644 --- a/handler/MainHandler.php +++ b/handler/MainHandler.php @@ -3,6 +3,15 @@ class MainHandler extends request_handler { function GET_index() { + global $config; + add_meta([ + 'og:type' => 'website', + '$url' => 'https://'.$config['domain'].'/', + '$title' => lang('meta_index_title'), + '$description' => lang('meta_index_description'), + '$image' => 'https://'.$config['domain'].'/img/4in1-preview.jpg' + ]); + set_title('$site_title'); set_skin_opts(['is_index' => true]); render('main/index'); @@ -77,18 +86,13 @@ class MainHandler extends request_handler { $other_langs[] = $pl->value; } - add_meta( - ['property' => 'og:title', 'content' => $pt->title], - ['property' => 'og:url', 'content' => $config['domain'].$post->getUrl()] - ); - if (($img = $pt->getFirstImage()) !== null) - add_meta(['property' => 'og:image', 'content' => $img->getDirectUrl()]); - add_meta([ - 'name' => 'description', - 'property' => 'og:description', - 'content' => $pt->getDescriptionPreview(155) + '$title' => $pt->title, + '$url', $config['domain'].$post->getUrl(), + '$description' => $pt->getDescriptionPreview(155) ]); + if (($img = $pt->getFirstImage()) !== null) + add_meta(['$image' => $img->getDirectUrl()]); set_skin_opts(['articles_lang' => $lang->value]); diff --git a/htdocs/img/4in1-preview.jpg b/htdocs/img/4in1-preview.jpg new file mode 100644 index 0000000..e28d6ec Binary files /dev/null and b/htdocs/img/4in1-preview.jpg differ diff --git a/skin/base.phps b/skin/base.phps index bad2f9f..25d83f5 100644 --- a/skin/base.phps +++ b/skin/base.phps @@ -29,7 +29,7 @@ return << {$title} - {$ctx->renderMeta($meta)} + {$ctx->meta($meta)} {$ctx->renderStatic($static, $theme)} if_true($body_class, ' class="'.implode(' ', $body_class).'"')}> @@ -100,7 +100,7 @@ ThemeSwitcher.init(); HTML; } -function renderMeta($ctx, $meta) { +function meta($ctx, $meta) { if (empty($meta)) return ''; return implode('', array_map(function(array $item): string { @@ -108,6 +108,7 @@ function renderMeta($ctx, $meta) { foreach ($item as $k => $v) $s .= ' '.htmlescape($k).'="'.htmlescape($v).'"'; $s .= '>'; + $s .= "\n"; return $s; }, $meta)); } diff --git a/strings/main.yaml b/strings/main.yaml index f191a9f..d2ac36e 100644 --- a/strings/main.yaml +++ b/strings/main.yaml @@ -20,6 +20,10 @@ toc: 'Table of Contents' lang_en: "English" lang_ru: "Русский" +# meta +meta_index_title: "4in1. Mask of Shakespeare, mysteries of Bacon, book by Cartier, secrets of the NSA" +meta_index_description: "This is the official web site of the book \"4in1\". The book has emerged as an outcome of many years of journalistic investigations, published as a series of articles over the last few years on the kiwi arXiv website." + # blog blog_new_post: "New post" blog_view_post: "View post"