globewalldesk
globewalldesk

Reputation: 554

Redcarpet gem appends parsed markdown outside of the enclosing span

In my Rails app, I have a textarea box that I want people to be able to use markdown on. The redcarpet gem works fine for purposes of rendering the markdown, but it appends it after the enclosing span. This screws up my design; the top of the paragraph should appear between the "play" icon and the "pencil" icon (same as the title is in this picture):

enter image description here

Here's the html.erb with the markdown call. As you can see, it's entirely enclosed in a <span> tag:

<p class="user_desc">
  <span class="glyphicon glyphicon-play"></span>&nbsp;&nbsp;
  <span class="glyphicon glyphicon-pencil"></span>
  <span id="user_title_text"><%= markdown(@user.description) %></span>
</p>

Here is how the HTML is rendered via ERb and Redcarpet:

<p class="user_desc">
  <span class="glyphicon glyphicon-play"></span>&nbsp;&nbsp;
  <span class="glyphicon glyphicon-pencil"></span>
  <span id="user_title_text"></span></p>
<p>
  Hi! I started <a href="https://www.startthis.org" rel="nofollow" 
  target="_blank">StartThis.org</a>. My background is in philosophy (Ph.D., 
  Ohio State, 2000). I like ideas and thinking them through. I also like 
  organizing things online, especially educational and reference projects.
</p>
(etc.)

In other words, the markdown method is called (and I expected it to be interpolated in) span#user_title_text, it was actually appended after the span.

What's the best way to fix this? I hunted for similar problems but couldn't find any. I guess I could prepare the HTML in a string in a helper method and pass it separately to the view (maybe? Nope, I just tried it and it has the same effect!), but what's the best practice/solution to this? Sorry if this is kind of obvious, I'm a noob to all this.

Thinking a little bit more, considering that preparing the parsed markdown in advance, in the controller, has the same effect, maybe the problem is with how rails/ERb does the interpolation?

TIA

UPDATE: Note the <p> in the above code. This surrounded a span which surrounded the markdown call...which generates <p> tags!

Also note the &nbsp;&nbsp; in the code above. After fixing the <p> tags (changed them to <div>s), thanks to Matt's advice, I tried removing the html entities...and then it was fixed. Why?!

TIA again.

Upvotes: 0

Views: 194

Answers (1)

matt
matt

Reputation: 79723

Are you looking at the rendered source in the browser’s inspector?

What I think is happening is the HTML is being rendered as you would expect, resulting in something like:

<p class="user_desc">
  <span class="glyphicon glyphicon-play"></span>&nbsp;&nbsp;
  <span class="glyphicon glyphicon-pencil"></span>
  <span id="user_title_text"><p>Hello, here is some markdown.</p>

<p>Here is another paragraph.</p>
</span>
</p>

However this is not valid HTML, as it contains a <p> inside another <p>, so the browser is correcting it when it parses it. It does this by adding any needed close tags before the next opening <p> tag, and the result is what you see in the browser.

To fix it you will need to ensure your template will result in valid HTML whatever markdown is entered by the user. In particular here you need to change the surrounding p, and also (since p is not allowed as a child of span) you will need to change the last <span>. Replacing them both with divs might work for you:

<div class="user_desc">
  <span class="glyphicon glyphicon-play"></span>&nbsp;&nbsp;
  <span class="glyphicon glyphicon-pencil"></span>
  <div id="user_title_text"><%= markdown(@user.description) %></div>
</div>

Since this produces p elements that are children of divs, they remain valid and are not changed by the browser.

Upvotes: 4

Related Questions