J'ai créé un bookmarklet pour créer la table des matières des posts de forum

Table des matières :

J’ai créé un bookmarklet pour générer une table des matières (ToC) repliable comme celle montrée ci-dessus.

J’espère que cela aidera les membres assidus qui rédigent de longs textes !

Résumé

J’écris parfois de longs sujets/messages et j’avais besoin d’une ToC pour faciliter la lecture.
J’ai trouvé des travaux existants, tels que DiscoTOC - automatic table of contents, mais j’avais besoin d’un outil juste pour moi, sans avoir à installer quelque chose dans toute la communauté.

Après avoir publié un message structuré, cliquez sur le bookmarklet et la ToC sera copiée dans votre presse-papiers. Modifiez le message et collez la ToC en haut !

Comment utiliser

Installation

  1. Enregistrez une page en tant que favori.
  2. Modifiez le nom, par exemple “:clipboard: Copier la ToC du forum dans le presse-papiers.”
  3. Modifiez l’URL et collez le code suivant. Personnalisez le code si nécessaire - voir les deux éléments “Optionnel” ci-dessous.
javascript:(function() {
	const copyForumTocToClipboard = function() {
		const urlMatch = window.location.href.match(/\/t\/[^\/]*\/\d+\/?(\d*)/);
		if (!urlMatch) return;

		const postIndex = urlMatch ? urlMatch[1] : 1;
		const anchors = document.querySelectorAll('#post_' + postIndex + ' div.cooked h6 a.anchor,h5 a.anchor,h4 a.anchor,h3 a.anchor,h2 a.anchor,h1 a.anchor');
		if (!anchors) return;

		let toc = '';
		anchors.forEach(anchor => {
			toc +=
				' '.repeat((anchor.parentNode.nodeName[1] - 1) * 4) +
				`<a href="${anchor.href}">${anchor.parentNode.textContent}</a><br>\n`;
		});
		if (!toc) return;

		navigator.clipboard.writeText('<details open><summary>Table of contents: </summary><ul>\n' + toc + '</ul></details>');
	};

	copyForumTocToClipboard();
})();

Ce que fait le code

  1. Vérifie si l’URL ressemble à un message de communauté : https://{domaine}/t/{titre}/{id_sujet}(/{index_message}).
  2. Vérifie si des ancres :link: (titres tels que <h1> et # ) sont incluses dans le message.
  3. Génère le code HTML pour la ToC.
  4. Copie le code dans le presse-papiers.

Génération de la ToC

  1. Publiez un message avec une structure (HTML <h1>, <h2>, … et Markdown # , ## , …). Discourse attribuera des ancres à chaque titre.
  2. Assurez-vous que votre message est sélectionné en regardant la barre de progression (par exemple, 1/22) ou l’URL (par exemple, /1).
  3. Cliquez sur le bookmarklet dans la barre des favoris.
  4. La ToC est copiée dans votre presse-papiers.

Utilisation de la ToC

  1. Cliquez sur l’icône crayon pour modifier le message.
  2. Collez le code en haut.
  3. Vérifiez si les éléments de la ToC sont correctement affichés (Problème connu : le bookmarklet manque certains emojis).
  4. (Optionnel) Modifiez/traduisez “Table of contents”.
  5. (Optionnel) Supprimez open si vous souhaitez que la ToC soit repliée par défaut.
  6. Cliquez sur “Save Edit”. Si vous le faites quelques minutes après la publication du message, l’icône de crayon “edited” ne sera pas ajoutée à votre message.

Notes techniques pour les techniciens

  • Vous pouvez également copier et coller le code JavaScript dans la console du développeur.
    • J’ai encapsulé le code dans une fonction car return; ne fonctionne pas lorsqu’il est utilisé en dehors des fonctions.
  • L’approche '\u0026nbsp;'.repeat() semble désordonnée lors de la prévisualisation du sujet, mais elle est la plus belle dans le message réel (comparée à l’utilisation de <li></li>) à mon avis.
  • Lorsque j’ai testé querySelectorAll, le premier élément de h6 a.anchor,h5 a.anchor, ... n’a pas été trouvé. J’ai mis h6 au début car c’est probablement le moins utilisé.
  • Le bookmarklet pourrait cesser de fonctionner si Discourse modifie son interface utilisateur/DOM. Merci de me répondre si vous trouvez des erreurs.

Captures d’écran

En tant que nouvel utilisateur sur meta.discourse.org, je ne peux pas ajouter plusieurs images, j’ai donc regroupé toutes les captures d’écran en une seule image :

18 « J'aime »

Ohh sympa - cela pourrait-il être étendu pour créer une table des matières pour l’intégralité du message avec toutes les réponses ?

3 « J'aime »

Les publications se chargent généralement par lots d’environ 20. Je suppose qu’il serait difficile de créer une table des matières de toutes les publications en une seule fois.

4 « J'aime »

Très cool ! Merci de partager @ShunS !

J’adore la façon dont vous avez formulé le problème que vous résolvez avec cet outil, et comment il est conçu pour répondre aux besoins des utilisateurs importants sur les sites qui, eux-mêmes, n’ont peut-être pas les autorisations nécessaires pour modifier les choses sur le site tel qu’il existe aujourd’hui.

10 « J'aime »

Merci pour vos réponses :slight_smile:

Comme le dit @Lhc_fl, l’approche DOM (HTML/JavaScript) est limitée en nombre d’éléments que nous pouvons gérer. L’API Discourse pourrait aider pour de telles actions.
Un autre problème avec la création d’une table des matières pour les réponses est qu’il n’est pas facile de définir quel serait le titre de chaque réponse. Nous pourrions utiliser des informations comme l’auteur et la date, mais je ne suis pas sûr que ce soit plus utile que la barre de progression existante.

Merci @mcwumbly !

6 « J'aime »

@ShunS c’est très cool, merci de partager. Bienvenue aussi chez Meta :wave: :slight_smile:

5 « J'aime »

C’est fabuleux et exactement ce que je cherchais. Cela semble résoudre ce problème

Pourquoi ne pas soumettre cela à Discourse pour l’inclure en tant que plugin ou fonctionnalité officielle ? Il pourrait être inclus dans la barre d’outils du compositeur/éditeur pour insérer automatiquement une table des matières dans le message.

6 « J'aime »

J’ai une suggestion : est-il possible d’ajouter une puce au début de la ligne de la table des matières ? Dans mon cas, chaque titre est une longue ligne, donc la puce aide à différencier une entrée de la suivante.

1 « J'aime »

Salut @RBoy, merci pour vos commentaires et votre suggestion !

Un plugin d’éditeur serait formidable, mais cela demanderait beaucoup d’efforts pour lire le code source de Discourse afin de comprendre la logique de gestion des emojis et de définition du texte/ancre de l’en-tête, et de créer un dépôt pour le plugin.

Un plugin (apparemment) simple comme Spoiler Alert est un gros dépôt et je n’ai pas la bande passante pour m’engager pleinement dans le développement. J’espère donc que Discourse pourra prioriser les demandes de fonctionnalités comme Automatic Table of Contents generation et développer une fonctionnalité native en attendant :folded_hands:


Ci-dessous se trouve la version avec les puces. Les espaces entre <ul> et </ul> sont plutôt trop grands, j’ai donc préféré la version originale sans puces.

Capture d’écran :

Code :

javascript:(function() {
	const copyForumTocToClipboard = function() {
		const urlMatch = window.location.href.match(/\/t\/[^\/]*\/\d+\/?(\d*)/);
		if (!urlMatch) return;

		const postIndex = 1;
		const anchors = document.querySelectorAll('#post_' + postIndex + ' div.cooked h6 a.anchor,h5 a.anchor,h4 a.anchor,h3 a.anchor,h2 a.anchor,h1 a.anchor');

		let toc = '';
		let currentLevel = 1;
		anchors.forEach(anchor => {
			newLevel = anchor.parentNode.nodeName[1];
			levelChange = newLevel - currentLevel;
			toc +=
				((levelChange >= 0) ? '<ul>'.repeat(levelChange) : '</ul>'.repeat(levelChange * -1)) +
				`<li><a href="${anchor.href}">${anchor.parentNode.textContent}</a></li>`;
			currentLevel = newLevel;
		});
		if (newLevel > 1) toc += '</ul>'.repeat(newLevel - 1);
		toc = '<details open><summary>Table of contents: </summary><ul>\n' + toc + '</ul></details>';

		navigator.clipboard.writeText(toc);
	};

	copyForumTocToClipboard();
})();
5 « J'aime »

Nous avons déjà un plugin ToC et il n’a pas besoin de maintenir la ToC dans le corps du message.

Je le recommanderais sans hésiter s’il est installé car il ne peut pas se désynchroniser.

Cet outil semble génial lorsque DiscoToC n’est pas disponible. Beau travail ! :+1:

4 « J'aime »

Cela peut être fait à l’aide d’un composant de thème. Vous pouvez examiner la méthode decorateCookedElement de l’api, elle devrait être utile.

4 « J'aime »

Salut @supermathie, merci pour ta réponse.

quand DiscoToC n’est pas disponible

Oui, c’est la différenciation. J’ai créé le bookmarklet car je ne suis pas en mesure de décider quel « composant de thème » installer sur le forum auquel je participe habituellement, et seules quelques personnes écrivent de longs textes qui nécessitent une table des matières.


Merci @Lhc_fl, c’est très utile !

J’ai cherché dans le dépôt GitHub et j’ai trouvé cette méthode. J’envisagerai de la développer (uniquement) lorsque j’aurai une bonne bande passante et que je verrai une forte demande pour cette fonctionnalité.

Cependant, si un composant de thème peut être ajouté à la communauté, il existe déjà DiscoTOC comme l’a dit @supermathie :slight_smile:

4 « J'aime »

Malheureusement, ce plug-in est totalement inutilisable lorsque l’en-tête comporte plus de quelques mots, car il met complètement le désordre. Si les en-têtes font une ou deux lignes (par exemple, une page FAQ), le plug-in Disco TOC met complètement le désordre sur la page, c’est pourquoi j’ai soulevé cette demande pour une table des matières en ligne (que celle-ci fournit) et qui est parfaite pour de telles pages

Avec la quantité de génie/talent parmi les équipes qui construisent Discourse, il ne devrait pas être si difficile d’inclure cette fonctionnalité incroyable comme alternative à DiscoTOC pour lui donner une gamme d’utilisation beaucoup plus large.