将 digest_custom_html 作为 HTML 处理(之前:覆盖 digest.html.erb)

TL;DR:

我想在摘要中添加一些内容。我以前可以覆盖模板,但现在不行了,原因不明。

因为覆盖模板是不好的,所以在摘要中有一些地方会被 digest_custom_html 替换,但它会插入文本,所以这些地方需要附加 .html_safe。至少有一个地方放错了(名字里有“above”,但实际上是在下面)。

我认为我有能力为此做一个 PR,除非因为它太简单了,别人做起来会更容易。

更长、更痛苦的故事。

我在这里做过:https://github.com/pfaffman/discourse-add-to-summary,但这似乎已经不起作用了。

我认为我想做的是,在不修改核心代码的情况下,覆盖 digest.html.erb 模板。我以前可以通过将其放在 app/views/user_notifications/digest.html.erb 来实现,并且该文件会被处理而不是核心文件。但这似乎不再起作用了。

现在,我们有一些很棒的 digest_custom_html,如下所示:

聪明的读者会注意到,热门话题大约在第 78 行开始,远早于第 277 行。我不确定我花了多少时间因为看错了地方而认为什么都没有发生。但这是题外话。

我确实设法在 plugin.rbafter_initialize 中做到了这一点。

  require_dependency "user_notifications"
  module ::UserNotificationsHelperOverride
    def digest_custom_html(position_key)
      puts "doing improved the digest: #{position_key}"
      if position_key == "below_popular_topics"
        puts "doing the custom html for above_popular_topics"

        # Custom HTML for the popular topics position
        "<div>MY COOOOOOOL TEXT</div>"
      else
        puts "doing the super for #{position_key}"
        super
      end
    end
  end

它确实在模板中我期望被更改的地方添加了文本!

可惜的是,它没有被当作 HTML,而是被当作纯文本。所以。。。

我在 all_the_plugins 中查找,没有发现任何人使用这段代码的例子。

如果我将类似这样的行更改为

        <%= digest_custom_html("below_popular_topics") %>

并替换为

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

这是否会是一个 PR 欢迎的更改?而且,既然我已经在做了,也许可以确保 position_key 的名称更符合它们的位置?

1 个赞

我提交了一个 PR:

2 个赞

我认为 digest_custom_html 未生成可解析的 HTML 是一个 bug,因此我将重新归类。

1 个赞

@martin,抱歉点名你,但你是最后修改 digest.html.erb 的人(两年前)。你介意看看这个 PR 吗?

1 个赞

该插件已部署,我可能很快就会忘记它,所以如果有人想按预期使用这些 digest_custom_html 字段,您可以将类似这样的代码添加到您的 app.yml 中以修补源。我太懒了,无法创建一个替换所有这些的正则表达式,而是只做了我正在使用的那个。请根据您的用例进行修改。

我在插件中创建了一个模板,然后可以将其包含在 app.yml 中。这比处理整个 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 个赞

设置一个标签以帮助提醒团队打开 PR(Pull Request)是否有意义?

1 个赞

@david。我将再试一次,看看是否有人对这个 PR 感兴趣。如上所述;代码显然没有按预期工作,但没有人关心过。我做了一个变通方法,并部署了代码,在部署时修复了模板,但这并不是一个完美的解决方案。

1 个赞

您能否为您的方法覆盖结果添加 .html_safe?我认为没有理由将其保留在 erb 模板中?

总的目标,无论是在 Rails 还是 Ember 中,都是将“此字符串是 html 安全的”放在尽可能靠近编写/生成点的位置,这样开发人员就能清楚地知道他们需要确保 HTML 确实是安全的(即任何用户输入都已转义)

您的做法是可以的(只要经过测试),但这并不是这些方法的“预期”用途。如果这是一个故意的插件 api,它应该和其它插件一样在 plugin/instance.rb 中。

此方法的预期用途是将 markdown 放入匹配的翻译键中:

(另请注意那里的 html_safe - 这与您在任何覆盖中需要使用的技术相同)

2 个赞

我的天哪。显然……我可以!!!!我从来没想过我能把它放在那里,而不是放在模板的顶部(至少在我脑子里是这样渲染的)。

我现在看到并理解了 digest_custom 以及它在代码中调用 .html_safe,它很漂亮,就在我查看并试图理解的代码中,但它使用那种奇怪的无括号语法让我感到困惑(对我来说)。(或者我可能永远也看不到它)。

嗯,我确实在 locales 中看到了这些值,但与我之前覆盖模板相比,这是一个风险小得多的解决方案。

非常感谢你指明了正确的方向!

这是我还在做的另一件我觉得很傻的事情。我的 digest_custom_html 需要它被渲染的用户,所以我正在覆盖 digest 来设置 @user,这样我的 digets_custom_html 就可以访问 digest 所属的用户。有没有什么超级简单的方法可以避免这样做?

after_initialize do
  # Code which should run after Rails has finished booting
  # 在 Rails 完成启动后应运行的代码

  # 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 个赞

我没有在模板/方法中看到任何其他使用 user 变量的地方,所以是的,你所做的可能是最好的方法。

但即便如此,这类覆盖也不能被“支持”,并且随时可能中断。请确保你有一些测试来捕获它最终发生时的情况。

1 个赞

感谢确认!感谢你的时间。

明白了。这比覆盖整个模板要好得多,而这正是我之前为类似插件提出的解决方案。

而且,是的,应该有测试。:wink:

1 个赞

此主题在最后回复的 30 天后自动关闭。不再允许新的回复。