It's better when it's simple

User Tools

Site Tools


relativens plugin

Compatible with DokuWiki


plugin Links & media that don't start with / or : default to being relative to the namespace in which the current page is.

Last updated on
Conflicts with

This extension has not been updated in over 2 years. It may no longer be maintained or supported and may have compatibility issues.

Similar to relativelinks

Tagged with links, namespace

This plugin is a remake of relativelinks plugin. This does basically the same thing, but is implemented in a more subtle way. It also tries to handle media.

Download and Installation

Download and install the plugin using the Plugin Manager using the following URL. Refer to Plugins on how to install plugins manually.


 * Plugin relativens: Links & media that don't start with / or : default
 * to being relative to the namespace in which the current page is.
 * @license    GPL 2 (
 * @author     Peter Lamberg (pe78 [at] pelam dot fi)
 * @based_on   "pagespace" plugin by Symon Bent and "baselink" plugin Robert Meerman. Contains portion of code from DokuWiki source file handler.php.
if(!defined('DOKU_INC')) die();
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
class syntax_plugin_relativens extends DokuWiki_Syntax_Plugin {
    function getInfo() {
        return array('author' => 'Peter Lamberg',
                     'email'  => 'pe78 [at] pelam dot fi',
                     'date'   => '2008-12-30',
                     'name'   => 'relativens',
                     'desc'   => "Plugin relativens: Links & media that don't start with / or : default to being relative to the namespace in which the current page is.",
                     'url'    => '');
    function getType() {
        return 'substition';
    // before built in links & media
    function getSort(){ return 299; }
    function connectTo($mode) {
    function handle($match, $state, $pos, &$handler) {
        // Following link parsing code is originally copied from Dokuwiki handler.php
        // See which one we caught
        $isMedia = preg_match('/^\{\{/', $link);
        $isMedia = 0;
        $originalMatch = $match;
        // Strip the opening and closing markup
        // At same time detect if this is media or link
        // and handler.internallink do this too, but
        // they don't check if they replaced anything.
        $match = preg_replace(array('/^\{\{/','/\}\}$/u'),'',$match, 2, $isMedia);
        $match = preg_replace(array('/^\[\[/','/\]\]$/u'),'',$match, 2);
        // Split title from URL
        $linkAndTitle = preg_split('/\|/u',$match,2);
        $linkTrimmed = trim($linkAndTitle[0]);
        $modifiedMatch = $originalMatch;
        // Give special treatment to the first few characters
        // of internal links and media links (media links are always "internal"?).
        // Sadly excluding the non internal links is a complicated process
        // and we end up doing it twice, but at least the results of these
        // handle functions are cached.
        if($isMedia || $this->isLinkInternal($linkTrimmed)) {
            // unless it's explicitly absolute,
            // Make it look like relative
            $modifiedMatch = preg_replace('/(^(?:\[\[|\{\{)\s*)(?![\:\/])/', '\\1./', $modifiedMatch, 1);
        // let the regular handler take care of the rest
        if($isMedia) {
            $handler->media($modifiedMatch, $state, $pos);
            $handler->internallink($modifiedMatch, $state, $pos);
    function isLinkInternal($linkPart) {
        // If conditions copied from Dokuwiki handler.php
        if ( preg_match('/^[a-zA-Z\.]+>{1}.*$/u',$linkPart) ) {
            return false;
        }elseif ( preg_match('/^\\\\\\\\[\w.:?\-;,]+?\\\\/u',$linkPart) ) {
            return false;
        }elseif ( preg_match('#^([a-z0-9\-\.+]+?)://#i',$linkPart) ) {
            return false;
        }elseif ( preg_match('<'.PREG_PATTERN_VALID_EMAIL.'>',$linkPart) ) {
            return false;
        }elseif ( preg_match('!^#.+!',$linkPart) ) {
            return false;
            return true;
    function render($mode, &$renderer, $data) {
        // Should never come here, since we leech the original handler for most processing
        return false;


This code assumes php5 because of the preg_replace call - it has one argument too much for php4. To get it working on php4, change

$match = preg_replace(array('/^\{\{/','/\}\}$/u'),'',$match, 2, $isMedia);


$match = preg_replace(array('/^\{\{/','/\}\}$/u'),'',$match, 2);

To let it work more proper with media in php4 nevertheless, also change

       // See which one we caught
        $isMedia = preg_match('/^\{\{/', $link);

        $isMedia = 0;


       // See which one we caught
        $isMedia = preg_match('/^\{\{/', $match);

        // $isMedia = 0;

I'm not sure what all this implies, but it seems to be working here.

Allthough using this fix, other plugins that use the media link format (like { { mp3play>your:link:here } } ) seem to loose their trigger and get displayed as a normal media link.

pike 200901

I have also noticed some weird behaviour with media links…

I think I can see why that “mp3play” link would not work. The plugin assumes that:

  • Only “internal links” should be “relativized”
    • Links with special syntax like “mp3play>” are not considered“internal links”
  • Except, that all media links are considered “internal”

Then I think it proceeds and mucks up that mp3play> prefix by inserting ./ at the wrong place

The code that mangles the link to be relative should be made more sensible, or the assumption that media links are always relative should be removed…

I'll try to fix this and the php4 compatibility next time I need to hack our internal wiki…

Peter 200907

plugin/relativens.txt · Last modified: 2010-12-08 00:57 by ach