Trace: » CPUInfo » SheepShaver » Basilisk II JIT » VirtualBox OSE for Mandriva Linux » Welcome » M68K Emulator Testsuite » SheepShaver Help Center » NSPluginWrapper Downloads » About » About this site

About this site

So, why did I choose a Wiki instead of plain HTML, WML, Mambo, SPIP, [enter your favorite here]?

Well, simply because I wanted to try something else than the Website Meta Language and because Dokuwiki actually generates good looking pages. This would also enable contributors to add help contents for projects like Basilisk II or SheepShaver. ;-)

The following Dokuwiki plugins are installed: Boxes, Include. In addition to that, the Better navigation and ACH templates are also used. The latter two extensions are slightly patched to fit my needs, see hereunder for details.

Patches

Dokuwiki

I wanted {{this}} to get to the root of this site, though basedir or baseurl config items would probably have better fit this role.

--- dokuwiki-2005-09-22/inc/confutils.php	2005-09-22 19:21:09.000000000 +0200
+++ dokuwiki/inc/confutils.php	2005-11-07 21:19:30.000000000 +0100
@@ -111,7 +111,7 @@ function getInterwiki() {
     }
   }
   //add sepecial case 'this'
-  $wikis['this'] = DOKU_URL.'{NAME}';
+  $wikis['this'] = DOKU_URL.'../{NAME}';
   return $wikis;
 }

Include Plugin

Don’t use styles to include a page, simply make it a verbatim copy.

--- dokuwiki/lib/plugins/include/syntax.php	2005-09-27 02:13:04.000000000 +0200
+++ dokuwiki/lib/plugins/include/syntax.php	2005-11-13 21:35:41.000000000 +0100
@@ -122,9 +122,7 @@ class syntax_plugin_include extends Doku
             $renderer->info['cache'] = FALSE;
             
             // embed the included page
-            $renderer->doc .= '<div class="include">';
             $renderer->doc .= $text;
-            $renderer->doc .= '</div>';
             return true;
         }
         return false;

Multilingual Support

Multilingual support is very basic here, the top-level namespace identifies it. Paths and page names shall be equally named (both English and French here). This patch assumes the sidebar template is used but it can easily be adapted for others.

Note: I don’t know PHP so there are probably better means to achieve this.

--- dokuwiki-2005-09-22/inc/template.php	2005-10-21 13:43:58.000000000 +0200
+++ dokuwiki/inc/template.php	2005-11-12 11:35:00.000000000 +0100
@@ -248,6 +248,28 @@ function tpl_link($url,$name,$more=''){
 }
 
 /**
+ * Print links to alternate language pages
+ */
+function tpl_lang_links($pagename){
+  global $conf;
+  $path = explode(':', $pagename);
+  $lang = $path[0];
+  if (in_array($lang, $conf['available_languages'])) {
+    foreach ($conf['available_languages'] as $l) {
+      if ($l != $lang) {
+        $path[0] = $l;
+        $new_id = implode(':', $path);
+        if (@file_exists(wikiFN($new_id))) {
+          print "<div class=\"pagename\">[[";
+          tpl_link(wl($new_id), $l);
+          print "]]</div>\n";
+        }
+      }
+    }
+  }
+}
+
+/**
  * Prints a link to a WikiPage
  *
  * Wrapper around html_wikilink
--- dokuwiki-2005-09-22/lib/tpl/sidebar/main.php	2005-09-20 14:19:56.000000000 +0200
+++ dokuwiki/lib/tpl/sidebar/main.php	2005-11-07 21:25:00.000000000 +0100
@@ -71,6 +71,7 @@ include(dirname(__FILE__).'/sidebar.php'
       <div class="pagename">
         [[<?php tpl_link(wl($ID,'do=backlink'),$ID)?>]]
       </div>
+      <?php tpl_lang_links($ID)?>
     </div>
   
     <?php /*old includehook*/ @include(dirname(__FILE__).'/header.html')?>

Additional Plugins

Partial Include

This partially includes a page into another with at most n_sections sections. A section is identified as header or list tags for the specified optional_min_level level, if available (default: 1). It works for my needs and would probably fails for others. When n_sections items are reached, continuation link ([...]) is added. The code is derived from the Include and Blog plugins.

<?php
/**
 * Partial Include Plugin: displays parts of a wiki page within another
 * Usage:
 * {{subpage>page}} for "page" in same namespace
 * {{subpage>:page}} for "page" in top namespace
 * {{subpage>namespace:page}} for "page" in namespace "namespace"
 * {{subpage>.namespace:page}} for "page" in subnamespace "namespace"
 * {{subpage>page#n_sections;optional_min_level}} for a section of "page"
 *
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Gwenole Beauchesne <masked-email>
 */
 
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');
 
/**
 * All DokuWiki plugins to extend the parser/rendering mechanism
 * need to inherit from this class
 */
class syntax_plugin_partial_include extends DokuWiki_Syntax_Plugin {
 
    /**
     * return some info
     */
    function getInfo(){
        return array(
            'author' => 'Gwenole Beauchesne',
            'email'  => '<masked-email>',
            'date'   => '2005-11-01',
            'name'   => 'Partial Include Plugin',
            'desc'   => 'displays parts of a wiki page within another',
            'url'    => '',
        );
    }
 
    /**
     * What kind of syntax are we?
     */
    function getType(){
        return 'substition';
    }
 
    /**
     * Where to sort in?
     */
    function getSort(){
        return 309;
    }
 
    /**
     * Paragraph Type
     */
    function getPType(){
        return 'block';
    }
 
    /**
     * Connect pattern to lexer
     */
    function connectTo($mode) {
        $this->Lexer->addSpecialPattern('\{\{subpage.+?\}\}',$mode,'plugin_partial_include');
    }
 
    /**
     * Handle the match
     */
    function handle($match, $state, $pos, &$handler){
        global $ID;
        global $filechain;
 
        $match = substr($match,10,-2);                // strip markup
        $match = preg_split('/\#/u',$match,2);        // split hash from filename
        resolve_pageid(getNS($ID),$match[0],$exists); // resolve shortcuts
 
        // check for existence and permission
        if ((!$exists) || (auth_quickaclcheck($match[0]) < 1)) return false;
 
        // check for and establish start of $filechain
        if (!isset($filechain)) $filechain[] = $ID;
 
        // don't allow the same file to be included more than once
        if (in_array($match[0], $filechain)) return false;
 
        // add included page to the filechain
        $filechain[] = $match[0];
 
        // get sections information
        list($num, $level, $type) = explode(';',$match[1],3);
        if ($num == 0)
            $num = 1;
        if ($level == 0)
            $level = 1;
        if ($type == '')
            $type = 'header';
        switch ($type) {
        case 'header': case 'list': break;
        default: return false;
        }
 
        return array($match[0], $num, $level, $type);
    }    
 
    /**
     * Create output
     */
    function render($mode, &$renderer, $data) {
                            
        if($mode == 'xhtml'){
            $file = wikiFN($data[0]);
            if (!@file_exists($file)) return false;
 
            // get instructions
            $instr = p_cached_instructions($file, false);
 
            // filter section
            $instr = $this->{'_getSection_'.$data[3]}($data[1], $data[2], $more, $instr);
 
            // correct relative internal links and media
            $instr = $this->_correctRelNS($instr, $data[0]);
            
            // render the instructions on the fly
            $text = p_render('xhtml',$instr,$info);
 
            // remove toc, section edit buttons and category tags
            $patterns = array('!<div class="toc">.*?(</div>\n</div>)!s',
                              '#<!-- SECTION \[(\d*-\d*)\] -->#e',
                              '!<div class="category">.*?</div>!s');
            $replace  = array('','','');
            $text = preg_replace($patterns,$replace,$text);
 
            // prevent caching to ensure the included page is always fresh
            $renderer->info['cache'] = FALSE;
 
            // embed the included page
            $renderer->doc .= $text;
 
            // append continuation link
            if ($more) {
                $level = $data[2];
                $mlink = $renderer->internallink($data[0],'...','','true');
                switch ($data[3]) {
                case 'header':
                    $renderer->doc .= "<div class=\"level$level\">[$mlink]</div>";
                    break;
                case 'list': // <ul> is open at this stage
                    $renderer->doc .= "<li class=\"level$level\"><div class=\"li\">[$mlink]</div></li></ul>";
                }
            }
 
            return true;
        }
        return false;
    }
 
    /**
     * Get N 'header' sections including their subsections
     */
    function _getSection_header($max_sections,$min_level,&$more,$instructions){
        $more = 0;
        $n_sections = 0;
        foreach ($instructions as $instruction){
            if ($instruction[0] == 'header'){
                $level = $instruction[1][1];
                if ($level >= $min_level) {
                    if ($level == $min_level) {
                        $n_sections += 1;
                        if ($n_sections > $max_sections) {
                            $more = 1;
                            return $i;
                        }
                    }
                    $i[] = $instruction;
                } elseif ($n_sections && $level < $min_level)
                    return $i;
            } elseif ($n_sections) {
                $i[] = $instruction;
            }
        }
        return $i;
    }
    
    /**
     * Get N 'list items including their sublists
     * XXX factorisation candidate
     */
    function _getSection_list($max_sections,$min_level,&$more,$instructions){
        $more = 0;
        $n_sections = 0;
        for ($it = 0; $it < sizeof($instructions); $it++){
            $instruction = $instructions[$it];
            if ($instruction[0] == 'listitem_open'){
                $level = $instruction[1][0];
                if ($level >= $min_level) {
                    if ($level == $min_level) {
                        $n_sections += 1;
                        if ($n_sections == 1) 
                            $i[] = $instructions[$it-1];
                        elseif ($n_sections > $max_sections) {
                            $more = 1;
                            return $i;
                        }
                    }
                    $i[] = $instruction;
                } elseif ($n_sections && $level < $min_level)
                    return $i;
            } elseif ($n_sections) {
                $i[] = $instruction;
            }
        }
        return $i;
    }
    
    /**
     * Corrects relative internal links and media
     */
    function _correctRelNS($instr,$incl){
        global $ID;
        
        // check if included page is in same namespace
        $iNS = getNS($incl);
        if (getNS($ID) == $iNS) return $instr;
        
        // convert internal links and media from relative to absolute
        $n = count($instr);
        for($i = 0; $i < $n; $i++){
            if (substr($instr[$i][0], 0, 8) == 'internal'){
                
                // relative subnamespace
                if ($instr[$i][1][0]{0} == '.'){
                    $instr[$i][1][0] = $iNS.':'.substr($instr[$i][1][0], 1);
                    
                // relative link
                } elseif (strpos($instr[$i][1][0],':') === false) {
                    $instr[$i][1][0] = $iNS.':'.$instr[$i][1][0];
                }
            }
        }
        return $instr;
    }
}
 
//Setup VIM: ex: et ts=4 enc=utf-8 :

Downloads

This is actually a multiple include plugin, and is derived thereof. dist_YYYYMMDD pages are fetched from the specified namespace. At most count items are shown.

<?php
/**
 * Downloads Plugin: agglomerate several download wiki pages into another
 * Usage:
 * {{downloads>namespace}} add all dist_YYYYMMDD wiki pages from namespace
 * {{downloads>namespace#count}} add at most count wiki pages
 *
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Gwenole Beauchesne <masked-email>
 */
 
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');
 
 
/**
 * All DokuWiki plugins to extend the parser/rendering mechanism
 * need to inherit from this class
 */
class syntax_plugin_downloads extends DokuWiki_Syntax_Plugin {
 
    /**
     * return some info
     */
    function getInfo(){
        return array(
            'author' => 'Gwenole Beauchesne',
            'email'  => '<masked-email>',
            'date'   => '2005-11-06',
            'name'   => 'Downloads Plugin',
            'desc'   => 'Agglomerate several download wiki pages within another',
            'url'    => '',
        );
    }
 
    /**
     * What kind of syntax are we?
     */
    function getType(){
        return 'substition';
    }
 
    /**
     * Where to sort in?
     */
    function getSort(){
        return 311;
    }
    
    /**
     * Paragraph Type
     */
    function getPType(){
        return 'block';
    }
 
    /**
     * Connect pattern to lexer
     */
    function connectTo($mode) {
      $this->Lexer->addSpecialPattern("{{downloads>.+?}}",$mode,'plugin_downloads');
    }
 
    /**
     * Handle the match
     */
    function handle($match, $state, $pos, &$handler){
        global $ID;
        global $filechain;
 
		$maxd = 100;                                  // more than 100 downloads pages is getting insane
        $match = substr($match,12,-2);                // strip markup
        list($ns,$num) = explode('#',$match,2);       // split hash from namespace
        if (!is_numeric($num)) $num = $maxd;          // default to "all" download items
 
        function _isDistID($id) {
          list($tag,$date) = explode('_',noNS($id),2);
          return $tag === 'dist' && is_numeric($date);
        }
 
        $dpages = array_map(create_function('$var','return $var["id"];'),getRecents(0,$maxd,false,$ns,false));
        $dpages = array_filter($dpages, '_isDistID');
		if (!rsort($dpages)) return false;
		$chunks = array_chunk($dpages,$num);
		$dpages = $chunks[0];
 
        // check for and establish start of $filechain
        if (!isset($filechain)) $filechain[] = $ID;
 
        // don't allow the same file to be included more than once
        if (in_array($match[0], $filechain)) return false;
 
        // add included pages to the filechain
        $filechain = array_merge($filechain, $dpages);
 
        return $dpages;
    }    
 
    /**
     * Create output
     */
    function render($mode, &$renderer, $data) {
        
        if($mode == 'xhtml'){
          for ($i = 0; $i < sizeof($data); $i++){
            $id = $data[$i];
            $file = wikiFN($id);
            if (!@file_exists($file)) return false;
 
            // get instructions
            $instr = p_cached_instructions($file, false);
            
            // correct relative internal links and media
            $instr = $this->_correctRelNS($instr, $id);
            
            // render the instructructions on the fly
            $text = p_render('xhtml',$instr,$info);
            
            // remove toc, section edit buttons and category tags
            $patterns = array('!<div class="toc">.*?(</div>\n</div>)!s',
                              '#<!-- SECTION \[(\d*-\d*)\] -->#e',
                              '!<div class="category">.*?</div>!s');
            $replace  = array('','','');
            $text = preg_replace($patterns,$replace,$text);
 
            // prevent caching to ensure the included page is always fresh
            $renderer->info['cache'] = FALSE;
 
            // embed the included page
            if ($i)
              $renderer->doc .= '<hr noshade="noshade" size="1" />';
            $renderer->doc .= $text;
          }
          return true;
        }
        return false;
    }
    
    /**
     * Corrects relative internal links and media
     */
    function _correctRelNS($instr,$incl){
        global $ID;
        
        // check if included page is in same namespace
        $iNS = getNS($incl);
        if (getNS($ID) == $iNS) return $instr;
        
        // convert internal links and media from relative to absolute
        $n = count($instr);
        for($i = 0; $i < $n; $i++){
            if (substr($instr[$i][0], 0, 8) == 'internal'){
                
                // relative subnamespace
                if ($instr[$i][1][0]{0} == '.'){
 
                    $instr[$i][1][0] = $iNS.':'.substr($instr[$i][1][0], 1);
                    
                // relative link
                } elseif (strpos($instr[$i][1][0],':') === false) {
                    $instr[$i][1][0] = $iNS.':'.$instr[$i][1][0];
                }
            }
        }
        return $instr;
    }
}
 
//Setup VIM: ex: et ts=4 enc=utf-8 :
 
Recent changes RSS feed Creative Commons License Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki