What is meta? ×
Meta Stack Exchange is where users like you discuss bugs, features, and support issues that affect the software powering all 149 Stack Exchange communities.

I noticed an answer over on The Workplace that had a blank blockquote at the bottom of it. When I went to edit, I saw that there was nothing after the end of the text to cause it.

enter image description here

And the actual post with the blockquote:

enter image description here

Using developer tools (IE8) I eventually discovered that a <blockquote/> tag was stuck at the end of the answer (appears as <blockquote></blockquote> in the actual HTML).

Placing a blank line after the blockquote in the list makes this extra blockquote disappear (although the rest of the HTML appears unchanged).

Normally, when text follows a blockquote on the line immediately after it, it becomes part of the quote. It seems like the list structure takes priority here, and causes an extra blockquote to be insterted.

Additionally, if there is no blank line, blockquotes later in the post will show their text as plain text followed by an empty blockquote:

enter image description here

share|improve this question
    
Hmm, I'm only able to reproduce this in IE < 9. –  Tim Stone Nov 1 '12 at 18:02
    
Do you see the empty blockquote on workplace.stackexchange.com/revisions/208/1? I can't try to reproduce without rolling back. (CC @TimStone) –  Dennis Nov 1 '12 at 18:05
    
@Dennis Yeah, I can see it in IE8 mode. It seems the last block of text ends up outside of a <p> too (and then there's an empty <p> afterward), which happens in all browsers. –  Tim Stone Nov 1 '12 at 18:08
    
@TimStone: I can see the empty <p> tag (Chrome N where N tends to inifinity on Ubuntu), but not the <blockquote> tag. I wonder what would cause the source code to change from browser to browser. –  Dennis Nov 1 '12 at 18:13
    
@Dennis Looks like the conversion might be producing invalid HTML, so it probably boils down to how the different engines handle malformed markup. –  Tim Stone Nov 1 '12 at 18:16
    
Forgot to mention the other issue this causes, have included a screenshot –  Jim Nov 1 '12 at 18:20
    
@TimStone: Bingo! In the source code, </blockquote> is at the very end of the post, while in the output, the <blockquote> tag gets cut short by the next <li>. –  Dennis Nov 1 '12 at 18:20
    
@Dennis Yeah, I see where the issue is in the parser now, but addressing it might be more tricky. If balpha doesn't come along with some black magic I'll take a closer look after work. –  Tim Stone Nov 1 '12 at 18:35

2 Answers 2

up vote 7 down vote accepted

This is fixed in the next build (client-side change, server-side change).

Tim Stone's analysis is absolutely correct. The problem (once again) was this Markdown behavior:

If list items are separated by blank lines, Markdown will wrap the items in <p> tags in the HTML output.

So you have this:

                                            <ul>
- Hello                                         <li>Hello</li>
- world               -->                       <li>world</li>
                                            </ul>

versus this:

                                            <ul>
- Hello                                         <li><p>Hello</p></li>
                      -->                       <li><p>world</p></li>
- world                                     </ul>

This is sometimes referred to as "tight lists" versus "loose lists". The problem is that the behavior was unclear as to what should happen if there's more blocklevel stuff inside the list item, like a block quote. What the original Markdown does (and our versions did so far) is

  1. In a loose list, handle the whole range of Markdown (sub-lists, blockquotes, headers, you name it).
  2. In a tight list, only handle sub-lists, and then just do line-level things like italics and links.

So, a block quote inside a tight list wouldn't even work.

Except that it did, sort of. Given this:

- Never say
  > never
  again

we first handle the list. It's a tight list, so don't do any blocklevel things:

<ul>
<li>
Never say
  > never
again
</li>
</ul>

But now that we have this, the top-level blockquote handler runs (blockquotes are handled after lists). As most things in original markdown, this is just a string-replacement that updates what we have so far, and it is roughly as smart as Gary Larson's Ginger:

What we say to dogs

Here's what we say to the blockquote parser and what it hears:

<ul>                                        blah
<li>                                        blah
Never say                                   blah blah
  > never                                     > blah
again                                       blah
</li>                                       blah
</ul>                                       blah

And so it creates this:

<ul>                                        blah
<li>                                        blah
Never say                                   blah blah
<blockquote><p>never                        <blockquote><p>blah
again                                       blah
</li>                                       blah
</ul>                                       blah
</p></blockquote>                           </p></blockquote>

– which looks reasonable on the right, but is horribly broken on the left. However it's broken in a way that gives a good chance that it's still rendered as expected by the browser, which is why most of the time it seemed to work.

From now on, tight and loose lists will be handled identically, and the question whether text that isn't otherwise handled should be wrapped in <p> tags or not is the only difference between the two. That fixes this issue and various others where broken HTML was created. It's also consistent with CommonMarks behavior, and thus makes sense for us to adopt.

When running this over a bunch of Meta posts, the only post where this change causes an issue is this one, because the contents of the last bulleted list will now be interpreted as headers. Ironically, this particular problem would be fixed by a CommonMark feature that I'm arguing against.

share|improve this answer

As mentioned in the comments, the issue here is the malformed HTML produced by the blockquote-in-list syntax used in the original post. This happens when the parser considers the content of the list item to be inline and doesn't run the inner content through the block gamut, leaving the > ... to be matched by the top-level blockquote parser.

The blockquote regular expression is unaware of the list HTML generated by the previous top-level step, so it willing gobbles it up as if it was part of the intended blockquote content, producing malformed markup like:

<ul>
  <li>
    <blockquote>
      <p>Quoted text
  </li>
</ul>
      </p>
    </blockquote>

(indentation for emphasis)

This mess can in turn cause problems like the one you noticed, as well as even more obscure issues.

There are two quick-fixes for this, but I'm not positive about the impact of either beyond that they seem to pass MarkdownSharp's test cases when you account for whitespace-based discrepancies.

The first is to simply let the top-level blockquote parser do what it's been doing, but generate the list in such a way that any internal "inline" blockquotes are guaranteed to be considered terminated before the generated closing </li> tag.

This can be accomplished by modifying the ProcessListItems method's ListItemEvaluator to return extra newlines:

return string.Format("<li>{0}\n\n</li>\n", item);
//                           ^-^--- Additional newlines

I'm not particularly fond of this approach though because it makes the generated HTML a bit messier than it needs to be. It also seems more hackish than the second option, which is to specifically account for this case in the inline code path similarly to how nested lists are dealt with:

item = DoLists(Outdent(item));
item = DoBlockQuotes(item); // Handle the nested blockquote explicitly
item = item.TrimEnd('\n');
item = RunSpanGamut(item);

I'm not positive that either of these options is the ideal solution, but I don't see a very clean way of addressing this problem otherwise (and it does seem like something that should be addressed). Both options do fix your example and the one I linked to above, however, so hopefully this will be given some consideration.

share|improve this answer

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .