Criei um bookmarklet para criar o índice dos posts do fórum

Índice:

Criei um bookmarklet para gerar um índice (ToC) dobrável como o mostrado acima.

Espero que ajude os membros ávidos da comunidade que escrevem textos longos!

Resumo

Às vezes escrevo tópicos/posts longos e precisava de um ToC para facilitar a leitura.
Encontrei alguns trabalhos existentes, como DiscoTOC - automatic table of contents, mas precisava de uma ferramenta apenas para mim, sem precisar instalar algo em toda a comunidade.

Após publicar um post estruturado, clique no bookmarklet e o ToC será copiado para sua área de transferência. Edite o post e cole o ToC no topo!

Como usar

Instalação

  1. Salve uma página como um favorito.
  2. Edite o nome, como “:clipboard: Copiar ToC do fórum para a área de transferência.”
  3. Edite o URL e cole o seguinte código. Personalize o código se necessário - veja dois itens “Opcional” abaixo.
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();
})();

O que o código faz

  1. Verifica se o URL parece ser um post da comunidade: https://{domínio}/t/{título}/{ID_do_tópico}(/{ID_do_post}).
  2. Verifica se âncoras :link: (cabeçalhos como <h1> e # ) estão incluídas no post.
  3. Gera código HTML para o ToC.
  4. Copia o código para a área de transferência.

Gerando ToC

  1. Publique um post com estrutura (HTML <h1>, <h2>, … e Markdown # , ## , …). O Discourse atribuirá âncoras a cada cabeçalho.
  2. Certifique-se de que seu post esteja selecionado, olhando a barra de progresso (por exemplo, 1/22) ou o URL (por exemplo, /1).
  3. Clique no bookmarklet na barra de favoritos.
  4. O ToC é copiado para sua área de transferência.

Usando ToC

  1. Clique no ícone de lápis para editar o post.
  2. Cole o código no topo.
  3. Verifique se os itens do ToC estão sendo exibidos corretamente (Problema conhecido: o bookmarklet perde alguns emojis).
  4. (Opcional) Altere/traduza “Table of contents”.
  5. (Opcional) Exclua open se quiser recolher o ToC por padrão.
  6. Clique em “Salvar Edição”. Se você fizer isso alguns minutos após publicar o post, o ícone de lápis “editado” não será adicionado ao seu post.

Notas técnicas para pessoas técnicas

  • Você também pode copiar e colar o código JavaScript no console do desenvolvedor.
    • Eu envolvi o código em uma função porque return; não funciona quando usado fora de funções.
  • A abordagem '\u0026nbsp;'.repeat() parece confusa ao visualizar o tópico, mas parece melhor no post real (em comparação com o uso de <li></li>) na minha opinião.
  • Quando testei querySelectorAll, de alguma forma o primeiro item em h6 a.anchor,h5 a.anchor, ... não foi encontrado. Coloquei h6 no início porque é provavelmente o menos usado.
  • O bookmarklet pode parar de funcionar se o Discourse mudar sua interface/DOM. Por favor, responda-me se encontrar erros.

Capturas de tela

Como um novo usuário em meta.discourse.org, não posso adicionar várias imagens, então estou agrupando todas as capturas de tela em uma única imagem:

18 curtidas

Ohh legal - isso poderia ser estendido para criar um sumário para o post inteiro com todas as respostas?

3 curtidas

As postagens geralmente carregam cerca de 20 por vez, acho que seria difícil criar um índice de todas as postagens de uma vez.

4 curtidas

Muito legal! Obrigado por compartilhar @ShunS!

Adoro como você apresentou o problema que está resolvendo com esta ferramenta e como ela foi projetada para atender às necessidades de usuários importantes em sites que, por si só, podem não ter permissão para alterar as coisas no site como existem hoje.

10 curtidas

Obrigado pelas respostas :slight_smile:

Como @Lhc_fl diz, a abordagem DOM (HTML/JavaScript) tem um número limitado de itens que podemos gerenciar. A API do Discourse pode ajudar para tais ações.
Outro problema com a criação de um TOC para respostas é que não é fácil definir qual seria o título do cabeçalho para cada resposta. Poderíamos usar informações como o autor e a data, mas não tenho certeza de como isso seria mais útil do que a barra de progresso de rolagem existente.

Obrigado @mcwumbly!

6 curtidas

@ShunS isso é muito legal, obrigado por compartilhar. E seja bem-vindo à Meta :wave: :slight_smile:

5 curtidas

Isso é fabuloso e exatamente o que eu estava procurando. Parece resolver este problema

Por que não enviar isso para o Discourse para incluí-lo como um plugin ou recurso oficial? Poderia ser incluído na barra de ferramentas do composer/editor para inserir automaticamente um TOC na postagem.

6 curtidas

Tenho uma sugestão: é possível adicionar um marcador no início da linha do TOC? No meu caso, cada título é uma linha longa, então o marcador ajuda a diferenciar uma entrada da outra.

1 curtida

Olá @RBoy, obrigado pelo feedback e pela sugestão!

Um plugin de editor seria ótimo, mas daria muito trabalho ler o código-fonte do Discourse para entender a lógica de manipulação de emojis e definição do texto/âncora do cabeçalho e criar um repositório do plugin.

Um plugin (aparentemente) simples como o Spoiler Alert é um repositório grande e eu não tenho largura de banda para me comprometer totalmente com o desenvolvimento. Portanto, espero que o Discourse priorize solicitações de recursos como Automatic Table of Contents generation e desenvolva um recurso nativo nesse ínterim :folded_hands:


Abaixo está a versão com os marcadores. Os espaços entre <ul> e </ul> são um tanto grandes, então preferi a versão original sem marcadores.

Captura de tela:

Código:

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 curtidas

Já temos um plugin ToC e ele não precisa manter o ToC no corpo da postagem.

Eu definitivamente recomendaria este se instalado, pois não pode sair de sincronia.

Esta ferramenta parece ótima para quando o DiscoToC não está disponível. Bom trabalho! :+1:

4 curtidas

Isso pode ser feito usando um componente de tema. Você pode dar uma olhada no método decorateCookedElement da api, ele deve ser útil.

4 curtidas

HI @supermathie, obrigado pela resposta.

quando o DiscoToC não está disponível

Sim, essa é a diferenciação. Criei o bookmarklet porque não estou em posição de decidir qual “componente de tema” instalar no fórum em que costumo participar, e apenas algumas pessoas escrevem textos longos que precisam de um TOC.


Obrigado @Lhc_fl, isso é muito útil!

Pesquisei no repositório do GitHub e encontrei esse método. Vou considerar desenvolvê-lo (apenas) quando tiver boa disponibilidade e vir muita demanda pelo recurso.

No entanto, se um componente de tema puder ser adicionado à comunidade, já existe o DiscoTOC, como disse @supermathie :slight_smile:

4 curtidas

Infelizmente, esse plug-in é totalmente inutilizável quando o título tem mais do que algumas palavras, pois ele faz uma bagunça completa das coisas. Se os títulos tiverem uma ou duas linhas de comprimento (por exemplo, uma página de FAQ), o plug-in Disco TOC faz uma bagunça completa da página, e é por isso que levantei esta solicitação para um TOC inline (que este fornece) e é perfeito para tais páginas

Com a quantidade de genialidade/talento entre as equipes que constroem o Discourse, não deveria ser tão difícil incluir este recurso incrível como uma alternativa ao DiscoTOC para dar a ele uma gama muito mais ampla de uso.