使用 topic-thumbnails 时,我们的外部嵌入件缺少缩略图

我们正在为我们的产品推出一个论坛,其外部嵌入在允许我们使用 Iframes 后已能通过 OneBox 正常运行。

指向 embed 的直接链接,会整齐地转换为我们 oembed endpoint 的结果。
现在,我们首先关心的是,当启用 Topic List Thumbnails 时,我们希望缩略图能够显示出来。我不确定为什么缩略图没有被抓取到。

我们需要将集成添加到 lib/onebox/engine 吗?

补充说明,默认行为今天大部分都能正常工作,只是不支持我们的动态嵌入。我们希望加载 JS 而不是 Iframe。不可否认,这有另一种解决方案,即使用一些 JS 可选地调整 iframe 的大小,但我们短期内不打算为 oEmbed 通用实现这一点。

我知道 Using onebox images for topic thumbnails - #20 by david,但发现它对我的情况没有帮助。

1 个赞

在与 Discourse 团队通过电子邮件进行一些讨论后,我在此更新。

主要发现是,如果一个会变成 onebox 的链接被渲染成 iframe,缩略图将不会被加载。

这意味着链接:

https://app.everviz.com/embed/N0dDTJaOQ

是否渲染缩略图取决于是否允许来自该域的 iframe(“允许的 iframe”)。解决方案是某种方式将 iframe 注入帖子。我创建了一个 插件,它会这样做,并确保将 display: none 设置在图片上,以防止它出现在帖子中。

我认为可以将其推广为:

  1. 对于所有通用的 onebox,如果 get_oembed.thumbnail_url 存在,则静默加载并隐藏旁边的图片。
  2. 也许更好的解决方案是,添加通用支持来提取 get_oembed.thumbnail_url 并将其与帖子关联,而无需将其本身作为 cooked 区域的一部分。

相关位置:

  1. https://oembed.com/
  2. discourse/lib/onebox/engine at main · discourse/discourse · GitHub
  3. discourse/lib/onebox/engine/standard_embed.rb at main · discourse/discourse · GitHub

我对这种模态行为不太满意,即是否启用了“允许的 iframe”?如果 Discourse 在首次向 oembed 端点发送 GET 请求时提取并使用该端点的所有属性,那将是很好的。

更新

我有一个想法,就是使用客户端插件 API 将图片加载到帖子中。

api.decorateCooked($elem => {
    $elem[0].querySelectorAll('.my-iframe')
    .forEach(function (iframe) {

      // 工作

      iframe.insertAdjacentElement('beforebegin', thumbnail);
    });

  }, {id: 'unique_string'});

但是 Discourse 没有识别到任何内容。

似乎发生了以下两种情况之一:

  1. 我们太晚了,Discourse 已经完成了缩略图检索和生成。
  2. 我们的图片缺少某些属性,导致缩略图生成机制错过了它。

希望是后者。这里需要注意的一点是,图片从未上传到我们的 Discourse 实例,而只是从我们自己的服务器引用。

您尝试过这样做吗?为您的特定情况编写一个 onebox 可能会允许您为已处理的帖子提供一个 onebox 图片?然后缩略图就会自动工作。

我注意到 Youtube 的 onebox 我认为是在网站内部静态显示的,直到您点击播放按钮,然后它会显示一个 iframe。点击之前呈现的内容包括一张图片,然后这张图片会被拾取并缩略。显然 Discourse 无法从 iframe 中读取内容,因此这种技术是一个很好的方法。

我注意到您的示例在 header 标签中包含了一个 og:image,这非常完美。


我的建议是,在这里放弃 javascript,然后在 Rails 中进行处理。

这唯一的缺点是您的图片将是静态的,直到您重建帖子,假设目标图片也已更新。因此,如果您希望显示动态变化的缩略图,您可能需要更有创意。

3 个赞

您好 Robert,感谢您的回复!

编写插件是我做的第一件事,而且效果非常好——无论我把它放在 lib/onebox/engine 中,还是作为一个单独的插件。需要注意的是,我们使用的是托管计划,而插件在多租户计划中是不能使用的,因此在 Rails 中进行定制是不可能的。

这样我们就剩下三种选择:

  1. 运行我们自己的实例
  2. 尝试在客户端进行一些修改,看看是否可行
  3. 主线 Discourse 提交一个 PR

在此提出一个问题。我不确定这样的贡献是否会被接受,特别是如果它只是加载一张图片然后隐藏它。我该如何了解情况?

2 个赞

我已经在这方面取得了一些进展。查看:

api.composerBeforeSave

其回调在 composer.js 中处理。从那里,我们可以看到 createPosteditPost 方法调用 getCookedHtml,它或多或少地返回以下内容的 innerHTML

const editorPreviewNode = document.querySelector(
  "#reply-control .d-editor-preview"
);

这意味着,如果我们修改此选择器,我们或许可以强制插入等同于常规图像上传的 HTML。但是,修改 editorPreviewNode.innerHTML 似乎没有任何效果。

这是为什么,或者我可以在 composerBeforeSave 中修改什么来实现类似的功能?

这对我来说大部分是说得通的,我认为我们会接受一个 PR 来为 everviz.com(或类似的视觉化服务)的核心添加一个 onebox 引擎。但是,我会避免在 cooked 帖子中插入和隐藏图片,有一个更轻量级的选择。Discourse 的帖子处理器会查找上传,以下是元素:

所以将缩略图添加为 iframe 下方的锚点可能有效?你可以让它保持可见,或者使用像“hidden”这样的类来隐藏它。

5 个赞

您好,Penar,感谢您的回复。

使用

  <div>
   #{get_oembed.html}
   <a class="hidden" href="https://app.everviz.com/thumbnails/#{match[:uuid]}.png"></a>
  </div>

作为我的 to_html 方法,会产生以下输出:

  <div class="...">
    <iframe>
      ...
    </iframe>
    <a class="hidden" href="https://app.everviz.com/thumbnails/[...].png" rel="nofollow ugc noopener"></a>
  </div>

直接链接一张图片会产生:

<a href="https://app.everviz.com/thumbnails/[...].png" target="_blank" rel="noopener" class="onebox">
   <img src="//localhost:3000/uploads/default/original/1X/[...].png"
        style="aspect-ratio: 690 / 459;" loading="lazy">
</a>

这似乎是因为 image_onebox.rb 引擎仅在链接的图片不是由其他 onebox 引擎处理的上下文之外时才运行。

其后果是,目前建议的技术不起作用,因此有必要链接并隐藏一张图片,或者修改 Discourse 以适应这种情况。

在这种情况下,插入并隐藏一张图片是否可以接受的 PR?或者需要做更复杂的事情?

我不确定我是否理解,这不应该通过图片 onebox 引擎。

这个:

<a class="hidden" href="https://app.everviz.com/thumbnails/[...].png" rel="nofollow ugc noopener"></a>

不起作用吗?也就是说,当一个主题的第一个帖子在其“cooked”列中有这个时,图片在处理后会被识别为缩略图吗?

2 个赞

抱歉造成混淆,输出看起来像图片单框引擎。

建议的链接(已正确添加 UUID)不起作用。我从 Google 提取的此图片也不起作用(并且我在此处将其写为锚定标签。如果粘贴一些 HTML 等同于输出单框,这将解释我们的结果)。


https://static-cse.canva.com/blob/1031184/1600w-wK95f3XNRaM.jpg

1 个赞

啊,我的错,你说得对,那种方法行不通。我们生成缩略图时,只使用下载的图片,但锚标签中的图片不会被下载。

这里的一个替代方案可能是向核心添加一些类似 @merefield 推荐的功能,但将其包装成一个通用的 oneboxer,用于延迟加载的 iframe。也许可以添加一个新的站点设置 lazy_loaded_iframes,onebox 最初可以输出 OG 标签中的图片(这应该会被缩略图拾取),点击后,一小段 JavaScript 会将图片替换为正确的 iframe(类似于 YouTube iframe 的替换方式)。

这里一个棘手的细节是,使用的图片和 iframe 应该有相同的高度,否则这可能会在滚动/导航帖子时引入不必要的跳跃。

3 个赞