Ao tentar implementar [1] em sua Single Page Application (SPA) que não fornece páginas renderizadas no lado do servidor, você eventualmente encontrará problemas, veja: [2]
Portanto, após um pouco de experimentação, gostaria de apresentar a seguinte abordagem. O exemplo está em Vue.js, no entanto, pode ser facilmente adaptado para outros frameworks/libs.
Observação: Usarei o termo posts de blog onde uma seção de comentários do Discourse deve ser incorporada. Mas, claro, isso também pode significar páginas individuais em seu site.
1. Os problemas em [1]
1.1. javascripts/embed.js não pode funcionar com conteúdo renderizado no lado do cliente
O snippet <script>...</script> que é informado em [1] para inserir em seu HTML, portanto, não fará parte da implementação que estamos abordando aqui. Utilizaremos alguns trechos de javascripts/embed.js fornecidos por sua instância do Discourse como funções dentro de nossa SPA.
1.2. O Discourse não pode raspar conteúdo renderizado no lado do cliente
O Discourse cria automaticamente tópicos para cada post de blog e tenta acessar a URL original (de um post de blog) para determinar o título e o conteúdo. Isso falha com uma SPA, porque o Discourse obterá a parte sem JavaScript, por exemplo, Lamentamos, mas este site não funciona corretamente sem JavaScript ativado. Por favor, ative-o para continuar.
Utilizaremos o plugin RSS Polling para fornecer os dados necessários e criar os tópicos para nós.
2. A implementação
2.1 RSS Polling e o feed RSS/Atom
Crie um endpoint em seu site que forneça um feed RSS ou Atom para o plugin RSS Polling. Este endpoint pode ser apenas um arquivo estático formatado em XML ou uma função do lado do servidor fornecendo o conteúdo formatado em XML, exemplo:
URL: https://meusite.com/blog.atom
Conteúdo:
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Posts do Blog do Meu Site</title>
<link href="https://meusite.com/blog/"/>
<updated>2022-07-03T09:02:48.721Z</updated>
<id>urn:uuid:790c1857-b968-49cc-9fbd-bf7afe3552c2</id>
<entry>
<title>Um Artigo sobre Tecnologia</title>
<author>
<name>Seu Nome Aqui</name>
</author>
<link href="https://meusite.com/blog/um-artigo-sobre-tecnologia"/>
<id>urn:uuid:f6cc13e4-d2eb-4385-af28-c867a94f48dc</id>
<published>2022-07-03T00:00:00Z</published>
<updated>2022-07-03T00:00:00Z</updated>
<summary>Vamos discutir um pouco de tecnologia neste artigo.</summary>
</entry>
</feed>
Instale o plugin RSS Polling para Discourse conforme [3] (Discourse hospedado) ou [4] (auto-hospedado)
Configurações Recomendadas para RSS Polling em Admin → Configurações → Plugins:
| Chave | Valor |
|---|---|
| rss polling enabled | true |
| rss polling frequency | 10 (ou seja, 10 minutos) |
Adicione um novo feed na configuração do plugin RSS Polling em Admin → Plugins → RSS Polling
Configure-o conforme [3]:
| Chave | Valor |
|---|---|
| URL | https://meusite.com/blog.atom |
| Filtro de Categoria | <isso é opcional> |
| Autor | <defina um autor dos tópicos gerados automaticamente> |
| Categoria | <defina a(s) categoria(s) onde os tópicos gerados automaticamente serão postados> |
| Tags | <isso é opcional> |
2.2 Configuração do Roteador SPA
O Discourse usa a última parte do caminho da URL como identificador para um post de blog individual.
Exemplos:
https://meusite.com/blog/um-artigo-sobre-tecnologia
https://meusite.com/blog/outro-artigo-sobre-gatos
Configure seu roteador SPA de acordo, para que posts de blog individuais correspondam a URLs individuais.
Além disso: o Discourse fornecerá um link de volta para o post de blog individual, portanto, é uma boa experiência do usuário que, ao clicar, seu site exiba o artigo real.
2.3 O Componente Artigo
Como dito antes, não podemos usar a abordagem com o <script></script> de [1]. Então implementamos o iframe e algumas funções de javascripts/embed.js em nosso componente:
Article.vue
Coisas que você deve editar:
| item | descrição |
|---|---|
| #SEU-URL-DISCOURSE# | a URL de sua instância do Discourse, por exemplo, discourse.meusite.com) |
| #SEU-URL-SITE# | a URL de seu site, por exemplo, meusite.com possivelmente também %2Fblog%2F se o caminho dos posts do seu blog não for /blog/ |
<template>
<div id="article">
<!-- seu artigo formatado aqui -->
<iframe
v-if="slug"
v-bind:src="`https://#SEU-URL-DISCOURSE#/embed/comments?embed_url=https%3A%2F%2F#SEU-URL-SITE#%2Fblog%2F${slug}%2F`"
id="discourse-embed-frame"
width="100%"
v-bind:height="`${iframeHeight}px`"
frameborder="0"
scrolling="no"
referrerpolicy="no-referrer-when-downgrade"
/>
</div>
</template>
<script>
export default {
data: () => ({
slug: null, // o slug do post de blog, por exemplo, "um-artigo-sobre-tecnologia" enquanto a rota é "https://meusite.com/blog/um-artigo-sobre-tecnologia"
iframeHeight: 0 // O Discourse nos dirá a altura exata do iframe (veja: método receiveMessage)
}),
methods: {
// comunicação iframe
receiveMessage(event) {
if (!event) {
return;
}
if (!(event.origin || "").includes("#SEU-URL-DISCOURSE#")) {
return;
}
if (event.data) {
if (event.data.type === "discourse-resize" && event.data.height) {
this.iframeHeight = +event.data.height;
}
if (event.data.type === "discourse-scroll" && event.data.top) {
// encontrar o offset do iframe
const destY = this.findPosY(this.$refs["discourse-embed-frame"]) + event.data.top;
window.scrollTo(0, destY);
}
}
},
// Obrigado http://amendsoft-javascript.blogspot.ca/2010/04/find-x-and-y-coordinate-of-html-control.html
findPosY(obj) {
var top = 0;
if (obj.offsetParent) {
while (1) {
top += obj.offsetTop;
if (!obj.offsetParent) break;
obj = obj.offsetParent;
}
} else if (obj.y) {
top += obj.y;
}
return top;
}
},
async created() {
this.slug = this.$router.currentRoute.path.split("/")[2];
},
mounted() {
window.addEventListener("message", this.receiveMessage);
},
beforeDestroy() {
window.removeEventListener("message", this.receiveMessage);
}
}
</script>
2.4 Configuração de Incorporação do Discourse
Agora, com o polling do feed RSS/Atom em vigor e a implementação em seu site, podemos finalmente configurar a incorporação na instância do Discourse.
Vá para Admin → Personalizar → Incorporação e adicione um host:
| Chave | Valor |
|---|---|
| Hosts Permitidos | URL base do seu site> por exemplo, “meusite.com” |
| Nome da Classe | nome de classe opcional para estilização |
| Listagem de Caminhos Permitidos | por exemplo, “/blog/.*” |
| Postar para Categoria | mesma categoria configurada em Categoria de RSS Polling |
3. Observações Finais
O polling do feed RSS/Atom, bem como o próprio Discourse, criará um novo tópico se ele não existir para o post de blog individual. Certifique-se de que o polling do feed RSS/Atom ocorra primeiro (ou seja, espere até que o tópico seja criado antes de visitar o post de blog em seu site).
Motivo: O Discourse não consegue raspar o título e o resumo, então o tópico seria meusite.com com o resumo sendo Lamentamos, mas este site não funciona sem JavaScript. ![]()
Se por algum motivo o Discourse vier primeiro, você pode simplesmente excluir o tópico e esperar até que o feed RSS/Atom entre em vigor.
Saudações
– MK2k