Fix parsing of <pre> tags generated by extension tag hooks
authorThis, that and the other <at.light@live.com.au>
Sun, 8 Jan 2017 09:15:48 +0000 (20:15 +1100)
committerThis, that and the other <at.light@live.com.au>
Sat, 17 Mar 2018 12:20:50 +0000 (23:20 +1100)
When this part of BlockLevelPass::execute() encounters a block-level tag,
such as <hr>, one of $openMatch or $closeMatch will be truthy.

Without this patch, $this->closeParagraph() is unconditionally called in
this situation, which sets $this->inPre = false. If we're already inside a
<pre> tag, this makes the parser think we're no longer in a <pre>
environment, so it starts wrapping the <pre> tag's content in <p> tags as
if it was processing regular content.

We should only call $this->closeParagraph() in the case that (a) we are not
inside a <pre> tag, or (b) the block-level tag that is being opened is
itself a <pre> tag (in which case $preOpenMatch will be truthy, and
$this->inPre will have already been set to true).

This doesn't affect the parsing of <pre> tags that are written in wikitext,
since their content isn't parsed. It only affects hooks and the like that
return <pre> tags.

This doesn't solve the task T7718 that is mentioned in the code comment,
but if the testwiki test cases linked there are anything to go by, it
doesn't make the problem worse in any way.

This is required for Poem change I754f2e84f7d6efc0829765c82297f2de5f9ca149.

Change-Id: I469e633fc41d8ca73653c7e982c591092dcb1708

includes/parser/BlockLevelPass.php
tests/parser/parserTests.txt

index 7f78912..7c92d76 100644 (file)
@@ -304,8 +304,12 @@ class BlockLevelPass {
 
                                if ( $openMatch || $closeMatch ) {
                                        $pendingPTag = false;
-                                       # @todo T7718: paragraph closed
-                                       $output .= $this->closeParagraph();
+                                       // Only close the paragraph if we're not inside a <pre> tag, or if
+                                       // that <pre> tag has just been opened
+                                       if ( !$this->inPre || $preOpenMatch ) {
+                                               // @todo T7718: paragraph closed
+                                               $output .= $this->closeParagraph();
+                                       }
                                        if ( $preOpenMatch && !$preCloseMatch ) {
                                                $this->inPre = true;
                                        }
index f98044b..889f040 100644 (file)
@@ -18241,6 +18241,27 @@ this is a '''test'''
 <p>this is a <b>test</b></p>
 !! end
 
+!! test
+Parser hook: horizontal rule inside extension tag that outputs <pre>
+!! wikitext
+<tag>
+Hello
+<hr/>
+Goodbye
+</tag>
+!! html/php
+<pre>
+'
+Hello
+<hr/>
+Goodbye
+'
+array (
+)
+</pre>
+
+!! end
+
 ###
 ### (see tests/parser/parserTestsParserHook.php for the <statictag> extension)
 ###