Simplify usage of custom justfile targets

This commit is contained in:
Pascal Le Merrer 2026-03-03 22:39:06 +01:00
parent 7ae5406548
commit 2b450e1b51
7 changed files with 53 additions and 31 deletions

View file

@ -0,0 +1,5 @@
Title: Lettre n°14 — 09 mars 2026
Date: 2026-03-09 09:00
Category: Newsletter
JsonLD: <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°14", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Mar 09 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } </script>
<img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg">

View file

@ -1,14 +1,14 @@
Title: Accueil Title: Accueil
Date: 2026-03-02 09:00 Date: 2026-03-09 09:00
URL: URL:
save_as: index.html save_as: index.html
Category: Home Category: Home
JsonLD: { "@context": "https://schema.org", "@type": "WebPage", "name": "Accueil", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Mar 02 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } JsonLD: { "@context": "https://schema.org", "@type": "WebPage", "name": "Accueil", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Mar 09 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } }
<img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg"> <img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg">
# La [lettre n°13]({filename}/newsletter/craft-letter-13.md) est parue ! # La [lettre n°14]({filename}/newsletter/craft-letter-14.md) est parue !
La Craft Letter est une newsletter hebdomadaire dans laquelle je partage des articles La Craft Letter est une newsletter hebdomadaire dans laquelle je partage des articles
issus de ma veille technologique. Vous y trouverez des articles relatifs au développement logiciel d'une façon générale, qu'il soit front-end, back-end ou autre. Mais aussi des articles consacrés à l'architecture logicielle, la méthodologie, les outils, des projets open source, des conférences... issus de ma veille technologique. Vous y trouverez des articles relatifs au développement logiciel d'une façon générale, qu'il soit front-end, back-end ou autre. Mais aussi des articles consacrés à l'architecture logicielle, la méthodologie, les outils, des projets open source, des conférences...
@ -37,6 +37,7 @@ Pour savoir qui je suis, ou pourquoi j'écris cette lettre, je vous invite à vo
# Archives # Archives
* [Lettre n°14]({filename}/newsletter/craft-letter-14.md)
* [Lettre n°13]({filename}/newsletter/craft-letter-13.md) * [Lettre n°13]({filename}/newsletter/craft-letter-13.md)
* [Lettre n°12]({filename}/newsletter/craft-letter-12.md) * [Lettre n°12]({filename}/newsletter/craft-letter-12.md)
* [Lettre n°11]({filename}/newsletter/craft-letter-11.md) * [Lettre n°11]({filename}/newsletter/craft-letter-11.md)

View file

@ -40,8 +40,8 @@ devserver-global:
pelican -lr content -o output -s "{{CONFFILE}}" {{PELICANOPTS}} -b 0.0.0.0 pelican -lr content -o output -s "{{CONFFILE}}" {{PELICANOPTS}} -b 0.0.0.0
# generate using production settings # generate using production settings
publish number: publish:
just format {{number}} just format
pelican content -o output -s "{{PUBLISHCONF}}" {{PELICANOPTS}} pelican content -o output -s "{{PUBLISHCONF}}" {{PELICANOPTS}}
rsync -e ssh -av --delete-after /Users/pascal/Documents/craft-letter/output/ craftletter@ssh-craftletter.alwaysdata.net:/home/craftletter/www rsync -e ssh -av --delete-after /Users/pascal/Documents/craft-letter/output/ craftletter@ssh-craftletter.alwaysdata.net:/home/craftletter/www
@ -50,15 +50,15 @@ ssh:
ssh craftletter@ssh-craftletter.alwaysdata.net ssh craftletter@ssh-craftletter.alwaysdata.net
# Create the skeleton for a new issue of the newsletter, and reference it into the home page # Create the skeleton for a new issue of the newsletter, and reference it into the home page
new number: new:
PYTHONPATH=PWD venv/bin/python ./scripts/create_newsletter.py --number={{number}} PYTHONPATH=PWD venv/bin/python ./scripts/create_newsletter.py
# generate HTML email # generate HTML email
mail number: mail:
just format {{number}} just format
PYTHONPATH=PWD venv/bin/python ./scripts/prepare_email.py --number={{number}} PYTHONPATH=PWD venv/bin/python ./scripts/prepare_email.py
# Format the content of a given newsletter # Format the content of a given newsletter
format number: format:
PYTHONPATH=PWD venv/bin/python ./scripts/format.py --number={{number}} PYTHONPATH=PWD venv/bin/python ./scripts/format.py

View file

@ -30,17 +30,18 @@ def set_publication_date_for_seo(text: str, publication_date: datetime) -> str:
return text.replace("{DATE_UTC}", date_utc) return text.replace("{DATE_UTC}", date_utc)
# Parse the command line arguments # Find the number of the letter to create
parser = argparse.ArgumentParser() destination_path = Path(f"./content/newsletter")
parser.add_argument("-n", "--number", required=True, type=int, help="Newsletter number") p = destination_path.glob("craft-letter-*.md")
args = parser.parse_args() files = [x for x in p if x.is_file()]
letter_number = len(files) + 1
# Load the newsletter template # Load the newsletter template
template = Path("./template/newsletter.md") template = Path("./template/newsletter.md")
content = template.read_text() content = template.read_text()
new_content = content.replace("{LETTER_NUMBER}", str(args.number)) new_content = content.replace("{LETTER_NUMBER}", str(letter_number))
today = datetime.today() today = datetime.today()
next_monday = get_next_weekday(today, MONDAY) next_monday = get_next_weekday(today, MONDAY)
@ -52,9 +53,11 @@ new_content = set_publication_date_for_pelican(new_content, next_monday)
new_content = set_publication_date_for_seo(new_content, next_monday) new_content = set_publication_date_for_seo(new_content, next_monday)
# Create the new file # Create the new file
destination = Path(f"./content/newsletter/craft-letter-{args.number}.md") destination = destination_path / f"craft-letter-{letter_number}.md"
destination.write_text(new_content) destination.write_text(new_content)
print(f"Created letter #{letter_number}: {destination}")
# Load the homepage template # Load the homepage template
template = Path("./template/index.md") template = Path("./template/index.md")
content = template.read_text() content = template.read_text()
@ -63,15 +66,15 @@ new_content = set_publication_date_for_pelican(content, next_monday)
new_content = set_publication_date_for_seo(new_content, next_monday) new_content = set_publication_date_for_seo(new_content, next_monday)
link = ( link = f"[lettre n°{letter_number}]({{filename}}/newsletter/craft-letter-{letter_number}.md)"
f"[lettre n°{args.number}]({{filename}}/newsletter/craft-letter-{args.number}.md)"
)
new_content = new_content.replace("{LINK}", link) new_content = new_content.replace("{LINK}", link)
for i in reversed(range(args.number)): for i in reversed(range(letter_number)):
link = f"* [Lettre n°{i + 1}]({{filename}}/newsletter/craft-letter-{i + 1}.md)\n" link = f"* [Lettre n°{i + 1}]({{filename}}/newsletter/craft-letter-{i + 1}.md)\n"
new_content += link new_content += link
# Update the index page # Update the index page
destination = Path("./content/pages/index.md") destination = Path("./content/pages/index.md")
destination.write_text(new_content) destination.write_text(new_content)
print(f"Updated index page: {destination}")

View file

@ -1,5 +1,6 @@
import argparse import argparse
from pathlib import Path from pathlib import Path
from util import get_latest_newsletter_number
REPLACEMENTS = { REPLACEMENTS = {
" :": "&nbsp;:", " :": "&nbsp;:",
@ -9,11 +10,12 @@ REPLACEMENTS = {
"'": "", "'": "",
} }
parser = argparse.ArgumentParser()
parser.add_argument("-n", "--number", required=True, type=int, help="Newsletter number")
args = parser.parse_args()
file = Path(f"./content/newsletter/craft-letter-{args.number}.md") letter_number = get_latest_newsletter_number()
file = Path(f"./content/newsletter/craft-letter-{letter_number}.md")
print(f"Formatting letter #{letter_number}: {file}")
content = file.read_text() content = file.read_text()
for value, replacement in REPLACEMENTS.items(): for value, replacement in REPLACEMENTS.items():

View file

@ -9,14 +9,15 @@ import argparse
import re import re
from pathlib import Path from pathlib import Path
from util import get_latest_newsletter_number
MAIL_GENERATOR = "/opt/homebrew/bin/mdtosendy" MAIL_GENERATOR = "/opt/homebrew/bin/mdtosendy"
parser = argparse.ArgumentParser() # Find the number of the letter to create
parser.add_argument("-n", "--number", required=True, type=int, help="Newsletter number") letter_number = get_latest_newsletter_number()
args = parser.parse_args()
source = Path(f"./content/newsletter/craft-letter-{args.number}.md") source = Path(f"./content/newsletter/craft-letter-{letter_number}.md")
if not source.is_file(): if not source.is_file():
print(f"ERROR: file not found {source}") print(f"ERROR: file not found {source}")
@ -35,7 +36,7 @@ destination.write_text(output)
subprocess.run([MAIL_GENERATOR, str(destination)]) subprocess.run([MAIL_GENERATOR, str(destination)])
generated_mail = Path("mail") / f"craft-letter-{args.number}.html" generated_mail = Path("mail") / f"craft-letter-{letter_number}.html"
today = date.today() today = date.today()
mail_content = generated_mail.read_text() mail_content = generated_mail.read_text()
mail_content = mail_content.replace("{{YEAR}}", str(today.year)) mail_content = mail_content.replace("{{YEAR}}", str(today.year))

10
scripts/util.py Normal file
View file

@ -0,0 +1,10 @@
from pathlib import Path
def get_latest_newsletter_number():
# Find the number of the latest newsletter
destination_path = Path(f"./content/newsletter")
p = destination_path.glob("craft-letter-*.md")
files = [x for x in p if x.is_file()]
letter_number = len(files)
return letter_number