From cab99af90e4b5c9cc1d5f3ce769245876ac643a0 Mon Sep 17 00:00:00 2001 From: Jackmcbarn Date: Sun, 28 Dec 2014 15:07:49 -0500 Subject: [PATCH] Fix TOC anchor name collisions in edge cases Currently, the parser adds a "_2" to the second of two identical headlines to avoid collisions, but there's still a collision if another headline actually ends in "_2". This change causes the new headline to also be checked for a collision, and advances to "_3" or beyond if there is one. Bug: T26787 Change-Id: Id0a55aa4c1917bac2f8f0d4863fcb85bd3dff1ca --- includes/parser/Parser.php | 27 ++++++++++++--------------- tests/parser/parserTests.txt | 25 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/includes/parser/Parser.php b/includes/parser/Parser.php index 7884ca5d45..a9b0c82c62 100644 --- a/includes/parser/Parser.php +++ b/includes/parser/Parser.php @@ -4589,16 +4589,22 @@ class Parser { $legacyArrayKey = strtolower( $legacyHeadline ); } - # count how many in assoc. array so we can track dupes in anchors + # Create the anchor for linking from the TOC to the section + $anchor = $safeHeadline; + $legacyAnchor = $legacyHeadline; if ( isset( $refers[$arrayKey] ) ) { - $refers[$arrayKey]++; + for ( $i = 2; isset( $refers["${arrayKey}_$i"] ); ++$i ); + $anchor .= "_$i"; + $refers["${arrayKey}_$i"] = true; } else { - $refers[$arrayKey] = 1; + $refers[$arrayKey] = true; } - if ( isset( $refers[$legacyArrayKey] ) ) { - $refers[$legacyArrayKey]++; + if ( $legacyHeadline !== false && isset( $refers[$legacyArrayKey] ) ) { + for ( $i = 2; isset( $refers["${legacyArrayKey}_$i"] ); ++$i ); + $legacyAnchor .= "_$i"; + $refers["${legacyArrayKey}_$i"] = true; } else { - $refers[$legacyArrayKey] = 1; + $refers[$legacyArrayKey] = true; } # Don't number the heading if it is the only one (looks silly) @@ -4611,15 +4617,6 @@ class Parser { ) . ' ' . $headline; } - # Create the anchor for linking from the TOC to the section - $anchor = $safeHeadline; - $legacyAnchor = $legacyHeadline; - if ( $refers[$arrayKey] > 1 ) { - $anchor .= '_' . $refers[$arrayKey]; - } - if ( $legacyHeadline !== false && $refers[$legacyArrayKey] > 1 ) { - $legacyAnchor .= '_' . $refers[$legacyArrayKey]; - } if ( $enoughToc && ( !isset( $wgMaxTocLevel ) || $toclevel < $wgMaxTocLevel ) ) { $toc .= Linker::tocLine( $anchor, $tocline, $numbering, $toclevel, ( $isTemplate ? false : $sectionIndex ) ); diff --git a/tests/parser/parserTests.txt b/tests/parser/parserTests.txt index d9831e31e0..cc662808f5 100644 --- a/tests/parser/parserTests.txt +++ b/tests/parser/parserTests.txt @@ -13236,6 +13236,31 @@ Some text !! end +!! test +TOC anchors don't collide +!! wikitext +__FORCETOC__ +== Headline 2 == +== Headline == +== Headline 2 == +== Headline == +!! html +

Contents

+ +
+ +

Headline 2[edit]

+

Headline[edit]

+

Headline 2[edit]

+

Headline[edit]

+ +!! end + # perl -e 'print "="x$_," Level $_ heading","="x$_,"\n" for 1..10' !! test Handling of sections up to level 6 and beyond -- 2.20.1