Add new post generation feature with image support and toot shortcode

- Created a new markdown file for generating posts with an image cover in Hugo.
- Implemented a Python script to generate images with text overlay using PIL.
- Added a shortcode for displaying toots from Mastodon, including user information and media attachments.
This commit is contained in:
Fundor333
2025-07-10 01:39:59 +02:00
parent 3dde67966b
commit 7b30b6c67f
12 changed files with 240 additions and 23 deletions

View File

@@ -5,3 +5,4 @@
@import "author";
@import "menu";
@import "media";
@import "mastodon";

131
assets/sass/mastodon.scss Normal file
View File

@@ -0,0 +1,131 @@
.toot {
--toot-bg: var(--entry);
--toot-border: rgba(0, 0, 0, 0.1);
--toot-radius: 12px;
--toot-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
background: var(--toot-bg);
border: 1px solid var(--toot-border);
border-radius: var(--toot-radius);
box-shadow: var(--toot-shadow);
padding: 16px;
margin: 1.5rem auto;
max-width: 600px;
font-family: -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
}
.dark .toot {
--toot-border: rgba(255, 255, 255, 0.1);
--toot-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
.toot-header {
display: flex;
align-items: flex-start;
gap: 12px;
margin-bottom: 12px;
}
.toot-profile img {
width: 48px;
height: 48px;
border-radius: 4px;
display: block;
}
.toot-author {
display: flex;
flex-direction: column;
gap: 2px;
}
.toot-author-name {
color: var(--primary);
font-weight: 700;
text-decoration: none;
font-size: 15px;
line-height: 20px;
}
.toot-author-handle {
color: var(--secondary);
text-decoration: none;
font-size: 14px;
line-height: 18px;
}
.toot-content {
color: var(--content);
font-size: 15px;
line-height: 1.5;
margin: 12px 0;
}
.toot-content p {
margin: 0 0 12px;
}
.toot-content p:last-child {
margin-bottom: 0;
}
.toot-content a {
color: #2b90d9;
text-decoration: none;
}
.toot-content a:hover {
text-decoration: underline;
}
.toot-media-grid {
display: grid;
grid-gap: 8px;
margin: 12px 0;
border-radius: 12px;
overflow: hidden;
}
.toot-media-grid[data-count="1"] {
grid-template-columns: 1fr;
}
.toot-media-grid[data-count="2"] {
grid-template-columns: repeat(2, 1fr);
}
.toot-media-grid[data-count="3"] {
grid-template-columns: repeat(2, 1fr);
}
.toot-media-grid[data-count="3"] > :first-child {
grid-column: 1 / -1;
}
.toot-media-grid[data-count="4"] {
grid-template-columns: repeat(2, 1fr);
}
.toot-media-item img {
width: 100%;
height: auto;
display: block;
border-radius: 4px;
}
.toot-footer {
margin-top: 12px;
padding-top: 12px;
border-top: 1px solid var(--toot-border);
color: var(--secondary);
font-size: 14px;
}
.toot-date {
color: inherit;
text-decoration: none;
}
.toot-date:hover {
text-decoration: underline;
}

View File

@@ -26,7 +26,7 @@ series:
I am a HUGE RSS reader so sometime I find something interesting and I want to read the full post.
This time I find some article about this toot about personal website in the era of social network. [^original] [^response]
{{< mastodon "https://fosstodon.org/@JasonBrewster/112696028819666648" >}}
{{< toot instance="fosstodon.org" id="112696028819666648" >}}
[^original]: [Why Have a Personal Site Instead of Social Media?](https://kevquirk.com/blog/why-have-a-personal-site-instead-of-social-media) the original post which is a response to the mastodon twoot

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

View File

@@ -0,0 +1,37 @@
---
title: "Generate Post With Img for Hugo"
date: 2025-07-10T00:36:34+02:00
draft: true
feature_link: "https://www.midjourney.com/home/"
feature_text: ""
description: How I create new post on Hugo and generate an image as cover
isStarred: false
tags:
- image
- hugo
- script
- hacking
categories:
- dev
- fingerfood
images:
keywords:
series:
- Hugo tricks
reply:
repost:
like:
rsvp:
bookmark:
---
Some days ago I find a new post from a blog I follow about "[Open Graph Meta Tags on Hugo and WordPress Blogs](https://www.burgeonlab.com/blog/hugo-and-wordpress-open-graph-meta-tags/)" as a toot
{{< toot instance="fosstodon.org" id="114818281454845557" >}}
and I find I do the same thing and some more. I generate a default cover because I prefer to have a "standard" generated image or a specific image as the feature image. The image set in the settings is a default, a "if all other image fall use this" kind of stuff.
## How I generate the post?
When I write a post I launch a [makefile command](/post/2021/the-team-makefile/)

View File

@@ -26,11 +26,11 @@ A lot of time ago I implement the Webmention in my site following a lot of blogp
One of them was a bigger ispiration for my implementation[^indiewebify] and I have some chat with the author of the post over Mastodon for the implementation of the syndications link in a static site[^synd] and how to implement it.
{{< mastodon "https://mastodon.social/@fundor333/108752916197327869">}}
{{< toot instance="mastodon.social" id="108752916197327869">}}
<br><hr>
{{< mastodon "https://fosstodon.org/@chringel/108754642028626230" >}}
{{< toot instance="fosstodon.org" id="108754642028626230" >}}
After 3 years I find the solution in a post about webmetions!

View File

@@ -30,9 +30,9 @@ syndication:
I have a friend who read my blog using my feed. And sometime he pings me for some problem with the feed, like a drop of all the article as new
{{<mastodon "https://social.lol/@robb/113854214799861227">}}
{{<toot instance="social.lol" id="113854214799861227">}}
{{<mastodon "https://mastodon.social/@andreagrandi/113854638640440084" >}}
{{<toot instance="mastodon.social" id="113854638640440084" >}}
And after read some other post with the same problem ( [Robb Knight problem with feed reader](https://rknight.me/notes/202501190902/) [Kev other problem with feed reader](https://kevquirk.com/notes/20250528-1702?utm_source=fundor333.com&utm_medium=link&utm_campaign=blogging&ref=fundor333.com) ) I understand a little this: Atom is newer and superior than Rss.

View File

@@ -5,7 +5,7 @@
"inizio": "05/2021",
"roles": [
{
"description": "Autodeploy and some Wordpress automation. GitLab, MariaDB, Bash and Nginx",
"description": "Develop and update auto-deploy and some Wordpress automation. GitLab, MariaDB, Bash and Nginx",
"role": "Dev Ops"
},
{

View File

@@ -1,15 +0,0 @@
<div class="mastodon">
{{- with .Get 0 }}
<iframe
src="{{ . }}/embed"
class="mastodon-embed"
style="max-width: 100%; border: 0"
width="400"
allow="fullscreen"
allowfullscreen="allowfullscreen">
</iframe>
<script src="https://fosstodon.org/embed.js" async="async"></script>
{{- else }}
{{- errorf "The %q shortcode requires a positional parameter: the url of the post. See %s" .Name .Position }}
{{- end }}
</div>

View File

@@ -0,0 +1,63 @@
{{ $masIns := .Get "instance" }}
{{ $id := .Get "id" }}
{{ $tootLink := "" }}
{{ $handleInst := "" }}
{{ $urlToGet := print "https://" $masIns "/api/v1/statuses/" $id }}
{{ with resources.GetRemote $urlToGet }}
{{ $json := .Content | unmarshal }}
{{ if isset $json "account" }}
{{ $tootLink = print "https://" $masIns "@" $json.account.acct "/status/" $id }}
{{ $handleInst = print "@" $json.account.acct "@" $masIns }}
{{ end }}
{{ if isset $json "content" }}
<div class="toot">
<div class="toot-header">
<a class="toot-profile" href="https://{{ $masIns }}/@{{ $json.account.acct }}" rel="noopener">
<img src="{{ $json.account.avatar }}"
alt="Avatar for {{ $handleInst }}"
loading="lazy">
</a>
<div class="toot-author">
<a class="toot-author-name"
href="https://{{ $masIns }}/@{{ $json.account.acct }}"
rel="noopener">{{ $json.account.display_name }}</a>
<a class="toot-author-handle"
href="https://{{ $masIns }}/@{{ $json.account.acct }}"
rel="noopener">{{ $handleInst }}</a>
</div>
</div>
<div class="toot-content">{{ $json.content | safeHTML }}</div>
{{ with $json.media_attachments }}
{{ $count := len . }}
<div class="toot-media-grid" data-count="{{ $count }}">
{{ range . }}
{{ if eq .type "image" }}
<div class="toot-media-item">
<img src="{{ .url }}"
alt=""
loading="lazy">
</div>
{{ end }}
{{ end }}
</div>
{{ end }}
<div class="toot-footer">
<a href="{{ $tootLink }}"
class="toot-date"
rel="noopener">{{ dateFormat "3:04 PM · Jan 2, 2006" $json.created_at }}</a>
</div>
</div>
{{ end }}
{{ else }}
<div class="toot">
<p style="text-align: center; color: var(--secondary); margin: 0;">
[Source not online at time of site build.]
</p>
</div>
{{ end }}

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
{"Target":"add.min.2cb5f38e4616791f2cedc13a69000b1925f4fe15e51fd0e72f72f2e3673f38cb.css","MediaType":"text/css","Data":{"Integrity":"sha256-LLXzjkYWeR8s7cE6aQALGSX0/hXlH9DnL3Ly42c/OMs="}}
{"Target":"add.min.0108858c01d2eebf16bdefad77575ee1f39a405b572b664bf6570d20b85a1a0e.css","MediaType":"text/css","Data":{"Integrity":"sha256-AQiFjAHS7r8Wve+td1de4fOaQFtXK2ZL9lcNILhaGg4="}}