Corrigindo digest_custom_html para ser tratado como HTML (antes: Sobrepor digest.html.erb)

TL;DR:

Estou tentando adicionar algumas coisas ao resumo. Eu costumava substituir o template, mas não posso mais fazer isso, por razões não claras.

Como substituir templates é ruim, existem alguns lugares no resumo que são substituídos por digest_custom_html, mas ele insere o texto, então esses precisam ter .html_safe anexado. Pelo menos um está no lugar errado (tem “acima” no nome, mas na verdade está abaixo).

Acho que tenho as habilidades para um PR sobre isso, a menos que, por ser tão simples, seja mais fácil para outra pessoa fazer.

A história mais longa e dolorosa.

Eu fiz isso aqui: GitHub - pfaffman/discourse-add-to-summary: Add text to summary before and after title, mas isso parece ter parado de funcionar.

Acho que o que quero fazer, sem alterações no core, é substituir o template digest.html.erb. Eu costumava conseguir fazer isso colocando-o em app/views/user_notifications/digest.html.erb e esse arquivo seria processado em vez do do core. Isso não parece mais funcionar.

Agora, temos alguns digest_custom_html legais como este:

O leitor atento notará que os tópicos populares começam por volta da linha 78, muito antes da linha 277. Não tenho certeza de quanto tempo perdi pensando que nada estava acontecendo porque eu estava olhando no lugar errado. Mas divago.

Eu consegui fazer isso em plugin.rb after_initialize.

  require_dependency "user_notifications"
  module ::UserNotificationsHelperOverride
    def digest_custom_html(position_key)
      puts "fazendo melhoria no resumo: #{position_key}"
      if position_key == "below_popular_topics"
        puts "fazendo o html customizado para a posição abaixo dos tópicos populares"

        # HTML customizado para a posição dos tópicos populares
        "<div class='custom-popular-topics'>MEU TEXTO LEGAL</div>"
      else
        puts "fazendo o super para #{position_key}"
        super
      end
    end
  end

E isso de fato está adicionando texto no lugar que eu esperaria que fosse alterado no template!

. . . .

Olhei em all_the_plugins e não encontrei exemplos de ninguém usando esse código.

Seria um PR-welcome se eu alterasse as linhas como

        <%= digest_custom_html("below_popular_topics") %>

e as substituísse por

        <%= digest_custom_html("below_popular_topics").html_safe %>

E, enquanto estou nisso, talvez garantir que os nomes das position_keys sejam mais semelhantes à sua posição?

1 curtida

Fiz um PR:

2 curtidas

Decidi que digest_custom_html não produzir HTML que possa ser analisado é um bug, então estou recategorizando.

1 curtida

@martin, desculpe chamá-lo, mas você foi a última pessoa a mexer em digest.html.erb (há dois anos). Você se importaria de dar uma olhada neste PR?

1 curtida

Este plugin foi implantado e provavelmente esquecerei disso muito em breve, então, se alguém quiser usar esses campos digest_custom_html conforme pretendido, você pode adicionar código como este ao seu app.yml para corrigir o código-fonte. Eu estava com muita preguiça para criar uma regex que substituísse todos eles e, em vez disso, fiz apenas aquele que eu estava usando. Modifique conforme apropriado para o seu caso de uso.

Criei um template no plugin que pode então ser incluído no app.yml. Isso o torna um pouco mais fácil do que se preocupar com um bloco inteiro de yaml.

hooks:
  after_code:
    - replace:
        filename: "/var/www/discourse/app/views/user_notifications/digest.html.erb"
        from: 'digest_custom_html("above_footer") '
        to: 'digest_custom_html("above_footer").html_safe '
1 curtida

Faria sentido ter uma tag para ajudar a alertar a equipe sobre PRs abertos?

1 curtida

Olá @david. Vou tentar mais uma vez para ver se alguém está interessado neste PR. Como descrito acima; o código claramente não está funcionando como pretendido, mas ninguém jamais se importou. Fiz uma solução alternativa e implantei o código com uma correção para corrigir o template na implantação, mas não é uma solução elegante.

1 curtida

Você poderia adicionar o .html_safe ao resultado da sua substituição de método? Não acho que haja necessidade de estar no template erb?

O objetivo geral, tanto em Rails quanto em Ember, é colocar a marcação “esta string é segura para HTML” o mais próximo possível do ponto de autoria/geração, para que fique muito claro para os desenvolvedores que eles precisam garantir que o HTML seja realmente seguro (ou seja, qualquer entrada do usuário seja escapada).

O que você está fazendo está ok (desde que seja testado), mas não é o uso “pretendido” para esses métodos. Se fosse uma API de plugin intencional, estaria em plugin/instance.rb com os outros.

O uso pretendido para este método é colocar markdown na chave de tradução correspondente:

(Observe também o html_safe lá - essa é a mesma técnica que você precisaria usar em qualquer substituição)

2 curtidas

O.M.G. Aparentemente . . . Eu posso!!! Nunca teria ocorrido a mim que eu poderia colocá-lo lá e não até o final do template onde (pelo menos na minha cabeça) ele é renderizado.

Agora eu vejo e entendo que digest_custom e que ele está chamando .html_safe, muito bonito, no código que eu olhei e tentei entender, mas é confuso (para mim) que ele esteja usando aquela sintaxe sem parênteses. (Ou talvez eu nunca o teria visto).

Bem, eu vejo os valores nos locais, mas em comparação com a substituição do template como eu estava fazendo antes, esta é uma solução muito menos arriscada.

Muito obrigado por me colocar no caminho certo!

Aqui está outra coisa que estou fazendo que parece boba. Meu digest_custom_html precisa do usuário para o qual está sendo renderizado, então o que estou fazendo é substituir digest para definir @user para que meu digets_custom_html possa ter acesso ao usuário para o qual o resumo é destinado. Existe alguma maneira super fácil de evitar isso?

after_initialize do
  # Código que deve ser executado após o Rails terminar de inicializar

  # require_relative \"lib/discourse_add_jobs_to_digest/user_notifications_helper_override\"
  require_relative \"lib/discourse_add_jobs_to_digest/engine\"
  require_relative \"lib/discourse_add_jobs_to_digest/job_api\"

  require_dependency \"user_notifications\"
  module ::UserNotificationsHelperOverride
    def digest_custom_html(position_key)
      if position_key == "above_footer"
        DiscourseAddJobsToDigest::JobApi.get_jobs_html(@user).html_safe
      else
        super
      end
    end
  end

  UserNotificationsHelper.prepend(::UserNotificationsHelperOverride)

  module ::UserNotificationsOverride
    def digest(user, opts = {})
      @user = user
      super
    end
  end
  UserNotifications.prepend(::UserNotificationsOverride)
end
2 curtidas

Não vejo mais nada no template/métodos que utilize uma variável user, então, sim, o que você fez é provavelmente a melhor maneira de fazer isso.

Mas, ainda assim, esse tipo de substituição não pode ser ‘suportado’ e pode quebrar a qualquer momento. Certifique-se de ter alguns testes para capturar isso quando eventualmente acontecer.

1 curtida

Obrigado pela confirmação! Agradeço seu tempo.

Entendido. Isso ainda é muito melhor do que substituir o template inteiro, que foi minha solução anterior para um plugin semelhante.

E, sim, deveriam haver testes. :wink:

1 curtida

Este tópico foi fechado automaticamente 30 dias após a última resposta. Novas respostas não são mais permitidas.