# HTMLメール変換でテーブル以降の要素がすべて削除される問題

**URL:** <https://meta.discourse.org/t/html-email-conversion-drops-tables-and-everything-trailing-it/141195>\
**Category:** Bug\
**Created:** [2020 年 2 月 10 日午後 3:41 UTC](https://meta.discourse.org/t/html-email-conversion-drops-tables-and-everything-trailing-it/141195 "2020-02-10T15:41:29Z")\
**Posts on this page:** 1\
**Showing post:** 5

<div class="post-metadata">

**Author:** ![zogstrip](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/zogstrip/32/512781_2.png) [@zogstrip](https://meta.discourse.org/u/zogstrip)\
**Post date:** [2020 年 4 月 29 日午後 3:37 UTC](https://meta.discourse.org/t/html-email-conversion-drops-tables-and-everything-trailing-it/141195/5 "2020-04-29T15:37:50Z")

</div>

> [@brechtm](#):
>
> HTML テーブルを投稿に貼り付けることは問題なく動作するため、HTML テーブルをそのまま Markdown 投稿に含めることができない理由はないと思われます。

その理由は、サーバー側で HTML から Markdown への変換を処理するコードが `<table>` をサポートしていなかったためです 😉

この PR がマージされれば修正されます 👌

> <https://github.com/discourse/discourse/pull/9586>
>
> TLDR; this commit vastly improves how whitespaces are handled when converting fr…om HTML to Markdown.
> It also adds support for converting HTML \`\<tables\>\` to markdown tables.
> 
> \---
> 
> The previous \`remove\_whitespaces!\` method was traversing the whole HTML tree and used a heuristic to remove
> leading and trailing whitespaces whenever it was appropriate (ie. mostly before and after HTML block elements)
> 
> It was a good idea, but it was very limited and leaded to bad conversion when the html had leading whitespaces on several lines for example.
> One such example can be found \[here\](https://meta.discourse.org/t/86782).
> 
> For various reasons, most of the whitespaces in a HTML file is ignored when the page is being displayed in a browser.
> The rules that the browsers follow are the \[CSS' White Space Processing Rules\](https://www.w3.org/TR/css-text-3/#white-space-rules).
> They can be quite complicated when you take into account RTL languages and other various tidbits but they boils down to the following:
> 
> \- Collapse whitespaces down to one space (0x20) inside an inline context (ie. nodes/tags that are being displaying on the same line)
> \- Remove any leading/trailing whitespaces inside an inline context
> 
> One quick & dirty way of getting this 90% solved would be to do \`HTML.gsub!(/\[\[:space:\]\]+/, " ")\`.
> We would also need to hoist \`\<pre\>\` elements in order to not mess with their whitespaces.
> Unfortunately, this solution let some whitespaces creep around HTML tags which leads to more \`.strip!\` calls than I can bear.
> 
> I decided to "\_emulate\_" the browser's handling of whitespaces and came up with a solution in 4 parts
> 
> \#### 1. \`remove\_not\_allowed!\`
> 
> The HtmlToMarkdown library is recursively "visiting" all the nodes in the HTML in order to convert them to Markdown.
> All the nodes that aren't handled by the library (eg. \`\<script\>\`, \`\<style\>\` or any non-textual HTML tags) are "swallowed".
> In order to reduce the number of nodes visited, the method \`remove\_not\_allowed!\` will automatically delete all the nodes
> that have no "visitor" (eg. a \`visit\_\<tag\>\` method) defined.
> 
> \#### 2. \`remove\_hidden!\`
> 
> Similar purpose as the previous method (eg. reducing number of nodes visited), there's no point trying to convert something that is hidden.
> The \`remove\_hidden!\` method removes any nodes that was hidden using the "hidden" HTML attribute, some CSS or with a width or height equal to 0.
> 
> \#### 3. \`hoist\_line\_breaks!\`
> 
> The \`hoist\_line\_breaks!\` method is there to handle \`\<br\>\` tags. I know those tiny \`\<br\>\` don't do much but they can be quite annoying.
> The \`\<br\>\` tags are inline elements but they visually work like a block element (ie. they create a new line).
> If you have the following HTML "\`\<i\>Foo\<br\>Bar\</i\>\`", it ends up visually similar to "\`\<i\>Foo\</i\>\<br\>\<i\>Bar\</i\>\`".
> The latter being much more easy to process than the former, so that's what this method is doing.
> The \`hoist\_line\_breaks\` will hoist \`\<br\>\` tags out of inline tags until their parent is a block element.
> 
> \#### 4. \`remove\_whitespaces!\`
> 
> The \`remove\_whitespaces!\` is where all the whitespace removal is happening. It's broken down into 4 methods as well
> 
> \- \`remove\_whitespaces!\`
> \- \`is\_inline?\`
> \- \`collapse\_spaces!\`
> \- \`remove\_trailing\_space!\`
> 
> The \`remove\_whitespace!\` method is recursively walking the HTML tree (skipping \`\<pre\>\` tags).
> If a node has any children, they will be chunked into groups of inline elements vs block elements.
> For each chunks of inline elements, it will call the \`collapse\_space!\` and \`remove\_trailing\_space!\` methods.
> For each chunks of block elements, it will call \`remote\_whitespace!\` to keep walking the HTML tree recursively.
> 
> The \`is\_inline?\` method determines whether a node is part of a inline context.
> A node is inline iif it's a text node or it's an inline tag, but not \`\<br\>\`, and all its children are also inline.
> 
> The \`collapse\_spaces!\` method will collapse any kind of (white) space into a single space (" ") character, even across tags.
> For example, if we have "\` Foo \\n\<i\> Bar \</i\>\\t42\`", it will return "\`Foo \<i\>Bar \</i\>42\`".
> 
> Finally, the \`remove\_trailing\_space!\` method is there to remove any trailing space that might creep in at the end of the inline chunk.
> 
> This solution is not 100% bullet-proof.
> It does not support RTL languages at all and has some caveats that I felt were not worth the work to get properly fixed.
> 
> \---
> 
> FIX: switched Nokogiri to Nokogumbo for better HTML5 parsing
> FIX: better detection of hidden elements when converting HTML to Markdown
> FIX: take into account the \`allowed\_href\_schemes\` site setting when converting HTML \`\<a\>\` to Markdown
> FIX: added support for 'mailto:' scheme when converting \`\<a\>\` from HTML to Markdown
> FIX: added support for \`\<img\>\` dimensions when converting from HTML to Markdown
> FIX: added support for \`\<dl\>\`, \`\<dd\>\` and \`\<dt\>\` when converting from HTML to Markdown
> FIX: added support for multilines emphases, strongs and strikes when converting from HTML to Markdown
> FIX: added support for \`\<acronym\>\` when converting from HTML to Markdown
> DEV: remove unused 'sanitize' gem
> 
> Wow, did you just read all that?! Congratz, here's a cookie: 🍪.

---

_[View the full topic](https://meta.discourse.org/t/html-email-conversion-drops-tables-and-everything-trailing-it/141195)._
