Проблема с рендерингом Markdown при изображении, окруженном HTML

Связано с 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>[...]
Изображение

Возможно ли разрешить отображение изображений Markdown, окружённых HTML, пожалуйста?

@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 />
Роскошное геймерское кресло, геймерские наушники и быстрая бесплатная доставка с официальной гарантией импортера &#8211; всего за 679₪!!!</p>
<p style="text-align: center;">Используйте на кассе эксклюзивный купон &#8211; <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>Гарантия: 1 год</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 мм на 2 разъёма 3,5 мм</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 />
    Роскошное геймерское кресло, геймерские наушники и быстрая бесплатная доставка с официальной гарантией импортера &#8211; всего за 679₪!!!
</p>
<p style="text-align: center;">Используйте на кассе эксклюзивный купон &#8211; <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>Гарантия: 1 год</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 мм на 2 разъёма 3,5 мм</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>
    

ИЛИ

  • Мы исправим движок Markdown для отображения <p>![](upload://6zqK52dO23i1JsYH2oyMU12U2ro.jpeg)</p>. Обратите внимание, что это не отображается даже в демо-версии CommonMark.

@sam, знаешь ли ты, есть ли какая-то намеренная причина, по которой изображения Markdown не отображаются на той же строке, что и <p>?

3 лайка

Это часть спецификации CommonMark

**test**

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

Мы категорически не хотим отклоняться от спецификации в этом вопросе. Я полагаю, мы исправим проблему с прямыми ссылками на изображения, добавив два переноса строки для таких случаев. Хотя, думаю, это случается довольно редко и во многом является следствием собственных действий.

5 лайков

Я не думаю, что это так уж редко, особенно когда Discourse связан с популярными инструментами, такими как WP-Discourse или любыми другими инструментами, использующими API.

Пожалуйста, рассмотрите возможность добавления пустой строки. Это, кажется, не станет разрушающим изменением и будет достаточно легко реализовать. :pray:

3 лайка

@Arkshine мы много обсуждали это внутри. Для нас ключевым моментом является сохранение целостности контента, поэтому решение с переносом строк, скорее всего, не будет реализовано.

Однако мы обязательно что-то сделаем — уничтожение изображений задачей pull_hotlinked_images недопустимо. Надеемся вскоре найти решение :eyes:

5 лайков

Обходное решение этой проблемы заключается в том, чтобы запретить Discourse загружать удалённые изображения. Это можно сделать, добавив домен изображения в настройку сайта «disabled image download domains» (запрещённые домены для загрузки изображений). Также можно запретить Discourse загружать все удалённые изображения, отключив настройку сайта «download remote images to local» (загружать удалённые изображения локально). Подробную информацию см. по ссылке: Fix broken images for posts created by the WP Discourse and RSS plugins.

4 лайка

В нашем случае мы не можем этого сделать, потому что используем официальный компонент миниатюры темы, который требует локальное изображение. Мы решили проблему, добавив переносы строк перед любым тегом <img> в содержимом до создания темы с помощью WP-Discourse. Это решение подходит не всем, но у нас оно работает. Немного грустно, что Discourse не поддерживает такое законное использование.

Но да, если вы не привязаны к плагину/компоненту и/или не можете исправить содержимое до создания темы, это, безусловно, разумное обходное решение.

2 лайка

Мы всё ещё планируем исправить эту проблему. К сожалению, это сложная ошибка, глубоко заложенная в нашу систему рендеринга Markdown, и её трудно устранить. Но мы обязательно займёмся этим — извините, что процесс затянулся!

5 лайков

Я просто хочу добавить здесь примечание, что проблема затрагивает также посты с изображениями, созданные через плагин Discourse RSS.

6 лайков

Извините за множество сообщений в этой теме, но проблема также касается изображений в постах, созданных через наш плагин Zendesk, когда включена настройка «Синхронизировать комментарии из Zendesk». Сложность этого случая заключается в том, что невозможно заранее узнать источник изображений, поэтому обходное решение — добавление источника изображения в настройку «Запрещённые домены для загрузки изображений» — не сработает.

Есть ли способ предотвратить загрузку удалённых изображений на локальный сервер, если тег изображения обернут в HTML-теги?

1 лайк

Боюсь, что это совершенно невозможно. Если мы сделаем что-то подобное, мы позволим третьим сторонам отслеживать активность на форуме, внедряя отслеживающий GIF. Загрузка удалённых изображений — это часть функции безопасности.

Вместо этого, я думаю, нам нужна «умная» система, работающая аналогично тому, как @tgxworld несколько лет назад создал наши ремейкеры изображений, которая работает в обратном направлении от HTML и обеспечивает стабильность изменений путём повторной обработки. К сожалению, это очень сложное изменение.

4 лайка

Эта проблема снова возникла

Просто мысли вслух, но интересно, можем ли мы обойти эту сложную проблему (т. е. преобразование HTML в Markdown). Краткое резюме (чтобы помочь осмыслить это):

  1. Discourse поддерживает импорт HTML для создания содержимого постов (например, HTML из WP Discourse).

  2. В некоторых случаях пользователь ожидает, что целостность исходного HTML будет сохранена в точности.

  3. «Целостность» здесь включает как минимум два аспекта:

    1. Как отображается содержимое, например, переносы строк.
    2. Где размещены медиафайлы, например, загрузка изображений на локальный сервер, чтобы избежать битых ссылок, или, возможно, по соображениям безопасности.
  4. Преобразование HTML в Markdown потенциально создаёт проблемы для первого типа целостности, однако в настоящее время это необходимо для обеспечения второго типа целостности.

Таким образом, одним из способов решения этой проблемы для некоторых импортированных постов могло бы быть хранение импортированного HTML непосредственно как обработанного содержимого поста, а задача pull_hotlinked_images поддерживала бы загрузку изображений в таком содержимом без преобразования тегов img в Markdown.

Да, проще говоря, возможно, код мог бы поддерживать загрузку изображений по прямым ссылкам без необходимости преобразования тегов img в Markdown. Для таких постов вы бы вставляли URL загруженного изображения в обработанное содержимое вместо исходного.

3 лайка

Сложность в том, как вообще редактировать посты с этим флагом. Редактор будет в режиме «сырого» HTML, и вся панель инструментов перестанет работать и так далее.

1 лайк