Je me demande si nous pouvons utiliser les filtres pour afficher une catégorie en utilisant la vue docs et A-Z (par ordre alphabétique).
Nous avons un glossaire qui devrait afficher la vue thématique ordonnée 
Actuellement, la vue des filtres est séparée des docs :
J’ai fini par utiliser un composant Theme personnalisé pour cela :
// A-Z nécessite l'intégralité de la catégorie : le cœur ne peut pas trier une liste de sujets par titre
// (TopicQuery::SORTABLE_MAPPING n'a pas de "title"), donc nous épuisons la liste paginée
// avant le tri. Limité — les catégories de documentation sont petites ; tout ce qui est plus grand retombe sur
// le tri de ce qui est chargé, ce que le MutationObserver ci-dessous maintient à jour.
// ponytail : supprimez cette boucle entière si le cœur fournit un jour un tri par titre côté serveur.
const MAX_DOC_PAGES = 12; // ~360 sujets à 30 par page
let docLoadRun = 0;
async function loadAllDocTopics(api) {
const run = ++docLoadRun;
// `controller:discovery/topics` est obsolète dans les versions actuelles de Discourse
// (id d'obsolescence : discourse.discovery-topics-controller). La découverte utilise désormais un
// contrôleur dédié par filtre ; les catégories de documentation sont toujours la liste des sujets les plus récents,
// donc nous cherchons ce contrôleur directement. Échouer ici signifie simplement que nous trions
// la première page, donc chaque étape est chaînée en option.
const list = api.container.lookup("controller:discovery/latest")?.model;
if (!list?.loadMore) {
return;
}
for (let page = 0; page < MAX_DOC_PAGES; page++) {
if (!list.more_topics_url) {
return;
}
const before = list.topics?.length ?? 0;
await list.loadMore();
// Navigation partielle pendant le chargement, ou la liste a cessé de croître — dans les deux cas, arrêter.
if (run !== docLoadRun || (list.topics?.length ?? 0) === before) {
return;
}
}
}
// Trie la liste des sujets de la documentation de A à Z, en utilisant la collation de la langue de la page <html lang>.
let docSortObservers = new Map();
function docSortLocale() {
const lang = document.documentElement.lang;
if (!lang) {
return undefined;
}
try {
Intl.getCanonicalLocales(lang); // lève une RangeError pour une étiquette malformée
return lang;
} catch {
return undefined; // retombe sur le fuseau horaire par défaut du navigateur
}
}
function sortDocTopicList(body, locale) {
const rows = [...body.querySelectorAll(":scope > .topic-list-item")];
if (rows.length < 2) {
return;
}
const sorted = [...rows].sort((a, b) => {
const titleA = a.querySelector(".title")?.textContent.trim() ?? "";
const titleB = b.querySelector(".title")?.textContent.trim() ?? "";
return titleA.localeCompare(titleB, locale);
});
if (sorted.every((row, i) => rows[i] === row)) {
return; // déjà trié — empêche l'observateur de se nourrir de lui-même
}
// Insérer avant ce qui suit les lignes, en gardant tout sentinel de chargement supplémentaire à la fin.
const anchor = rows[rows.length - 1].nextSibling;
// Épingler la première ligne visible pour que les insertions au-dessus ne fassent pas sauter le défilement.
const pinned = rows.find((row) => row.getBoundingClientRect().bottom > 0);
const pinnedTop = pinned?.getBoundingClientRect().top;
// Observateur en pause pour que nos propres déplacements ne réentrent pas dans cette fonction.
const observer = docSortObservers.get(body);
observer?.disconnect();
sorted.forEach((row) => body.insertBefore(row, anchor));
observer?.observe(body, { childList: true });
if (pinned) {
window.scrollBy(0, pinned.getBoundingClientRect().top - pinnedTop);
}
}
function sortDocCategoryTopicLists() {
docSortObservers.forEach((observer) => observer.disconnect());
docSortObservers = new Map();
const locale = docSortLocale();
// Ce n'est pas un conteneur flex/grid, donc le réordonnancement doit déplacer les nœuds DOM — l'ordre CSS est ignoré.
document.querySelectorAll(".topic-list.doc-simple-mode .topic-list-body").forEach((body) => {
// try/finally pour que la liste soit toujours révélée même si le tri lève une exception.
try {
sortDocTopicList(body, locale);
} finally {
body.classList.add("docs-sorted");
}
// Trier une seule fois lorsque le chargement se calme — le réordonnancement en cours de chargement bloquait le chargeur.
let settleTimer = null;
const observer = new MutationObserver(() => {
window.clearTimeout(settleTimer);
settleTimer = window.setTimeout(() => {
sortDocTopicList(body, locale);
}, 400);
});
observer.observe(body, { childList: true });
docSortObservers.set(body, observer);
});
}
Je pense que le code peut très probablement être amélioré, j’accepte volontiers les suggestions et/ou les PR.