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:
@@ -5,3 +5,4 @@
|
||||
@import "author";
|
||||
@import "menu";
|
||||
@import "media";
|
||||
@import "mastodon";
|
||||
|
||||
131
assets/sass/mastodon.scss
Normal file
131
assets/sass/mastodon.scss
Normal 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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
BIN
content/post/2025/generate-post-with-img-for-hugo/cover.png
Normal file
BIN
content/post/2025/generate-post-with-img-for-hugo/cover.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 MiB |
37
content/post/2025/generate-post-with-img-for-hugo/index.md
Normal file
37
content/post/2025/generate-post-with-img-for-hugo/index.md
Normal 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/)
|
||||
@@ -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!
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
63
layouts/shortcodes/toot.html
Normal file
63
layouts/shortcodes/toot.html
Normal 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
@@ -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="}}
|
||||
Reference in New Issue
Block a user