feat: add site-wide social preview image settings (#1463)

- Add configuration field `social_preview_image` that sets the site-wide default social preview image.  

   For pages that do not have `page.image` set in font matter, the seo tag will use the image specified by `site.social_preview_image` as the Open Graph image.

- Refactored the generation of image URLs to reduce redundant code and enhance fault tolerance for missing or repeated slash `/` when defining image paths.
This commit is contained in:
Cotes Chung 2024-01-10 09:04:27 +08:00 committed by GitHub
parent 82d8f2db98
commit 241bb4df78
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 65 additions and 47 deletions

View file

@ -75,6 +75,10 @@ img_cdn: "https://chirpy-img.netlify.app"
# the avatar on sidebar, support local or CORS resources # the avatar on sidebar, support local or CORS resources
avatar: "/commons/avatar.jpg" avatar: "/commons/avatar.jpg"
# The URL of the site-wide social preview image used in SEO `og:image` meta tag.
# It can be overridden by a customized `page.image` in front matter.
social_preview_image: # string, local or CORS resources
# boolean type, the global switch for TOC in posts. # boolean type, the global switch for TOC in posts.
toc: true toc: true

View file

@ -1,5 +1,3 @@
<!-- The Head -->
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#f7f7f7"> <meta name="theme-color" media="(prefers-color-scheme: light)" content="#f7f7f7">
@ -11,29 +9,38 @@
content="width=device-width, user-scalable=no initial-scale=1, shrink-to-fit=no, viewport-fit=cover" content="width=device-width, user-scalable=no initial-scale=1, shrink-to-fit=no, viewport-fit=cover"
> >
{% capture seo_tags %} {%- capture seo_tags -%}
{% seo title=false %} {% seo title=false %}
{% endcapture %} {%- endcapture -%}
<!-- Setup Open Graph image -->
{% if page.image %} {% if page.image %}
{% assign img = page.image.path | default: page.image %} {% assign src = page.image.path | default: page.image %}
{% unless img contains '://' %} {% unless src contains '://' %}
{% assign img_path = page.img_path | append: '/' | append: img | replace: '//', '/' %} {%- capture img_url -%}
{% capture target %}"{{ img | absolute_url }}"{% endcapture %} {% include img-url.html src=src img_path=page.img_path %}
{% if site.img_cdn contains '//' %}
<!-- it's a cross-origin URL -->
{% capture replacement %}"{{ site.img_cdn }}{{ img_path }}"{% endcapture %}
{% else %}
<!-- it's a local file path -->
{%- capture replacement -%}
"{{ site.img_cdn | append: '/' | append: img_path | replace: '//', '/' | absolute_url }}"
{%- endcapture -%} {%- endcapture -%}
{% endif %}
{% assign seo_tags = seo_tags | replace: target, replacement %} {%- capture old_url -%}{{ src | absolute_url }}{%- endcapture -%}
{%- capture new_url -%}{{ img_url }}{%- endcapture -%}
{% assign seo_tags = seo_tags | replace: old, new %}
{% endunless %} {% endunless %}
{% elsif site.social_preview_image %}
{%- capture img_url -%}
{% include img-url.html src=site.social_preview_image %}
{%- endcapture -%}
{%- capture og_image -%}
<meta property="og:image" content="{{ img_url }}" />
{%- endcapture -%}
{% assign old_meta_clip = '<meta name="twitter:card"' %}
{% assign new_meta_clip = og_image | append: old_meta_clip %}
{% assign seo_tags = seo_tags | replace: old_meta_clip, new_meta_clip %}
{% endif %} {% endif %}
{{ seo_tags }} {{ seo_tags }}

24
_includes/img-url.html Normal file
View file

@ -0,0 +1,24 @@
{%- comment -%}
Generate image final URL based on `site.img_cdn`, `page.img_path`
Arguments:
src - basic image path, required
img_path - relative path of image, optional
Return:
image URL
{%- endcomment -%}
{% assign url = include.src %}
{%- if url -%}
{%- comment -%} CND URL {%- endcomment -%}
{% assign prefix = site.img_cdn | default: '' | relative_url %}
{%- comment -%} Add page image path prefix {%- endcomment -%}
{% assign url = include.img_path | default: '' | append: '/' | append: url %}
{% assign url = prefix | append: '/' | append: url | replace: '///', '/' | replace: '//', '/' | replace: ':', ':/' %}
{%- endif -%}
{{- url -}}

View file

@ -48,23 +48,6 @@
{% assign _img_content = null %} {% assign _img_content = null %}
{% assign _img_snippets = _content | split: IMG_TAG %} {% assign _img_snippets = _content | split: IMG_TAG %}
<!-- CDN URL -->
{% if site.img_cdn %}
{% if site.img_cdn contains '//' %}
{% assign _path_prefix = site.img_cdn %}
{% else %}
{% assign _path_prefix = site.img_cdn | relative_url %}
{% endif %}
{% else %}
{% assign _path_prefix = site.baseurl %}
{% endif %}
<!-- Add image path -->
{% if page.img_path %}
{% assign _path = page.img_path | append: '/' | replace: '//', '/' %}
{% assign _path_prefix = _path_prefix | append: _path %}
{% endif %}
{% for _img_snippet in _img_snippets %} {% for _img_snippet in _img_snippets %}
{% if forloop.first %} {% if forloop.first %}
{% assign _img_content = _img_snippet %} {% assign _img_content = _img_snippet %}
@ -113,6 +96,12 @@
{% assign _final_src = null %} {% assign _final_src = null %}
{% assign _lazyload = true %} {% assign _lazyload = true %}
{%- capture _img_url -%}
{% include img-url.html src=_src img_path=page.img_path %}
{%- endcapture -%}
{% assign _path_prefix = _img_url | remove: _src %}
{% unless _src contains '//' %} {% unless _src contains '//' %}
{% assign _final_src = _path_prefix | append: _src %} {% assign _final_src = _path_prefix | append: _src %}
{% assign _src_alt = 'src="' | append: _path_prefix %} {% assign _src_alt = 'src="' | append: _path_prefix %}

View file

@ -3,18 +3,12 @@
<aside aria-label="Sidebar" id="sidebar" class="d-flex flex-column align-items-end"> <aside aria-label="Sidebar" id="sidebar" class="d-flex flex-column align-items-end">
<header class="profile-wrapper"> <header class="profile-wrapper">
<a href="{{ '/' | relative_url }}" id="avatar" class="rounded-circle"> <a href="{{ '/' | relative_url }}" id="avatar" class="rounded-circle">
{% if site.avatar != empty and site.avatar %} {%- if site.avatar != empty and site.avatar -%}
{% capture avatar_url %} {%- capture avatar_url -%}
{% if site.avatar contains '://' %} {% include img-url.html src=site.avatar %}
{{ site.avatar }} {%- endcapture -%}
{% elsif site.img_cdn != empty and site.img_cdn %} <img src="{{- avatar_url -}}" width="112" height="112" alt="avatar" onerror="this.style.display='none'">
{{ site.avatar | prepend: site.img_cdn }} {%- endif -%}
{% else %}
{{ site.avatar | relative_url }}
{% endif %}
{% endcapture %}
<img src="{{ avatar_url | strip }}" width="112" height="112" alt="avatar" onerror="this.style.display='none'">
{% endif %}
</a> </a>
<h1 class="site-title"> <h1 class="site-title">