HTML 包围图像时的 Markdown 渲染问题

相关于 Thumbnail generation & markdown rendering issue

当 Discourse 下载图像并将其 HTML 替换为 Markdown 语法时——在我们的场景中,结果如下:

[...]<a href="<link_here>" target="_blank">![|150x150](upload://l0iarnA6SPVAyJN5l7pnQxZnPvE.jpeg)</a>[...]

Discourse 无法渲染该图像。

图像

image

要解决此问题,您至少需要在上方添加一个空行:

[...]<a href="<link_here>" target="_blank">

![|150x150](upload://l0iarnA6SPVAyJN5l7pnQxZnPvE.jpeg)</a>[...]
图像

是否有可能允许渲染被 HTML 包围的 Markdown 图像?

@david

5 个赞

让我们在 Meta 上试试这个。我正在一个链接内热链接这张图片:

<a href="https://discourse.org"><img src="..."/></a>

让我们看看当图片被加载时会发生什么…

3 个赞

@Arkshine 看起来效果不错——它已成功渲染了 <a href="https://discourse.org">![](upload://6zqK52dO23i1JsYH2oyMU12U2ro.jpeg)</a>

你能分享一下链接周围的更多 HTML 结构吗?

2 个赞
未格式化
<div data-wp><a href="https://www.mooki.co.il/gaming/hbilvt-giiming-mwtlmvt/mvwb-giiming-khvl-sparkfox-wvlhn-giiming-mqcvei-lumi-whvr-2" target="_blank">![](upload://vAPxoqZB2QvWCrX4kbbzSO5BYYb.png)</a><div><div data-buy><a href="https://www.mooki.co.il/gaming/hbilvt-giiming-mwtlmvt/mvwb-giiming-khvl-sparkfox-wvlhn-giiming-mqcvei-lumi-whvr-2" target="_blank">购买</a><span data-clipboard-text="GLA679" data-coupon>GLA679</span><i></i></div><div data-price>₪679 <span data-old-price>₪1378</span></div></div></div><hr /><p><small>&nbsp;发布于:&nbsp;<a href="https://zuzu.deals/%d7%91%d7%9c%d7%a2%d7%93%d7%99-%d7%95%d7%91%d7%9e%d7%97%d7%99%d7%a8-%d7%97%d7%98%d7%99%d7%a4%d7%94-%d7%9e%d7%95%d7%a9%d7%91-%d7%92%d7%99%d7%99%d7%9e%d7%99%d7%a0%d7%92-%d7%90%d7%93%d7%95%d7%9d-spark/"></a></small></p><br /><p>![](upload://npQfkOhEIdPiFymVdtVyKmwRShL.png)</p>
<p style="text-align: center;">无论您是一名游戏玩家,还是仅仅整天坐着工作,感到背部急需一把更好的椅子,这里还有一个独家超值优惠!<br />
奢华游戏椅、游戏耳机,并享受免费快速配送,附带官方进口商保修 – 仅需 679₪!!!</p>
<p style="text-align: center;">结账时使用独家优惠码 – <strong>GLA679</strong></p>
<div> ![](upload://3c2tvGxZnMqoIn2fVfHA02wocm.jpeg)</div>
<div>
<h3 style="text-align: center;">SPARKFOX GC60P 专业游戏座椅</h3>
</div>
<div>专为电脑游戏设计,为用户提供极致舒适体验的游戏座椅</div>
<div>
<ul>
<li>高靠背座椅</li>
<li>长时间游戏也能保持极致舒适</li>
<li>配备颈托和腰托一对</li>
<li>材质类型:模制泡沫</li>
<li>框架类型:金属</li>
<li>材质:带碳纤维的人造革</li>
<li>扶手:可上下调节</li>
<li>机构类型:蝴蝶式</li>
<li>升降类型:Class4 液压</li>
<li>靠背调节范围:90°-180°</li>
<li>底座类型:尼龙</li>
<li>轮子材质:尼龙</li>
<li>承重能力:最高 150 公斤</li>
<li>保修:一年</li>
</ul>
<div><strong>尺寸</strong></div>
<div>
<ul>
<li>宽度:67 厘米</li>
<li>深度:67 厘米</li>
<li>可变高度:124-132 厘米</li>
</ul>
<h3></h3>
<p>![](upload://7t26ZtW6tL3vobWYqbpCbRftvpV.jpeg)</p>
<h3 style="text-align: center;">SPARKFOX K1 游戏耳机</h3>
<div>专为最大程度的听音和语音舒适度及背景噪音消除而设计的游戏耳机</div>
<div>
<ul>
<li>适用于市场上大多数游戏主机</li>
<li>支持在电话和笔记本电脑上进行音频播放和通话管理</li>
<li>音量调节器位于耳机线缆上,便于操作</li>
<li>配备 50 毫米大尺寸驱动单元,提供卓越音质</li>
<li>具备音量和静音控制按钮</li>
<li>大型软垫耳罩,提供最大舒适度</li>
<li>头梁可调节,完美贴合您的头部</li>
<li>直接连接至 3.5 毫米控制器输出接口</li>
</ul>
</div>
<div>附带专用转接头,通过 3.5 毫米一分二 splitter 将耳机连接至台式电脑</div>
</div>
</div>
<p>&nbsp;</p>
<div data-custom-html=""></div>
格式化
<div data-wp>
    <a href="https://www.mooki.co.il/gaming/hbilvt-giiming-mwtlmvt/mvwb-giiming-khvl-sparkfox-wvlhn-giiming-mqcvei-lumi-whvr-2" target="_blank">![](upload://vAPxoqZB2QvWCrX4kbbzSO5BYYb.png)</a>
    <div>
        <div data-buy>
            <a href="https://www.mooki.co.il/gaming/hbilvt-giiming-mwtlmvt/mvwb-giiming-khvl-sparkfox-wvlhn-giiming-mqcvei-lumi-whvr-2" target="_blank">购买</a>
            <span data-clipboard-text="GLA679" data-coupon>GLA679</span><i></i>
        </div>
        <div data-price>₪679 <span data-old-price>₪1378</span></div>
    </div>
</div>
<hr />
<p>
    <small>&nbsp;发布于:&nbsp;<a href="https://zuzu.deals/%d7%91%d7%9c%d7%a2%d7%93%d7%99-%d7%95%d7%91%d7%9e%d7%97%d7%99%d7%a8-%d7%97%d7%98%d7%99%d7%a4%d7%94-%d7%9e%d7%95%d7%a9%d7%91-%d7%92%d7%99%d7%99%d7%9e%d7%99%d7%a0%d7%92-%d7%90%d7%93%d7%95%d7%9d-spark/"></a></small>
</p>
<br />
<p>![](upload://npQfkOhEIdPiFymVdtVyKmwRShL.png)</p>
<p style="text-align: center;">
    无论您是一名游戏玩家,还是仅仅整天坐着工作,感到背部急需一把更好的椅子,这里还有一个独家超值优惠!<br />
    奢华游戏椅、游戏耳机,并享受免费快速配送,附带官方进口商保修 – 仅需 679₪!!!
</p>
<p style="text-align: center;">结账时使用独家优惠码 – <strong>GLA679</strong></p>
<div>![](upload://3c2tvGxZnMqoIn2fVfHA02wocm.jpeg)</div>
<div>
    <h3 style="text-align: center;">SPARKFOX GC60P 专业游戏座椅</h3>
</div>
<div>专为电脑游戏设计,为用户提供极致舒适体验的游戏座椅</div>
<div>
    <ul>
        <li>高靠背座椅</li>
        <li>长时间游戏也能保持极致舒适</li>
        <li>配备颈托和腰托一对</li>
        <li>材质类型:模制泡沫</li>
        <li>框架类型:金属</li>
        <li>材质:带碳纤维的人造革</li>
        <li>扶手:可上下调节</li>
        <li>机构类型:蝴蝶式</li>
        <li>升降类型:Class4 液压</li>
        <li>靠背调节范围:90°-180°</li>
        <li>底座类型:尼龙</li>
        <li>轮子材质:尼龙</li>
        <li>承重能力:最高 150 公斤</li>
        <li>保修:一年</li>
    </ul>
    <div><strong>尺寸</strong></div>
    <div>
        <ul>
            <li>宽度:67 厘米</li>
            <li>深度:67 厘米</li>
            <li>可变高度:124-132 厘米</li>
        </ul>
        <h3></h3>
        <p>![](upload://7t26ZtW6tL3vobWYqbpCbRftvpV.jpeg)</p>
        <h3 style="text-align: center;">SPARKFOX K1 游戏耳机</h3>
        <div>专为最大程度的听音和语音舒适度及背景噪音消除而设计的游戏耳机</div>
        <div>
            <ul>
                <li>适用于市场上大多数游戏主机</li>
                <li>支持在电话和笔记本电脑上进行音频播放和通话管理</li>
                <li>音量调节器位于耳机线缆上,便于操作</li>
                <li>配备 50 毫米大尺寸驱动单元,提供卓越音质</li>
                <li>具备音量和静音控制按钮</li>
                <li>大型软垫耳罩,提供最大舒适度</li>
                <li>头梁可调节,完美贴合您的头部</li>
                <li>直接连接至 3.5 毫米控制器输出接口</li>
            </ul>
        </div>
        <div>附带专用转接头,通过 3.5 毫米一分二 splitter 将耳机连接至台式电脑</div>
    </div>
</div>
<p>&nbsp;</p>
<div data-custom-html=""></div>
编辑器截图

1 个赞

这与这里提出的问题相同:Images not publishing to Discourse in WP 5.3 - #6 by simon

3 个赞

啊哈!@simon,升级 WordPress 插件能修复旧帖子吗?还是只修复新帖子?

3 个赞

该修复仅适用于通过 WordPress 区块编辑器发布的帖子。如果在 WordPress 上点击“更新 Discourse 主题”按钮,也可以修复旧帖子。除非有人编写脚本遍历旧帖子,否则需要为每篇帖子手动执行此操作。

4 个赞

让我们试试这个 HTML:

<p><img src="..."/></p>

![](upload://6zqK52dO23i1JsYH2oyMU12U2ro.jpeg)

4 个赞

我认为这也应该在 Discourse 中修复,以防万一帖子是由非 WordPress 集成发布的。总结如下:

  1. 我发布了 <p><img src="..."/></p>。这是完全有效的 HTML。

  2. pull_hotlinked_images 获取了图片,并将标记替换为 <p>![](upload://6zqK52dO23i1JsYH2oyMU12U2ro.jpeg)</p>

  3. 这无法渲染。

因此,这里有两个可能的修复方案。要么:

  • 修复 InlineUploads,使其在标记中添加一个空行。这样可以正常渲染:
    <p>
    
    ![](upload://6zqK52dO23i1JsYH2oyMU12U2ro.jpeg)
    </p>
    

或者

@sam 你知道为什么 Markdown 图片无法在与 <p> 同一行渲染吗?是否有故意这样设计的原因?

3 个赞

这是 CommonMark 规范的一部分

**test**

<p>**test**</p>

我们绝对不想在这里偏离规范。我想我们可以通过为这种情况注入两个换行符来修复拉取热链图片的问题,使其能够兼容。不过我认为这种情况相当罕见,而且某种程度上是自找的。

5 个赞

我认为这并不那么罕见,尤其是当 Discourse 与 WP-Discourse 等流行工具,或任何使用 API 的工具关联时。

请考虑添加一个空行。这似乎不会造成破坏性变更,而且实现起来相当简单。:pray:

3 个赞

@Arkshine 我们内部对此进行了大量讨论。对我们来说,关键在于保持内容的完整性,因此换行解决方案可能不会实施。

但我们肯定会采取一些措施——让 pull_hotlinked_images 任务销毁图像是不可接受的。希望很快能拿出解决方案:eyes:

5 个赞

解决此问题的一种变通方法是阻止 Discourse 下载远程图片。可以通过将图片域名添加到“禁用图片下载域名”站点设置来实现。此外,也可以通过禁用“将远程图片下载到本地”站点设置,阻止 Discourse 下载所有远程图片。详情请参见 https://meta.discourse.org/t/fix-broken-images-for-posts-created-by-the-wp-discourse-and-rss-plugins/160773。

4 个赞

在我们的案例中,我们无法这样做,因为我们使用的是官方的话题缩略图组件,该组件需要本地图片。我们通过在使用 WP-Discourse 创建话题之前,在内容中任何 <img> 标签前添加换行符来解决这个问题。这不是适用于所有人的解决方案,但对我们有效。Discourse 不支持这种合法用法,有点令人遗憾。

但确实,如果你不受插件/组件的限制,和/或无法在话题创建之前修复内容,这绝对是一个合理的变通方法。

2 个赞

我们仍在计划修复该问题。不幸的是,这是我们的 Markdown 渲染系统中一个较深层次的问题,修复起来比较复杂。但我们一定会解决它——很抱歉耗时这么久!

5 个赞

我顺便补充一下,该问题同样影响通过 Discourse RSS 插件创建的包含图片的帖子。

6 个赞

抱歉在这个话题中多次发帖,但该问题同样影响通过我们的 Zendesk 插件创建的帖子中的图片,前提是启用了“从 Zendesk 同步评论”设置。这种情况的难点在于无法预先知道图片的来源,因此将图片 src 添加到“禁用图片下载域名”设置中的变通方法将不起作用。

是否有一种方法可以在图片标签被 HTML 标签包裹时,阻止远程图片下载到本地?

1 个赞

恐怕这完全不可行。如果我们这样做,第三方就可以通过在论坛中注入追踪 GIF 来跟踪使用情况。下载远程图片实际上是一项安全功能。

相反,我认为我们需要一个更“智能”的系统,其工作方式类似于 @tgxworld 几年前构建的图片重映射器:从 HTML 反向工作,并通过重新渲染来确保变更的稳定性。很遗憾,这是一个非常复杂的改动。

4 个赞

这个问题又出现了

只是随口说说,我在想我们是否能绕过这个棘手的问题(即 HTML 到 Markdown 的转换)。再回顾一下(仅为了帮助理清思路):

  1. Discourse 支持导入 HTML 以创建帖子内容(例如来自 WP Discourse 的 HTML)。

  2. 在某些上下文中,用户期望原始 HTML 的完整性被完全保留。

  3. 此处的“完整性”至少包含两个方面:

    1. 内容的渲染方式,例如换行符
    2. 媒体资源的托管位置,例如将图片下载到本地以避免图片链接失效,或出于安全考虑
  4. HTML 到 Markdown 的转换可能会影响第一种完整性,但目前为了保障第二种完整性,这种转换是必要的。

因此,针对某些导入的帖子,一种可能的解决方案是直接将导入的 HTML 存储为已渲染的帖子内容,同时让 pull_hotlinked_images 作业支持下载此类内容中的图片,而无需将 img 标签转换为 Markdown。

是的,更简单地说,代码或许可以支持下载热链接图片,而无需将 img 标签转换为 Markdown。对于此类帖子,你将在已渲染的内容中插入下载后的图片 URL,而不是原始 URL(而非原始 HTML 中的 URL)参考此处

3 个赞

棘手的问题在于,如何编辑带有该标志的帖子。编辑器将处于原始 HTML 模式,整个工具栏也会失效,等等。

1 个赞