MediaWiki auto generates numbers in the table of contents. Is there any way to reference these numbers from inside the sections? For example:
==Section==
==Section==
==Section==
===Sub-Section===
Here in {{VARIABLE}}, we talk about. . .
And have {{VARIABLE}} replaced with 3.1?
If you are familiar with LaTeX, I mean something like \ref{a_section}
.
Here is one possible solution. It requires three files to be placed in [wiki_installation_dir]/extensions/GetSectionNumber/.
GetSectionNumber.php:
<?php
if ( !defined( 'MEDIAWIKI' ) ) {
die( 'This file is an extension to MediaWiki and thus not a valid entry point.' );
}
$wgExtensionCredits['parserhook'][] = array(
'path' => __FILE__,
'name' => 'Get Section Number',
'descriptionmsg' => 'Parser function to get the section number, given a title.',
'version' => 0.8,
'author' => 'Seamus J.',
'url' => '',
);
# Place this line in LocalSettings.php:
# require_once "$IP/extensions/GetSectionNumber/GetSectionNumber.php";
# This indicates where to find the localisation file. It is not optional.
$wgExtensionMessagesFiles['GetSectionNumber'] = __DIR__ . '/GetSectionNumber.i18n.php';
$wgAutoloadClasses['ExtGetSectionNumber'] = __DIR__ . '/GetSectionNumber_body.php';
# This indicates where in parser.php this code will run.
$wgHooks['ParserBeforeInternalParse'][] = 'ExtGetSectionNumber::onPBIParseDoFirst';
$wgHooks['ParserBeforeInternalParse'][] = 'ExtGetSectionNumber::onPBIParseDoSecond';
GetSectionNumber_body.php:
class ExtGetSectionNumber {
static $numHeadings = 0;
static $sectionNumber;
private static $hasRun = false;
# This function is called by the hook ParserBeforeInternalParse.
# It registers the parser function that processes 'secnum'.
public static function onPBIParseDoFirst( $parser ) {
$parser->setFunctionHook( 'secnum', 'ExtGetSectionNumber::secnum' );
return true;
}
# This function is called by the hook ParserBeforeInternalParse.
# It parses the text to find the headlines and generate their numbering.
public static function onPBIParseDoSecond( $parser, $text ) {
if (self::$hasRun) return true;
self::$hasRun = true;
$matchArray = array();
#global $sectionNumber;
$sectionNumber = array();
# Taken verbatim from doHeadings in parser.php
# Replaces all '=' with the right <h> tags
for ( $i = 6; $i >= 1; --$i ) {
$h = str_repeat( '=', $i );
$text = preg_replace( "/^$h(.+)$h\\s*$/m", "<h$i>\\1</h$i>", $text );
}
# Taken from formatHeadings in parser.php and modified a bit
# \start generate numbers
self::$numHeadings = preg_match_all(
#'/tocnumber">(?<level>[\d\.]+)<[^<>]+>[\s]<[^<>]+>(?<heading>[^<]+)/',
'/<H(?P<level>[1-6])(?:.*?>)\s*(?P<header>[\s\S]*?)\s*<\/H[1-6] *>/i',
$text,
$matchArray);
# $headlines is an array of the headings on the wiki page
$headlines = $numHeadings !== false ? $matchArray['header'] : array();
# $headlineCount is an iterator used to access $matches
$headlineCount = 0;
# $level is the current level *according to* <hx> tags
# initialize this to first level, so that we can skip special case in loop
$level = $matchArray['level'][0];
# $numberingArray[0-4] tracks the current level in actual numbers
# it constructs the number string stored in $sectionNumbers
$numberingArray = array();
$numberingArray[0] = 0;
# $depth tracks how much of $numberingArray is relevant at each level
$depth = 0;
foreach ( $headlines as $headline ) {
# heading is a sibling to the last one
if ( $matchArray['level'][$headlineCount] == $level ) {
$numberingArray[$depth] += 1;
}
# heading is superior to the last one
elseif ( $matchArray['level'][$headlineCount] < $level ) {
$diff = $level - $matchArray['level'][$headlineCount];
$level -= $diff;
$depth -= $diff;
$numberingArray[$depth] += 1;
}
# heading is a subsection of the last one
elseif ( $matchArray['level'][$headlineCount] > $level ) {
$level += 1;
$depth += 1;
$numberingArray[$depth] = 1;
}
# generate the number
for ($i = 0; $i <= $depth; $i++) {
if ( $i === 0 ) { # we don't need a period at the start of the number
$sectionNumber[$headline][0] = $numberingArray[$i];
} else {
$sectionNumber[$headline][0] .= '.' . $numberingArray[$i];
}
}
# initialize the autoinc number to 1
$sectionNumber[$headline][1] = 1;
$headlineCount += 1;
}
# \end generate numbers
# transfer the local array to a class static one
# so we only need to run onPBIParseDoSecond once
self::$sectionNumber = $sectionNumber;
return true;
}
# This returns the formated number for the requested section heading.
# It is also capable of formating auto-incrementing "sub" numbers for use in lists, etc.
public static function secnum( $parser, $autoinc, $heading ) {
# if the requested heading exists
if (array_key_exists($heading,self::$sectionNumber)) {
$autoinc = strtoupper($autoinc);
if ($autoinc === 'Y' or $autoinc === 'YES') {
$output = '<strong>' . self::$sectionNumber[$heading][0]
. '.' . self::$sectionNumber[$heading][1] . '</strong>';
self::$sectionNumber[$heading][1]++; # increment for the next call
} else {
$output = '<strong>' . self::$sectionNumber[$heading][0] . '</strong>';
self::$sectionNumber[$heading][1] = 1; # reset the auto increment
}
} else {
$output = '<strong>' . htmlspecialchars($heading) . '</strong>';
}
return $output;
}
}
GetSectionNumber.i18n.php:
<?php
# Internationalization file for GetSectionNumber
# make sure $wgExtensionMessageFiles['GetSectionNumber'] = __DIR__ . '/GetSectionNumber.i18n.php
# is placed in GetSectionNumber.php
$magicWords = array();
/** English (en) **/
$magicWords['en'] = array(
'secnum' => array( 0, 'secnum' ),
);
Follow the instructions in the comments to install. To use, insert {{#secnum:$x|$T}}
in the wiki code wherever you want the numbers to appear. $x
is yes/YES/y/Y if you want to turn on auto-incrementing "sub" numbering (like if you are using this in a list, which is what I wanted it for) or N/n otherwise. $T
is the heading title of the section, spelled and spaced exactly as it is between the ='s.