Extension:Auto-Anchor

From MediaWiki.org
Jump to: navigation, search
MediaWiki extensions manual - list
Crystal Clear action run.png
Auto-Anchor

Release status: beta

Implementation Parser extension, Parser function
Description Create id attribute values using a similar mechanism that headers use
Author(s) David M. Sledge
Latest version 0.7.0 (2007-12-07)
MediaWiki ≥ 1.11.0
License GNU General Public License 2.0 or later
Download See instructions

Translate the Auto-Anchor extension if possible

Check usage and version matrix; code metrics

Introduction[edit | edit source]

One thing about wiki headers is that, with the following:

==='''[[some page|Header Text]] More ''Text'''''===

MediaWiki is smart enough to strip out all the markup and hyper-linking from the text to create an anchor with the name "Header_Text_More_Text." However, it's been found that sometimes this mechanism is desired outside the headers, because, although, it does a great job making destination anchors, one doesn't necessarily want every destination anchor showing up in the TOC. And though you can manually create the destination anchor like so:

<span id="Header Text More Text">'''[[some page|Header Text]] More ''Text'''''</span>

Some of us are just plain lazy. This is where this simple little extension comes into play.

Usage[edit | edit source]

{{#anc: wikitext [| count ]}}

Where count is 0 or any positive integer. It specifies the number of wiki-headers that already have "wikitext". This is needed because there no way for the extension to know what IDs are already in use. (See bugzilla:7356.)

Examples[edit | edit source]

{{#anc: '''Runnin' Down''' [[A Dream]] }}

gives Runnin' Down A Dream where the ID of the surrounding span tag is Runnin.27_Down_A_Dream. So if I want to link to that section I can just copy the text and paste into a wiki-syntax link:

[[#Runnin' Down A Dream|Link!  Damn you!]]

yields Link! Damn you!.

Specifying count as "4"

{{#anc: '''Runnin' Down''' [[A Dream]] | 4 }}

gives the id as Runnin.27_Down_A_Dream_5 without changing the displayed text.

Don't Templates Like Anchor Already Do This?[edit | edit source]

The template doesn't strip out any markup. So if a template named Template:Anchor were used whose content is

<span id="{{{id|{{{1}}}}}}">{{{1}}}</span>

using the above example like so

{{anchor|'''Runnin' Down''' [[A Dream]]}}

would give the id as .27.27.27Runnin.27_Down.27.27.27_.5B.5BA_Dream.5D.5D.

Known Issues[edit | edit source]

Download instructions[edit | edit source]

Please cut and paste the code found below and place it in $IP/extensions/AutoAnchor/AutoAnchor.php and $IP/extensions/AutoAnchor/AutoAnchor.i18n.php. Note: $IP stands for the root directory of your MediaWiki installation, the same directory that holds LocalSettings.php.

Installation[edit | edit source]

To install this extension, add the following to LocalSettings.php:

require_once("$IP/extensions/AutoAnchor/AutoAnchor.php");

Code[edit | edit source]

AutoAnchor.php[edit | edit source]

<?php
 
$wgExtensionFunctions[] = array( 'ExtAutoAnchor', 'setup' );
$wgHooks['LanguageGetMagic'][] = 'ExtAutoAnchor::languageGetMagic';
$wgExtensionCredits['parserhook'][] = array(
    'name' => 'Auto-Anchor Extension',
    'author' => 'David M. Sledge',
    "url"    => "http://www.mediawiki.org/wiki/Extension:Auto-Anchor",
    'version' => ExtAutoAnchor::VERSION,
    "description" => "Create header-like anchors IDs without headers",
);
 
class ExtAutoAnchor
{
    const VERSION = '0.7.0';
    public static $ids = array();
 
    public static function setup()
    {
        global $wgParser;
 
        $wgParser->setFunctionHook( 'anc', array( __CLASS__, 'autoAnchor' ) );
    }
 
    public static function languageGetMagic( &$magicWords, $langCode )
    {
        require_once( dirname( __FILE__ ) . '/AutoAnchor.i18n.php' );
 
        foreach( AutoAnchor_i18n::magicWords( $langCode ) as $word => $trans )
            $magicWords[$word] = $trans;
 
        return true;
    }
 
    public static function autoAnchor( &$parser, $input, $count = '0' )
    {
        // need some input to make the id
        if ( $input === '' )
            // error:  no input
            return '';
 
        // get the value of the 'count' attribute  This attribute indicates the
        // number of wiki headers that use this text.  This extension is unable
        // to get that information itself so it must be supplied by the user; if
        // not specified, it defaults to 0.
        $count = intval( $attrs["count"] );
 
        // make sure it's not less than 0
        if ( $count < 0 )
            $count = 0;
 
        // parse the input
        $parsedInput = $parser->recursiveTagParse( $input );
        // strip out the encoded link to get the displayed text which
        // will be used to generate the span tag's id attribute value.
        $id = $parser->replaceLinkHoldersText( $parsedInput );
        // strip out any HTML markup
        $id = trim( preg_replace( '/<.*?>/m', '', $id ) );
        // escape the string so it contains valid
        // characters for the id attribute
        $id = Sanitizer::escapeId( $id, Sanitizer::NONE );
        // make sure the ID is unique
        $id = self::getUniqueID( $id, $count );
        // put it all together
        $spanid = "<span id=\"$id\">$input</span>";
 
        return $spanid;
    }
 
    // known limitation:  MediaWiki currently (v1.11.0) has no mechanism for
    // enforcing id-uniqueness within an article, so it's entirely possible that
    // another HTML tag will have the same id attribute value as the ones
    // supplied by this method.  We can however, enforce uniqueness the with IDs
    // generated within this extension
    private static function getUniqueID( $id, $count )
    {
        $count++;
 
        // if this isn't the first instance of this id, we append the number of
        // this instance to the id:  "wikitext_2", "wikitext_3",
        // "wikitext_4",... "wikitext_n".
        if ( in_array( $count == 1 ? $id : $id . '_' . $count, self::$ids ) )
        {
            // of course we have to make sure "wikitext_x" doesn't already exist
            // if it does, we increment x by one until we hit an id that doesn't
            // exist yet
            for ( $count++; in_array( $id . '_' . $count, self::$ids ); $count++ ) ;
 
            self::$ids[] = $id . '_' . $count;
 
            return end( self::$ids );
        }
 
        self::$ids[] = $count == 1 ? $id : $id . '_' . $count;
 
        return end( self::$ids );
    }
}

AutoAnchor.i18n.php[edit | edit source]

<?php
 
class AutoAnchor_i18n
{
    private static $words = array(
    // English
        'en' => array(
            'anc'  => array( 0, 'anc' ),
        ),
    );
 
    private static $messages = array(
    // English
        'en' => array(),
    );
 
    public static function getMessages()
    {
        return self::$messages;
    }
 
    /**
     * Get translated magic words, if available
     *
     * @param string $lang Language code
     * @return array
     */
    public static function magicWords( $lang )
    {
        // English is used as a fallback, and the English synonyms are
        // used if a translation has not been provided for a given word
        return ( $lang == 'en' || !isset( self::$words[$lang] ) ) ?
            self::$words['en'] :
            array_merge( self::$words['en'], self::$words[$lang] );
    }
}

See also[edit | edit source]

meta:Help:Section