Extension:Auto-Anchor
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 it is available at translatewiki.net |
|
Check usage and version matrix; code metrics |
Contents
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]
- No guarantee of ID uniqueness.
- Does not ensure the first character of the ID is a letter. Blocked by bugzilla:4515.
- Newlines as part of the input may result in overlapping HTML tags blocks.
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] ); } }