mirror of
https://github.com/squidfunk/mkdocs-material.git
synced 2024-11-24 07:30:12 +01:00
Added blog and social cards tutorials (#7014)
* added tutorials page and blog tutorial * proof reading, some language improvements * split blog tutorial into parts and reworked on the basis of comments, improved language, added missing things * + custom slugify function example * +blog tutorial on engagement * + section blog ToC * + instructions for X/FB share buttons and started discussion system * fix: module name `code` shadowed Python standard library module * added What's next section * +blog tutorial engagement part * fix: updated Giscus code snippet * trying multiple tutorials with headings for each group * + basic social cards tutorial * + custom social card tutorial * + estimated time for custom card tutorial * added tutorial sections to nav * fixed typos, removed sponsor icon from level one heading * removed "tutorial" from level one heading * added headings to custom layout example * fixed broken link * fixes after run-through, added links to template repos * added comment for @squidfunk * clarified use of logos, some proof-reading * removed question I left for @squidfunk * clarified relationship between background color and image * added override for the background image * fixed wording and indentation * changed example to be releases, not events * being more specific where to add the last bit of code in the layout --------- Co-authored-by: squidfunk <martin.donath@squidfunk.com>
This commit is contained in:
parent
c8ee11ff2b
commit
50d7c54bdf
375
docs/tutorials/blogs/basic.md
Normal file
375
docs/tutorials/blogs/basic.md
Normal file
@ -0,0 +1,375 @@
|
|||||||
|
# Basic blogs
|
||||||
|
|
||||||
|
Blogs are a great way to engage with your audience. Software developers can use
|
||||||
|
a blog to announce new features, demonstrate their usage and provide background
|
||||||
|
information. You can demonstrate competence by commenting on the state of the
|
||||||
|
art or document your own work as best practice. Posts on current topics can help
|
||||||
|
draw in visitors for your main website and can keep your audience engaged. Of
|
||||||
|
course, you can blog about any topics close to your heart.
|
||||||
|
|
||||||
|
The [blog plugin] makes running a blog alongside your other content easy but you
|
||||||
|
can also configure it to run a stand-alone blog if posts are the only kind
|
||||||
|
of content you need.
|
||||||
|
|
||||||
|
After a brief overview of the basic concepts of a blog, this tutorial guides you
|
||||||
|
through the process of configuring the [blog plugin], setting up your blog,
|
||||||
|
creating posts, and defining post metadata.
|
||||||
|
|
||||||
|
[blog plugin]: ../../plugins/blog.md
|
||||||
|
|
||||||
|
__Time required:__ typically 20 minutes
|
||||||
|
|
||||||
|
## Key concepts
|
||||||
|
|
||||||
|
**Post, excerpt**: a blog consists of a number of self-contained _posts_ (often called
|
||||||
|
articles) and an index page that shows the posts in reverse chronological order, with
|
||||||
|
the most recent post at the top. The index page usually shows only a short _excerpt_ and a
|
||||||
|
link that the user can click to navigate to the full post.
|
||||||
|
|
||||||
|
**Metadata**: both the index page and the post itself list information such as
|
||||||
|
when you published the post, when you updated it, who the author is, and what the
|
||||||
|
expected reading time is.
|
||||||
|
|
||||||
|
**Slug**: since the blog posts are primarily arranged by time and not into a hierarchy,
|
||||||
|
their URLs do not reflect such a structure. Instead, each post's URL
|
||||||
|
contains a shortened description, the _slug_, which is usually derived from
|
||||||
|
the first heading in the post.
|
||||||
|
|
||||||
|
**Navigation**: the main navigation structure is the timeline, which you can
|
||||||
|
subdivide into _categories_. The main index page shows the more recent posts
|
||||||
|
while an _archive_ section allows access to older ones, organized by year.
|
||||||
|
In addition, posts can be _tagged_ and _tag index pages_ provide an additional
|
||||||
|
navigation structure based on content.
|
||||||
|
|
||||||
|
You can see all these elements on the [Material for MkDocs blog].
|
||||||
|
|
||||||
|
[Material for MkDocs blog]: https://squidfunk.github.io/mkdocs-material/blog/
|
||||||
|
|
||||||
|
## Setting up your blog
|
||||||
|
|
||||||
|
The blog plugin is part of Material for MkDocs but you need to configure it
|
||||||
|
in the `mkdocs.yml`.
|
||||||
|
|
||||||
|
!!! example "Set up a blog"
|
||||||
|
|
||||||
|
If you have not done so already, create a project for your blog,
|
||||||
|
then edit the `mkdocs.yml` file to make sure if has the following content:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
site_name: Blog Tutorial
|
||||||
|
site_description: an example blog set up following the tutorial
|
||||||
|
site_url: http://www.example.com
|
||||||
|
|
||||||
|
theme:
|
||||||
|
name: material
|
||||||
|
|
||||||
|
plugins:
|
||||||
|
- search
|
||||||
|
- blog
|
||||||
|
```
|
||||||
|
|
||||||
|
The blog plugin will create a directory structure for your blog posts if it
|
||||||
|
does not exist, so simply run `mkdocs serve` to get:
|
||||||
|
|
||||||
|
```
|
||||||
|
docs
|
||||||
|
├── blog
|
||||||
|
│ ├── index.md
|
||||||
|
│ └── posts
|
||||||
|
└── index.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Now create your first blog post in `docs/blog/posts`. You can use any
|
||||||
|
naming convention and directory structure you like for your posts, as long as
|
||||||
|
they are inside `docs/blog/posts`.
|
||||||
|
|
||||||
|
Each post _must_ have a page header, which appears at the top of the Markdown
|
||||||
|
code between lines with three dashes. Within this header, you need to have at
|
||||||
|
least a `date` entry but you can add other data, as you will see below.
|
||||||
|
Following the header comes the page content. Note that it is important
|
||||||
|
to have a level one heading as the plugin uses it to produce the _slug_. Also,
|
||||||
|
by adding `<!-- more -->` to the page, you can define where the excerpt will end
|
||||||
|
that the index page shows.
|
||||||
|
|
||||||
|
!!! example "Write your first post"
|
||||||
|
|
||||||
|
Create a file `docs/blog/posts/myfirst.md` with the following contents:
|
||||||
|
|
||||||
|
```
|
||||||
|
---
|
||||||
|
date:
|
||||||
|
created: 2023-12-31
|
||||||
|
---
|
||||||
|
|
||||||
|
# Happy new years eve!
|
||||||
|
|
||||||
|
We hope you are all having fun and wish you all the best for the new year!
|
||||||
|
<!-- more -->
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
|
||||||
|
tempor incididunt ut labore et dolore magna aliqua.
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, run `mkdocs serve` and point your web browser at
|
||||||
|
`http://localhost:8000/blog`.
|
||||||
|
|
||||||
|
The blog plugin automatically creates navigation elements for
|
||||||
|
the blog. The index page shows only the extract. When you select the
|
||||||
|
"Continue reading" link, you will get to the full blog post. Note how it
|
||||||
|
has a URL generated from the first-level heading.
|
||||||
|
|
||||||
|
!!! tip "Navigation"
|
||||||
|
|
||||||
|
We also have a [tutorial on navigation] that shows you how to change the
|
||||||
|
automatically created navigation and integrate the blog into your existing
|
||||||
|
navigation structure. It shows how to create secondary nagigation, produce
|
||||||
|
author pages, and control pagination.
|
||||||
|
|
||||||
|
[tutorial on navigation]: navigation.md
|
||||||
|
|
||||||
|
## Post metadata
|
||||||
|
|
||||||
|
In addition to the date, you can provide other metadata and give the plugin
|
||||||
|
instructions, such as to treat a post as a draft or to pin it.
|
||||||
|
|
||||||
|
### Drafts
|
||||||
|
|
||||||
|
You may want to produce a draft of a blog post and work with it locally but
|
||||||
|
exclude it from the build that you publish. Simply add a field to the page
|
||||||
|
header to indicate that a post is still in draft form.
|
||||||
|
|
||||||
|
!!! example "Create a draft"
|
||||||
|
|
||||||
|
Create a second blog post in `docs/blogs/posts/draft.md` with the following
|
||||||
|
contents:
|
||||||
|
|
||||||
|
```hl_lines="3"
|
||||||
|
---
|
||||||
|
date:
|
||||||
|
created: 2024-01-01
|
||||||
|
draft: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Happy new year!
|
||||||
|
|
||||||
|
Happy 2024 to everyone. Wishing you all the best!
|
||||||
|
<!-- more -->
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
|
||||||
|
tempor incididunt ut labore et dolore magna aliqua.
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, note how the draft appears on the index page but with a label that
|
||||||
|
indicates that it is a draft. When you run `mkdocs build`, the draft will
|
||||||
|
_not_ appear in the output:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ mkdocs build
|
||||||
|
$ ls site/blog
|
||||||
|
site/blog
|
||||||
|
├── 2023
|
||||||
|
│ └── 12
|
||||||
|
│ └── 31
|
||||||
|
│ └── happy-new-years-eve
|
||||||
|
│ └── index.html
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
The first blog post for 2024 is not there yet because it is still in draft
|
||||||
|
stage. Remember to remove the `draft` setting in the header when it is time
|
||||||
|
to publish it.
|
||||||
|
|
||||||
|
If you are using the [Insiders Edition], you can also create
|
||||||
|
a folder to keep your drafts in and use the [Meta plugin] to add the
|
||||||
|
`draft` header setting to all the posts in that folder. This has the advantage
|
||||||
|
that it is easier to see which posts are still in draft form. We will cover the
|
||||||
|
Meta plugin later on.
|
||||||
|
|
||||||
|
[Meta plugin]: ../../plugins/meta.md
|
||||||
|
|
||||||
|
### Edits
|
||||||
|
|
||||||
|
Sometimes, bloggers need to update a post. This might happen when you make
|
||||||
|
a mistake or when something changes that you need to reflect in the post. To
|
||||||
|
indicate you have edited a post, you can include an `updated` date in the page
|
||||||
|
header.
|
||||||
|
|
||||||
|
!!! example "Editing a post"
|
||||||
|
|
||||||
|
Make a change to your first blog post, then add an edit date to the header:
|
||||||
|
|
||||||
|
```hl_lines="3 4"
|
||||||
|
---
|
||||||
|
date:
|
||||||
|
created: 2023-12-31
|
||||||
|
updated: 2024-01-02
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
The Metadata section of the blog post itself will contain the edit date,
|
||||||
|
though the index page omits this detail by default.
|
||||||
|
|
||||||
|
### Reading time
|
||||||
|
|
||||||
|
To give the reader some idea of how long it might take them to read a post,
|
||||||
|
a read time is automatically calculated. If you want to override this, you can
|
||||||
|
do so in the page header by specifying the number of minutes you estimate
|
||||||
|
your readers will take the read the post.
|
||||||
|
|
||||||
|
!!! example "Overriding the reading time"
|
||||||
|
|
||||||
|
Add a reading time override to your first blog post:
|
||||||
|
|
||||||
|
```hl_lines="5"
|
||||||
|
---
|
||||||
|
date:
|
||||||
|
created: 2023-12-31
|
||||||
|
updated: 2024-01-02
|
||||||
|
readtime: 15
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pinning
|
||||||
|
|
||||||
|
Sometimes, blog authors want to 'pin' a specific post so that it will always
|
||||||
|
appear at the top of the index page, no matter what else gets published. If you
|
||||||
|
are using the [Insiders Edition], you can achieve this by adding the `pin`
|
||||||
|
attribute in the page header:
|
||||||
|
|
||||||
|
!!! example "Pin a post <!-- md:sponsors -->"
|
||||||
|
|
||||||
|
Add the `pin` attribute to your first blog post:
|
||||||
|
|
||||||
|
```hl_lines="5"
|
||||||
|
---
|
||||||
|
date:
|
||||||
|
created: 2023-12-31
|
||||||
|
updated: 2024-01-02
|
||||||
|
readtime: 15
|
||||||
|
pin: true
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
Observe how this makes the post appear on top of the index page even though
|
||||||
|
its publication date is prior to other posts. A small pin icon shows that the
|
||||||
|
post has been pinned.
|
||||||
|
|
||||||
|
### Related links <!-- md:sponsors -->
|
||||||
|
|
||||||
|
When your blog is part of a wider site such as technical documentation, you
|
||||||
|
will want to provide links from blog posts into your other content. One way you
|
||||||
|
can do this is to have a related links section. In the [Insiders Edition], the
|
||||||
|
blog plugin can create one for you if you provide link targets in your page
|
||||||
|
header:
|
||||||
|
|
||||||
|
!!! example "Add a related links section <!-- md:sponsors -->"
|
||||||
|
|
||||||
|
Add the following to a blog post:
|
||||||
|
|
||||||
|
``` hl_lines="5-7"
|
||||||
|
---
|
||||||
|
date:
|
||||||
|
created: 2023-12-31
|
||||||
|
...
|
||||||
|
links:
|
||||||
|
- index.md
|
||||||
|
- blog/index.md
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
The related links appear underneath the Metadata section.
|
||||||
|
|
||||||
|
The nice thing here is that you do not need to provide a page title. The plugin
|
||||||
|
will deduce the link text by applying the same logic that MkDocs uses for the
|
||||||
|
main navigation. In fact, the syntax is the same as that of the `nav` section
|
||||||
|
in the `mkdocs.yml`, so you can override the title if you want and even define
|
||||||
|
subsections:
|
||||||
|
|
||||||
|
!!! example "Override the page titles"
|
||||||
|
|
||||||
|
Change the link section to override the page titles:
|
||||||
|
|
||||||
|
```hl_lines="6-9"
|
||||||
|
---
|
||||||
|
date:
|
||||||
|
created: 2023-12-31
|
||||||
|
...
|
||||||
|
links:
|
||||||
|
- Homepage: index.md
|
||||||
|
- Blog index: blog/index.md
|
||||||
|
- External links:
|
||||||
|
- Material documentation: https://squidfunk.github.io/mkdocs-material
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
The plugin renders related links in the left sidebar on screens that are wide
|
||||||
|
enough and at the bottom of the post on narrow screens. Change the size of your
|
||||||
|
browser window to see this in action.
|
||||||
|
|
||||||
|
## Meta plugin <!-- md:sponsors -->
|
||||||
|
|
||||||
|
The Meta plugin is available in the [Insiders Edition].
|
||||||
|
It helps simplify the management of metadata that is common to a group of
|
||||||
|
files in the same subdirectory. Instead of having to repeat the
|
||||||
|
same metadata in the page headers of a number of files, you can add a
|
||||||
|
`.meta.yml` file in the directory and the Meta plugin will merge its contents
|
||||||
|
into the headers of all the pages contained.
|
||||||
|
Settings from the page header take precedence, so you can always override
|
||||||
|
settings by adding them to a post's header.
|
||||||
|
|
||||||
|
For example, you may want to manage drafts by keeping them in a directory
|
||||||
|
together so that they are not only flagged as drafts but also easier to find.
|
||||||
|
(Otherwise, you would need to inspect the page headers or trace back from the
|
||||||
|
output to the files to figure out which posts are drafts.)
|
||||||
|
|
||||||
|
!!! example "Drafts using the Meta plugin <!-- md:sponsors -->"
|
||||||
|
|
||||||
|
You first need to activate the plugin in your `mkdocs.yaml`:
|
||||||
|
|
||||||
|
```yaml hl_lines="4"
|
||||||
|
plugins:
|
||||||
|
- search
|
||||||
|
- blog
|
||||||
|
- meta
|
||||||
|
```
|
||||||
|
|
||||||
|
Now create the folder for the drafts:
|
||||||
|
|
||||||
|
=== "MacOS/Linux"
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ mkdir docs/blog/posts/drafts
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "Windows"
|
||||||
|
TODO
|
||||||
|
|
||||||
|
Now, within this folder, crate a file `.meta.yml` that contains:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
draft: true
|
||||||
|
```
|
||||||
|
|
||||||
|
Add another blog post and store it in `docs/blog/posts/drafts`. When you
|
||||||
|
look at it locally, you will see the label that identifies it as a draft,
|
||||||
|
while in the version built for publication it does not appear. To move a
|
||||||
|
post from draft status to published, simply move it outside `drafts/`.
|
||||||
|
|
||||||
|
[Insiders Edition]: ../../insiders/index.md
|
||||||
|
|
||||||
|
## What's next?
|
||||||
|
|
||||||
|
You should now have a working blog. However, as it accumulates content, you
|
||||||
|
may want to make sure that people can find posts they are interested in, so
|
||||||
|
you may want to add secondary navigation with tags and categories. You may
|
||||||
|
have more than one author and want to attribute posts to them as well as
|
||||||
|
generate author pages for them. We have a [tutorial on navigation, pagination,
|
||||||
|
and authors] that covers these topics.
|
||||||
|
|
||||||
|
[tutorial on navigation, pagination, and authors]: navigation.md
|
||||||
|
|
||||||
|
You may want to increase engagement with your blog by allowing people to
|
||||||
|
subscribe to an RSS feed or by setting up a comment system. The [engagement
|
||||||
|
and dissemination tutorial] walks you through setting these up.
|
||||||
|
|
||||||
|
[engagement and dissemination tutorial]: engage.md
|
369
docs/tutorials/blogs/engage.md
Normal file
369
docs/tutorials/blogs/engage.md
Normal file
@ -0,0 +1,369 @@
|
|||||||
|
# Engagement and dissemination
|
||||||
|
|
||||||
|
You can foster reader engagement and improve the dissemination of content
|
||||||
|
on your blog by providing an RSS feed that people can subscribe to and by
|
||||||
|
integrating a discussion system. To learn more about who is or is not reading
|
||||||
|
your posts, you may want to integrate an analytics system. You may also want
|
||||||
|
to post on social media when you public a new blog post. This tutorial gives
|
||||||
|
you a leg up on all of these topics.
|
||||||
|
|
||||||
|
__Time required:__ typically 30 minutes
|
||||||
|
|
||||||
|
## RSS feeds
|
||||||
|
|
||||||
|
An _RSS feed_ allows users to subscribe to a blog so that they get notified when
|
||||||
|
you publish new posts. RSS Feed readers are often used to access blogs that a
|
||||||
|
user follows. They usually support downloading the blog content for offline
|
||||||
|
consumption.
|
||||||
|
|
||||||
|
An easy way to create an RSS feed for your blog is to use the
|
||||||
|
[MkDocs RSS Plugin], which is well integrated with Material for MkDocs.
|
||||||
|
Since it is a third-party plugin, you need to install it before using it.
|
||||||
|
|
||||||
|
[MkDocs RSS Plugin]: https://guts.github.io/mkdocs-rss-plugin
|
||||||
|
|
||||||
|
|
||||||
|
!!! example "Add an RSS feed"
|
||||||
|
|
||||||
|
Install the RSS plugin into your project:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ pip install mkdocs-rss-plugin
|
||||||
|
```
|
||||||
|
|
||||||
|
It is important that have the `site_name`, `site_description` and
|
||||||
|
`site_url` settings configured as [instructed in the basic blog tutorial].
|
||||||
|
The RSS plugin makes use of this information to construct the feed, so make
|
||||||
|
sure you have configured them.
|
||||||
|
|
||||||
|
[instructed in the basic blog tutorial]: basic.md#setting-up-your-blog
|
||||||
|
|
||||||
|
Now, configure the plugin in the `mkdocs.yml`. The options provided restrict
|
||||||
|
the pages that RSS entries are created for to the blog posts, which is
|
||||||
|
probably what you want. Also note the configuration of the date fields to
|
||||||
|
match the format that Material for MkDocs uses to accommodate both a
|
||||||
|
creation date and a date for updates.
|
||||||
|
|
||||||
|
```yaml hl_lines="9"
|
||||||
|
plugins:
|
||||||
|
- ...
|
||||||
|
- rss:
|
||||||
|
match_path: "blog/posts/.*"
|
||||||
|
date_from_meta:
|
||||||
|
as_creation: date.created
|
||||||
|
as_update: date.updated
|
||||||
|
```
|
||||||
|
|
||||||
|
Have a look at http://localhost:8000/feed_rss_created.xml to see the RSS
|
||||||
|
feed in all its XML glory. You can use a browser like Firefox or Chrome that
|
||||||
|
can display the raw RSS feed or use `curl` to get the feed and `xmllint` to
|
||||||
|
format it. (You may need to install these tools.)
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -s http://localhost:8000/feed_rss_created.xml | xmllint --format -
|
||||||
|
```
|
||||||
|
|
||||||
|
You may also want to try your feed with a feed reader. There are various desktop
|
||||||
|
and mobile apps as well as online services. Of course, to use the latter you
|
||||||
|
will need to deploy your project somewhere that is accessible to them.
|
||||||
|
|
||||||
|
This minimal configuration should work well if you have not made any changes
|
||||||
|
to the default configuration of the blog plugin. For more information on adapting
|
||||||
|
the feed to your needs, see [the RSS plugin's documentation].
|
||||||
|
|
||||||
|
[the RSS plugin's documentation]: https://guts.github.io/mkdocs-rss-plugin/
|
||||||
|
|
||||||
|
## Social media buttons
|
||||||
|
|
||||||
|
Social media buttons can serve two purposes: to allow your readers to navigate
|
||||||
|
to your social media profiles or to share content you have published via their
|
||||||
|
own accounts.
|
||||||
|
|
||||||
|
### Profile links
|
||||||
|
|
||||||
|
Links to social media profiles a usually provided in the footer of pages and
|
||||||
|
Material for MkDocs makes this easy. All you need to do is to provide the
|
||||||
|
necessary links and define the icons to use.
|
||||||
|
|
||||||
|
!!! example "Adding social media profile links"
|
||||||
|
|
||||||
|
Add an `extra` section to your `mkdocs.yml` and, within it, a `social`
|
||||||
|
section to contain a list of link definitions. These consist of the logo
|
||||||
|
to use and the link to the profile.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
extra:
|
||||||
|
social:
|
||||||
|
- icon: fontawesome/brands/mastodon
|
||||||
|
name: squidfunk on Mastodon
|
||||||
|
link: https://fosstodon.org/@squidfunk
|
||||||
|
```
|
||||||
|
|
||||||
|
For the `icon`, you can choose any valid path to an icon bundled with the
|
||||||
|
theme. The `name` will be used as the title attribute for the icon and
|
||||||
|
including this improves accessibility.
|
||||||
|
For popular social media systems, the link needs to be absolute and
|
||||||
|
needs to include the scheme, most likely `https://`.
|
||||||
|
|
||||||
|
You can also use other schemes. For example, to cerate an icon that allows
|
||||||
|
people to create an email, add this:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
extra:
|
||||||
|
social:
|
||||||
|
- icon: /fontawesome/regular/envelope
|
||||||
|
name: send me an email
|
||||||
|
link: mailto:<email-address>
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, you can specify a URL within your site, such as to your contact
|
||||||
|
page. It is possible to specify only the path to the page:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
extra:
|
||||||
|
social:
|
||||||
|
- icon: /material/mailbox
|
||||||
|
name: contact us
|
||||||
|
link: /contact
|
||||||
|
```
|
||||||
|
|
||||||
|
### Share and like buttons
|
||||||
|
|
||||||
|
Adding buttons that let people share your content on social media is a bit
|
||||||
|
more involved, which is why there are companies offering components for this.
|
||||||
|
|
||||||
|
|
||||||
|
!!! tip "Data Protection"
|
||||||
|
|
||||||
|
"Share" and "Like" buttons that use integrations provided by social media
|
||||||
|
companies often leave copious data traces even when the user does not
|
||||||
|
interact with these buttons. If you choose to integate such feature on
|
||||||
|
your site please be aware of the data protection implications and your
|
||||||
|
duties as a provider to ensure that processing occurs only once the user
|
||||||
|
has granted consent.
|
||||||
|
|
||||||
|
This implementation of share buttons deliberately does not use third party code.
|
||||||
|
It supports sharing to Twitter/X and Facebook without causing a data flow to
|
||||||
|
these companies whenever someone views the pages. Only when someone clicks a
|
||||||
|
share button will there be interactions with those companies' servers.
|
||||||
|
|
||||||
|
!!! example "Add share buttons"
|
||||||
|
|
||||||
|
In order to add the share buttons, you can add a hook that appends buttons
|
||||||
|
for sharing the current page.
|
||||||
|
|
||||||
|
Create a directory `hooks` in your project root and configure it
|
||||||
|
in your `mkdocs.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
hooks:
|
||||||
|
- hooks/socialmedia.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Add the file `hooks/socialmedia.py` with the following Python code:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from textwrap import dedent
|
||||||
|
import urllib.parse
|
||||||
|
import re
|
||||||
|
|
||||||
|
x_intent = "https://twitter.com/intent/tweet"
|
||||||
|
fb_sharer = "https://www.facebook.com/sharer/sharer.php"
|
||||||
|
include = re.compile(r"blog/[1-9].*")
|
||||||
|
|
||||||
|
def on_page_markdown(markdown, **kwargs):
|
||||||
|
page = kwargs['page']
|
||||||
|
config = kwargs['config']
|
||||||
|
if not include.match(page.url):
|
||||||
|
return markdown
|
||||||
|
|
||||||
|
page_url = config.site_url+page.url
|
||||||
|
page_title = urllib.parse.quote(page.title+'\n')
|
||||||
|
|
||||||
|
return markdown + dedent(f"""
|
||||||
|
[Share on :simple-x:]({x_intent}?text={page_title}&url={page_url}){{ .md-button }}
|
||||||
|
[Share on :simple-facebook:]({fb_sharer}?u={page_url}){{ .md-button }}
|
||||||
|
""")
|
||||||
|
```
|
||||||
|
|
||||||
|
The hook first checks if the current page is a blog post and then appends
|
||||||
|
Markdown code for the share buttons. The buttons use icons, so you also need
|
||||||
|
to configure the following markdown extensions:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
markdown_extensions:
|
||||||
|
- attr_list
|
||||||
|
- pymdownx.emoji:
|
||||||
|
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
||||||
|
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Add a discussion system
|
||||||
|
|
||||||
|
Allowing your readers to comment on your posts is a great way of receiving
|
||||||
|
feedback, learning something, as well as giving readers the opportunity to
|
||||||
|
discuss the content and the topic it is about.
|
||||||
|
|
||||||
|
There are plenty of discussion system out there and you will need to consider
|
||||||
|
your audience when choosing one appropriate for your blog. Likewise, you will
|
||||||
|
also need to consider existing commitments to communication channels. If you
|
||||||
|
are a heavy user Slack, for example, you may have a string preference for this
|
||||||
|
system. Consider that when you add a communication channel, you will need to
|
||||||
|
be prepared to use it regularly and to moderate discussions.
|
||||||
|
|
||||||
|
### Giscus integration
|
||||||
|
|
||||||
|
In this tutorial, we will be using [Giscus] because it is free, open source,
|
||||||
|
and uses [GitHub Discussions] as a backend. Because a lot of users of Material
|
||||||
|
for MkDocs use GitHub, this seems like an obvious choice.
|
||||||
|
|
||||||
|
[Giscus]: https://giscus.app/
|
||||||
|
[GitHub Discussions]: https://docs.github.com/en/discussions
|
||||||
|
|
||||||
|
To add Giscuss to your blog you will need to go through a number of steps:
|
||||||
|
|
||||||
|
1. Create a GitHub repository if there is not already one
|
||||||
|
2. Turn on discussions and install the [Giscus app]
|
||||||
|
3. Configure the code needed to embed Giscus into your blog
|
||||||
|
4. Add the code to your MkDocs project
|
||||||
|
|
||||||
|
[Giscus app]: https://github.com/apps/giscus
|
||||||
|
|
||||||
|
You may want to create a test repository for this tutorial that you can
|
||||||
|
scrap later on. The instructions below assume that you are user "example"
|
||||||
|
and that you create a repository "giscus-test." The repository will need
|
||||||
|
to be public for people to be able to use the discussions.
|
||||||
|
|
||||||
|
In the instructions given below, you will need to replace at least the username
|
||||||
|
but also the repository name if you chose another name such as when you
|
||||||
|
want to work directly on an existing repository.
|
||||||
|
|
||||||
|
!!! example "Turn on discussions and install the Giscus app"
|
||||||
|
|
||||||
|
Once the repository is set up, go to its settings page and find
|
||||||
|
`Features` in the `General` section. Tick the checkbox for `Discussions`.
|
||||||
|
You will see that `Discussions` appears in the top navigation for the
|
||||||
|
repository. If you are using a live repository then you may want to add some
|
||||||
|
minimal content to the dicussions section at this point and come back to the
|
||||||
|
tutorial.
|
||||||
|
|
||||||
|
Next, you need to install the [Giscus app] by following the link in this
|
||||||
|
sentence, and choosing `Install`, then following the instructions to choose
|
||||||
|
where the Giscus app is to be installed:
|
||||||
|
|
||||||
|
1. Choose the account or organization for the repository you want to use.
|
||||||
|
2. Choose to install only on select repositories and select the one you
|
||||||
|
want to use. Note that you can choose more than one repository here.
|
||||||
|
3. Select `Install` at the end. You may need to authenticate to give
|
||||||
|
permission for this to happen.
|
||||||
|
4. You will end up on the `Applications` page in your settings, where you
|
||||||
|
can control the Gicsus app and uninstall it if so desired.
|
||||||
|
|
||||||
|
That is all the preparation you will need for the repository. Next, it is time
|
||||||
|
to generate a piece of code that embeds Giscuss in your site. The resulting code
|
||||||
|
snippet will look something like this:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="https://giscus.app/client.js"
|
||||||
|
data-repo="<username>/<repository>"
|
||||||
|
data-repo-id="..."
|
||||||
|
data-category="Announcements"
|
||||||
|
data-category-id="..."
|
||||||
|
data-mapping="title"
|
||||||
|
data-strict="1"
|
||||||
|
data-reactions-enabled="1"
|
||||||
|
data-emit-metadata="1"
|
||||||
|
data-input-position="top"
|
||||||
|
data-theme="preferred_color_scheme"
|
||||||
|
data-lang="en"
|
||||||
|
data-loading="lazy"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
async>
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! example "Configure the code needed to embed Giscus into your blog"
|
||||||
|
|
||||||
|
Go to the [Giscus homepage] and configure the embedding code. There are a
|
||||||
|
number of settings:
|
||||||
|
|
||||||
|
1. Choose the language
|
||||||
|
2. Enter the username / organization name and repository name
|
||||||
|
3. Choose how the discussions are to be mapped to the page on your blog.
|
||||||
|
Because for a blog post the title is the basis of the URL, it makes
|
||||||
|
sense to use the `Discussion title contains page <title>` option.
|
||||||
|
4. Under `Discussion Category` choose `Announcements` to limit the creation
|
||||||
|
of new discussions to Giscuss and people with maintainer or admin
|
||||||
|
permissions.
|
||||||
|
5. Under `Features`, select the following:
|
||||||
|
1. Enable reactions for the main post
|
||||||
|
2. Emit discussion metadata
|
||||||
|
3. Place the comment box above the comments
|
||||||
|
6. Under `Theme`, select `Preferred color scheme` so that Giscus matches
|
||||||
|
the color scheme selected by the user for your site.
|
||||||
|
|
||||||
|
[Giscus homepage]: https://giscus.app/
|
||||||
|
|
||||||
|
With these settings in place, you now need to integrate the code into your
|
||||||
|
site. There is a partial `partials/comments.html` that exists for this purpose
|
||||||
|
and is empty be default. It is included by the `content.html` partial, so will
|
||||||
|
be included for every page on your site. You may or may not want this. In this
|
||||||
|
tutorial, you will limit the Giscus integration to only blog posts but it is
|
||||||
|
easy enough to leave out the code that achieves this if you want to have Giscus
|
||||||
|
discussions active for every page.
|
||||||
|
|
||||||
|
!!! example "Add Giscus integration code"
|
||||||
|
|
||||||
|
First, you need to create an `overrides` directory that will contain the
|
||||||
|
templates and partials you want to override.
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir -p overrides/partials
|
||||||
|
```
|
||||||
|
|
||||||
|
You need to declare it in your `mkdocs.yaml`:
|
||||||
|
|
||||||
|
```yaml hl_lines="3"
|
||||||
|
theme:
|
||||||
|
name: material
|
||||||
|
custom_dir: overrides
|
||||||
|
```
|
||||||
|
|
||||||
|
Now add a file `overrides/partials/comments.html` and paste in the code
|
||||||
|
snippet you obtained from the Giscus homepage. Look at the result locally
|
||||||
|
and you will see that the integration is active on all pages of the site.
|
||||||
|
If you want to restrict it to your blog posts, you need to add a conditional
|
||||||
|
around the Giscus script that tests if comments should be included. A simple
|
||||||
|
way of doing this is to test for a metadata flag:
|
||||||
|
|
||||||
|
```html
|
||||||
|
{% if page.meta.comments %}
|
||||||
|
<script>...</script>
|
||||||
|
{% endif %}
|
||||||
|
```
|
||||||
|
|
||||||
|
The disadvantage is that you now need to manually turn on comments for each
|
||||||
|
blog post - unless you want to turn them off on some. To get the comments
|
||||||
|
section on all blog posts, use code like this:
|
||||||
|
|
||||||
|
```html
|
||||||
|
{% if page.file.src_uri.startswith('blog/posts') %}
|
||||||
|
<script>...</script>
|
||||||
|
{% endif %}
|
||||||
|
```
|
||||||
|
|
||||||
|
You should see now that the Giscus comments are added at the bottom of your
|
||||||
|
blog posts but not on other pages.
|
||||||
|
|
||||||
|
## What's next?
|
||||||
|
|
||||||
|
This is the end of the blog tutorial. We hope you have enjoyed it and manage to
|
||||||
|
set up your blog the way you like it. There are numerous other features and
|
||||||
|
options that we have not been able to cover here. The [blog plugin reference]
|
||||||
|
provides comprehensive documentation for the plugin. You may also want to
|
||||||
|
look at the [social plugin tutorial] to generate social cards for your blog
|
||||||
|
posts that get displayed when you post links to social media systems.
|
||||||
|
|
||||||
|
[blog plugin reference]: https://squidfunk.github.io/mkdocs-material/plugins/blog/
|
||||||
|
[social plugin tutorial]: ../social/basic.md
|
525
docs/tutorials/blogs/navigation.md
Normal file
525
docs/tutorials/blogs/navigation.md
Normal file
@ -0,0 +1,525 @@
|
|||||||
|
# Navigation, authors, and pagination
|
||||||
|
|
||||||
|
The Blog plugin provides blog-style navigation with a reverse-chronological
|
||||||
|
index page and an archive organized by year by default. This tutorial shows
|
||||||
|
how you can configure details of the default navigation, configure authors, and
|
||||||
|
add more navigation options using categories and the [Tags plugin].
|
||||||
|
|
||||||
|
[Tags plugin]: ../../plugins/tags.md
|
||||||
|
|
||||||
|
__Time required:__ typically 30 minutes
|
||||||
|
|
||||||
|
## Integrating navigation
|
||||||
|
|
||||||
|
So far, you have let the Blog plugin and MkDocs worry about navigation. For some
|
||||||
|
use cases, this might be enough and it is simply sufficient to not declare a
|
||||||
|
`nav` section in the `mkdocs.yml`.
|
||||||
|
|
||||||
|
However, you may want to integrate a blog with other content and a navigation
|
||||||
|
structure that you have defined in the `nav` section of the configuration.
|
||||||
|
In such cases, you need to provide a place where the Blog plugin should
|
||||||
|
attach the blog navigation to the rest of the navigation structure.
|
||||||
|
|
||||||
|
!!! example "Integrate with site navigation"
|
||||||
|
|
||||||
|
Add the following to your `mkdocs.yml` to see how the Blog plugin can
|
||||||
|
integrate the blog navigation with the overall navigation structure.
|
||||||
|
Note that the only thing you need to specify at this point is the
|
||||||
|
index page for the blog and its path must match the `blog_dir` setting,
|
||||||
|
which is `blog` by default:
|
||||||
|
|
||||||
|
```yaml hl_lines="5 6"
|
||||||
|
nav:
|
||||||
|
- Home: index.md
|
||||||
|
- Install: install.md
|
||||||
|
- Usage: usage.md
|
||||||
|
- Blog:
|
||||||
|
- blog/index.md
|
||||||
|
```
|
||||||
|
|
||||||
|
You will notice that "Blog" is duplicated in the navigation structure. To
|
||||||
|
avoid this, you can use the `navigation.indexes` feature to make the blog
|
||||||
|
index the seciton index page for the blog:
|
||||||
|
|
||||||
|
```yaml hl_lines="3 4"
|
||||||
|
theme:
|
||||||
|
name: material
|
||||||
|
features:
|
||||||
|
- navigation.indexes
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! tip "Stand-alone blog"
|
||||||
|
|
||||||
|
If what you need is a stand-alone blog instead of one that is integrated with
|
||||||
|
a larger site, this can be done by using the `blog_dir` configuration option.
|
||||||
|
To see how this is done, see [setting up a blog].
|
||||||
|
The rest of the tutorial assumes that you are integrating the blog with
|
||||||
|
a wider site.
|
||||||
|
|
||||||
|
[Setting up a blog]: ../../setup/setting-up-a-blog.md#blog-only
|
||||||
|
|
||||||
|
!!! tip "Adding pages"
|
||||||
|
|
||||||
|
You can add additional pages to the blog section by putting them into
|
||||||
|
`docs/blog` (and adding them to the navigation). The blog archive will be
|
||||||
|
added to the navigation after these pages.
|
||||||
|
|
||||||
|
## Configuring the archive
|
||||||
|
|
||||||
|
By default, the blog archive lists posts by year only. If you want to add
|
||||||
|
listings by month, you can configure the date format for the archive.
|
||||||
|
|
||||||
|
!!! example "Organize posts by month"
|
||||||
|
|
||||||
|
Add the following to your `mkdocs.yml` to get a listing with the month
|
||||||
|
name (in the language selected in the theme options):
|
||||||
|
|
||||||
|
```yaml hl_lines="2"
|
||||||
|
- blog:
|
||||||
|
archive_date_format: MMMM yyyy
|
||||||
|
```
|
||||||
|
|
||||||
|
If you do not want the full month name, you can make the the date
|
||||||
|
configuration `MM/yyyy`, for example.
|
||||||
|
|
||||||
|
If you want to add the day, you can add a placeholder for them.
|
||||||
|
For example, to get an American-style output, make it `MM/dd/yyyy`.
|
||||||
|
For the plugin to sort the blog posts by the full date, you will
|
||||||
|
also need to set the `archive_url_date_format` to include the month
|
||||||
|
and day, so make it `MM/dd/yyyy` as well.
|
||||||
|
|
||||||
|
## Using categories
|
||||||
|
|
||||||
|
Categories are a way to make blog posts accessible by topic while retaining
|
||||||
|
the navigation structure based on chronology within each category listing.
|
||||||
|
Use them when there is a limited set of non-overlapping categories that
|
||||||
|
you can sort your posts into.
|
||||||
|
|
||||||
|
Categories appear in the main navigation, so are directly accessible from there.
|
||||||
|
This implies that there are relatively few categories as otherwise the
|
||||||
|
`categories` section in your main navigation will become too crowded.
|
||||||
|
|
||||||
|
|
||||||
|
!!! example "Add a category"
|
||||||
|
|
||||||
|
Add a category to your first blog post by adding it to the page header:
|
||||||
|
|
||||||
|
``` hl_lines="4 5""
|
||||||
|
---
|
||||||
|
date: 2023-12-31
|
||||||
|
updated: 2024-01-02
|
||||||
|
categories:
|
||||||
|
- Holidays
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
Now that the blog post has been categorised, `Holidays` appears under
|
||||||
|
`Categories` in the main navigation and the blog post appears in the
|
||||||
|
index page for this category.
|
||||||
|
|
||||||
|
|
||||||
|
!!! tip "Single or multiple categories?"
|
||||||
|
|
||||||
|
While it is traditionally the case that a blog post would belong to only
|
||||||
|
one category, Material for MkDocs actually allows you to assign more
|
||||||
|
than one. While this gives you a degree of freedom, you should
|
||||||
|
probably not use this too much, not least because you can use tags to
|
||||||
|
deal with multiple classifications. We will cover them in the next step.
|
||||||
|
|
||||||
|
Material allows you to control which categories blog authors can use. You
|
||||||
|
declare them in the `mkdocs.yml`. This way you can make sure everyone sticks
|
||||||
|
to agreed categories and that the plugin detects typos.
|
||||||
|
|
||||||
|
!!! example "Control your categories"
|
||||||
|
|
||||||
|
Add a `categories_allowed` entry to the configuration of the Blog plugin
|
||||||
|
with the entries "Holidays" and "News":
|
||||||
|
|
||||||
|
```yaml hl_lines="5-7"
|
||||||
|
plugins:
|
||||||
|
- search
|
||||||
|
- blog:
|
||||||
|
archive_date_format: MMMM yyyy
|
||||||
|
categories_allowed:
|
||||||
|
- Holidays
|
||||||
|
- News
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, when you add a category to a blog post that does not match one of these
|
||||||
|
two, you should get a build error.
|
||||||
|
|
||||||
|
## Using tags
|
||||||
|
|
||||||
|
The [Tags plugin] provides another way to classify blog posts and to make
|
||||||
|
them accessible independently of the main navigation structure. Tags are useful
|
||||||
|
for making related content easily discoverable even if it is in different parts
|
||||||
|
of the navigation hierarchy.
|
||||||
|
|
||||||
|
[Tags plugin]: https://squidfunk.github.io/mkdocs-material/plugins/tags/
|
||||||
|
|
||||||
|
You may have a tutorial like this one as well as a more comprehensive setup guide
|
||||||
|
and reference documentation. Adding the same tag to all three shows that they
|
||||||
|
are related. As you will see, it is possible to navigate from a tagged page to
|
||||||
|
the tag index and, from there, to other pages that carry the same tag.
|
||||||
|
|
||||||
|
!!! example "Enable the plugin and add tags"
|
||||||
|
|
||||||
|
First, you need to add the plugin to your `mkdocs.yml`:
|
||||||
|
|
||||||
|
```yaml hl_lines="8"
|
||||||
|
plugins:
|
||||||
|
- search
|
||||||
|
- blog:
|
||||||
|
archive_date_format: MMMM yyyy
|
||||||
|
categories_allowed:
|
||||||
|
- Holidays
|
||||||
|
- News
|
||||||
|
- tags
|
||||||
|
```
|
||||||
|
|
||||||
|
Once this is done, you can add tags to posts in the page header:
|
||||||
|
|
||||||
|
``` hl_lines="9-12""
|
||||||
|
---
|
||||||
|
date:
|
||||||
|
created: 2023-12-31
|
||||||
|
updated: 2024-01-02
|
||||||
|
authors:
|
||||||
|
- material
|
||||||
|
categories:
|
||||||
|
- Holidays
|
||||||
|
tags:
|
||||||
|
- new year
|
||||||
|
- hogmanay
|
||||||
|
- festive season
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
You should see the tags that you defined at the top of the post. However, at the
|
||||||
|
moment that is it. While the blog plugin automatically creates an index page for
|
||||||
|
categories, the tags plugin does not do the same for tags. This is because the
|
||||||
|
tags plugin is not specific for blogs. You can use it for any site content, so
|
||||||
|
it is not obvious were the tag index should go.
|
||||||
|
|
||||||
|
You can configure a basic tag index using the public version of Material for
|
||||||
|
MkDocs. The Insider Edition supports this as well, of course, but also provides
|
||||||
|
an alternative index mechanism that allows for an arbitrary number of tag
|
||||||
|
indexes, scoped listings, shadow tags, nested tags, and much more.
|
||||||
|
|
||||||
|
!!! example "Adding a tags index"
|
||||||
|
=== "Basic tag index"
|
||||||
|
|
||||||
|
To configure a tag index using the public version, add a `tags_file` entry
|
||||||
|
to your configuration of the tags plugin and configure it in your `nav`
|
||||||
|
section. Remember to add a colon at the end of the existing `tags` entry.
|
||||||
|
|
||||||
|
```yaml hl_lines="8-9 17"
|
||||||
|
plugins:
|
||||||
|
- search
|
||||||
|
- blog:
|
||||||
|
archive_date_format: MMMM yyyy
|
||||||
|
categories_allowed:
|
||||||
|
- Holidays
|
||||||
|
- News
|
||||||
|
- tags:
|
||||||
|
tags_file: blog/tags.md
|
||||||
|
|
||||||
|
nav:
|
||||||
|
- Home: index.md
|
||||||
|
- Install: install.md
|
||||||
|
- Usage: usage.md
|
||||||
|
- Blog:
|
||||||
|
- blog/index.md
|
||||||
|
Tags: blog/tags.md
|
||||||
|
```
|
||||||
|
|
||||||
|
The tag index will be appended to the configured page, which you should
|
||||||
|
now create at the location specified.
|
||||||
|
|
||||||
|
Note that you can put the tag index page anywhere in your primary
|
||||||
|
navigation, so if you are using tags elsewhere instead of just in your
|
||||||
|
blog then you may want to have the tag index outside the blog section
|
||||||
|
of the navigation.
|
||||||
|
|
||||||
|
|
||||||
|
=== "Insider Edition"
|
||||||
|
|
||||||
|
To add a tag index, you add a placeholder in a Markdown file to tell
|
||||||
|
the plugin to insert an index at that point. This means that you
|
||||||
|
can add content before and after the index. Crucially, you can add
|
||||||
|
placeholders in multiple pages, each with a configuration of what
|
||||||
|
subset of tags should be displayed in the index.
|
||||||
|
|
||||||
|
The simplest index page looks like this. Create it under `docs/tags.md`.
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Tag index
|
||||||
|
<!-- material/tags -->
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, you may want to keep the tags for your blog separate from tags
|
||||||
|
you use in the rest of your page. You can achieve this by assigning
|
||||||
|
the tag index a scope. Put the following under `docs/blog/tags.md`:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Tag index for the blog
|
||||||
|
<!-- material/tags { scope: true } -->
|
||||||
|
```
|
||||||
|
|
||||||
|
You now have two index pages: one covers the whole site and one
|
||||||
|
covers only the blog. Add both to the navigation:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
nav:
|
||||||
|
- Home: index.md
|
||||||
|
- Tags: tags.md
|
||||||
|
- Blog:
|
||||||
|
- blog/index.md
|
||||||
|
- blog/tags.md
|
||||||
|
```
|
||||||
|
|
||||||
|
The tags plugin in the Insider Edition is an incredibly powerful tool
|
||||||
|
and we can only scratch the surface of what is possible with it. If you
|
||||||
|
want to explore more after you have worked for this part of the tutorial,
|
||||||
|
have a look at the [tags plugin reference].
|
||||||
|
|
||||||
|
[tags plugin reference]: ../../plugins/tags.md
|
||||||
|
|
||||||
|
## Defining authors
|
||||||
|
|
||||||
|
If your blog has more than one author then you may want to identify the author
|
||||||
|
for each blog post. The blog plugin allows you to create a file that contains
|
||||||
|
the author information and to then reference the authors of a particular post in
|
||||||
|
the page header.
|
||||||
|
|
||||||
|
!!! example "Create author info"
|
||||||
|
|
||||||
|
Create a file `docs/blog/.authors.yml` with this content:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
authors:
|
||||||
|
team:
|
||||||
|
name: Team
|
||||||
|
description: Creator
|
||||||
|
avatar: https://simpleicons.org/icons/materialformkdocs.svg
|
||||||
|
squidfunk:
|
||||||
|
name: Martin Donath
|
||||||
|
description: Creator
|
||||||
|
avatar: https://github.com/squidfunk.png
|
||||||
|
```
|
||||||
|
|
||||||
|
and then add a line to the header of the first post:
|
||||||
|
|
||||||
|
|
||||||
|
```hl_lines="5-6"
|
||||||
|
---
|
||||||
|
date:
|
||||||
|
created: 2023-12-31
|
||||||
|
updated: 2024-01-02
|
||||||
|
authors:
|
||||||
|
- team
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that `authors` is a list, so you can specify multiple authors.
|
||||||
|
|
||||||
|
With the Insiders edition, you can create custom author index pages that
|
||||||
|
can highlight the contributions of an author as well as provide additional
|
||||||
|
information about them.
|
||||||
|
|
||||||
|
!!! example "Add author page <!-- md:sponsors -->"
|
||||||
|
|
||||||
|
First, you need to enable author profiles in the `mkdocs.yml`:
|
||||||
|
|
||||||
|
```yaml hl_lines="8"
|
||||||
|
plugins:
|
||||||
|
- search
|
||||||
|
- blog:
|
||||||
|
archive_date_format: MMMM yyyy
|
||||||
|
categories_allowed:
|
||||||
|
- Holidays
|
||||||
|
- News
|
||||||
|
authors_profiles: true
|
||||||
|
```
|
||||||
|
|
||||||
|
Check your blog to see that there is now an extra entry in the main
|
||||||
|
navigation next to `archive` and `categories` that lists the authors and
|
||||||
|
their contributions.
|
||||||
|
|
||||||
|
To customize the author page, you can create a page that overrides the one
|
||||||
|
generated by default. First, create the `author` directory that the profile
|
||||||
|
pages will live in:
|
||||||
|
|
||||||
|
```hl_lines="3"
|
||||||
|
docs
|
||||||
|
├── blog
|
||||||
|
│ ├── author
|
||||||
|
│ ├── index.md
|
||||||
|
│ └── posts
|
||||||
|
│ ├── draft.md
|
||||||
|
│ └── myfirst.md
|
||||||
|
└── index.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Then create a page `docs/blog/author/team.md`:
|
||||||
|
|
||||||
|
```
|
||||||
|
# The Material Team
|
||||||
|
|
||||||
|
A small group of people dedicated to making writing documentation easy, if
|
||||||
|
not outright fun! Here are some of the things we have blogged about:
|
||||||
|
```
|
||||||
|
|
||||||
|
As you can see, the author index gets appended to the content you have
|
||||||
|
written in the Markdown file.
|
||||||
|
|
||||||
|
## Pagination
|
||||||
|
|
||||||
|
Once your blog starts growing, you may not want to pay attention to the number
|
||||||
|
of posts displayed per page. By default, the plugin displays up to 10 posts on
|
||||||
|
the index pages. You can change this number separately for the main index,
|
||||||
|
the archive index pages, and the category index pages.
|
||||||
|
|
||||||
|
!!! example "Changing pagination"
|
||||||
|
|
||||||
|
Add five more blog posts, then set the pagination setting to show five per
|
||||||
|
page only:
|
||||||
|
|
||||||
|
```yaml hl_lines="7"
|
||||||
|
- blog:
|
||||||
|
archive_date_format: MMMM yyyy
|
||||||
|
categories_allowed:
|
||||||
|
- Holidays
|
||||||
|
- News
|
||||||
|
authors_profiles: true
|
||||||
|
pagination_per_page: 5
|
||||||
|
```
|
||||||
|
|
||||||
|
You will see that the pagination setting for archive and category pages
|
||||||
|
are inherited from the setting you added. If you want to have different
|
||||||
|
settings for the different index pages, you can specify each setting
|
||||||
|
separately:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- blog:
|
||||||
|
archive_date_format: MMMM yyyy
|
||||||
|
categories_allowed:
|
||||||
|
- Holidays
|
||||||
|
- News
|
||||||
|
authors_profiles: true
|
||||||
|
pagination_per_page: 5
|
||||||
|
archive_pagination_per_page: 10
|
||||||
|
categories_pagination_per_page: 10
|
||||||
|
```
|
||||||
|
|
||||||
|
## Blog table of contents
|
||||||
|
|
||||||
|
Another thing you may want to do once you have a large enough number of posts
|
||||||
|
is to turn on the function that produces a table of contents for the blog
|
||||||
|
index pages, giving your readers the opportunity to quickly scan the content
|
||||||
|
of each page for something that interests them without having to scroll
|
||||||
|
(assuming that the number of post per page is not too big).
|
||||||
|
|
||||||
|
!!! example "Turn on the table of contents feature"
|
||||||
|
|
||||||
|
To produce a table of contents for the blog index pages, add the following
|
||||||
|
to the configuration of the blog plugin:
|
||||||
|
|
||||||
|
```yaml hl_lines="2"
|
||||||
|
- blog:
|
||||||
|
blog_toc: true
|
||||||
|
archive_date_format: MMMM yyyy
|
||||||
|
# ...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Custom slugs
|
||||||
|
|
||||||
|
If, for some reason, you are not happy with the way that Material for MkDocs
|
||||||
|
turns headings into slugs, you can create your own slugify function or you
|
||||||
|
can manually define a slug for a specific post.
|
||||||
|
|
||||||
|
!!! example "Slugify function"
|
||||||
|
|
||||||
|
To define your own slugify function, you need to write a Python function
|
||||||
|
that converts text into a slug given additional arguments from the
|
||||||
|
configuration. You also need to write a function that returns that
|
||||||
|
function.
|
||||||
|
|
||||||
|
Say you want to define two slugify functions that you can switch between.
|
||||||
|
The first one returns a slug similar to what the default slugify function
|
||||||
|
produces. The second one cuts the result of that up into words and returns
|
||||||
|
a slug based on a maximum of five of them:
|
||||||
|
|
||||||
|
```python
|
||||||
|
import re, functools, unicodedata
|
||||||
|
|
||||||
|
RE_HTML_TAGS = re.compile(r'</?[^>]*>', re.UNICODE)
|
||||||
|
RE_INVALID_SLUG_CHAR = re.compile(r'[^\w\- ]', re.UNICODE)
|
||||||
|
RE_WHITESPACE = re.compile(r'\s', re.UNICODE)
|
||||||
|
|
||||||
|
def _make_slug(text, sep, **kwargs):
|
||||||
|
slug = unicodedata.normalize('NFC', text)
|
||||||
|
slug = RE_HTML_TAGS.sub('', slug)
|
||||||
|
slug = RE_INVALID_SLUG_CHAR.sub('', slug)
|
||||||
|
slug = slug.strip().lower()
|
||||||
|
slug = RE_WHITESPACE.sub(sep, slug)
|
||||||
|
return slug
|
||||||
|
|
||||||
|
def _make_slug_short(text, sep, **kwargs):
|
||||||
|
words = _make_slug(text, sep, **kwargs).split(sep)
|
||||||
|
return sep.join(words[:5])
|
||||||
|
|
||||||
|
def slugify(**kwargs):
|
||||||
|
if 'short' in kwargs and kwargs['short']:
|
||||||
|
return functools.partial(_make_slug_short, **kwargs)
|
||||||
|
return functools.partial(_make_slug, **kwargs)
|
||||||
|
```
|
||||||
|
Save this code in `ext/slugs.py` and also add an (empty) `__init__.py`
|
||||||
|
file to indicate that the directory is a module. Now you can configure
|
||||||
|
your custom slugify code like this:
|
||||||
|
|
||||||
|
```yaml hl_lines="4-6"
|
||||||
|
plugins:
|
||||||
|
- blog:
|
||||||
|
# other entries omitted
|
||||||
|
post_slugify: !!python/object/apply:ext.slugs.slugify
|
||||||
|
kwds:
|
||||||
|
short: true
|
||||||
|
```
|
||||||
|
|
||||||
|
Change the heading of a blog post to be longer than five words and observe
|
||||||
|
how the slugify function shortens the URL. Change the `short` attribute to
|
||||||
|
`false` and you can turn this off again.
|
||||||
|
|
||||||
|
If you want to influence the slug only for a single blog post, you can define
|
||||||
|
it manually by specifying it in the header of the post. Note that this is meant
|
||||||
|
as a last resort option. Specifying a custom slug manually for every post would
|
||||||
|
be tedious.
|
||||||
|
|
||||||
|
!!! example "Manually define slug"
|
||||||
|
|
||||||
|
If, for example, you wanted the slug to be 'ny-eve' instead of the somewhat
|
||||||
|
lengthy 'happy-new-years-eve', you could add the following:
|
||||||
|
|
||||||
|
```hl_lines="7"
|
||||||
|
---
|
||||||
|
date:
|
||||||
|
created: 2023-12-31
|
||||||
|
updated: 2024-01-02
|
||||||
|
readtime: 15
|
||||||
|
pin: true
|
||||||
|
slug: ny-eve
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
The URL for this post should now be
|
||||||
|
`http://localhost:8000/blog/2023/01/31/ny-eve/`.
|
||||||
|
|
||||||
|
## What's next?
|
||||||
|
|
||||||
|
You may want to increase engagement with your blog by allowing people to
|
||||||
|
subscribe to an RSS feed, by providing links to your social media profiles, by
|
||||||
|
providing share and like buttons, or by setting up a comment system.
|
||||||
|
The [engagement and dissemination tutorial] walks you through setting these up.
|
||||||
|
|
||||||
|
[engagement and dissemination tutorial]: engage.md
|
56
docs/tutorials/index.md
Normal file
56
docs/tutorials/index.md
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# Tutorials
|
||||||
|
|
||||||
|
In addition to the basic getting started guides, we offer tutorials that aim to
|
||||||
|
show how you can use Material for MkDocs in different use cases. In contrast to
|
||||||
|
the getting started guides or the reference documentation, the tutorials show
|
||||||
|
the breadth of features available in Material for MkDocs but also within
|
||||||
|
the wider MkDocs ecosystem.
|
||||||
|
|
||||||
|
The tutorials guide you through worked examples, so by following them you should
|
||||||
|
gain not only an understanding of how to use Material for MkDocs, but also
|
||||||
|
a template for your own projects. For convenience, these templates are also
|
||||||
|
available as template repositories on GitHub.
|
||||||
|
|
||||||
|
The tutorials assume that you have installed either the [public version] or the
|
||||||
|
[Insiders edition] of Material for MkDocs and that you have worked through the
|
||||||
|
[creating your site] setup guide.
|
||||||
|
|
||||||
|
Note that where the features we use require the Insiders edition, we mark these
|
||||||
|
with the heart icon: <!-- md:sponsors --> If you are using the public version
|
||||||
|
then you can skip these steps. Sometimes there will be ways of achieving the
|
||||||
|
same goal that differ between the public version and the Insider edition. In
|
||||||
|
that case, we will show them in a tabbed view so you can see one or the other.
|
||||||
|
|
||||||
|
[public version]: ../getting-started.md
|
||||||
|
[Insiders edition]: ../insiders/getting-started.md
|
||||||
|
[creating your site]: ../creating-your-site.md
|
||||||
|
|
||||||
|
!!! note "Feedback wanted!"
|
||||||
|
The tutorials are a recent addition to our documentation and we are still
|
||||||
|
working out what shape they should have in the end. Please contact us if you
|
||||||
|
want to provide feedback. <!--- TODO: how? -->
|
||||||
|
|
||||||
|
Note, however, that suggestions should be specific and feasible. We want to
|
||||||
|
focus on creating more content at the moment, instead of developing a
|
||||||
|
specific styling or behaviour for the tutorials. If there are worthwhile
|
||||||
|
improvements that we can make through simple customization then we are happy
|
||||||
|
to consider those.
|
||||||
|
|
||||||
|
## Blogs
|
||||||
|
* [Basics](blogs/basic.md) (20 min) <br/>
|
||||||
|
covers the basics of setting up a blog, including post metadata.
|
||||||
|
* [Navigation, pagination, multiple authors](blogs/navigation.md) (30 min)<br/>
|
||||||
|
describes how to make it easier for your readers to find content.
|
||||||
|
* [Engagement and dissemination](blogs/engage.md) (30 min)<br/>
|
||||||
|
walks you through ways of increasing engagement with your content.
|
||||||
|
|
||||||
|
[:octicons-repo-template-24: Template Repository](https://github.com/mkdocs-material/create-blog)
|
||||||
|
|
||||||
|
## Social cards
|
||||||
|
* [Basics](social/basic.md) (20 min) <br/>
|
||||||
|
shows you how to configure Material for MkDocs to create social cards for
|
||||||
|
your content.
|
||||||
|
* [Custom cards](social/custom.md) (15 min)<br/>
|
||||||
|
shows you how to design your own custom social cards.
|
||||||
|
|
||||||
|
[:octicons-repo-template-24: Template Repository](https://github.com/mkdocs-material/create-social-cards)
|
203
docs/tutorials/social/basic.md
Normal file
203
docs/tutorials/social/basic.md
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
# Basic social cards
|
||||||
|
|
||||||
|
Social cards are images that other systems such as social media can display as
|
||||||
|
a preview for content linked to. It is easy to get started with the social
|
||||||
|
plugin, true to the motto of Material with MkDocs: "batteries included."
|
||||||
|
|
||||||
|
## Basics
|
||||||
|
|
||||||
|
Before you start, there are just a couple of [dependencies to install]. These
|
||||||
|
are libraries for image processing that the plugin needs to produce the social
|
||||||
|
cards, as well as their Python bindings.
|
||||||
|
|
||||||
|
[dependencies to install]: https://squidfunk.github.io/mkdocs-material/plugins/requirements/image-processing/
|
||||||
|
|
||||||
|
With those prerequisites met, it is simply a matter of activating the plugin,
|
||||||
|
which will:
|
||||||
|
|
||||||
|
* produce the social cards as PNG images for each page in your site;
|
||||||
|
* create meta data in the headers of your site's pages that will provide
|
||||||
|
social media systems with key information and tell them how to find the
|
||||||
|
social card image.
|
||||||
|
|
||||||
|
!!! example "Add social cards"
|
||||||
|
|
||||||
|
Simply add the social plugin to your list of plugins:
|
||||||
|
|
||||||
|
```yaml hl_lines="3"
|
||||||
|
plugins:
|
||||||
|
- search
|
||||||
|
- social
|
||||||
|
- ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, then you run `mkdocs build` and look at the `site` directory, you will
|
||||||
|
see that it contains subfolders under `assets/images/social` that reflect
|
||||||
|
the structure of your Markdown files. Each page has a corresponding PNG file
|
||||||
|
that contains the social card image.
|
||||||
|
|
||||||
|
Have a look at the generated HTML and you will see the metadata produced in
|
||||||
|
the `head` element, including one entry that points to the image.
|
||||||
|
|
||||||
|
## Background color
|
||||||
|
|
||||||
|
The social plugin has configuration options for changing aspects such as colors,
|
||||||
|
images, fonts, logos, the title, even the description. You can configure them
|
||||||
|
for all social cards in the `mkdocs.yml` and, in the Insiders Edition, they can
|
||||||
|
be overridden in the page header for individual pages.
|
||||||
|
|
||||||
|
!!! example "Change the background color"
|
||||||
|
|
||||||
|
To change the background color to an attention-grabbing hot pink,
|
||||||
|
you might add:
|
||||||
|
|
||||||
|
```yaml hl_lines="4-5"
|
||||||
|
plugins:
|
||||||
|
...
|
||||||
|
- social:
|
||||||
|
cards_layout_options:
|
||||||
|
background_color: "#ff1493"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Logos
|
||||||
|
|
||||||
|
By default, the plugin uses the logo that you set for the whole site, either
|
||||||
|
through the `theme.logo` or the `theme.icon.logo` setting. The difference
|
||||||
|
between the two is that the `theme.icon.logo` version will directly embed the
|
||||||
|
logo's SVG code into the HTML, allowing it to inherit CSS color settings. When
|
||||||
|
you use `theme.logo`, the Material includes the logo as an image.
|
||||||
|
|
||||||
|
You can set your own logo specific for the social cards as well. The path used
|
||||||
|
is relative to your project root and needs to point to an SVG file or a pixel
|
||||||
|
image. It should be rectangular and have a transparent background.
|
||||||
|
|
||||||
|
!!! example "Set your own logo"
|
||||||
|
|
||||||
|
```yaml hl_lines="3-4"
|
||||||
|
plugins:
|
||||||
|
- social:
|
||||||
|
cards_layout_options:
|
||||||
|
logo: docs/assets/images/ourlogo.png
|
||||||
|
```
|
||||||
|
|
||||||
|
## Background images
|
||||||
|
|
||||||
|
In addition to adding your own logo, the most impactful way to personalize your
|
||||||
|
social cards is to add a background image instead of the default solid color
|
||||||
|
background. Make sure you choose one that will contrast well with the other
|
||||||
|
elements of the card.
|
||||||
|
|
||||||
|
Also, the background color gets rendered *on top of* the background image,
|
||||||
|
allowing you to use a transparent color to tint an image. To use just the image,
|
||||||
|
use the color value `transparent`.
|
||||||
|
|
||||||
|
!!! example "Add background image"
|
||||||
|
|
||||||
|
```yaml hl_lines="4 5"
|
||||||
|
plugins:
|
||||||
|
- social:
|
||||||
|
cards_layout_options:
|
||||||
|
background_image: layouts/background.png
|
||||||
|
background_color: transparent
|
||||||
|
```
|
||||||
|
|
||||||
|
The path to the background image is resolved from the root of your project,
|
||||||
|
so this is where you should make the `layouts` directory and place the
|
||||||
|
background image. The default site of the social cards included with the plugin
|
||||||
|
is 1200x630 pixels, so choose an image that size or one that scales well to it.
|
||||||
|
|
||||||
|
## Additional layouts and styles <!-- md:sponsors -->
|
||||||
|
|
||||||
|
The Insiders Edition provides additional layouts as well as the option to
|
||||||
|
configure different styles for different (kinds of) pages.
|
||||||
|
|
||||||
|
The Insiders Edition comes with a number of additional layouts for the social
|
||||||
|
cards. For example, the `default/variant` layout adds a page icon to the card.
|
||||||
|
You can use this to distinguish social cards visually, depending on what kind
|
||||||
|
of page you are sharing.
|
||||||
|
|
||||||
|
For example, imagine you have a set of pages that advertise events and you want
|
||||||
|
to include a calendar icon as a visual indication that a card advertises an
|
||||||
|
event. In the following, you will set up a directory for event pages and use
|
||||||
|
the meta plugin to assign them a calendar icon.
|
||||||
|
|
||||||
|
!!! example "Social cards for event pages"
|
||||||
|
|
||||||
|
First, create a directory in your `docs` directory to hold the event pages:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ mkdir docs/events
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, add a file `.meta.yml` inside this new directory with settings for
|
||||||
|
the page icon and a hot pink background color that will stand out on
|
||||||
|
social media. Note that you can override the background image by setting it
|
||||||
|
to `null` here since it is not visible anyway because of the opaque coloring.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
icon: material/calendar-plus
|
||||||
|
social:
|
||||||
|
cards_layout_options:
|
||||||
|
background_image: null
|
||||||
|
background_color: "#ff1493"
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
Now add a page within the `docs/events` directoy. It does not need to have
|
||||||
|
any special content, just a top level header.
|
||||||
|
|
||||||
|
To turn on the `default/variant` layout in `mkdocs.yml`, add the
|
||||||
|
`cards_layout` option and also add the meta plugin:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
plugins:
|
||||||
|
- meta
|
||||||
|
- social:
|
||||||
|
cards_layout: default/variant
|
||||||
|
```
|
||||||
|
|
||||||
|
After running `mkdocs build`, you can see that the social card at
|
||||||
|
`site/assets/images/social/events/index.png` features the page icon.
|
||||||
|
|
||||||
|
Note that the icon will also appear next to the navigation element for the
|
||||||
|
page. If that is not what you want then you will need to modify the social
|
||||||
|
card template to gets its icons from another source. You can learn how to
|
||||||
|
do this in the [custom social cards tutorial](custom.md).
|
||||||
|
|
||||||
|
## Per-page settings <!-- md:sponsors -->
|
||||||
|
|
||||||
|
With the Insiders Edition, you can customize the card layout for each
|
||||||
|
page by adding settings to the page header. You have effectively done this
|
||||||
|
in the previous exercise, but using the meta plugin to affect a whole set of
|
||||||
|
pages.
|
||||||
|
|
||||||
|
Say that in addition to regular events you also have the odd webinar and
|
||||||
|
for this you want to set a different icon and also set the description to
|
||||||
|
indicate that the event is part of the webinar series.
|
||||||
|
|
||||||
|
!!! example "Override card style in page header"
|
||||||
|
|
||||||
|
Add the following to the top of the page in `docs/events` or create a new
|
||||||
|
one:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
icon: material/web
|
||||||
|
social:
|
||||||
|
cards_layout_options:
|
||||||
|
description: Our Webinar Series
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
## What's next?
|
||||||
|
|
||||||
|
With the Insiders Edition, you can also define custom layouts if the
|
||||||
|
configuration options introduced above as not enough to meet your needs.
|
||||||
|
Continue to the [custom social cards tutorial](custom.md) if you want to
|
||||||
|
find out how to do this.
|
||||||
|
|
||||||
|
Social cards are particularly useful for blog posts. If you have a blog,
|
||||||
|
you need to do nothing more than to turn on both plugins to create social cards
|
||||||
|
to advertise your latest blog posts. If you do not have one yet but would like
|
||||||
|
to, why not check out the [blog tutorials](../index.md#blogs)?
|
142
docs/tutorials/social/custom.md
Normal file
142
docs/tutorials/social/custom.md
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
# Custom cards
|
||||||
|
|
||||||
|
The Insiders Edition allows you to define custom layouts for your social cards
|
||||||
|
to suit your specific needs if the configuration options are not enough.
|
||||||
|
For example, you may want to define a social card to advertise a new release
|
||||||
|
of your product. It should have an icon indicating a launch announcement as
|
||||||
|
well as the version number of the release on the card.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
You can either design a custom layout from scratch or use an existing layout
|
||||||
|
as the basis that you add to or otherwise modify. In this tutorial, you will
|
||||||
|
use the default layout as the basis.
|
||||||
|
|
||||||
|
!!! example "Copy default layout to customize <!-- md:sponsors -->"
|
||||||
|
|
||||||
|
Copy the default social card layout from your installation of Material
|
||||||
|
for MkDocs to a new directory `layouts`. The instructions below assume you
|
||||||
|
are in your project root and have a virtual environment within this. The
|
||||||
|
path on your machine, of course, may differ.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ mkdir layouts
|
||||||
|
$ cp venv/lib/python3.12/site-packages/material/plugins/social/templates/default/variant.yml \
|
||||||
|
layouts/release.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
Before customizing the social cards, you need to tell the plugin where to
|
||||||
|
find them as well as tell MkDocs to watch for any changes. Add the following
|
||||||
|
to the plugin configuration in your `mkdocs.yml`:
|
||||||
|
|
||||||
|
``` yaml hl_lines="2-6"
|
||||||
|
plugins:
|
||||||
|
- social:
|
||||||
|
cards_layout_dir: layouts
|
||||||
|
|
||||||
|
watch:
|
||||||
|
- layouts
|
||||||
|
```
|
||||||
|
|
||||||
|
Have a look at the contents of `release.yml`. You will see that there are:
|
||||||
|
|
||||||
|
* a number of definitions of content pulled from the site,
|
||||||
|
* definitions of tags that end up in the `meta` elements in the page header
|
||||||
|
of each page,
|
||||||
|
* a specification that consists of a number of layers that the social plugin
|
||||||
|
applies on top of each other in the order in which they are defined.
|
||||||
|
|
||||||
|
## Define page metadata
|
||||||
|
|
||||||
|
In the following, you will add a version number to the social card. This
|
||||||
|
assumes you have a changelog page with information about each release.
|
||||||
|
Add the version number of the latest version to the page header (so it does
|
||||||
|
not need to be parsed out of the Markdown content):
|
||||||
|
|
||||||
|
!!! example "Defining the release data <!-- md:sponsors -->"
|
||||||
|
|
||||||
|
Create a page `docs/changelog.md` with the following content:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
icon: material/rocket-launch-outline
|
||||||
|
social:
|
||||||
|
cards_layout: release
|
||||||
|
cards_layout_options:
|
||||||
|
title: New release!
|
||||||
|
latest: 1.2.3
|
||||||
|
---
|
||||||
|
|
||||||
|
# Releases
|
||||||
|
```
|
||||||
|
|
||||||
|
## Extract page metadata
|
||||||
|
|
||||||
|
With the data defined in the page header, you can now add code to the layout
|
||||||
|
that pulls it out and makes it available to render later on. This is to separate
|
||||||
|
the data manipulation from the actual layout instructions and so make the
|
||||||
|
layout file easier to read.
|
||||||
|
|
||||||
|
!!! example "Adding data definitions"
|
||||||
|
|
||||||
|
Add the following at the top of the layout file:
|
||||||
|
|
||||||
|
```yaml hl_lines="2-9"
|
||||||
|
definitions:
|
||||||
|
- &latest >-
|
||||||
|
{%- if 'latest' in page.meta %}
|
||||||
|
{{ page.meta['latest']}}
|
||||||
|
{%- else -%}
|
||||||
|
No release version data defined!
|
||||||
|
{%- endif -%}
|
||||||
|
```
|
||||||
|
|
||||||
|
The code presented here checks whether the page header contains the necessary
|
||||||
|
entries and spits out a message to the social card if not. Unfortunately, there
|
||||||
|
is no straightforward way to raise an exception or log an error, so the messages
|
||||||
|
merely appear in the social card produced.
|
||||||
|
|
||||||
|
## Add release version layer
|
||||||
|
|
||||||
|
The next step is to use these data definitions in a new layer and add it to the
|
||||||
|
ones already present.
|
||||||
|
|
||||||
|
!!! example "Render release version"
|
||||||
|
|
||||||
|
Finally, add the following to end of the custom layout:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- size: { width: 990, height: 50 }
|
||||||
|
offset: { x: 50, y: 360 }
|
||||||
|
typography:
|
||||||
|
content: *latest
|
||||||
|
align: start
|
||||||
|
color: *color
|
||||||
|
```
|
||||||
|
|
||||||
|
You should now see the social plugin use the custom layout on the changelog page
|
||||||
|
you set up.
|
||||||
|
|
||||||
|
## Adjust layout
|
||||||
|
|
||||||
|
Finally, the rocket icon used for the changelog page is not quite in the right
|
||||||
|
position. Find the please where the `page_icon` variable is used to create the
|
||||||
|
page icon layer and adjust the horizontal position to 600 instead of 800.
|
||||||
|
|
||||||
|
!!! tip "Debugging layout files"
|
||||||
|
|
||||||
|
Should you find that your layouts are causing your MkDocs build to fail,
|
||||||
|
there are a number of things you can do:
|
||||||
|
|
||||||
|
1. Run Mkdocs with the `--verbose` option to get more detailed reporting.
|
||||||
|
2. Comment out things you recently added or that you suspect are the cause
|
||||||
|
3. Install the `jinja2` command-line tool with `pip install Jinja2` and
|
||||||
|
run it over your layout file, for example: `jinja2 event.yml`.
|
||||||
|
|
||||||
|
## What's next?
|
||||||
|
|
||||||
|
If you do not have a blog yet, why not check out the
|
||||||
|
[blog tutorials](../index.md#blogs) and learn how to set one up? The social
|
||||||
|
plugin will help you draw attention to your posts on social media.
|
||||||
|
|
||||||
|
Check out the [other tutorials](../index.md) we have prepared for you.
|
12
mkdocs.yml
12
mkdocs.yml
@ -174,6 +174,9 @@ markdown_extensions:
|
|||||||
custom_checkbox: true
|
custom_checkbox: true
|
||||||
- pymdownx.tilde
|
- pymdownx.tilde
|
||||||
|
|
||||||
|
not_in_nav: |
|
||||||
|
/tutorials/**/*.md
|
||||||
|
|
||||||
# Page tree
|
# Page tree
|
||||||
nav:
|
nav:
|
||||||
- Home: index.md
|
- Home: index.md
|
||||||
@ -188,6 +191,15 @@ nav:
|
|||||||
- Philosophy: philosophy.md
|
- Philosophy: philosophy.md
|
||||||
- Alternatives: alternatives.md
|
- Alternatives: alternatives.md
|
||||||
- License: license.md
|
- License: license.md
|
||||||
|
- Tutorials:
|
||||||
|
- tutorials/index.md
|
||||||
|
- "Blogs":
|
||||||
|
- tutorials/blogs/basic.md
|
||||||
|
- tutorials/blogs/navigation.md
|
||||||
|
- tutorials/blogs/engage.md
|
||||||
|
- "Social cards":
|
||||||
|
- tutorials/social/basic.md
|
||||||
|
- tutorials/social/custom.md
|
||||||
- Changelog:
|
- Changelog:
|
||||||
- changelog/index.md
|
- changelog/index.md
|
||||||
- How to upgrade: upgrade.md
|
- How to upgrade: upgrade.md
|
||||||
|
Loading…
Reference in New Issue
Block a user