fix: align social card rendering with Material

Signed-off-by: squidfunk <martin.donath@squidfunk.com>
This commit is contained in:
squidfunk
2026-09-23 14:02:25 +02:00
parent 62eb292f69
commit 1a89694f11
53 changed files with 718 additions and 26 deletions
+44
View File
@@ -0,0 +1,44 @@
# Social plugin compatibility matrix
These projects compare the user-visible output of Material for MkDocs and
Zensical with the same `mkdocs.yml` and source files. Run the matrix from the
repository root:
```console
/Users/squidfunk/.workspace/squidfunk/repos/mkdocs-material/community/venv/bin/python \
scripts/social_compatibility.py \
--mkdocs /Users/squidfunk/.workspace/squidfunk/repos/mkdocs-material/community/venv/bin/mkdocs \
--zensical .venv/bin/zensical
```
| Case | Behavior |
| --- | --- |
| `basic` | Custom layout, root and nested card routes, page title and metadata |
| `filters` | Include precedence, exclude patterns, page-level opt-out |
| `metadata` | Meta plugin inheritance and page-level layout options |
| `multiple` | Ordered plugin instances, separate card directories and metadata |
| `no-site-url` | Cards generated without public image metadata |
| `image-only` | Bundled image-only layout and a local SVG dependency |
| `bundled` | Default, accent, invert and variant layouts with typography |
| `logo-icon` | Explicit theme logo icon and omitted font settings |
| `debug` | Build-time debug grid and color settings |
| `blog` | Cards for generated blog views and posts |
The check compares generated card paths, dimensions and every card's mean RGB
pixel difference, plus each page's social metadata. A case passes when the
metadata and dimensions match and every card's mean RGB difference is at most
1 on a 0–255 scale. PNG file bytes may differ between image libraries even
when the visible output is the same. Build logs and full output are kept in a
temporary directory only while the command runs; pass `--output PATH` to keep
them for inspection.
The bundled, logo-icon and debug cases download Roboto from Google Fonts on
their first build.
Use `--font-cache PATH` to seed both temporary projects from an existing Material
font cache and run it without a network connection.
On 2026-09-23, all 10 cases matched using Material for MkDocs 9.7.1 with
Pillow 12.1.1 and this Zensical branch. The highest mean RGB difference was
0.566 (bundled layout); card paths, dimensions and social metadata matched in
every case. This is a compatibility sample, not a guarantee for every possible
layout or Material version.
@@ -0,0 +1 @@
# Advanced
@@ -0,0 +1 @@
# Guide
+6
View File
@@ -0,0 +1,6 @@
---
title: Home & Intro
description: A concise & useful description.
---
# Welcome
+12
View File
@@ -0,0 +1,12 @@
tags:
og:type: website
og:title: '{{ page.meta.get("title", page.title) }}'
og:description: '{{ page.meta.get("description", config.site_description) | x }}'
og:image: '{{ image.url }}'
og:image:width: '{{ image.width }}'
og:image:height: '{{ image.height }}'
og:url: '{{ page.canonical_url }}'
twitter:card: summary_large_image
size: { width: 320, height: 168 }
layers:
- background: { color: '#123456' }
+10
View File
@@ -0,0 +1,10 @@
site_name: Social parity
site_description: A small parity site.
site_url: https://example.test/docs/
site_dir: site
theme:
name: material
plugins:
- social:
cache: false
cards_layout: flat
+1
View File
@@ -0,0 +1 @@
# Journal
@@ -0,0 +1,5 @@
---
date: 2026-09-20
---
# First post
@@ -0,0 +1,5 @@
---
date: 2026-09-21
---
# Second post
+1
View File
@@ -0,0 +1 @@
# Home
+6
View File
@@ -0,0 +1,6 @@
tags:
og:title: '{{ page.meta.get("title", page.title) }}'
og:image: '{{ image.url }}'
size: { width: 320, height: 168 }
layers:
- background: { color: '#123456' }
+9
View File
@@ -0,0 +1,9 @@
site_name: Social blog
site_url: https://example.test/docs/
site_dir: site
theme: { name: material }
plugins:
- blog
- social:
cache: false
cards_layout: flat
+7
View File
@@ -0,0 +1,7 @@
---
title: An accent card
social:
cards_layout: default/accent
---
# Accent
+6
View File
@@ -0,0 +1,6 @@
---
title: A thoughtful beginning
description: A concise introduction to the project.
---
# Home
+7
View File
@@ -0,0 +1,7 @@
---
title: An inverted card
social:
cards_layout: default/invert
---
# Invert
+7
View File
@@ -0,0 +1,7 @@
---
title: A variant card
social:
cards_layout: default/variant
---
# Variant
+19
View File
@@ -0,0 +1,19 @@
site_name: Bundled cards
site_description: A site description for cards.
site_url: https://example.test/docs/
site_dir: site
theme:
name: material
palette:
primary: deep purple
font:
text: Roboto
plugins:
- social:
cache: false
cache_dir: social-cache
cards_layout: default
cards_layout_options:
background_color: '#4c1d95'
color: '#ffffff'
font_family: Roboto
+1
View File
@@ -0,0 +1 @@
# Debug view
+5
View File
@@ -0,0 +1,5 @@
tags:
og:image: '{{ image.url }}'
size: { width: 320, height: 168 }
layers:
- background: { color: '#123456' }
+14
View File
@@ -0,0 +1,14 @@
site_name: Debug cards
site_url: https://example.test/docs/
site_dir: site
theme: { name: material }
plugins:
- social:
cache: false
cache_dir: social-cache
cards_layout: flat
debug: true
debug_on_build: true
debug_grid: true
debug_grid_step: 32
debug_color: red
@@ -0,0 +1 @@
# Include wins over exclude
@@ -0,0 +1 @@
# Included guide
@@ -0,0 +1,6 @@
---
social:
cards: false
---
# Page opt-out
+1
View File
@@ -0,0 +1 @@
# Home
+5
View File
@@ -0,0 +1,5 @@
tags:
og:image: '{{ image.url }}'
size: { width: 320, height: 168 }
layers:
- background: { color: '#abcdef' }
+10
View File
@@ -0,0 +1,10 @@
site_name: Social filters
site_url: https://example.test/docs/
site_dir: site
theme: { name: material }
plugins:
- social:
cache: false
cards_layout: flat
cards_include: ['guides/**']
cards_exclude: ['guides/hidden.md']
@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="630">
<rect width="1200" height="630" fill="#345678"/>
</svg>

After

Width:  |  Height:  |  Size: 125 B

+1
View File
@@ -0,0 +1 @@
# Image card
+10
View File
@@ -0,0 +1,10 @@
site_name: Social image only
site_url: https://example.test/docs/
site_dir: site
theme: { name: material }
plugins:
- social:
cache: false
cards_layout: default/only/image
cards_layout_options:
background_image: docs/background.svg
+6
View File
@@ -0,0 +1,6 @@
---
title: A bright idea
description: A card with a logo icon.
---
# Home
+11
View File
@@ -0,0 +1,11 @@
site_name: Logo icon cards
site_url: https://example.test/docs/
site_dir: site
theme:
name: material
icon:
logo: material/star
plugins:
- social:
cache: false
cache_dir: social-cache
@@ -0,0 +1,4 @@
social:
cards_layout_options:
background_color: '#445566'
label: inherited
@@ -0,0 +1 @@
# Inherited options
@@ -0,0 +1,8 @@
---
social:
cards_layout_options:
background_color: '#778899'
label: page
---
# Page options
+1
View File
@@ -0,0 +1 @@
# Global options
@@ -0,0 +1,6 @@
tags:
og:image: '{{ image.url }}'
x:label: '{{ layout.label }}'
size: { width: 320, height: 168 }
layers:
- background: { color: '{{ layout.background_color }}' }
+12
View File
@@ -0,0 +1,12 @@
site_name: Social metadata
site_url: https://example.test/docs/
site_dir: site
theme: { name: material }
plugins:
- meta
- social:
cache: false
cards_layout: flat
cards_layout_options:
background_color: '#112233'
label: global
+1
View File
@@ -0,0 +1 @@
# Guide
+1
View File
@@ -0,0 +1 @@
# Home
@@ -0,0 +1,6 @@
tags:
og:image: '{{ image.url }}'
x:instance: '{{ layout.label }}'
size: { width: 320, height: 168 }
layers:
- background: { color: '{{ layout.color }}' }
+17
View File
@@ -0,0 +1,17 @@
site_name: Social instances
site_url: https://example.test/docs/
site_dir: site
theme: { name: material }
plugins:
- social:
cache: false
cards_layout: flat
cards_dir: assets/cards/first
cards_include: ['index.md']
cards_layout_options: { label: first, color: '#102030' }
- social:
cache: false
cards_layout: flat
cards_dir: assets/cards/second
cards_include: ['guide.md']
cards_layout_options: { label: second, color: '#405060' }
@@ -0,0 +1 @@
# Home
@@ -0,0 +1,5 @@
tags:
og:image: '{{ image.url }}'
size: { width: 320, height: 168 }
layers:
- background: { color: '#123456' }
+7
View File
@@ -0,0 +1,7 @@
site_name: Social without URL
site_dir: site
theme: { name: material }
plugins:
- social:
cache: false
cards_layout: flat
+9
View File
@@ -571,6 +571,13 @@ def _apply_defaults(config: dict, path: str) -> dict:
elif "theme" not in config:
config["theme"] = {}
font_explicit = "font" in config["theme"]
configured_icons = config["theme"].get("icon")
logo_icon_explicit = (
isinstance(configured_icons, dict)
and configured_icons.get("logo") is not None
)
# Set defaults for custom theme directory
set_default(config["theme"], "custom_dir", None, str)
@@ -600,6 +607,7 @@ def _apply_defaults(config: dict, path: str) -> dict:
config["theme"] = {**theme_config, **config["theme"]}
theme = config["theme"]
theme["font_explicit"] = font_explicit
# Set defaults for theme name
# (we do this after loading the theme configuration
@@ -632,6 +640,7 @@ def _apply_defaults(config: dict, path: str) -> dict:
# Set defaults for theme icons
icon = set_default(theme, "icon", {}, dict)
icon["logo_explicit"] = logo_icon_explicit
set_default(icon, "repo", None, str)
set_default(icon, "annotation", None, str)
set_default(icon, "tag", {}, dict)