Skip to content

Commit

Permalink
Sort anchors by their associatedPageIndex value
Browse files Browse the repository at this point in the history
This value is always integer, so we don't have to parse things
like Roman numerals (which can exist in anchor text itself),
and we can impose meaningful order on arbitrary string anchors
(which can be surrounded by numeric anchors).

For example, anchor "pg5" can be followed by "pgimage1", then by "pg6".

We are intentionally ignoring anchors with negative numbers,
as this is a convention for anchors that are not supposed to be
in the navigation template.
  • Loading branch information
edwardspec committed Nov 7, 2024
1 parent c53fcdc commit 4dc8de6
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 69 deletions.
3 changes: 1 addition & 2 deletions extension.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@
"MediaWiki\\PrevNextImageLinks\\AssociatedImage": "includes/AssociatedImage.php",
"MediaWiki\\PrevNextImageLinks\\Hooks": "includes/Hooks.php",
"MediaWiki\\PrevNextImageLinks\\NavigationTemplate": "includes/NavigationTemplate.php",
"MediaWiki\\PrevNextImageLinks\\PageFinder": "includes/PageFinder.php",
"MediaWiki\\PrevNextImageLinks\\RomanNumeral": "includes/util/RomanNumeral.php"
"MediaWiki\\PrevNextImageLinks\\PageFinder": "includes/PageFinder.php"
},
"ExtensionMessagesFiles": {
"PrevNextImageLinksMagic": "PrevNextImageLinks.i18n.magic.php"
Expand Down
46 changes: 15 additions & 31 deletions includes/NavigationTemplate.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ public static function pfSubpageAnchorNavigation( Parser $parser, $pageName ) {

/**
* Find all subpages of $title, find all tags like <span id="pg123"> inside each subpage,
* then generate links to every #pg<number> anchor, sorted by number after "pg".
* then generate links to every #pg<number> anchor,
* sorted by first parameter of {{#set_associated_index:}} that is associated with this anchor.
* @param PageIdentity $title
* @return string|array
*/
Expand All @@ -59,7 +60,11 @@ protected function generate( PageIdentity $title ) {

// Find all subpages of $title.
$res = $dbr->newSelectQueryBuilder()
->select( [ 'page_title AS title', 'pp_value AS anchor' ] )
->select( [
'page_title AS title',
'pp_value AS anchor',
'pp_propname AS sortkey'
] )
->from( 'page' )
->join( 'page_props', null, [ 'pp_page = page_id' ] )
->where( [
Expand All @@ -80,29 +85,29 @@ protected function generate( PageIdentity $title ) {
foreach ( $res as $row ) {
// Strip standard prefix ("pg").
$shownAnchor = preg_replace( '/^pg/', '', $row->anchor );
$number = $this->parseAnchorNumber( $row->anchor );
if ( $number < 0 ) {
// Negative numbers (e.g. "pg-5") are NOT shown in the navigation template.
if ( !$shownAnchor || $shownAnchor[0] === '-' ) {
// Empty anchors and anchors with negative numbers (e.g. "pg-5")
// are NOT shown in the navigation template.
continue;
}

$sortkey = intval( preg_replace( '/^associatedPageIndex\./', '', $row->sortkey ) );

$anchorsFound[] = [
'title' => $row->title,
'anchor' => $row->anchor,
'text' => $shownAnchor,
'number' => $number
'sortkey' => $sortkey
];
}

uasort( $anchorsFound, static function ( $a, $b ) {
// Sort by number.
$cmp = $a['number'] - $b['number'];
$cmp = $a['sortkey'] - $b['sortkey'];
if ( $cmp !== 0 ) {
return $cmp;
}

// If numbers are the same (likely non-numeric anchors?),
// then sort by displayed text.
// If sortkeys are the same, then sort by displayed text.
return strcmp( $a['text'], $b['text'] );
} );

Expand All @@ -119,25 +124,4 @@ protected function generate( PageIdentity $title ) {
);
return [ $resultHtml, 'isHTML' => true ];
}

/**
* Detect the number inside the string $anchor, e.g. "15" in "pg15" or "9" in "pg-ix".
* @param string $anchor
* @return int
*/
protected function parseAnchorNumber( $anchor ) {
// Decimal number?
if ( preg_match( '/\-?[0-9]+/', $anchor, $matches ) ) {
return (int)$matches[0];
}

$value = RomanNumeral::romanToInteger( $anchor );
if ( $value ) {
// Found and successfully parsed roman numeral.
return $value;
}

// Default (no number found). These anchors can still be shown.
return 0;
}
}
36 changes: 0 additions & 36 deletions includes/util/RomanNumeral.php

This file was deleted.

0 comments on commit 4dc8de6

Please sign in to comment.