mirror of
https://github.com/zensical/zensical.git
synced 2026-09-26 08:15:34 +00:00
fix: align social card rendering with Material
Signed-off-by: squidfunk <martin.donath@squidfunk.com>
This commit is contained in:
+44
@@ -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
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
title: Home & Intro
|
||||
description: A concise & useful description.
|
||||
---
|
||||
|
||||
# Welcome
|
||||
@@ -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
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
# Journal
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
date: 2026-09-20
|
||||
---
|
||||
|
||||
# First post
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
date: 2026-09-21
|
||||
---
|
||||
|
||||
# Second post
|
||||
@@ -0,0 +1 @@
|
||||
# Home
|
||||
@@ -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' }
|
||||
@@ -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
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: An accent card
|
||||
social:
|
||||
cards_layout: default/accent
|
||||
---
|
||||
|
||||
# Accent
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
title: A thoughtful beginning
|
||||
description: A concise introduction to the project.
|
||||
---
|
||||
|
||||
# Home
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: An inverted card
|
||||
social:
|
||||
cards_layout: default/invert
|
||||
---
|
||||
|
||||
# Invert
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: A variant card
|
||||
social:
|
||||
cards_layout: default/variant
|
||||
---
|
||||
|
||||
# Variant
|
||||
+19
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
# Debug view
|
||||
@@ -0,0 +1,5 @@
|
||||
tags:
|
||||
og:image: '{{ image.url }}'
|
||||
size: { width: 320, height: 168 }
|
||||
layers:
|
||||
- background: { color: '#123456' }
|
||||
+14
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
# Home
|
||||
@@ -0,0 +1,5 @@
|
||||
tags:
|
||||
og:image: '{{ image.url }}'
|
||||
size: { width: 320, height: 168 }
|
||||
layers:
|
||||
- background: { color: '#abcdef' }
|
||||
+10
@@ -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 |
@@ -0,0 +1 @@
|
||||
# Image card
|
||||
@@ -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
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
title: A bright idea
|
||||
description: A card with a logo icon.
|
||||
---
|
||||
|
||||
# Home
|
||||
@@ -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
|
||||
@@ -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 }}' }
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
# Guide
|
||||
@@ -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 }}' }
|
||||
@@ -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' }
|
||||
@@ -0,0 +1,7 @@
|
||||
site_name: Social without URL
|
||||
site_dir: site
|
||||
theme: { name: material }
|
||||
plugins:
|
||||
- social:
|
||||
cache: false
|
||||
cards_layout: flat
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user