Page MenuHomePhabricator

TOC not properly rendered when using $wgMaxTocLevel
Closed, ResolvedPublic


Author: gouroulapin

How to reproduce this bug:

  • I used a clean install of MediaWiki 1.6.6
  • I set "$wgMaxTocLevel = 3;" in LocalSettings.php
  • I create a test page:

header 1

header 2

header 2.1

header 2.2.1

header 3

header 3.1

header 3.2

  • I click on Preview, or Save (the result is the same)
  • The TOC is not rendered as it should:

Roughly, there are too much "</ul></li>" generated.
It probably comes from improper calls to function tocUnindent()
(includes/Linker.php) from parser (includes/Parser.php).

This was my first bug report, I hope it is accurate.

Thanks for your excellent work,

Best regards.

Version: 1.6.x
Severity: minor



Event Timeline

bzimport raised the priority of this task from to Low.Nov 21 2014, 9:15 PM
bzimport set Reference to bz6204.
bzimport added a subscriber: Unknown Object (MLST).

dbu wrote:

The problem is indeed in function formatHeadings in Parser.php
The following line always unindents from the current depth, altough we might did
not reach that depth.

if( $toclevel<$wgMaxTocLevel ) {

$toc .= $sk->tocUnindent( $prevtoclevel - $toclevel );


I fixed it in my code using
$toc .= $sk->tocUnindent( min($prevtoclevel, $wgMaxTocLevel-1) - $toclevel );

From the svn repository, i think the bug is still present in current versions.
Can anybody confirm or deny this?

Fixed in r21725 along with a couple related bugs.

r21725 fixed the issue with $wgMaxTocLevel = 3 but it caused the same
bug with the default $wgMaxTocLevel = 999 (see bug #9760).

I reverted a small part of r21725 to solve bug #9760, thus reopening this one.

I meant bug #9764 instead of bug #9760.

Added a parser test in r21833 :

TOC with wgMaxTocLevel=3 (bug 6204)

Fixed in r21837.

We unindented line without checking if we did an indent before, that
was not always the case cause $wgMaxTocLevel actually prevent the indenting
of heading above its level.

brandono wrote:

This is not fixed yet (as of 1.11). This is the corner case.

for example when wgMaxTocLevel = 3

Section 1

Section 1.1

Section 1.1.1==== <<-- this is hidden
Section <<-- this is hidden

Section 2== <<-- this only gets UnIndented ONCE... not twice.

The problem is $prevtoclevel is not kept track of properly. The fix is to track it whenever we indent/unindent. You cannot (should not) track it with toclevel changes because those can fluctuate outside of the $wgMaxTocLevel area.

around line 3561, remove $prevtoclevel set

if( $toclevel ) {

$prevlevel = $level;
//$prevtoclevel = $toclevel;  //<<---commented out


around line 3605, track $prevtoclevel.

if( $toclevel<$wgMaxTocLevel ) {

if($prevtoclevel < $wgMaxTocLevel) {
    # Unindent only if the previous toc level was shown :p
    $toc .= $sk->tocUnindent( $prevtoclevel - $toclevel );
    $prevtoclevel = $toclevel; //<<--added.
} else {
    $toc .= $sk->tocLineEnd();


This fixed it for us by tracking $prevtoclevel only with actual indentation/unindentations. Might not be the right fix for everybody though. Thoughts?

Corrected example text (was missing a =):

Section 1

Section 1.1

Section 1.1.1

Section 2

Should add some parser test cases for this?

conrad.irwin wrote:

Fixed (finally) in r72336.

brandono wrote:

I've long since moved on from this project but it's nice to see you guys still care :P.