Topic embedding richiede attenzione

Mi è stato ricordato oggi dopo aver cliccato sul pulsante “Mostra post completo” per Introducing Discourse AI. Il post completo visualizzato su Discourse non contiene immagini e molte intestazioni. Ad aggiungere confusione, le didascalie delle immagini vengono visualizzate, ma senza le immagini associate.

Potrebbe essere possibile risolvere il problema su Meta per il suo blog (Ghost?) regolando l’impostazione del sito allowed embed selectors di Meta: Configuring allowed embed selectors. Per esperienza passata, so che ottenere questa impostazione può essere un processo complicato. Se provi a regolarla, presta molta attenzione ai risultati.

Discourse ha un grande potenziale per funzionare come sistema di commenti per post esterni, ma per fare un buon lavoro, cliccare sul pulsante “Mostra post completo” deve recuperare in modo affidabile tutti gli elementi del post esterno. Penso che il problema sia che la gemma Ruby Readability utilizzata per l’analisi dei post esterni non sia destinata al lavoro per cui Discourse la sta utilizzando. Inoltre, non è attivamente mantenuta: GitHub - cantino/ruby-readability: Port of arc90's readability project to Ruby.

3 Mi Piace

Sì, a questo punto o passiamo a qualcos’altro che lo renda leggermente migliore o cambiamo la strategia di embedding rendendo il Show Full Post in un Read Full Post che è un semplice link al post originale. Potrebbe essere inutile combattere con tutti i possibili problemi di embedding in ogni sito web, dopotutto.

4 Mi Piace

@sam ho appena corretto questo, dai un’occhiata.

3 Mi Piace

Ci stiamo preparando a pubblicare il nostro blog su Ghost e a utilizzare le integrazioni Ghost > Discourse. Sono davvero felice di vedere questo cambiamento!

4 Mi Piace

Le immagini vengono ora caricate. Non sono bravo nei puzzle di tipo “trova le differenze”, ma vedo ancora alcune differenze:

  • Manca il titolo Semantic Related Topics
  • Manca il titolo Community Sentiment
  • Manca un elenco puntato nella sezione Modules Providers
  • Manca il titolo Installing Discourse AI on your community

Idealmente, il prompt “Sign up for our newsletter” dovrebbe essere escluso dal post incorporato.

Avere la possibilità di citare facilmente il post incorporato sembra importante. Pensandoci ora, non sono sicuro quale sia il comportamento previsto quando si fa clic sui pulsanti “espandi/collassa” e “vai al post” per le citazioni di un post incorporato.

È un problema complicato. Dovrebbe essere semplice come sanificare l’HTML contenuto nell’elemento article o main di un post, ma sospetto che ci sarebbero ancora problemi con quell’approccio. Ad esempio, richiederebbe una gestione speciale per evitare la duplicazione dell’elemento h1 di un post del blog se l’elemento header si trova all’interno dell’elemento article.

1 Mi Piace

Penso che tutto ciò stia accadendo anche in readability.js, questa è la vista lettore di Firefox:

<h2 id="installing-discourse-ai-on-your-community">
      <strong>Installing Discourse AI on your community</strong>
    </h2>

Vedrò se c’è un modo semplice per risolvere questo problema…

Non sono sicuro di questo… ma se vogliamo davvero farlo, possiamo aggiungere .discourse-newsletter-signup a blocked_embed_selectors

4 Mi Piace

Sì, readablity.js si basa sullo stesso codice di GitHub - cantino/ruby-readability: Port of arc90's readability project to Ruby, quindi probabilmente viene utilizzata la stessa logica per rimuovere quegli elementi. readablity.js generalmente fa un lavoro migliore di Ruby Readability.

Il CTA dell’email è confuso perché l’input dell’email viene rimosso dal post incorporato. Tecnicamente, non sono sicuro che il CTA appartenga all’interno dell’article.

1 Mi Piace

Sto solo riproponendo questo, dato che concordo con @simon sul fatto che questo dovrebbe essere ripensato a un certo punto.

Una buona parte delle richieste di supporto per il plugin WP Discourse riguarda in realtà problemi di crawling di leggibilità di qualche tipo.

Penso che questo riassuma il mio istinto su questo.

Detto questo, al momento non ho una soluzione ottimale oltre a questa.

Ma sono desideroso di contribuire a una soluzione migliore dello status quo, poiché ridurrebbe il carico di lavoro di supporto di WP Discourse.

1 Mi Piace

Esaminano i problemi, ma sono lenti a risolverli…

Configurare MiniRacer per includere la leggibilità non è troppo difficile… Ho fatto un prototipo.

È possibile che si possa passare a questa implementazione, ma ci siamo già discostati, quindi finiremmo per rinunciare a delle funzionalità.

Questo non è un problema facile da risolvere.

2 Mi Piace

Sì, giusto, tuttavia ritengo che sarà un gioco infinito di acchiappa la talpa. Ci sarà sempre una versione di:

Il post sul mio sito web appare come X e quando clicco su “Mostra post completo” appare come Y e voglio che siano identici.

Suppongo che la mia domanda più profonda sia se ci sia un reale beneficio per questa funzionalità, che non sarà mai perfetta, rispetto a

Rendendolo un pulsante “Mostra post completo”, le persone si aspettano una fedeltà che Discourse non potrà mai offrire completamente. La mia preoccupazione riguarda più la gestione delle aspettative.

Suppongo che tu stia chiedendo la rimozione della funzionalità di embedding. Non sono sicuro di essere d’accordo. Penso che i siti che incorporano contenuti molto disordinati dovrebbero utilizzare questa semplice forma di “link all’originale”. Tuttavia, i siti che incorporano contenuti meglio strutturati possono utilizzare la modalità lettura, sebbene imperfetta.

1 Mi Piace

Non necessariamente. Sto dicendo che è necessaria una migliore gestione delle aspettative.

Il 99% delle persone che gestiscono un sito web non saprà se il proprio HTML è sufficientemente semantico per essere facilmente analizzato da una gemma come readability, o anche solo che questo è ciò che determina il funzionamento della funzionalità. L’assunzione predefinita degli utenti è che ci sia un problema “in Discourse” (o più spesso nel plugin WP Discourse) quando non c’è una fedeltà al 100% tra il post sul loro sito e il contenuto che appare quando l’utente fa clic su “Mostra post completo”.

Rendere un’opzione come avere una CTA “Leggi post completo” facile da abilitare, e forse predefinita, aiuterebbe, penso.

2 Mi Piace

Quello che intendevo con questo è che Ruby Readability è “uno strumento per estrarre il contenuto leggibile primario di una pagina web”. Per il caso di un sito che pubblica post su Discourse, penso che sia sicuro presumere che il contenuto leggibile primario della pagina web sia noto e possa essere definito da un selettore CSS esterno. Ad esempio, article, .entry-content, .post, ecc.

Il tipo di strumento che immagino consentirebbe semplicemente ai siti di definire un selettore esterno per il contenuto del loro post, quindi sanificare l’HTML contenuto in quel selettore. Una versione leggermente più sofisticata consentirebbe ai siti di definire selettori interni che desiderano escludere da Discourse.

Sul mio sito WordPress ho un post con markup completamente standard. Vorrei pubblicare tutto ciò che si trova nel div .entry-content su Discourse. Funziona quasi, ma non riesco a capire come configurare l’impostazione allowed embed selector su Discourse per recuperare gli elementi di elenco del post. Questo è il tipo di problema che ho visto i siti incontrare. Senza poter eseguire Rails.cache.clear, è davvero difficile da configurare.

La pubblicazione del post come onebox è una soluzione ragionevole per questo.

Modifica: l’opzione debug è utile per capire cosa sta succedendo: GitHub - cantino/ruby-readability: Port of arc90's readability project to Ruby. Nel caso degli elenchi esclusi nel mio post WordPress:

Conditionally cleaned ul#. with weight 0 and content score 0 because it has too many links for its weight (0).

È un elenco perfettamente legittimo, però.

Una funzionalità molto richiesta con gli embed espansi è consentire ai video di Youtube di apparire nel contenuto espanso. Impedire che ciò accada è codificato nella gemma: ruby-readability/lib/readability.rb at master · cantino/ruby-readability · GitHub. Non sono sicuro che valga la pena fare una PR per poter sovrascrivere quell’elenco con un’opzione.

2 Mi Piace

Non mi lascerò trasportare troppo, ma nel fine settimana stavo usando Nokogiri per qualcos’altro. È piuttosto avvincente. Ho pensato di dare un’occhiata al codice di embedding mentre Nokogiri era ancora fresco nella mia mente.

Il mio interesse in questo è che vorrei vedere Discourse utilizzato più ampiamente dai siti di notizie e di blogging. Se ciò dovesse accadere, posso immaginare che i nuovi proprietari di siti si frustrassero con l’attuale funzionalità di embedding. Ecco un’idea per migliorarla:

Aggiungere due nuovi attributi opzionali al modello EmbeddableHost:

  • target_selector: il selettore CSS esterno che contiene il contenuto da incorporare
  • exclude_selectors: un elenco di selettori CSS da escludere dal contenuto selezionato da target_selector.

Un pulsante “Configura” dovrebbe essere aggiunto a ogni riga di Embeddable Host nella pagina Admin / Embedding. Cliccando su quel pulsante si apre una pagina simile alla pagina Email / Riepilogo anteprima.

La pagina Configura Host avrebbe un modulo con campi per inserire le impostazioni target_selector ed exclude_selectors dell’host e un campo URL che consentirebbe di testare i valori forniti su una pagina Web specifica. Il test essenzialmente eseguirebbe TopicEmbed.parse_html con i valori target_selector ed exclude_selectors forniti, quindi visualizzerebbe i risultati.


Le modifiche al codice parse_html sono facili da testare. Ecco un possibile approccio. Nota che questo codice è solo una prova di concetto:

modificato in topic_embed.rb (discourse/app/models/topic_embed.rb at main · discourse/discourse · GitHub)

###########################################################################
    # `target_selector` e `exclude_selectors` dovrebbero idealmente essere trovati dal record `EmbeddableHost` del dominio
    # queste impostazioni particolari sono state utilizzate per testare contro boingboing.net
    target_selector = 'article'
    exclude_selectors = ['.article-header, .share-comments-container', '.boing-single-post-rev-content', '.next-post-list-container', '.boing-end-of-article-container-on-single-post-pages']

    if defined?(target_selector) && target_selector.present?
      read_doc = article_content(html, target_selector, exclude_selectors)
    else
      # fallback a Readability se `target_selector` non è impostato per l'host
      read_doc = Readability::Document.new(html, opts)
    end
    ###########################################################################

Per testare senza creare una nuova classe, ecco un metodo article_content di base aggiunto alla classe TopicEmbed:

  def self.article_content(html, target_selector, exclude_selectors = [])
    doc = Nokogiri::HTML(html)
    # rimuove commenti e tag script
    doc.xpath('//comment()').each { |i| i.remove }
    doc.css("script, style").each { |i| i.remove }

    # ottiene il NodeSet per il target_selector
    # forse fallback a Readability qui se il set restituito è vuoto
    selected_nodes = doc.css(target_selector)

    # esclude i nodi
    unless exclude_selectors.empty?
      selected_nodes.css(*exclude_selectors).each do |node|
        node.remove
      end
    end

    # gestisce le dimensioni delle immagini, potrebbe necessitare di miglioramenti
    selected_nodes.css('img').each do |img|
      img.remove_attribute('width')
      img.remove_attribute('height')
    end

    # solo per divertimento, consente gli iframe se la loro origine è consentita
    # usa `[data-sanitized="true"]` per evitare che gli iframe vengano rimossi nel passaggio remove_empty_nodes
    allowed_iframe_sources = SiteSetting.allowed_iframes.split('|')
    selected_nodes.css('iframe').each do |iframe|
      allowed = allowed_iframe_sources.any? do |allowed_source|
        iframe['src'].start_with?(allowed_source)
      end

      if allowed
        iframe['data-sanitized'] = 'true'
        iframe['width'] = '690'
        iframe['height'] = '388'
      else
        iframe.remove
      end
    end

    # rimuove nodi 'p' e 'div' vuoti
    selected_nodes.css('p', 'div').each do |node|
      node.remove if node.content.strip.empty? && !node.at_css('iframe[data-sanitized="true"]')
    end

    # converte i nodi in una stringa e restituisce un oggetto con un metodo `content`
    content = selected_nodes.to_s
    OpenStruct.new(content: content)
  end

Sono abbastanza sicuro che basterebbe un po’ di aggiustamenti su più domini per ottenere il risultato giusto. I risultati che ho ottenuto finora per BBS sono buoni.

L’obiettivo è creare qualcosa che i proprietari di siti possano facilmente capire e configurare da soli. Con questo approccio, più specifico è il target_selector, più facile sarà configurare gli exclude_selectors. Ad esempio, per un sito WordPress, se .entry-content fosse selezionato come target_selector, non sarebbe necessaria alcuna configurazione aggiuntiva. Se i proprietari di siti volessero ottenere più dell’HTML di base .entry-content, potrebbero capire come farlo nella pagina Configura Host.

L’unico vero problema che vedo è per gli host con HTML molto incoerente. Quel caso potrebbe essere gestito mantenendo Ruby Readability come fallback.