Partials get wrapped in <p> tags

We are using a mix of partials, custom helpers, and variables to produce single-source documentation. It looks something like this:

<% if productA? %>
  <%= partial "includes/snippets/snippet-prodA.md" %>
<% end %>

<% if productB? %>
  <%= partial "includes/snippets/snippet-prodB.md" %>
<% end %>

It outputs the expected content: according to the variables we set in the config.rb file, the correct markdown content is included and converted to HTML.

The issue we are having is that the content in the partial is wrapped in a paragraph tag. For example, assuming that the markdown file includes the following content:

# This is my heading

This is some text.

This will be output in HTML as follows:

<p><h1 id='this-is-my-heading'>This is my heading</h1>
<p>This is some text.</p>
</p>

This extra paragraph tag is creating havoc on our formatting.

The issue occurs only if the partial is included in a custom helper. My helper function looks like this:

helpers do
  def productA?
    config[:product_environment]  == "productA"
  end
end

Has anyone ever encountered this? Any ideas on how to solve this?

Note: We are using the Slate framework, built on Middleman.

Thanks!

I took a quick look, but couldn’t reproduce the issue with as a middleman app. To debug this, I’d recommend you create a standalone middleman app, and try to reproduce it there. If you can’t, perhaps this is an issue in Slate itself.

Where are you calling those partials from? Layout or yet another template code?

Thanks! I’ll try what you are recommending and will let you know.

I am calling the partials from a markdown file so that I can insert product-specific content depending on variables I set in my config.rb file. So my markdown file looks something like this:

# Some common header

Some common text

<% if productA? %>
  <%= partial "includes/snippets/snippet-prodA.md" %>
<% end %>

<% if productB? %>
  <%= partial "includes/snippets/snippet-prodB.md" %>
<% end %>

Then we have a suspect. Markdown parser adds <P> since the ERB code segment is a paragraph, according to its logic. I have one project that also uses ERB inside Markdown code and I have those <P> tags too. In my case this is not harmful (if not useful), since I need <P> anyway.

Interesting edge-case, I don’t know the solution. Yet.

Found a solution, at least for kramdown gem (which is a default Markdown parser for Middleman), working in my Middleman 3.4.1 project. But this should not change for the current Middleman 4.x, since it’s not related to Middleman code.

Just put your ERB segment in empty divs:

# Some common header

Some common text

<div>
<% if productA? %>
  <%= partial "includes/snippets/snippet-prodA.md" %>
<% end %>

<% if productB? %>
  <%= partial "includes/snippets/snippet-prodB.md" %>
<% end %>
</div>

According to kramdown documentation:

kramdown allows you to use block-level HTML tags (div, p, pre, …) to markup whole blocks of text – just start a line with a block-level HTML tag. kramdown syntax is normally not processed inside an HTML tag but this can be changed with the parse_block_html option.

Thanks @komor72! (Sorry for the delay, did not have access to my work computer yesterday).

So now I understand the problem, thanks!!!

I had tried this solution last week, but because we also use HTML inside our markdown files (for example, to create more complex tables), the div gets added to the HTML output and the CSS associated with divs is applied.

The idea solution would be that nothing gets applied, i.e., that the erb code is first executed, so the content of the partial gets imported, and then the markdown parsing happens.

Another option might be to create some class for the div that says: do nothing in this div. I’m not a CSS expert, so I don’t know if that can be done (I’ll check with our CSS expert here).

The usual way quite the opposite: a div with no class attribute is neutral and is not styled at all. If you want to make any styling to div, then you assign a class to it and use in your CSS. Your CSS expert will know to handle this.

1 Like

Just checked with her. It seems that the issue we are having with using divs is that it messes up floating.

The Slate CSS uses divs as follows:

// the div is the tocify hidden div for placeholding stuff
&>h1, &>h2, &>div {
clear:both;
}

So we cannot use that element to solve the issue. Is there a way to set this up so that the erb code is first executed, so that the content of the partial gets imported before the markdown parsing happens?

If you make your main page-template an ERB (or HAML) that includes *.md partials, then it should do. So, instead of Markdown code page.md:

# Some common header

Some common text

<% if productA? %>
  <%= partial "includes/snippets/snippet-prodA.md" %>
<% end %>

<% if productB? %>
  <%= partial "includes/snippets/snippet-prodB.md" %>
<% end %>

maybe you should try page.haml:

%h1 Some common header

%p Some common text

- if productA?
  = partial "includes/snippets/snippet-prodA.md"

- if productB?
  = partial "includes/snippets/snippet-prodB.md"

Although it’s hard for me to imagine, that the CSS code makes ALL divs cleared. This should be strictly inside some class/id. But maybe I’m uninformed. Maybe Slate assumes handling Markdown-only content with no extensions/fancy-coding whatsoever.

So I’ve been able to solve part of the issue.

Using (in part) what you recommend above, I have renamed my main index.html.md.erb file to index.html.erb. This file did not contain any markdown, only partials, so the partials in these files are now processed correctly (and not included in a p). Thank you!

My other files have the .md.erb suffix, but I’m still running into the issue in these files. Since the partials in these files are usually much smaller (e.g., a few paragraphs, and not a whole H1 section), having a p doesn’t cause issues (so far). All of the writers are already using ERB, so I’d like to avoid having to start using HAML.

Maybe we are pushing the Slate template too far!

Of course ERB or HAML is no different for your problem, because the root issue is Markdown parser. So if you are already using ERB, there’s no need to switch to HAML (except you miss the beauty of HAML code and some of its ugly dark corners :wink: ).

Sure, because first thing is: Markdown parser is parsing the MD syntax making HTML out of it, and it treats the ERB fragments as plain text, which should be put in <P> tags. Then the next thing in chain of command is ERB parser, which parses the ERB code, leaving the rest of text/html/whatever verbatim, including the opening <P> and closing </P> bits.

I’m still thinking about defining your custom CSS:

div.erb-parse { clear: none !important; }

and then using it in your DIVs:

# Some common header

Some common text

<div class='erb-parse'>
<% if productA? %>
  <%= partial "includes/snippets/snippet-prodA.md" %>
<% end %>
...
</div>
1 Like

We tried your suggestion, but the HTML output is still weird. I think Slate uses divs a certain way, which may cause problems. I’m going to ask help from a dev here, hopefully he’ll see something I’m not seeing. Next step will be to post the issue to the Slate community.

I’ll let you know if we fix it. Thanks so much for your help @komor72!!!

Late to the party, but I wanted to share my solution. I “cheat” with post-processing. I include most of my partials in tables, which results in both the wrapped <p> tags and an empty table row.

I use sed and perl to clear out the artifacts.

It’s kludgy, but it’s lightweight, fairly obvious to fix in the future when Slate/Middleman changes to break the process, and the output looks just the way I expect. With my focus on tables, it’s also probably too specialized to use straight out of the box for most folks, but might be useful if you can find similar patterns to clear out of your output.

# sed here because I needed changes on a single line
# Remove wrapping <p>
sed -i.bak -E "s/^<td>(.*)<p>(.*)<\/p><\/td>/<td>\1\2<\/td>/" build/index.html
# perl here because the easiest way to change multiple lines with sed is to use perl
# Remove empty table rows
perl -i.original -p0e 's/<tr>\n<td><\/td>\n<td><\/td>\n<\/tr>\n//g' build/index.html
rm build/index.html.bak
rm build/index.html.original