parser: Omit outputting newline after final line
[lhc/web/wiklou.git] / includes / parser / BlockLevelPass.php
index bb448b2..25f4b5c 100644 (file)
@@ -61,15 +61,26 @@ class BlockLevelPass {
                $this->lineStart = $lineStart;
        }
 
+       /**
+        * @return bool
+        */
+       private function hasOpenParagraph() {
+               return $this->lastSection !== '';
+       }
+
        /**
         * If a pre or p is open, return the corresponding close tag and update
         * the state. If no tag is open, return an empty string.
+        * @param bool $atTheEnd Omit trailing newline if we've reached the end.
         * @return string
         */
-       private function closeParagraph() {
+       private function closeParagraph( $atTheEnd = false ) {
                $result = '';
-               if ( $this->lastSection !== '' ) {
-                       $result = '</' . $this->lastSection . ">\n";
+               if ( $this->hasOpenParagraph() ) {
+                       $result = '</' . $this->lastSection . '>';
+                       if ( !$atTheEnd ) {
+                               $result .= "\n";
+                       }
                }
                $this->inPre = false;
                $this->lastSection = '';
@@ -106,13 +117,13 @@ class BlockLevelPass {
        private function openList( $char ) {
                $result = $this->closeParagraph();
 
-               if ( '*' === $char ) {
+               if ( $char === '*' ) {
                        $result .= "<ul><li>";
-               } elseif ( '#' === $char ) {
+               } elseif ( $char === '#' ) {
                        $result .= "<ol><li>";
-               } elseif ( ':' === $char ) {
+               } elseif ( $char === ':' ) {
                        $result .= "<dl><dd>";
-               } elseif ( ';' === $char ) {
+               } elseif ( $char === ';' ) {
                        $result .= "<dl><dt>";
                        $this->DTopen = true;
                } else {
@@ -129,14 +140,14 @@ class BlockLevelPass {
         * @return string
         */
        private function nextItem( $char ) {
-               if ( '*' === $char || '#' === $char ) {
+               if ( $char === '*' || $char === '#' ) {
                        return "</li>\n<li>";
-               } elseif ( ':' === $char || ';' === $char ) {
+               } elseif ( $char === ':' || $char === ';' ) {
                        $close = "</dd>\n";
                        if ( $this->DTopen ) {
                                $close = "</dt>\n";
                        }
-                       if ( ';' === $char ) {
+                       if ( $char === ';' ) {
                                $this->DTopen = true;
                                return $close . '<dt>';
                        } else {
@@ -154,11 +165,11 @@ class BlockLevelPass {
         * @return string
         */
        private function closeList( $char ) {
-               if ( '*' === $char ) {
+               if ( $char === '*' ) {
                        $text = "</li></ul>";
-               } elseif ( '#' === $char ) {
+               } elseif ( $char === '#' ) {
                        $text = "</li></ol>";
-               } elseif ( ':' === $char ) {
+               } elseif ( $char === ':' ) {
                        if ( $this->DTopen ) {
                                $this->DTopen = false;
                                $text = "</dt></dl>";
@@ -188,7 +199,8 @@ class BlockLevelPass {
                $pendingPTag = false;
                $inBlockquote = false;
 
-               foreach ( $textLines as $inputLine ) {
+               $lineCount = count( $textLines );
+               foreach ( $textLines as $i => $inputLine ) {
                        # Fix up $lineStart
                        if ( !$this->lineStart ) {
                                $output .= $inputLine;
@@ -272,7 +284,7 @@ class BlockLevelPass {
                                        $char = $prefix[$commonPrefixLength];
                                        $output .= $this->openList( $char );
 
-                                       if ( ';' === $char ) {
+                                       if ( $char === ';' ) {
                                                # @todo FIXME: This is dupe of code above
                                                if ( $this->findColonNoLinks( $t, $term, $t2 ) !== false ) {
                                                        $t = $t2;
@@ -289,7 +301,7 @@ class BlockLevelPass {
                        }
 
                        # If we have no prefixes, go to paragraph mode.
-                       if ( 0 == $prefixLength ) {
+                       if ( $prefixLength == 0 ) {
                                # No prefix (not in list)--go to paragraph mode
                                # @todo consider using a stack for nestable elements like span, table and div
 
@@ -340,7 +352,7 @@ class BlockLevelPass {
                                        }
                                        $inBlockElem = !$closeMatch;
                                } elseif ( !$inBlockElem && !$this->inPre ) {
-                                       if ( ' ' == substr( $t, 0, 1 )
+                                       if ( substr( $t, 0, 1 ) == ' '
                                                && ( $this->lastSection === 'pre' || trim( $t ) != '' )
                                                && !$inBlockquote
                                        ) {
@@ -357,7 +369,6 @@ class BlockLevelPass {
                                                if ( $pendingPTag ) {
                                                        $output .= $this->closeParagraph();
                                                        $pendingPTag = false;
-                                                       $this->lastSection = '';
                                                }
                                        } else {
                                                # paragraph
@@ -369,7 +380,6 @@ class BlockLevelPass {
                                                        } else {
                                                                if ( $this->lastSection !== 'p' ) {
                                                                        $output .= $this->closeParagraph();
-                                                                       $this->lastSection = '';
                                                                        $pendingPTag = '<p>';
                                                                } else {
                                                                        $pendingPTag = '</p><p>';
@@ -395,7 +405,11 @@ class BlockLevelPass {
                        if ( $pendingPTag === false ) {
                                if ( $prefixLength === 0 ) {
                                        $output .= $t;
-                                       $output .= "\n";
+                                       // Add a newline if there's an open paragraph
+                                       // or we've yet to reach the last line.
+                                       if ( $i < $lineCount - 1 || $this->hasOpenParagraph() ) {
+                                               $output .= "\n";
+                                       }
                                } else {
                                        // Trim whitespace in list items
                                        $output .= trim( $t );
@@ -405,15 +419,13 @@ class BlockLevelPass {
                while ( $prefixLength ) {
                        $output .= $this->closeList( $prefix2[$prefixLength - 1] );
                        --$prefixLength;
-                       if ( !$prefixLength ) {
+                       // Note that a paragraph is only ever opened when `prefixLength`
+                       // is zero, but we'll choose to be overly cautious.
+                       if ( !$prefixLength && $this->hasOpenParagraph() ) {
                                $output .= "\n";
                        }
                }
-               if ( $this->lastSection !== '' ) {
-                       $output .= '</' . $this->lastSection . '>';
-                       $this->lastSection = '';
-               }
-
+               $output .= $this->closeParagraph( true );
                return $output;
        }