Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/pr_checker_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,18 @@ jobs:
if: ${{ github.repository_owner == 'geotribu' }}

steps:
- name: Install French locale
id: locale-fr
shell: bash
run: |
sudo locale-gen fr_FR.UTF-8
sudo update-locale LANG=fr_FR.UTF-8

- name: Get source code
uses: actions/checkout@v4



- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -234,3 +234,4 @@ linkchecker_report.html
gource.ini
avatars/
mkdocs-generated-configuration.yml
latest_content.yml
1 change: 1 addition & 0 deletions content/articles/.pages
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
title: "📖 Articles"

nav:
- "Derniers articles": index.md
- "2025"
- "2024"
- "2023"
Expand Down
13 changes: 13 additions & 0 deletions content/articles/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
title: "Liste des derniers articles parus"
template: custom_templates/index_articles.html
# theme customizations
hide:
- footer
- navigation
- toc
search:
exclude: true
---

<!-- Page qui utilise un template personnalisé (cf clé "template" dans l'en-tête) -->
74 changes: 74 additions & 0 deletions content/theme/custom_templates/index_articles.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{% extends "base.html" %}

{% block styles %}
{{ super() }}

<link rel=stylesheet href=../theme/assets/stylesheets/homepage.min.css>
{% endblock %}

<!-- Render hero under tabs -->
{% block tabs %}
{{ super() }}

<!-- Hero for landing page -->
<div class="tx-container">
<div class="md-grid md-typeset">
<div class="tx-hero">
<div class="tx-hero__title">
<h1 style="visibility: hidden">Geotribu</h1>
</div>
<div class="tx-hero__image">
<img src="https://cdn.geotribu.fr/img/internal/charte/geotribu_logo_rectangle_384x80.png"
alt="Bannière Geotribu" draggable="false" title="logo Geotribu">
</div>
<div class="tx-hero__content">
<p>Site collaboratif sur la géomatique <span class="em">libre</span> et <span class="em">ouverte</span>.</p>
</div>
</div>
</div>
</div>

<!-- Content -->
<div class="md-container secondary-section">
<div class="g">
{% if config.extra.latest %}{% for contenu in config.extra.latest.articles %}
<div class="section" id="articles">
<div class="component-wrapper">
<div class="first-column">
<a class="toclink" href="/{{ contenu.url_rel | default('/') }}">
<h3>{{ contenu.title | default('Titre') }}</h3>
</a>

{% if contenu.subtitle %}<h4>{{ contenu.subtitle | default('Sous-titre') }}</h4>{%
endif
%}
{% for tag in contenu.tags %}
<a class="md-tag md-tag-icon" href="/tags/#tag:{{ tag | lower }}">{{ tag }}</a>{{ ", " if not loop.last else
"" }}
{% endfor %}
<h5>{{ "Publié le {}".format(contenu.date | date_localized ) |
default('vendredi 9 août 1985') }} par {{ contenu.authors | default('Prénom NOM') | join(", ") }}</h5>
<p>{{ contenu.description | default('Description') }}</p>
<a href="/{{ contenu.url_rel | default('/') }}" class="md-button">Lire cet article...</a>
</div>
<div class="second-column">
<div class="image-wrapper">
<a href="/{{ contenu.url_rel | default('/') }}" hreflang="{{ contenu.language | default('fr') }}"
title="Lien vers le dernier article">
<img
src="{{ contenu.image | default('https://cdn.geotribu.fr/img/internal/charte/geotribu_logo_rectangle_384x80.png') }}"
alt="Illustration du dernier article publié" decoding="async" loading="lazy" draggable="false">
<div class="image-overlay">{{ contenu.title | default('Placeholder') }}, par {{
contenu.authors | default('Prénom NOM') | join(", ") }}</div>
</a>
</div>
</div>
</div>
</div>
{% endfor %}{% endif %}

</div>
</div>


{% endblock %}
8 changes: 7 additions & 1 deletion hooks/mkdocs/G000_load_subconfigs.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

logger = logging.getLogger("mkdocs")
log_prefix = f"[{__name__}] "
witness_output = Path("./latest_content.yml")

# ###########################################################################
# ########## Functions #############
Expand Down Expand Up @@ -135,6 +136,11 @@ def on_config(config: MkDocsConfig) -> MkDocsConfig:
)

config["extra"]["latest"] = latest_contents
print(
latest_contents,
file=witness_output.open(mode="w", encoding="UTF-8"),
)
logger.info(
log_prefix + "Contenus récents ajoutés à la configuration globale du site."
log_prefix + "Contenus récents ajoutés à la configuration globale du site. "
f"Également écrits dans le fichier témoin : {witness_output.resolve()}"
)
12 changes: 11 additions & 1 deletion hooks/mkdocs/G005_jinja_filters.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
# standard library
import datetime
import logging

# 3rd party
import mkdocs.plugins
from babel.dates import format_date
from geotribu_cli.utils.slugger import sluggy
from jinja2 import Environment
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.structure.files import Files

# globals
logger = logging.getLogger("mkdocs")
log_prefix = f"[{__name__}] "


def date_localized(in_date: datetime.date):
"Localize a date using babel."
return format_date(date=in_date, format="long", locale="fr_FR")


@mkdocs.plugins.event_priority(-50)
Expand All @@ -29,10 +37,12 @@ def on_env(env: Environment, config: MkDocsConfig, files: Files) -> Environment:
Returns:
Environment: global Jinja Environment
"""
env.filters["date_localized"] = date_localized
env.filters["slugger"] = sluggy

logger.info(
"Jinja2 filters added for templates: slugger (handy filter to slugify a string)"
log_prefix
+ "Jinja2 filters added for templates: slugger (handy filter to slugify a string)"
)

return env
6 changes: 4 additions & 2 deletions hooks/mkdocs/G006_authors_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@


logger = logging.getLogger("mkdocs")

log_prefix = f"[{__name__}] "
dico_contributors = {}
exclude_files = [
"confidentialite.md",
Expand Down Expand Up @@ -64,12 +64,14 @@ def on_page_markdown(
):
if (
"articles" in page.file.abs_src_path
and "index" not in page.file.name
and "templates" not in page.file.abs_src_path
):
page_authors = page.meta.get("authors")
if not isinstance(page_authors, list):
logger.warning(
f"L'entrée 'authors' de l'en-tête de la page '{page.file.abs_src_path}' est incorrecte."
log_prefix
+ f"L'entrée 'authors' de l'en-tête de la page '{page.file.abs_src_path}' est incorrecte."
)
return

Expand Down
117 changes: 117 additions & 0 deletions scripts/mkdocs_populate_latest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#! python3 # noqa: E265

"""Script permettant de lister les derniers contenus avec leurs propriétés
dans un fichier YAML. Utilisé pour la page d'accueil et les pages
d'index des derniers contenus publiés.
"""

# ############################################################################
# ########## Libraries #############
# ##################################

# standard library
import locale
import logging
from datetime import datetime
from pathlib import Path
from typing import Literal
from zoneinfo import ZoneInfo

# 3rd party
import yaml
from mkdocs.structure.pages import Page
from mkdocs.utils.meta import get_data

# ###########################################################################
# ########## Global ################
# ##################################

# journalisation
logger = logging.getLogger("mkdocs")

# gestion des dates
config_tz = ZoneInfo("Europe/Paris")
locale.setlocale(locale.LC_TIME, "fr_FR.UTF-8")

# ###########################################################################
# ########## Functions #############
# ##################################


def format_datetime(in_datetime_string: str, out_format: str = "long") -> str:
"""Formatte un datetime au format textuel standard (isocalendar) en version textuelle.
Proche du fonctionnement de 'babel.format_date'.

:param str in_datetime_string: chaîne de caractères en entrée. Doit être au format ISO.
:param str out_format: format de sortie, defaults to "long"

:return str: chaîne de caractères formatée
"""
dt = datetime.fromisoformat(in_datetime_string).replace(tzinfo=config_tz)
if out_format == "long":
return dt.strftime("%A %d %B %Y")


def get_latest_content(
content_type: Literal["articles", "rdp"], count: int = 10
) -> list[dict]:
"""Liste les X (défini par 'count') derniers contenus d'un certain type
en retournant les métadonnées de chaque contenu, ainsi que quelques
attributs personnalisés.

:param Literal[&quot;articles&quot;, &quot;rdp&quot;] content_type: type de contenu à lister
:param int count: nombre de contenus à lister, defaults to 10

:return list[dict]: liste des contenus avec leurs attributs
"""
output_contents_list: list[Page] = []

if content_type == "articles":
glob_pattern = "202*/202*.md"
elif content_type == "rdp":
glob_pattern = "202*/rdp_202*.md"

for content in sorted(
Path(f"content/{content_type}/").glob(glob_pattern), reverse=True
)[:count]:
with content.open(encoding="utf-8-sig", errors="strict") as f:
source = f.read()
# markdown, meta = get_data(source)

# ajout attributs personnalisés
output_contents_list.append(
# ajout URL relative
get_data(source)[1]
| {"url_rel": str(content.relative_to("content/"))[:-3]}
# ajoute la date au format textuel
| {
"date_txt_full": format_datetime(
in_datetime_string=get_data(source)[1].get("date"),
out_format="long",
)
}
)

return output_contents_list


# ###########################################################################
# ########## Main ##################
# ##################################

output_dict = {"latest": {"articles": [], "rdp": []}}
# print(get_latest_content(content_type="articles"))
for k in output_dict.get("latest"):
output_dict["latest"][k] = get_latest_content(content_type=k)

# écrit le fichier final
with Path("config/extra_latest.yml").open("w", encoding="UTF-8") as out_file:
yaml.safe_dump(
output_dict,
out_file,
allow_unicode=True,
default_flow_style=False,
encoding="UTF8",
# indent=4,
sort_keys=True,
)
Loading