Positioned block elements and styling for ad-hoc layout, columns etc.
Compatible with DokuWiki
2006-11-06
The missing download url means that this extension cannot be installed via the Extension Manager. Please see Publishing a Plugin on dokuwiki.org. Recommended are public repository hosts like GitHub, GitLab or Bitbucket.
This extension has not been updated in over 2 years. It may no longer be maintained or supported and may have compatibility issues.
The Layout Plugin allows for positioned block elements to be added to wiki markup. In addition, block elements can have styles applied from an external .css stylesheet. The plugin is intended to add ad-hoc styling and layout capability to DokuWiki. Layout statements can be nested to provide more complex layouts.
NEW: (20070530)
<layout [l:N] [r:N] [t:N] [b:N] [w:N] [h:N] [z:N] [id:"ID"] [s:CLASS|"CLASSES..."] [s:"[!]PAGENAME[:]?CLASSNAME] [p:0|-]> wiki markup </layout>
[p:-] | position: relative; | optional; Default is absolute positioning |
---|---|---|
[s:“style1 style2 …”} | styles defined in layout.css | optional |
[s:“PAGENAME?CLASSNAME] | class=“CLASSNAME” if on the PAGENAME page; trailing ”:“ checks if descendent | optional |
[s:”!PAGENAME?CLASSNAME] | class=“CLASSNAME” if not on the PAGENAME pagetrailing “:” checks if descendent | optional |
[em] | units; em, % | optional; Default is pixels |
[z:nn} | z-index | optional |
[w:] | width | optional |
[h:] | height | optional |
[l:] | left | optional |
[r:] | right | optional |
[t:] | top | optional |
[b:] | bottom | optional |
[pl:] | padding-left | optional |
[pr:] | padding-right | optional |
[pt:] | padding-top | optional |
[pb:] | padding-bottom | optional |
[ml:] | margin-left | optional |
[mr:] | margin-right | optional |
[mt:] | margin-top | optional |
[mb:] | margin-bottom | optional |
simple column example
Layout uses shorthands for inline CSS markup.
Note that DW section heading markup does not work within layout tags.
<layout p:- w:20%> some left column content </layout> <layout l:25% w:75%> some right column content </layout>
style selectors based on page name/namespace
<layout s:"plugin:layout?h1"> H1 </layout>
<div class=“H1”>H1</div>
<layout s:"plugin:someotherpage?h1"> Not H1 </layout>
<div>Not H1</div>
<layout s:"plugin:?h1"> H1 </layout>
<div class=“H1”>H1</div>
<layout s:"plugin?h1"> Not H1 </layout>
<div>Not H1</div>
syntax.php
<?php /** * Layout Plugin: create absolute positioned layouts. * Version: 0.1alpha * * Syntax: <layout [l:N] [r:N] [t:N] [b:N] [w:N] [h:N] [z:N] [id:"ID"] [s:CLASS|"CLASSES..."] [s:"[!]PAGENAME?CLASSNAME] [p:0|-]>...content...</layout> * * Example: <layout r:30 w:60 t:40 z:100> * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * @author Ivan A-R <ivalrom@gmail.com> * @author Green Box <greenboxster@gmail.com> * @author Luke Howson <mail@lukehowson.com> */ 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_layout extends DokuWiki_Syntax_Plugin { function getInfo(){ return array( 'author' => 'Ivan A-R', 'email' => 'ivalrom@gmail.com', 'date' => '2006-11-17', 'name' => 'Layout Plugin', 'desc' => 'create absolute positioned layouts', 'url' => 'http://iar.spb.ru/projects/dowkuwiki/layout', ); } function getType(){ return 'container';} function getAllowedTypes() { return array('container', 'substition', 'protected', 'disabled', 'formatting', 'paragraphs'); } function getPType(){ return 'block';} function getSort(){ return 196; } // override default accepts() method to allow nesting // - ie, to get the plugin accepts its own entry syntax function accepts($mode) { if ($mode == substr(get_class($this), 7)) return true; return parent::accepts($mode); } /** * Connect pattern to lexer */ function connectTo($mode) { $this->Lexer->addEntryPattern('<lo.*?>(?=.*?</lo.*?>)',$mode,'plugin_layout'); $this->Lexer->addEntryPattern('<layout.*?>(?=.*?</layout.*?>)',$mode,'plugin_layout'); } function postConnect() { $this->Lexer->addExitPattern('</lo.*?>', 'plugin_layout'); $this->Lexer->addExitPattern('</layout.*?>', 'plugin_layout'); } /** * Handle the match */ function handle($match, $state, $pos, &$handler){ switch ($state) { case DOKU_LEXER_ENTER: $data = (substr($match, 3, -1)); return array(1, $data); case DOKU_LEXER_MATCHED: return array(2, $match); case DOKU_LEXER_UNMATCHED: return array(3, $match); case DOKU_LEXER_EXIT: return array(4, ''); } return false; } /** * Create output */ function render($mode, &$renderer, $indata) { list($instr, $data) = $indata; if('xhtml' == $mode){ switch($instr) { case 1: $param = $this->_parse_param($data); $style = ''; $class = ''; $position = 'position:absolute; '; foreach($param as $k => $v) { switch(strtolower($k)) { case 'l': $style .= 'left:'.$this->_sufix($v, 'px').'; '; break; case 'r': $style .= 'right:'.$this->_sufix($v, 'px').'; '; break; case 't': $style .= 'top:'.$this->_sufix($v, 'px').'; '; break; case 'b': $style .= 'bottom:'.$this->_sufix($v, 'px').'; '; break; case 'w': $style .= 'width:'.$this->_sufix($v, 'px').'; '; break; case 'h': $style .= 'height:'.$this->_sufix($v, 'px').'; '; break; case 'z': $style .= 'z-index:'.$v.'; '; break; case 'id': $style .= 'id:'.$v.'; '; break; case 'pl': $style .= 'padding-left:'.$this->_sufix($v, 'px').'; '; break; case 'pr': $style .= 'padding-right:'.$this->_sufix($v, 'px').'; '; break; case 'pt': $style .= 'padding-top:'.$this->_sufix($v, 'px').'; '; break; case 'pb': $style .= 'padding-bottom:'.$this->_sufix($v, 'px').'; '; break; case 'ml': $style .= 'margin-left:'.$this->_sufix($v, 'px').'; '; break; case 'mr': $style .= 'margin-right:'.$this->_sufix($v, 'px').'; '; break; case 'mt': $style .= 'margin-top:'.$this->_sufix($v, 'px').'; '; break; case 'mb': $style .= 'margin-bottom:'.$this->_sufix($v, 'px').'; '; break; case 'p': switch($v) { case '-': $position = 'position:relative; '; break; case 0: $position = ''; break; // none } break; case 's': $instructions = split(' ', $v); foreach ($instructions as $instruction) { $instruction = trim($instruction, ' "'); if (preg_match("/\?/", $instruction)) { $out = $this->_outputClass($instruction); } else { $out = $instruction; } if($out != "") { if($class != "") $class .= " "; $class .= $out; } } break; } } $renderer->doc .= "<div"; if ($class) $renderer->doc .= ' class="'.$class.'"'; if ($style) $renderer->doc .= ' style="'.$position.$style.'"'; $renderer->doc .= '>'; break; case 2: case 3: $renderer->doc .= $data; break; case 4: $renderer->doc .= "</div>"; break; } return true; } return false; } function _outputClass($instruction) { // $matchType points to _eq for PAGE?CLASS syntax and // _isAncestor for NAMESPACE:?CLASS syntax if(preg_match('/:\?/', $instruction) ) { $matchType = "_isAncestor"; } else { $matchType = "_eq"; } if($this->_hasA($instruction, "?") ) { if($this->_hasA($instruction, "!")) { if ( $this->$matchType($this->_pageName($instruction), getID() ) ) { return ""; } } else if (!($this->$matchType($this->_pageName($instruction), getID() ) ) ) { return ""; } } return $this->_className($instruction); } // named equality operator function _eq($a, $b) { return ($a == $b); } function _isAncestor($ancestor, $descendent) { $ancestor = substr($ancestor, 0, strlen($ancestor) - 1); $anc = split (':', $ancestor); $desc = split (':', $descendent); if(sizeof($anc) > sizeof($desc) ) { return false; } for ($i = 0; $i != sizeof($anc); $i++) { if ( $anc[$i] != $desc[$i] ) {return false;} } return true; } // Returns the page name in an "s:[!]PAGENAME?CLASSNAME" string function _pageName($str) { $R = array(); preg_match('/!?(.*?)\\?/', $str, $R); return $R[1]; } // Returns the class name in an "s:[!]PAGENAME?CLASSNAME" string function _className($str) { $R = array(); preg_match("/\\?(.*)/", $str, $R); return $R[1]; } // sees if a string has a particular character function _hasA($str, $char) { return !(strpos($str, $char) === FALSE ); } function _parse_param($str) { $R = array(); preg_match_all('/(\\w+):("[^"]*"|\\S*)|(\\w+)/', $str, $R); $keys = array(); $option = 1; $quotedValue = 2; $unquotedValue = 3; foreach($R[0] as $k => $v) { if($R[$option][$k]) { $keys[$R[$option][$k]] = $R[$quotedValue][$k]; } else { // ? $keys[$R[$unquotedValue][$k]] = TRUE; } } return $keys; } function _sufix($val, $sufix) { if(preg_match('/^\-?[0-9]+$/', $val)) { // If only numeric value return $val.$sufix; // Add default suffix } else { return $val; } } } //Setup VIM: ex: et ts=4 enc=utf-8 :s
style.css
* Example Styles for Layout plugin for DokuWiki * * @author Ivan A-R <ivalrom@gmail.com> * @author Green Box <greenboxster@gmail.com> * * Styles to be applied by layout plugin. * Modify to suit... */ div.red { background-color: #FFFFCC; font-size: 12pt; } div.lay border: 1px solid red; padding: 0.5em; } div.layout2 { font-size: 8pt; } div.centrec { padding-left:200px; padding-right:150px; } div.backred { background-color: #FFFFCC; } div.textbig p { color:red; font-size:120%; }
Very nice indeed!
However, I have two comments/bugs to mention:
First, the nomenclature for specifying the class seems to be
<layout s:myclass> Foo Bar </layout>
and not st:myclass.
Second, the corresponding HTML has an extra whitespace inserted:
<div class=" myclass"> <p> Foo Bar </p> </div>
– Niklas Volbers
Fixed these problems
– Luke Howson
Bug or something:
When in order to render two columns you give
<layout w:35%> ... </layout> <layout l:36% w:63%> ... </layout>
the menu bar is strangely rendered twice.
However if you put the second column relative it renders right.
<layout w:35%> ... </layout> <layout l:36% w:63% p:-> ... </layout>
– H.P. 2008-05-18
Thanks to Chris Smith for advice.
Erm.. How does one install it? I'm only interested in the columns feature; is that working? And how does one use it; there are no examples for setting up columns. Thanks!
Manual install, as described here: installation Bernd
The example above with two columns works with IE, but with Fire Fox there is a problem: The second column starts about half a row below the first column. StinkyWinky 2008/08/06 10:11