feature: add blog plugin replacement

Signed-off-by: squidfunk <martin.donath@squidfunk.com>
This commit is contained in:
Martin Donath
2026-09-22 17:04:24 +02:00
committed by GitHub
parent a85875ed26
commit 5825381d75
88 changed files with 11885 additions and 198 deletions
+34
View File
@@ -0,0 +1,34 @@
# Material blog compatibility fixtures
These fixtures define the user-visible compatibility target for the native
Zensical blog implementation. They are built with the pinned Material checkout
and reduced to semantic JSON manifests by `scripts/blog_compatibility.py`.
Run the compatibility check from the repository root:
```console
uv run python scripts/blog_compatibility.py \
--mkdocs ../mkdocs-material/community/venv/bin/mkdocs \
--zensical .venv/bin/zensical
```
Pass `--update` only after reviewing an intentional Material baseline change.
The harness compares routes, titles, navigation, page relations, ordered view
memberships, pagination, links, and normalized excerpt fragments. It does not
compare complete generated documents or theme assets. The Zensical build uses
the built-in UI distribution, so this also validates the native blog templates.
The fixtures are divided by compatibility concern:
- `vertical-slice` defines the executable contract for phases 1 through 5.
- `mutations` records ordered clean-build snapshots for route, content,
ordering, draft, deletion, and pagination changes.
- `grouped-views` covers archive, category, and author membership.
- `standalone` records a blog omitted from configured navigation.
- `multiple-instances` proves instance isolation.
- `collisions` records Material's unsafe last-writer behavior as an upstream
quirk. Zensical is expected to diagnose the collision instead of reproducing
it.
Additional focused fixtures are added before implementing deferred
compatibility areas such as advanced date formatting and custom templates.
@@ -0,0 +1 @@
# Blog
@@ -0,0 +1,8 @@
---
date: 2024-01-02
slug: collision
---
# First claimant
First claimant content.
@@ -0,0 +1,8 @@
---
date: 2024-01-02
slug: collision
---
# Second claimant
Second claimant content.
+72
View File
@@ -0,0 +1,72 @@
{
"outputs": [
"404.html",
"blog/2024/01/02/collision/index.html",
"blog/index.html"
],
"navigation": [
{
"title": "Blog",
"url": "/docs/blog/"
}
],
"pages": {
"blog/2024/01/02/collision/index.html": {
"document_title": "Second claimant - Blog collision oracle",
"canonical": "/docs/blog/2024/01/02/collision/",
"relations": {
"prev": null,
"next": "/docs/blog/2024/01/02/collision/"
},
"active_ancestors": [
"Blog"
],
"headings": [
{
"level": 1,
"id": "second-claimant",
"title": "Second claimant"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/index.html": {
"document_title": "Blog - Blog collision oracle",
"canonical": "/docs/blog/",
"relations": {
"prev": null,
"next": null
},
"active_ancestors": [
"Blog"
],
"headings": [],
"links": [],
"posts": [
{
"title": "First claimant",
"url": "/docs/blog/2024/01/02/collision/",
"date": "2024-01-02 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"first-claimant\"><a class=\"toclink\" href=\"2024/01/02/collision/\">First claimant</a></h2><p>First claimant content.</p></div>"
},
{
"title": "Second claimant",
"url": "/docs/blog/2024/01/02/collision/",
"date": "2024-01-02 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"second-claimant\"><a class=\"toclink\" href=\"2024/01/02/collision/\">Second claimant</a></h2><p>Second claimant content.</p></div>"
}
],
"pagination": null
}
}
}
+16
View File
@@ -0,0 +1,16 @@
site_name: Blog collision oracle
site_url: https://example.test/docs/
use_directory_urls: true
theme:
name: material
plugins:
- material/blog:
archive: false
categories: false
authors: false
pagination: false
nav:
- Blog: blog/index.md
@@ -0,0 +1,10 @@
authors:
alice:
name: Alice Example
description: Writes examples
avatar: https://example.test/alice.png
bob:
name: Bob Example
description: Reviews examples
avatar: https://example.test/bob.png
slug: reviewer
@@ -0,0 +1 @@
# Blog
@@ -0,0 +1,22 @@
---
date:
created: 2024-02-03T10:30:00.123456+01:00
updated: 2024-02-04
authors:
- alice
- bob
categories:
- Release Notes
- Engineering
links:
- Notes: notes.md#detail
pin: true
---
# Alpha heading
Alpha excerpt.
<!-- more -->
Alpha remainder.
@@ -0,0 +1,12 @@
---
title: Beta metadata
date: 2024-01-02
authors:
- alice
categories:
- Engineering
---
# Beta heading
Beta excerpt.
@@ -0,0 +1 @@
# Home
@@ -0,0 +1,3 @@
# Notes
## Detail
+625
View File
@@ -0,0 +1,625 @@
{
"outputs": [
"404.html",
"blog/2024/01/02/beta-metadata/index.html",
"blog/2024/02/03/alpha-heading/index.html",
"blog/archive/2024/01/index.html",
"blog/archive/2024/02/index.html",
"blog/author/alice/index.html",
"blog/author/alice/page/2/index.html",
"blog/author/reviewer/index.html",
"blog/category/engineering/index.html",
"blog/category/engineering/page/2/index.html",
"blog/category/release-notes/index.html",
"blog/index.html",
"blog/page/2/index.html",
"index.html",
"notes/index.html"
],
"navigation": [
{
"title": "Home",
"url": "/docs/"
},
{
"title": "Notes",
"url": "/docs/notes/"
},
{
"title": "Blog",
"url": "/docs/blog/",
"children": [
{
"title": "Archive",
"children": [
{
"title": "February 2024",
"url": "/docs/blog/archive/2024/02/"
},
{
"title": "January 2024",
"url": "/docs/blog/archive/2024/01/"
}
]
},
{
"title": "Categories",
"children": [
{
"title": "Engineering",
"url": "/docs/blog/category/engineering/"
},
{
"title": "Release Notes",
"url": "/docs/blog/category/release-notes/"
}
]
},
{
"title": "Authors",
"children": [
{
"title": "Alice Example",
"url": "/docs/blog/author/alice/"
},
{
"title": "Bob Example",
"url": "/docs/blog/author/reviewer/"
}
]
}
]
}
],
"pages": {
"blog/2024/01/02/beta-metadata/index.html": {
"document_title": "Beta metadata - Grouped blog oracle",
"canonical": "/docs/blog/2024/01/02/beta-metadata/",
"relations": {
"prev": null,
"next": "/docs/blog/2024/02/03/alpha-heading/"
},
"active_ancestors": [],
"headings": [
{
"level": 1,
"id": "beta-heading",
"title": "Beta heading"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/2024/02/03/alpha-heading/index.html": {
"document_title": "Alpha heading - Grouped blog oracle",
"canonical": "/docs/blog/2024/02/03/alpha-heading/",
"relations": {
"prev": "/docs/blog/2024/01/02/beta-metadata/",
"next": null
},
"active_ancestors": [],
"headings": [
{
"level": 1,
"id": "alpha-heading",
"title": "Alpha heading"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/archive/2024/01/index.html": {
"document_title": "January 2024 - Grouped blog oracle",
"canonical": "/docs/blog/archive/2024/01/",
"relations": {
"prev": "/docs/blog/archive/2024/02/",
"next": null
},
"active_ancestors": [
"Archive",
"January 2024"
],
"headings": [],
"links": [],
"posts": [
{
"title": "Beta heading",
"url": "/docs/blog/2024/01/02/beta-metadata/",
"date": "2024-01-02 00:00:00+00:00",
"authors": [
"Alice Example"
],
"categories": [
{
"title": "Engineering",
"url": "/docs/blog/category/engineering/"
}
],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"beta-heading\"><a class=\"toclink\" href=\"../../../2024/01/02/beta-metadata/\">Beta heading</a></h2><p>Beta excerpt.</p></div>"
}
],
"pagination": {
"current": 1,
"links": []
}
},
"blog/archive/2024/02/index.html": {
"document_title": "February 2024 - Grouped blog oracle",
"canonical": "/docs/blog/archive/2024/02/",
"relations": {
"prev": "/docs/blog/category/release-notes/",
"next": "/docs/blog/archive/2024/01/"
},
"active_ancestors": [
"Archive",
"February 2024"
],
"headings": [],
"links": [],
"posts": [
{
"title": "Alpha heading",
"url": "/docs/blog/2024/02/03/alpha-heading/",
"date": "2024-02-03 10:30:00.123456+01:00",
"authors": [
"Alice Example"
],
"categories": [
{
"title": "Release Notes",
"url": "/docs/blog/category/release-notes/"
},
{
"title": "Engineering",
"url": "/docs/blog/category/engineering/"
}
],
"pinned": true,
"continue": "/docs/blog/2024/02/03/alpha-heading/",
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"alpha-heading\"><a class=\"toclink\" href=\"../../../2024/02/03/alpha-heading/\">Alpha heading</a></h2><p>Alpha excerpt.</p><nav class=\"md-post__action\"><a href=\"../../../2024/02/03/alpha-heading/\"> Continue reading </a></nav><hr/></div>"
}
],
"pagination": {
"current": 1,
"links": []
}
},
"blog/author/alice/index.html": {
"document_title": "Alice Example - Grouped blog oracle",
"canonical": "/docs/blog/author/alice/",
"relations": {
"prev": "/docs/blog/",
"next": "/docs/blog/author/reviewer/"
},
"active_ancestors": [
"Authors",
"Alice Example"
],
"headings": [],
"links": [],
"posts": [
{
"title": "Alpha heading",
"url": "/docs/blog/2024/02/03/alpha-heading/",
"date": "2024-02-03 10:30:00.123456+01:00",
"authors": [
"Alice Example"
],
"categories": [
{
"title": "Release Notes",
"url": "/docs/blog/category/release-notes/"
},
{
"title": "Engineering",
"url": "/docs/blog/category/engineering/"
}
],
"pinned": true,
"continue": "/docs/blog/2024/02/03/alpha-heading/",
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"alpha-heading\"><a class=\"toclink\" href=\"../../2024/02/03/alpha-heading/\">Alpha heading</a></h2><p>Alpha excerpt.</p><nav class=\"md-post__action\"><a href=\"../../2024/02/03/alpha-heading/\"> Continue reading </a></nav><hr/></div>"
}
],
"pagination": {
"current": 1,
"links": [
{
"title": "2",
"url": "/docs/blog/author/alice/page/2/"
},
{
"title": "",
"url": "/docs/blog/author/alice/page/2/"
},
{
"title": "",
"url": "/docs/blog/author/alice/page/2/"
}
]
}
},
"blog/author/alice/page/2/index.html": {
"document_title": "Alice Example - Grouped blog oracle",
"canonical": "/docs/blog/author/alice/page/2/",
"relations": {
"prev": "/docs/blog/",
"next": "/docs/blog/author/reviewer/"
},
"active_ancestors": [
"Authors"
],
"headings": [],
"links": [],
"posts": [
{
"title": "Beta heading",
"url": "/docs/blog/2024/01/02/beta-metadata/",
"date": "2024-01-02 00:00:00+00:00",
"authors": [
"Alice Example"
],
"categories": [
{
"title": "Engineering",
"url": "/docs/blog/category/engineering/"
}
],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"beta-heading\"><a class=\"toclink\" href=\"../../../../2024/01/02/beta-metadata/\">Beta heading</a></h2><p>Beta excerpt.</p></div>"
}
],
"pagination": {
"current": 2,
"links": [
{
"title": "",
"url": "/docs/blog/author/alice/"
},
{
"title": "",
"url": "/docs/blog/author/alice/"
},
{
"title": "1",
"url": "/docs/blog/author/alice/"
}
]
}
},
"blog/author/reviewer/index.html": {
"document_title": "Bob Example - Grouped blog oracle",
"canonical": "/docs/blog/author/reviewer/",
"relations": {
"prev": "/docs/blog/author/alice/",
"next": "/docs/blog/category/engineering/"
},
"active_ancestors": [
"Authors",
"Bob Example"
],
"headings": [],
"links": [],
"posts": [
{
"title": "Alpha heading",
"url": "/docs/blog/2024/02/03/alpha-heading/",
"date": "2024-02-03 10:30:00.123456+01:00",
"authors": [
"Alice Example"
],
"categories": [
{
"title": "Release Notes",
"url": "/docs/blog/category/release-notes/"
},
{
"title": "Engineering",
"url": "/docs/blog/category/engineering/"
}
],
"pinned": true,
"continue": "/docs/blog/2024/02/03/alpha-heading/",
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"alpha-heading\"><a class=\"toclink\" href=\"../../2024/02/03/alpha-heading/\">Alpha heading</a></h2><p>Alpha excerpt.</p><nav class=\"md-post__action\"><a href=\"../../2024/02/03/alpha-heading/\"> Continue reading </a></nav><hr/></div>"
}
],
"pagination": {
"current": 1,
"links": []
}
},
"blog/category/engineering/index.html": {
"document_title": "Engineering - Grouped blog oracle",
"canonical": "/docs/blog/category/engineering/",
"relations": {
"prev": "/docs/blog/author/reviewer/",
"next": "/docs/blog/category/release-notes/"
},
"active_ancestors": [
"Categories",
"Engineering"
],
"headings": [],
"links": [],
"posts": [
{
"title": "Alpha heading",
"url": "/docs/blog/2024/02/03/alpha-heading/",
"date": "2024-02-03 10:30:00.123456+01:00",
"authors": [
"Alice Example"
],
"categories": [
{
"title": "Release Notes",
"url": "/docs/blog/category/release-notes/"
},
{
"title": "Engineering",
"url": "/docs/blog/category/engineering/"
}
],
"pinned": true,
"continue": "/docs/blog/2024/02/03/alpha-heading/",
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"alpha-heading\"><a class=\"toclink\" href=\"../../2024/02/03/alpha-heading/\">Alpha heading</a></h2><p>Alpha excerpt.</p><nav class=\"md-post__action\"><a href=\"../../2024/02/03/alpha-heading/\"> Continue reading </a></nav><hr/></div>"
}
],
"pagination": {
"current": 1,
"links": [
{
"title": "2",
"url": "/docs/blog/category/engineering/page/2/"
},
{
"title": "",
"url": "/docs/blog/category/engineering/page/2/"
},
{
"title": "",
"url": "/docs/blog/category/engineering/page/2/"
}
]
}
},
"blog/category/engineering/page/2/index.html": {
"document_title": "Engineering - Grouped blog oracle",
"canonical": "/docs/blog/category/engineering/page/2/",
"relations": {
"prev": "/docs/blog/author/reviewer/",
"next": "/docs/blog/category/release-notes/"
},
"active_ancestors": [
"Categories"
],
"headings": [],
"links": [],
"posts": [
{
"title": "Beta heading",
"url": "/docs/blog/2024/01/02/beta-metadata/",
"date": "2024-01-02 00:00:00+00:00",
"authors": [
"Alice Example"
],
"categories": [
{
"title": "Engineering",
"url": "/docs/blog/category/engineering/"
}
],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"beta-heading\"><a class=\"toclink\" href=\"../../../../2024/01/02/beta-metadata/\">Beta heading</a></h2><p>Beta excerpt.</p></div>"
}
],
"pagination": {
"current": 2,
"links": [
{
"title": "",
"url": "/docs/blog/category/engineering/"
},
{
"title": "",
"url": "/docs/blog/category/engineering/"
},
{
"title": "1",
"url": "/docs/blog/category/engineering/"
}
]
}
},
"blog/category/release-notes/index.html": {
"document_title": "Release Notes - Grouped blog oracle",
"canonical": "/docs/blog/category/release-notes/",
"relations": {
"prev": "/docs/blog/category/engineering/",
"next": "/docs/blog/archive/2024/02/"
},
"active_ancestors": [
"Categories",
"Release Notes"
],
"headings": [],
"links": [],
"posts": [
{
"title": "Alpha heading",
"url": "/docs/blog/2024/02/03/alpha-heading/",
"date": "2024-02-03 10:30:00.123456+01:00",
"authors": [
"Alice Example"
],
"categories": [
{
"title": "Release Notes",
"url": "/docs/blog/category/release-notes/"
},
{
"title": "Engineering",
"url": "/docs/blog/category/engineering/"
}
],
"pinned": true,
"continue": "/docs/blog/2024/02/03/alpha-heading/",
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"alpha-heading\"><a class=\"toclink\" href=\"../../2024/02/03/alpha-heading/\">Alpha heading</a></h2><p>Alpha excerpt.</p><nav class=\"md-post__action\"><a href=\"../../2024/02/03/alpha-heading/\"> Continue reading </a></nav><hr/></div>"
}
],
"pagination": {
"current": 1,
"links": []
}
},
"blog/index.html": {
"document_title": "Blog - Grouped blog oracle",
"canonical": "/docs/blog/",
"relations": {
"prev": "/docs/notes/",
"next": "/docs/blog/author/alice/"
},
"active_ancestors": [],
"headings": [],
"links": [],
"posts": [
{
"title": "Alpha heading",
"url": "/docs/blog/2024/02/03/alpha-heading/",
"date": "2024-02-03 10:30:00.123456+01:00",
"authors": [
"Alice Example"
],
"categories": [
{
"title": "Release Notes",
"url": "/docs/blog/category/release-notes/"
},
{
"title": "Engineering",
"url": "/docs/blog/category/engineering/"
}
],
"pinned": true,
"continue": "/docs/blog/2024/02/03/alpha-heading/",
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"alpha-heading\"><a class=\"toclink\" href=\"2024/02/03/alpha-heading/\">Alpha heading</a></h2><p>Alpha excerpt.</p><nav class=\"md-post__action\"><a href=\"2024/02/03/alpha-heading/\"> Continue reading </a></nav><hr/></div>"
}
],
"pagination": {
"current": 1,
"links": [
{
"title": "2",
"url": "/docs/blog/page/2/"
},
{
"title": "",
"url": "/docs/blog/page/2/"
},
{
"title": "",
"url": "/docs/blog/page/2/"
}
]
}
},
"blog/page/2/index.html": {
"document_title": "Blog - Grouped blog oracle",
"canonical": "/docs/blog/page/2/",
"relations": {
"prev": "/docs/notes/",
"next": "/docs/blog/author/alice/"
},
"active_ancestors": [],
"headings": [],
"links": [],
"posts": [
{
"title": "Beta heading",
"url": "/docs/blog/2024/01/02/beta-metadata/",
"date": "2024-01-02 00:00:00+00:00",
"authors": [
"Alice Example"
],
"categories": [
{
"title": "Engineering",
"url": "/docs/blog/category/engineering/"
}
],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"beta-heading\"><a class=\"toclink\" href=\"../../2024/01/02/beta-metadata/\">Beta heading</a></h2><p>Beta excerpt.</p></div>"
}
],
"pagination": {
"current": 2,
"links": [
{
"title": "",
"url": "/docs/blog/"
},
{
"title": "",
"url": "/docs/blog/"
},
{
"title": "1",
"url": "/docs/blog/"
}
]
}
},
"index.html": {
"document_title": "Grouped blog oracle",
"canonical": "/docs/",
"relations": {
"prev": null,
"next": "/docs/notes/"
},
"active_ancestors": [
"Home"
],
"headings": [
{
"level": 1,
"id": "home",
"title": "Home"
}
],
"links": [],
"posts": [],
"pagination": null
},
"notes/index.html": {
"document_title": "Notes - Grouped blog oracle",
"canonical": "/docs/notes/",
"relations": {
"prev": "/docs/",
"next": "/docs/blog/"
},
"active_ancestors": [
"Notes"
],
"headings": [
{
"level": 1,
"id": "notes",
"title": "Notes"
},
{
"level": 2,
"id": "detail",
"title": "Detail"
}
],
"links": [],
"posts": [],
"pagination": null
}
}
}
+22
View File
@@ -0,0 +1,22 @@
site_name: Grouped blog oracle
site_url: https://example.test/docs/
use_directory_urls: true
theme:
name: material
features:
- navigation.indexes
plugins:
- material/blog:
archive_date_format: MMMM yyyy
archive_url_date_format: yyyy/MM
authors_profiles: true
pagination_per_page: 1
pagination_format: "$link_first $link_previous ~1~ $link_next $link_last"
nav:
- Home: index.md
- Notes: notes.md
- Blog:
- blog/index.md
@@ -0,0 +1 @@
# Home
@@ -0,0 +1 @@
# Journal
@@ -0,0 +1,7 @@
---
date: 2024-01-02
---
# Journal post
Journal content.
@@ -0,0 +1 @@
# News
@@ -0,0 +1,7 @@
---
date: 2024-02-03
---
# News post
News content.
@@ -0,0 +1,141 @@
{
"outputs": [
"404.html",
"index.html",
"journal/2024/01/02/journal-post/index.html",
"journal/index.html",
"news/2024/02/03/news-post/index.html",
"news/index.html"
],
"navigation": [
{
"title": "Home",
"url": "/docs/"
},
{
"title": "Journal",
"url": "/docs/journal/"
},
{
"title": "News",
"url": "/docs/news/"
}
],
"pages": {
"index.html": {
"document_title": "Multiple blogs oracle",
"canonical": "/docs/",
"relations": {
"prev": null,
"next": "/docs/journal/"
},
"active_ancestors": [
"Home"
],
"headings": [
{
"level": 1,
"id": "home",
"title": "Home"
}
],
"links": [],
"posts": [],
"pagination": null
},
"journal/2024/01/02/journal-post/index.html": {
"document_title": "Journal post - Multiple blogs oracle",
"canonical": "/docs/journal/2024/01/02/journal-post/",
"relations": {
"prev": null,
"next": null
},
"active_ancestors": [
"Journal"
],
"headings": [
{
"level": 1,
"id": "journal-post",
"title": "Journal post"
}
],
"links": [],
"posts": [],
"pagination": null
},
"journal/index.html": {
"document_title": "Journal - Multiple blogs oracle",
"canonical": "/docs/journal/",
"relations": {
"prev": "/docs/",
"next": "/docs/news/"
},
"active_ancestors": [
"Journal"
],
"headings": [],
"links": [],
"posts": [
{
"title": "Journal post",
"url": "/docs/journal/2024/01/02/journal-post/",
"date": "2024-01-02 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"journal-post\"><a class=\"toclink\" href=\"2024/01/02/journal-post/\">Journal post</a></h2><p>Journal content.</p></div>"
}
],
"pagination": null
},
"news/2024/02/03/news-post/index.html": {
"document_title": "News post - Multiple blogs oracle",
"canonical": "/docs/news/2024/02/03/news-post/",
"relations": {
"prev": null,
"next": null
},
"active_ancestors": [
"News"
],
"headings": [
{
"level": 1,
"id": "news-post",
"title": "News post"
}
],
"links": [],
"posts": [],
"pagination": null
},
"news/index.html": {
"document_title": "News - Multiple blogs oracle",
"canonical": "/docs/news/",
"relations": {
"prev": "/docs/journal/",
"next": null
},
"active_ancestors": [
"News"
],
"headings": [],
"links": [],
"posts": [
{
"title": "News post",
"url": "/docs/news/2024/02/03/news-post/",
"date": "2024-02-03 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"news-post\"><a class=\"toclink\" href=\"2024/02/03/news-post/\">News post</a></h2><p>News content.</p></div>"
}
],
"pagination": null
}
}
}
@@ -0,0 +1,27 @@
site_name: Multiple blogs oracle
site_url: https://example.test/docs/
use_directory_urls: true
theme:
name: material
plugins:
- material/blog:
blog_dir: journal
post_dir: journal/posts
archive: false
categories: false
authors: false
pagination: false
- material/blog:
blog_dir: news
post_dir: news/posts
archive: false
categories: false
authors: false
pagination: false
nav:
- Home: index.md
- Journal: journal/index.md
- News: news/index.md
@@ -0,0 +1,7 @@
---
date: 2024-03-01
---
# Gamma
Initial gamma excerpt.
@@ -0,0 +1,7 @@
---
date: 2024-03-01
---
# Gamma
Edited gamma excerpt.
@@ -0,0 +1,7 @@
---
title: Renamed gamma
slug: moved-gamma
date: 2024-03-01
---
Renamed gamma excerpt.
@@ -0,0 +1,8 @@
---
title: Renamed gamma
slug: moved-gamma
date: 2023-12-01
pin: true
---
Renamed gamma excerpt.
@@ -0,0 +1,9 @@
---
title: Renamed gamma
slug: moved-gamma
date: 2023-12-01
pin: true
draft: true
---
Renamed gamma excerpt.
@@ -0,0 +1 @@
# Blog
@@ -0,0 +1,7 @@
---
date: 2024-01-01
---
# Alpha
Alpha excerpt.
@@ -0,0 +1,7 @@
---
date: 2024-02-01
---
# Beta
Beta excerpt.
+912
View File
@@ -0,0 +1,912 @@
{
"steps": [
{
"name": "baseline",
"manifest": {
"outputs": [
"404.html",
"blog/2024/01/01/alpha/index.html",
"blog/2024/02/01/beta/index.html",
"blog/index.html"
],
"navigation": [
{
"title": "Blog",
"url": "/docs/blog/"
}
],
"pages": {
"blog/2024/01/01/alpha/index.html": {
"document_title": "Alpha - Blog mutation oracle",
"canonical": "/docs/blog/2024/01/01/alpha/",
"relations": {
"prev": null,
"next": "/docs/blog/2024/02/01/beta/"
},
"active_ancestors": [
"Blog"
],
"headings": [
{
"level": 1,
"id": "alpha",
"title": "Alpha"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/2024/02/01/beta/index.html": {
"document_title": "Beta - Blog mutation oracle",
"canonical": "/docs/blog/2024/02/01/beta/",
"relations": {
"prev": "/docs/blog/2024/01/01/alpha/",
"next": null
},
"active_ancestors": [
"Blog"
],
"headings": [
{
"level": 1,
"id": "beta",
"title": "Beta"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/index.html": {
"document_title": "Blog - Blog mutation oracle",
"canonical": "/docs/blog/",
"relations": {
"prev": null,
"next": null
},
"active_ancestors": [
"Blog"
],
"headings": [],
"links": [],
"posts": [
{
"title": "Beta",
"url": "/docs/blog/2024/02/01/beta/",
"date": "2024-02-01 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"beta\"><a class=\"toclink\" href=\"2024/02/01/beta/\">Beta</a></h2><p>Beta excerpt.</p></div>"
},
{
"title": "Alpha",
"url": "/docs/blog/2024/01/01/alpha/",
"date": "2024-01-01 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"alpha\"><a class=\"toclink\" href=\"2024/01/01/alpha/\">Alpha</a></h2><p>Alpha excerpt.</p></div>"
}
],
"pagination": {
"current": 1,
"links": []
}
}
}
}
},
{
"name": "insert",
"manifest": {
"outputs": [
"404.html",
"blog/2024/01/01/alpha/index.html",
"blog/2024/02/01/beta/index.html",
"blog/2024/03/01/gamma/index.html",
"blog/index.html",
"blog/page/2/index.html"
],
"navigation": [
{
"title": "Blog",
"url": "/docs/blog/"
}
],
"pages": {
"blog/2024/01/01/alpha/index.html": {
"document_title": "Alpha - Blog mutation oracle",
"canonical": "/docs/blog/2024/01/01/alpha/",
"relations": {
"prev": null,
"next": "/docs/blog/2024/02/01/beta/"
},
"active_ancestors": [
"Blog"
],
"headings": [
{
"level": 1,
"id": "alpha",
"title": "Alpha"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/2024/02/01/beta/index.html": {
"document_title": "Beta - Blog mutation oracle",
"canonical": "/docs/blog/2024/02/01/beta/",
"relations": {
"prev": "/docs/blog/2024/01/01/alpha/",
"next": "/docs/blog/2024/03/01/gamma/"
},
"active_ancestors": [
"Blog"
],
"headings": [
{
"level": 1,
"id": "beta",
"title": "Beta"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/2024/03/01/gamma/index.html": {
"document_title": "Gamma - Blog mutation oracle",
"canonical": "/docs/blog/2024/03/01/gamma/",
"relations": {
"prev": "/docs/blog/2024/02/01/beta/",
"next": null
},
"active_ancestors": [
"Blog"
],
"headings": [
{
"level": 1,
"id": "gamma",
"title": "Gamma"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/index.html": {
"document_title": "Blog - Blog mutation oracle",
"canonical": "/docs/blog/",
"relations": {
"prev": null,
"next": null
},
"active_ancestors": [
"Blog"
],
"headings": [],
"links": [],
"posts": [
{
"title": "Gamma",
"url": "/docs/blog/2024/03/01/gamma/",
"date": "2024-03-01 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"gamma\"><a class=\"toclink\" href=\"2024/03/01/gamma/\">Gamma</a></h2><p>Initial gamma excerpt.</p></div>"
},
{
"title": "Beta",
"url": "/docs/blog/2024/02/01/beta/",
"date": "2024-02-01 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"beta\"><a class=\"toclink\" href=\"2024/02/01/beta/\">Beta</a></h2><p>Beta excerpt.</p></div>"
}
],
"pagination": {
"current": 1,
"links": [
{
"title": "2",
"url": "/docs/blog/page/2/"
}
]
}
},
"blog/page/2/index.html": {
"document_title": "Blog - Blog mutation oracle",
"canonical": "/docs/blog/page/2/",
"relations": {
"prev": null,
"next": null
},
"active_ancestors": [],
"headings": [],
"links": [],
"posts": [
{
"title": "Alpha",
"url": "/docs/blog/2024/01/01/alpha/",
"date": "2024-01-01 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"alpha\"><a class=\"toclink\" href=\"../../2024/01/01/alpha/\">Alpha</a></h2><p>Alpha excerpt.</p></div>"
}
],
"pagination": {
"current": 2,
"links": [
{
"title": "1",
"url": "/docs/blog/"
}
]
}
}
}
}
},
{
"name": "edit-body",
"manifest": {
"outputs": [
"404.html",
"blog/2024/01/01/alpha/index.html",
"blog/2024/02/01/beta/index.html",
"blog/2024/03/01/gamma/index.html",
"blog/index.html",
"blog/page/2/index.html"
],
"navigation": [
{
"title": "Blog",
"url": "/docs/blog/"
}
],
"pages": {
"blog/2024/01/01/alpha/index.html": {
"document_title": "Alpha - Blog mutation oracle",
"canonical": "/docs/blog/2024/01/01/alpha/",
"relations": {
"prev": null,
"next": "/docs/blog/2024/02/01/beta/"
},
"active_ancestors": [
"Blog"
],
"headings": [
{
"level": 1,
"id": "alpha",
"title": "Alpha"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/2024/02/01/beta/index.html": {
"document_title": "Beta - Blog mutation oracle",
"canonical": "/docs/blog/2024/02/01/beta/",
"relations": {
"prev": "/docs/blog/2024/01/01/alpha/",
"next": "/docs/blog/2024/03/01/gamma/"
},
"active_ancestors": [
"Blog"
],
"headings": [
{
"level": 1,
"id": "beta",
"title": "Beta"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/2024/03/01/gamma/index.html": {
"document_title": "Gamma - Blog mutation oracle",
"canonical": "/docs/blog/2024/03/01/gamma/",
"relations": {
"prev": "/docs/blog/2024/02/01/beta/",
"next": null
},
"active_ancestors": [
"Blog"
],
"headings": [
{
"level": 1,
"id": "gamma",
"title": "Gamma"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/index.html": {
"document_title": "Blog - Blog mutation oracle",
"canonical": "/docs/blog/",
"relations": {
"prev": null,
"next": null
},
"active_ancestors": [
"Blog"
],
"headings": [],
"links": [],
"posts": [
{
"title": "Gamma",
"url": "/docs/blog/2024/03/01/gamma/",
"date": "2024-03-01 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"gamma\"><a class=\"toclink\" href=\"2024/03/01/gamma/\">Gamma</a></h2><p>Edited gamma excerpt.</p></div>"
},
{
"title": "Beta",
"url": "/docs/blog/2024/02/01/beta/",
"date": "2024-02-01 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"beta\"><a class=\"toclink\" href=\"2024/02/01/beta/\">Beta</a></h2><p>Beta excerpt.</p></div>"
}
],
"pagination": {
"current": 1,
"links": [
{
"title": "2",
"url": "/docs/blog/page/2/"
}
]
}
},
"blog/page/2/index.html": {
"document_title": "Blog - Blog mutation oracle",
"canonical": "/docs/blog/page/2/",
"relations": {
"prev": null,
"next": null
},
"active_ancestors": [],
"headings": [],
"links": [],
"posts": [
{
"title": "Alpha",
"url": "/docs/blog/2024/01/01/alpha/",
"date": "2024-01-01 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"alpha\"><a class=\"toclink\" href=\"../../2024/01/01/alpha/\">Alpha</a></h2><p>Alpha excerpt.</p></div>"
}
],
"pagination": {
"current": 2,
"links": [
{
"title": "1",
"url": "/docs/blog/"
}
]
}
}
}
}
},
{
"name": "change-title-and-slug",
"manifest": {
"outputs": [
"404.html",
"blog/2024/01/01/alpha/index.html",
"blog/2024/02/01/beta/index.html",
"blog/2024/03/01/moved-gamma/index.html",
"blog/index.html",
"blog/page/2/index.html"
],
"navigation": [
{
"title": "Blog",
"url": "/docs/blog/"
}
],
"pages": {
"blog/2024/01/01/alpha/index.html": {
"document_title": "Alpha - Blog mutation oracle",
"canonical": "/docs/blog/2024/01/01/alpha/",
"relations": {
"prev": null,
"next": "/docs/blog/2024/02/01/beta/"
},
"active_ancestors": [
"Blog"
],
"headings": [
{
"level": 1,
"id": "alpha",
"title": "Alpha"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/2024/02/01/beta/index.html": {
"document_title": "Beta - Blog mutation oracle",
"canonical": "/docs/blog/2024/02/01/beta/",
"relations": {
"prev": "/docs/blog/2024/01/01/alpha/",
"next": "/docs/blog/2024/03/01/moved-gamma/"
},
"active_ancestors": [
"Blog"
],
"headings": [
{
"level": 1,
"id": "beta",
"title": "Beta"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/2024/03/01/moved-gamma/index.html": {
"document_title": "Renamed gamma - Blog mutation oracle",
"canonical": "/docs/blog/2024/03/01/moved-gamma/",
"relations": {
"prev": "/docs/blog/2024/02/01/beta/",
"next": null
},
"active_ancestors": [
"Blog"
],
"headings": [
{
"level": 1,
"id": null,
"title": "Renamed gamma"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/index.html": {
"document_title": "Blog - Blog mutation oracle",
"canonical": "/docs/blog/",
"relations": {
"prev": null,
"next": null
},
"active_ancestors": [
"Blog"
],
"headings": [],
"links": [],
"posts": [
{
"title": "Renamed gamma",
"url": "/docs/blog/2024/03/01/moved-gamma/",
"date": "2024-03-01 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"renamed-gamma\"><a class=\"toclink\" href=\"2024/03/01/moved-gamma/\">Renamed gamma</a></h2><p>Renamed gamma excerpt.</p></div>"
},
{
"title": "Beta",
"url": "/docs/blog/2024/02/01/beta/",
"date": "2024-02-01 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"beta\"><a class=\"toclink\" href=\"2024/02/01/beta/\">Beta</a></h2><p>Beta excerpt.</p></div>"
}
],
"pagination": {
"current": 1,
"links": [
{
"title": "2",
"url": "/docs/blog/page/2/"
}
]
}
},
"blog/page/2/index.html": {
"document_title": "Blog - Blog mutation oracle",
"canonical": "/docs/blog/page/2/",
"relations": {
"prev": null,
"next": null
},
"active_ancestors": [],
"headings": [],
"links": [],
"posts": [
{
"title": "Alpha",
"url": "/docs/blog/2024/01/01/alpha/",
"date": "2024-01-01 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"alpha\"><a class=\"toclink\" href=\"../../2024/01/01/alpha/\">Alpha</a></h2><p>Alpha excerpt.</p></div>"
}
],
"pagination": {
"current": 2,
"links": [
{
"title": "1",
"url": "/docs/blog/"
}
]
}
}
}
}
},
{
"name": "change-date-and-pin",
"manifest": {
"outputs": [
"404.html",
"blog/2023/12/01/moved-gamma/index.html",
"blog/2024/01/01/alpha/index.html",
"blog/2024/02/01/beta/index.html",
"blog/index.html",
"blog/page/2/index.html"
],
"navigation": [
{
"title": "Blog",
"url": "/docs/blog/"
}
],
"pages": {
"blog/2023/12/01/moved-gamma/index.html": {
"document_title": "Renamed gamma - Blog mutation oracle",
"canonical": "/docs/blog/2023/12/01/moved-gamma/",
"relations": {
"prev": "/docs/blog/2024/02/01/beta/",
"next": null
},
"active_ancestors": [
"Blog"
],
"headings": [
{
"level": 1,
"id": null,
"title": "Renamed gamma"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/2024/01/01/alpha/index.html": {
"document_title": "Alpha - Blog mutation oracle",
"canonical": "/docs/blog/2024/01/01/alpha/",
"relations": {
"prev": null,
"next": "/docs/blog/2024/02/01/beta/"
},
"active_ancestors": [
"Blog"
],
"headings": [
{
"level": 1,
"id": "alpha",
"title": "Alpha"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/2024/02/01/beta/index.html": {
"document_title": "Beta - Blog mutation oracle",
"canonical": "/docs/blog/2024/02/01/beta/",
"relations": {
"prev": "/docs/blog/2024/01/01/alpha/",
"next": "/docs/blog/2023/12/01/moved-gamma/"
},
"active_ancestors": [
"Blog"
],
"headings": [
{
"level": 1,
"id": "beta",
"title": "Beta"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/index.html": {
"document_title": "Blog - Blog mutation oracle",
"canonical": "/docs/blog/",
"relations": {
"prev": null,
"next": null
},
"active_ancestors": [
"Blog"
],
"headings": [],
"links": [],
"posts": [
{
"title": "Renamed gamma",
"url": "/docs/blog/2023/12/01/moved-gamma/",
"date": "2023-12-01 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": true,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"renamed-gamma\"><a class=\"toclink\" href=\"2023/12/01/moved-gamma/\">Renamed gamma</a></h2><p>Renamed gamma excerpt.</p><hr/></div>"
},
{
"title": "Beta",
"url": "/docs/blog/2024/02/01/beta/",
"date": "2024-02-01 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"beta\"><a class=\"toclink\" href=\"2024/02/01/beta/\">Beta</a></h2><p>Beta excerpt.</p></div>"
}
],
"pagination": {
"current": 1,
"links": [
{
"title": "2",
"url": "/docs/blog/page/2/"
}
]
}
},
"blog/page/2/index.html": {
"document_title": "Blog - Blog mutation oracle",
"canonical": "/docs/blog/page/2/",
"relations": {
"prev": null,
"next": null
},
"active_ancestors": [],
"headings": [],
"links": [],
"posts": [
{
"title": "Alpha",
"url": "/docs/blog/2024/01/01/alpha/",
"date": "2024-01-01 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"alpha\"><a class=\"toclink\" href=\"../../2024/01/01/alpha/\">Alpha</a></h2><p>Alpha excerpt.</p></div>"
}
],
"pagination": {
"current": 2,
"links": [
{
"title": "1",
"url": "/docs/blog/"
}
]
}
}
}
}
},
{
"name": "toggle-draft",
"manifest": {
"outputs": [
"404.html",
"blog/2024/01/01/alpha/index.html",
"blog/2024/02/01/beta/index.html",
"blog/index.html"
],
"navigation": [
{
"title": "Blog",
"url": "/docs/blog/"
}
],
"pages": {
"blog/2024/01/01/alpha/index.html": {
"document_title": "Alpha - Blog mutation oracle",
"canonical": "/docs/blog/2024/01/01/alpha/",
"relations": {
"prev": null,
"next": "/docs/blog/2024/02/01/beta/"
},
"active_ancestors": [
"Blog"
],
"headings": [
{
"level": 1,
"id": "alpha",
"title": "Alpha"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/2024/02/01/beta/index.html": {
"document_title": "Beta - Blog mutation oracle",
"canonical": "/docs/blog/2024/02/01/beta/",
"relations": {
"prev": "/docs/blog/2024/01/01/alpha/",
"next": null
},
"active_ancestors": [
"Blog"
],
"headings": [
{
"level": 1,
"id": "beta",
"title": "Beta"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/index.html": {
"document_title": "Blog - Blog mutation oracle",
"canonical": "/docs/blog/",
"relations": {
"prev": null,
"next": null
},
"active_ancestors": [
"Blog"
],
"headings": [],
"links": [],
"posts": [
{
"title": "Beta",
"url": "/docs/blog/2024/02/01/beta/",
"date": "2024-02-01 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"beta\"><a class=\"toclink\" href=\"2024/02/01/beta/\">Beta</a></h2><p>Beta excerpt.</p></div>"
},
{
"title": "Alpha",
"url": "/docs/blog/2024/01/01/alpha/",
"date": "2024-01-01 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"alpha\"><a class=\"toclink\" href=\"2024/01/01/alpha/\">Alpha</a></h2><p>Alpha excerpt.</p></div>"
}
],
"pagination": {
"current": 1,
"links": []
}
}
}
}
},
{
"name": "delete-post",
"manifest": {
"outputs": [
"404.html",
"blog/2024/02/01/beta/index.html",
"blog/index.html"
],
"navigation": [
{
"title": "Blog",
"url": "/docs/blog/"
}
],
"pages": {
"blog/2024/02/01/beta/index.html": {
"document_title": "Beta - Blog mutation oracle",
"canonical": "/docs/blog/2024/02/01/beta/",
"relations": {
"prev": null,
"next": null
},
"active_ancestors": [
"Blog"
],
"headings": [
{
"level": 1,
"id": "beta",
"title": "Beta"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/index.html": {
"document_title": "Blog - Blog mutation oracle",
"canonical": "/docs/blog/",
"relations": {
"prev": null,
"next": null
},
"active_ancestors": [
"Blog"
],
"headings": [],
"links": [],
"posts": [
{
"title": "Beta",
"url": "/docs/blog/2024/02/01/beta/",
"date": "2024-02-01 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"beta\"><a class=\"toclink\" href=\"2024/02/01/beta/\">Beta</a></h2><p>Beta excerpt.</p></div>"
}
],
"pagination": {
"current": 1,
"links": []
}
}
}
}
}
]
}
+16
View File
@@ -0,0 +1,16 @@
site_name: Blog mutation oracle
site_url: https://example.test/docs/
use_directory_urls: true
theme:
name: material
plugins:
- material/blog:
archive: false
categories: false
authors: false
pagination_per_page: 2
nav:
- Blog: blog/index.md
+41
View File
@@ -0,0 +1,41 @@
[
{
"name": "baseline"
},
{
"name": "insert",
"copy": {
"changes/01-insert.md": "docs/blog/posts/gamma.md"
}
},
{
"name": "edit-body",
"copy": {
"changes/02-body.md": "docs/blog/posts/gamma.md"
}
},
{
"name": "change-title-and-slug",
"copy": {
"changes/03-route.md": "docs/blog/posts/gamma.md"
}
},
{
"name": "change-date-and-pin",
"copy": {
"changes/04-reorder.md": "docs/blog/posts/gamma.md"
}
},
{
"name": "toggle-draft",
"copy": {
"changes/05-draft.md": "docs/blog/posts/gamma.md"
}
},
{
"name": "delete-post",
"remove": [
"docs/blog/posts/alpha.md"
]
}
]
@@ -0,0 +1 @@
# Unlisted blog
@@ -0,0 +1,7 @@
---
date: 2024-01-02
---
# Unlisted post
The post and blog are built even though the blog is absent from navigation.
+1
View File
@@ -0,0 +1 @@
# Home
+80
View File
@@ -0,0 +1,80 @@
{
"outputs": [
"404.html",
"blog/2024/01/02/unlisted-post/index.html",
"blog/index.html",
"index.html"
],
"navigation": [
{
"title": "Home",
"url": "/docs/"
}
],
"pages": {
"blog/2024/01/02/unlisted-post/index.html": {
"document_title": "Unlisted post - Standalone blog oracle",
"canonical": "/docs/blog/2024/01/02/unlisted-post/",
"relations": {
"prev": null,
"next": null
},
"active_ancestors": [],
"headings": [
{
"level": 1,
"id": "unlisted-post",
"title": "Unlisted post"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/index.html": {
"document_title": "Unlisted blog - Standalone blog oracle",
"canonical": "/docs/blog/",
"relations": {
"prev": null,
"next": null
},
"active_ancestors": [],
"headings": [],
"links": [],
"posts": [
{
"title": "Unlisted post",
"url": "/docs/blog/2024/01/02/unlisted-post/",
"date": "2024-01-02 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"unlisted-post\"><a class=\"toclink\" href=\"2024/01/02/unlisted-post/\">Unlisted post</a></h2><p>The post and blog are built even though the blog is absent from navigation.</p></div>"
}
],
"pagination": null
},
"index.html": {
"document_title": "Standalone blog oracle",
"canonical": "/docs/",
"relations": {
"prev": null,
"next": null
},
"active_ancestors": [
"Home"
],
"headings": [
{
"level": 1,
"id": "home",
"title": "Home"
}
],
"links": [],
"posts": [],
"pagination": null
}
}
}
+16
View File
@@ -0,0 +1,16 @@
site_name: Standalone blog oracle
site_url: https://example.test/docs/
use_directory_urls: true
theme:
name: material
plugins:
- material/blog:
archive: false
categories: false
authors: false
pagination: false
nav:
- Home: index.md
@@ -0,0 +1,7 @@
---
title: Journal
---
# Rendered journal
Introductory content.
@@ -0,0 +1,6 @@
---
date: 2024-05-06
draft: true
---
# Draft post
@@ -0,0 +1,5 @@
---
date: 2023-12-01
---
Filename-derived excerpt.
@@ -0,0 +1,5 @@
---
date: 2099-01-01
---
# Future post
@@ -0,0 +1,9 @@
---
title: Metadata wins
date: 2024-03-04
slug: chosen-slug
---
# Content heading
Metadata excerpt without a separator.
@@ -0,0 +1,12 @@
---
date: 2024-01-02
pin: true
---
# Pinned heading
Pinned excerpt with a [relative link](../../notes.md#detail).
<!-- more -->
Pinned remainder.
@@ -0,0 +1,11 @@
---
date: 2024-02-03
---
# Über Café 東京
Unicode excerpt.
<!-- more -->
Unicode remainder.
@@ -0,0 +1 @@
# Home
@@ -0,0 +1,3 @@
# Notes
## Detail
+241
View File
@@ -0,0 +1,241 @@
{
"outputs": [
"404.html",
"blog/2023/12/01/filename-title/index.html",
"blog/2024/01/02/pinned-heading/index.html",
"blog/2024/02/03/über-café-東京/index.html",
"blog/2024/03/04/chosen-slug/index.html",
"blog/index.html",
"blog/page/2/index.html",
"index.html",
"notes/index.html"
],
"navigation": [
{
"title": "Home",
"url": "/docs/"
},
{
"title": "Notes",
"url": "/docs/notes/"
},
{
"title": "Blog",
"url": "/docs/blog/"
}
],
"pages": {
"blog/2023/12/01/filename-title/index.html": {
"document_title": "Filename title - Blog oracle",
"canonical": "/docs/blog/2023/12/01/filename-title/",
"relations": {
"prev": null,
"next": "/docs/blog/2024/02/03/%C3%BCber-caf%C3%A9-%E6%9D%B1%E4%BA%AC/"
},
"active_ancestors": [],
"headings": [
{
"level": 1,
"id": null,
"title": "Filename title"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/2024/01/02/pinned-heading/index.html": {
"document_title": "Pinned heading - Blog oracle",
"canonical": "/docs/blog/2024/01/02/pinned-heading/",
"relations": {
"prev": "/docs/blog/2024/03/04/chosen-slug/",
"next": null
},
"active_ancestors": [],
"headings": [
{
"level": 1,
"id": "pinned-heading",
"title": "Pinned heading"
}
],
"links": [
{
"title": "relative link",
"url": "/docs/notes/#detail"
}
],
"posts": [],
"pagination": null
},
"blog/2024/02/03/über-café-東京/index.html": {
"document_title": "Über Café 東京 - Blog oracle",
"canonical": "/docs/blog/2024/02/03/%C3%BCber-caf%C3%A9-%E6%9D%B1%E4%BA%AC/",
"relations": {
"prev": "/docs/blog/2023/12/01/filename-title/",
"next": "/docs/blog/2024/03/04/chosen-slug/"
},
"active_ancestors": [],
"headings": [
{
"level": 1,
"id": "uber-cafe",
"title": "Über Café 東京"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/2024/03/04/chosen-slug/index.html": {
"document_title": "Metadata wins - Blog oracle",
"canonical": "/docs/blog/2024/03/04/chosen-slug/",
"relations": {
"prev": "/docs/blog/2024/02/03/%C3%BCber-caf%C3%A9-%E6%9D%B1%E4%BA%AC/",
"next": "/docs/blog/2024/01/02/pinned-heading/"
},
"active_ancestors": [],
"headings": [
{
"level": 1,
"id": "content-heading",
"title": "Content heading"
}
],
"links": [],
"posts": [],
"pagination": null
},
"blog/index.html": {
"document_title": "Journal - Blog oracle",
"canonical": "/docs/blog/",
"relations": {
"prev": "/docs/notes/",
"next": null
},
"active_ancestors": [],
"headings": [],
"links": [],
"posts": [
{
"title": "Pinned heading",
"url": "/docs/blog/2024/01/02/pinned-heading/",
"date": "2024-01-02 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": true,
"continue": "/docs/blog/2024/01/02/pinned-heading/",
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"pinned-heading\"><a class=\"toclink\" href=\"2024/01/02/pinned-heading/\">Pinned heading</a></h2><p>Pinned excerpt with a <a href=\"../notes/#detail\">relative link</a>.</p><nav class=\"md-post__action\"><a href=\"2024/01/02/pinned-heading/\"> Continue reading </a></nav><hr/></div>"
},
{
"title": "Content heading",
"url": "/docs/blog/2024/03/04/chosen-slug/",
"date": "2024-03-04 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"content-heading\"><a class=\"toclink\" href=\"2024/03/04/chosen-slug/\">Content heading</a></h2><p>Metadata excerpt without a separator.</p></div>"
}
],
"pagination": {
"current": 1,
"links": [
{
"title": "2",
"url": "/docs/blog/page/2/"
}
]
}
},
"blog/page/2/index.html": {
"document_title": "Journal - Blog oracle",
"canonical": "/docs/blog/page/2/",
"relations": {
"prev": "/docs/notes/",
"next": null
},
"active_ancestors": [],
"headings": [],
"links": [],
"posts": [
{
"title": "Über Café 東京",
"url": "/docs/blog/2024/02/03/%C3%BCber-caf%C3%A9-%E6%9D%B1%E4%BA%AC/",
"date": "2024-02-03 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": "/docs/blog/2024/02/03/%C3%BCber-caf%C3%A9-%E6%9D%B1%E4%BA%AC/",
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"uber-cafe\"><a class=\"toclink\" href=\"../../2024/02/03/%C3%BCber-caf%C3%A9-%E6%9D%B1%E4%BA%AC/\">Über Café 東京</a></h2><p>Unicode excerpt.</p><nav class=\"md-post__action\"><a href=\"../../2024/02/03/%C3%BCber-caf%C3%A9-%E6%9D%B1%E4%BA%AC/\"> Continue reading </a></nav></div>"
},
{
"title": "Filename title",
"url": "/docs/blog/2023/12/01/filename-title/",
"date": "2023-12-01 00:00:00+00:00",
"authors": [],
"categories": [],
"pinned": false,
"continue": null,
"content": "<div class=\"md-post__content md-typeset\"><h2 id=\"filename-title\"><a class=\"toclink\" href=\"../../2023/12/01/filename-title/\">Filename title</a></h2><p>Filename-derived excerpt.</p></div>"
}
],
"pagination": {
"current": 2,
"links": [
{
"title": "1",
"url": "/docs/blog/"
}
]
}
},
"index.html": {
"document_title": "Blog oracle",
"canonical": "/docs/",
"relations": {
"prev": null,
"next": "/docs/notes/"
},
"active_ancestors": [
"Home"
],
"headings": [
{
"level": 1,
"id": "home",
"title": "Home"
}
],
"links": [],
"posts": [],
"pagination": null
},
"notes/index.html": {
"document_title": "Notes - Blog oracle",
"canonical": "/docs/notes/",
"relations": {
"prev": "/docs/",
"next": "/docs/blog/"
},
"active_ancestors": [
"Notes"
],
"headings": [
{
"level": 1,
"id": "notes",
"title": "Notes"
},
{
"level": 2,
"id": "detail",
"title": "Detail"
}
],
"links": [],
"posts": [],
"pagination": null
}
}
}
+22
View File
@@ -0,0 +1,22 @@
site_name: Blog oracle
site_url: https://example.test/docs/
use_directory_urls: true
theme:
name: material
features:
- navigation.indexes
plugins:
- material/blog:
archive: false
categories: false
authors: false
pagination_per_page: 2
draft_if_future_date: true
nav:
- Home: index.md
- Notes: notes.md
- Blog:
- blog/index.md
File diff suppressed because it is too large Load Diff
+21
View File
@@ -239,6 +239,27 @@ class TestThemeLoadingToml:
config_path = _make_toml_project(tmp_path)
_build(config_path) # must not raise
def test_blog_icons_can_be_overridden(self, tmp_path: Path) -> None:
"""Blog icon settings pass through configuration to templates."""
custom = _make_custom_dir(tmp_path)
custom.joinpath("main.html").write_text(
"{{ config.theme.icon.blog.back }}",
encoding="utf-8",
)
config_path = _make_toml_project(
tmp_path,
toml_extra=(
'[project.theme]\ncustom_dir = "overrides"\n'
'[project.theme.icon.blog]\nback = "octicons/arrow-left-16"\n'
),
)
_build(config_path)
assert (
tmp_path / "site" / "index.html"
).read_text() == "octicons/arrow-left-16"
def test_unknown_theme_name_raises(self, tmp_path: Path) -> None:
"""theme.name set to an uninstalled theme -> config error raised."""
config_path = _make_toml_project(
+17
View File
@@ -341,6 +341,23 @@ class TestPluginShimming:
}
assert config["plugins_hash"] == cfg_module._hash(config["plugins"])
def test_material_blog_instances_preserve_order_and_aliases(
self, tmp_path: Path
) -> None:
config = self._parse_yaml(
tmp_path,
plugins=[
{"material/blog": {"blog_dir": "journal"}},
{"blog": {"blog_dir": "news"}},
],
)
assert config["plugins"]["blogs"] == {
"config": [
{"name": "blog", "config": {"blog_dir": "journal"}},
{"name": "blog", "config": {"blog_dir": "news"}},
]
}
def test_material_offline_alias_is_normalized(self, tmp_path: Path) -> None:
config = self._parse_yaml(tmp_path, plugins=["material/offline"])
assert "material/offline" not in config["plugins"]
+26 -3
View File
@@ -181,7 +181,7 @@ def test_silently_discards_unsupported_mike_options(
assert capsys.readouterr().err == ""
@pytest.mark.parametrize("name", [*PYTHON_PLUGINS, "tags"])
@pytest.mark.parametrize("name", [*PYTHON_PLUGINS, "tags", "blog"])
def test_plugin_configuration_must_be_a_mapping(name: str) -> None:
with pytest.raises(
ConfigurationError,
@@ -194,7 +194,6 @@ def test_plugin_configuration_must_be_a_mapping(name: str) -> None:
"name",
[
"external", # does not exist
"material/blog", # exists but isn't supported yet
"literate_nav", # misspelling (`_` instead of `-`)
],
)
@@ -210,11 +209,35 @@ def test_ignores_unsupported_plugins(
assert capsys.readouterr().err == ""
@pytest.mark.parametrize("name", ["external", "material/blog", "literate_nav"])
@pytest.mark.parametrize("name", ["external", "literate_nav"])
def test_ignores_unsupported_plugin_names(name: str) -> None:
assert _convert_plugins([name]) == _convert_plugins([])
@pytest.mark.parametrize("name", ["blog", "material/blog"])
@pytest.mark.parametrize("data", [None, {"blog_dir": "journal"}])
@pytest.mark.parametrize("as_list", [False, True])
def test_preserves_blog_plugins(
name: str, data: dict[str, Any] | None, as_list: bool
) -> None:
value = {name: data}
plugins = _convert_plugins([value] if as_list else value)
assert plugins["blogs"]["config"] == [
{"name": "blog", "config": data or {}}
]
@pytest.mark.parametrize("name", ["blog", "material/blog"])
@pytest.mark.parametrize("data", [True, 42, "config", []])
def test_rejects_invalid_blog_configuration(name: str, data: Any) -> None:
with pytest.raises(
ConfigurationError,
match="blog configuration must be a mapping",
):
_convert_plugins({name: data})
@pytest.mark.parametrize("prefix", ["", "material/"])
@pytest.mark.parametrize("value", [True, False, "auto", 42, [], {}, None])
@pytest.mark.parametrize(
+16
View File
@@ -120,6 +120,7 @@ _PLUGIN_UNSUPPORTED_OPTIONS = {
"strip_title_tags",
),
"awesome-nav": (),
"blog": (),
"callouts": (
"aliases",
"breakless_lists",
@@ -633,6 +634,7 @@ def _apply_defaults(config: dict, path: str) -> dict:
set_default(icon, "repo", None, str)
set_default(icon, "annotation", None, str)
set_default(icon, "tag", {}, dict)
blog = set_default(icon, "blog", {}, dict)
if theme.get("variant") == "modern":
set_default(icon, "logo", "lucide/book-open", str)
set_default(icon, "edit", "lucide/file-pen", str)
@@ -645,6 +647,11 @@ def _apply_defaults(config: dict, path: str) -> dict:
set_default(icon, "close", "lucide/x", str)
set_default(icon, "previous", "lucide/arrow-left", str)
set_default(icon, "next", "lucide/arrow-right", str)
set_default(blog, "back", "lucide/arrow-left", str)
set_default(blog, "date", "lucide/calendar-days", str)
set_default(blog, "date_updated", "lucide/calendar-clock", str)
set_default(blog, "categories", "lucide/library", str)
set_default(blog, "readtime", "lucide/clock", str)
else:
set_default(icon, "logo", None, str)
set_default(icon, "edit", None, str)
@@ -657,6 +664,11 @@ def _apply_defaults(config: dict, path: str) -> dict:
set_default(icon, "close", None, str)
set_default(icon, "previous", None, str)
set_default(icon, "next", None, str)
set_default(blog, "back", "material/arrow-left", str)
set_default(blog, "date", "material/calendar", str)
set_default(blog, "date_updated", "material/calendar-clock", str)
set_default(blog, "categories", "material/bookshelf", str)
set_default(blog, "readtime", "material/clock-outline", str)
# Set defaults for theme admonition icons
admonition = set_default(icon, "admonition", {}, dict)
@@ -1521,6 +1533,7 @@ def _convert_plugins(value: Any, config: dict) -> dict:
"""Convert plugins configuration to something we can work with."""
plugins: dict[str, Any] = {}
tags: list[dict[str, Any]] = []
blogs: list[dict[str, Any]] = []
def add(name: Any, data: Any) -> None:
"""Canonicalize Material aliases while preserving tag instances."""
@@ -1540,6 +1553,8 @@ def _convert_plugins(value: Any, config: dict) -> dict:
if name == "tags":
_reject_unknown_options("tags", data, _TAGS_SUPPORTED_OPTIONS)
tags.append({"name": name, "config": data})
elif name == "blog":
blogs.append({"name": name, "config": data})
else:
plugins[name] = data
@@ -1567,6 +1582,7 @@ def _convert_plugins(value: Any, config: dict) -> dict:
# Rust owns tags defaults, value validation, scalar coercion and callable
# lowering. Python validates option names and preserves ordered instances.
plugins["tags"] = tags
plugins["blogs"] = blogs
# Search is enabled by default, even when it isn't explicitly configured.
search = plugins.pop("search", {})