4

How is the exact syntax of the <pre> tag? Can I put the closing </pre> tag on a new line? If I do, then the preview is completely messed up, but the final result is as expected. (I know that I can mark a code block by indenting it 4 spaces, but that method sometimes has drawbacks.)

To see the problem, hit the "edit" link and test the following: The messed-up preview can be fixed by any of the following three edits:

  • removing the </code> tag,
  • putting the </pre> tag on the same line as <pre>some more code,
  • indenting the line <pre><code>some code by one to three spaces.

Here's the test HTML code:

some code

Line followed by an empty line

Section title

Another line

some more code
5

2 Answers 2

4

The problem isn't so much that you put the closing </pre> tag on a new line, but rather that you have two sets of <pre> blocks with stuff in them, and you didn't write them in a way that the parser was hoping you would.

Essentially, what happens is that there's a set of regular expressions that attempt to temporarily remove raw HTML from the source prior to the Markdown syntax being parsed, and the first of these checks for something like the following:

<div>
    <!-- Possibly some content -->
</div>

Where it picks up the first tag (because it isn't indented), then attempts to find the closing tag by looking first for any number of lines, followed by the closing tag preceded only by a newline (i.e. the tag is not indented). The rationale for this in the original WMD source is that it avoids catching the closing tag of nested blocks, by imposing that they are indented:

<div>
    <div>
    inner block
    </div> <!-- This won't be considered the closing tag of the first div -->
</div>

Naturally, this isn't always how things work, so there's a more liberal <tag>...</tag> check after that. Unfortunately in this case, the damage is already done, because the parser has decided that the opening tag of your first block matches the closing tag of your second block, and has removed everything between them from being parsed as Markdown (since content inside of raw HTML is never parsed).

Of course, when the generated HTML is inserted into the preview, your <pre> blocks display correctly because the browser recognizes that they are how they're supposed to be. The pieces in between are still as you wrote them though, having not been parsed.

I'm not sure if there's any good way to go about fixing this, but I'll take a look. I suspect that the server-side parser is using a slightly more capable expression to do the nested block matching that isn't supported by the JavaScript regular expression engine, which would explain why it gets on a bit better here.

In your particular case, the most parser-friendly source would likely be the following:

<pre>
<code>some code</code>
</pre>

Line followed by an empty line

### Section title ###

Another line

<pre>
some more code
</pre>

Update:

I was able to come up with a modified expression that, while still not quite as good as the server-side parser, should handle cases like this more gracefully by scoping the non-indented closing tag to the closest non-indented opening tag. This would be a replacement for the first regex in _HashHTMLBlocks():

/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b(?:[^\n\r]*\n(?!<\2>))*?<\/\2>[ \t]*(?=\n+))/gm
8
  • Wow, thanks a lot for this detailed explanation; I think now I finally understand what's happening. The only thing I don't like about your parser-friendly version is that the <code> and </code> tags both have to be on the same lines as the code. Commented Jul 23, 2011 at 22:00
  • Yeah, that is a bit annoying unfortunately. I feel like the parser should be able to do a little better with this case, but I'm worried that a more correct approach might end up being a bit expensive. I'm still playing around with it though.
    – Tim Stone
    Commented Jul 25, 2011 at 5:50
  • Thanks a lot for looking into it. If improving the parser makes the preview slower, then maybe it's not worth it as it's probably an edge case. I'm quite happy already since now you told me "the precise syntax of the <pre> tag" - put it on a line of its own, without indentation. Commented Jul 25, 2011 at 16:03
  • Thanks for the update! I can't say I fully understand it, but that's not important. What I'm wondering about: in my posts, I can't use most of those HTML blocks anyway, can I? Commented Jul 26, 2011 at 9:13
  • Yep, that's right. What happens is that those blocks are permitted by the Markdown parser, but because Stack Exchange has stricter criteria for post entry there's another external step that removes all of the stuff that isn't allowed here.
    – Tim Stone
    Commented Jul 26, 2011 at 15:22
  • Hmm, I guess I'm being completely ignorant here, but why don't you removed all that stuff first? Commented Jul 26, 2011 at 16:11
  • There are some sanitation steps involving links and images (in particular, their URLs) that can only be easily performed after the Markdown parser has run. I imagine it's just easier to run all of the filtering at once, when you know all you have left in the post is the converted HTML.
    – Tim Stone
    Commented Jul 26, 2011 at 16:39
  • Ah, I think I understand - thanks! Commented Jul 27, 2011 at 8:20
2

You could just indent the code you want for format by four spaces instead. You can even select it and click the {} button or use the Ctrl-K shortcut to have it indented automatically.

This also has the advantage to escape special characters in the code block, so that for example special characters like < and html tags contained in the code are displayed correctly.

2
  • Thanks, but well, I know that. I struggled with the strange preview when writing that post. Commented Mar 22, 2011 at 18:38
  • 1
    It can be a disadvantage of the 4 space indentation method that special characters are escaped: I can't use <b>...</b> anymore. See also this nice answer. Commented Mar 22, 2011 at 18:40

You must log in to answer this question.

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