ajwillia-ms pushed a commit to branch master.

http://git.enlightenment.org/website/www.git/commit/?id=62069b6490d113a6c8a179a364f92f8ebc5040a4

commit 62069b6490d113a6c8a179a364f92f8ebc5040a4
Author: Andy Williams <a...@andywilliams.me>
Date:   Sat Jul 15 10:53:16 2017 +0100

    Add column plugin and re-flow columns on mobile
---
 public_html/lib/plugins/columns/action.php         | 675 +++++++++++++++++++++
 public_html/lib/plugins/columns/conf/default.php   |  12 +
 public_html/lib/plugins/columns/conf/metadata.php  |  12 +
 public_html/lib/plugins/columns/lang/en/lang.php   |  12 +
 .../lib/plugins/columns/lang/en/settings.php       |  12 +
 public_html/lib/plugins/columns/lang/es/lang.php   |  12 +
 .../lib/plugins/columns/lang/es/settings.php       |  12 +
 public_html/lib/plugins/columns/lang/ru/lang.php   |  12 +
 .../lib/plugins/columns/lang/ru/settings.php       |  12 +
 public_html/lib/plugins/columns/plugin.info.txt    |   7 +
 public_html/lib/plugins/columns/print.css          |  24 +
 public_html/lib/plugins/columns/rewriter.php       | 190 ++++++
 public_html/lib/plugins/columns/style.css          |  43 ++
 public_html/lib/plugins/columns/syntax.php         | 611 +++++++++++++++++++
 public_html/lib/tpl/e/css/modifications.css        |  11 +
 15 files changed, 1657 insertions(+)

diff --git a/public_html/lib/plugins/columns/action.php 
b/public_html/lib/plugins/columns/action.php
new file mode 100644
index 0000000..c96e54b
--- /dev/null
+++ b/public_html/lib/plugins/columns/action.php
@@ -0,0 +1,675 @@
+<?php
+
+/**
+ * Plugin Columns: Layout parser
+ *
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author     Mykola Ostrovskyy <spambo...@mail.ru>
+ */
+
+/* Must be run within Dokuwiki */
+if(!defined('DOKU_INC')) die();
+
+if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
+require_once(DOKU_PLUGIN . 'action.php');
+require_once(DOKU_PLUGIN . 'columns/rewriter.php');
+
+class action_plugin_columns extends DokuWiki_Action_Plugin {
+
+    private $block;
+    private $currentBlock;
+    private $currentSectionLevel;
+    private $sectionEdit;
+
+    /**
+     * Register callbacks
+     */
+    public function register(Doku_Event_Handler $controller) {
+        $controller->register_hook('PARSER_HANDLER_DONE', 'AFTER', $this, 
'handle');
+    }
+
+    /**
+     *
+     */
+    public function handle(&$event, $param) {
+        $this->reset();
+        $this->buildLayout($event);
+        $rewriter = new instruction_rewriter();
+        foreach ($this->block as $block) {
+            $block->processAttributes($event);
+            $rewriter->addCorrections($block->getCorrections());
+        }
+        $rewriter->process($event->data->calls);
+    }
+
+    /**
+     * Find all columns instructions and construct columns layout based on them
+     */
+    private function buildLayout(&$event) {
+        $calls = count($event->data->calls);
+        for ($c = 0; $c < $calls; $c++) {
+            $call =& $event->data->calls[$c];
+            switch ($call[0]) {
+                case 'section_open':
+                    $this->currentSectionLevel = $call[1][0];
+                    $this->currentBlock->openSection();
+                    break;
+
+                case 'section_close':
+                    $this->currentBlock->closeSection($c);
+                    break;
+
+                case 'plugin':
+                    if ($call[1][0] == 'columns') {
+                        $this->handleColumns($c, $call[1][1][0], 
$this->detectSectionEdit($event->data->calls, $c));
+                    }
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Reset internal state
+     */
+    private function reset() {
+        $this->block = array();
+        $this->block[0] = new columns_root_block();
+        $this->currentBlock = $this->block[0];
+        $this->currentSectionLevel = 0;
+        $this->sectionEdit = array();
+    }
+
+    /**
+     *
+     */
+    private function detectSectionEdit($call, $start) {
+        $result = null;
+        $calls = count($call);
+        for ($c = $start + 1; $c < $calls; $c++) {
+            switch ($call[$c][0]) {
+                case 'section_close':
+                case 'p_open':
+                case 'p_close':
+                    /* Skip these instructions */
+                    break;
+
+                case 'header':
+                    if (end($this->sectionEdit) != $c) {
+                        $this->sectionEdit[] = $c;
+                        $result = $call[$c][2];
+                    }
+                    break 2;
+
+                case 'plugin':
+                    if ($call[$c][1][0] == 'columns') {
+                        break;
+                    } else {
+                        break 2;
+                    }
+
+                default:
+                    break 2;
+            }
+        }
+        return $result;
+    }
+
+    /**
+     *
+     */
+    private function handleColumns($callIndex, $state, $sectionEdit) {
+        switch ($state) {
+            case DOKU_LEXER_ENTER:
+                $this->currentBlock = new columns_block(count($this->block), 
$this->currentBlock);
+                $this->currentBlock->addColumn($callIndex, 
$this->currentSectionLevel);
+                $this->currentBlock->startSection($sectionEdit);
+                $this->block[] = $this->currentBlock;
+                break;
+
+            case DOKU_LEXER_MATCHED:
+                $this->currentBlock->addColumn($callIndex, 
$this->currentSectionLevel);
+                $this->currentBlock->startSection($sectionEdit);
+                break;
+
+            case DOKU_LEXER_EXIT:
+                $this->currentBlock->endSection($sectionEdit);
+                $this->currentBlock->close($callIndex);
+                $this->currentBlock = $this->currentBlock->getParent();
+                break;
+        }
+    }
+}
+
+class columns_root_block {
+
+    private $sectionLevel;
+    private $call;
+
+    /**
+     * Constructor
+     */
+    public function __construct() {
+        $this->sectionLevel = 0;
+        $this->call = array();
+    }
+
+    /**
+     *
+     */
+    public function getParent() {
+        return $this;
+    }
+
+    /**
+     * Collect stray <newcolumn> tags
+     */
+    public function addColumn($callIndex, $sectionLevel) {
+        $this->call[] = $callIndex;
+    }
+
+    /**
+     *
+     */
+    public function openSection() {
+        $this->sectionLevel++;
+    }
+
+    /**
+     *
+     */
+    public function closeSection($callIndex) {
+        if ($this->sectionLevel > 0) {
+            $this->sectionLevel--;
+        }
+        else {
+            $this->call[] = $callIndex;
+        }
+    }
+
+    /**
+     *
+     */
+    public function startSection($callInfo) {
+    }
+
+    /**
+     *
+     */
+    public function endSection($callInfo) {
+    }
+
+    /**
+     * Collect stray </colums> tags
+     */
+    public function close($callIndex) {
+        $this->call[] = $callIndex;
+    }
+
+    /**
+     *
+     */
+    public function processAttributes(&$event) {
+    }
+
+    /**
+     * Delete all captured tags
+     */
+    public function getCorrections() {
+        $correction = array();
+        foreach ($this->call as $call) {
+            $correction[] = new instruction_rewriter_delete($call);
+        }
+        return $correction;
+    }
+}
+
+class columns_block {
+
+    private $id;
+    private $parent;
+    private $column;
+    private $currentColumn;
+    private $closed;
+
+    /**
+     * Constructor
+     */
+    public function __construct($id, $parent) {
+        $this->id = $id;
+        $this->parent = $parent;
+        $this->column = array();
+        $this->currentColumn = null;
+        $this->closed = false;
+    }
+
+    /**
+     *
+     */
+    public function getParent() {
+        return $this->parent;
+    }
+
+    /**
+     *
+     */
+    public function addColumn($callIndex, $sectionLevel) {
+        if ($this->currentColumn != null) {
+            $this->currentColumn->close($callIndex);
+        }
+        $this->currentColumn = new columns_column($callIndex, $sectionLevel);
+        $this->column[] = $this->currentColumn;
+    }
+
+    /**
+     *
+     */
+    public function openSection() {
+        $this->currentColumn->openSection();
+    }
+
+    /**
+     *
+     */
+    public function closeSection($callIndex) {
+        $this->currentColumn->closeSection($callIndex);
+    }
+
+    /**
+     *
+     */
+    public function startSection($callInfo) {
+        $this->currentColumn->startSection($callInfo);
+    }
+
+    /**
+     *
+     */
+    public function endSection($callInfo) {
+        $this->currentColumn->endSection($callInfo);
+    }
+
+    /**
+     *
+     */
+    public function close($callIndex) {
+        $this->currentColumn->close($callIndex);
+        $this->closed = true;
+    }
+
+    /**
+     * Convert raw attributes and layout information into column attributes
+     */
+    public function processAttributes(&$event) {
+        $columns = count($this->column);
+        for ($c = 0; $c < $columns; $c++) {
+            $call =& $event->data->calls[$this->column[$c]->getOpenCall()];
+            if ($c == 0) {
+                $this->loadBlockAttributes($call[1][1][1]);
+                $this->column[0]->addAttribute('columns', $columns);
+                $this->column[0]->addAttribute('class', 'first');
+            }
+            else {
+                $this->loadColumnAttributes($c, $call[1][1][1]);
+                if ($c == ($columns - 1)) {
+                    $this->column[$c]->addAttribute('class', 'last');
+                }
+            }
+            $this->column[$c]->addAttribute('block-id', $this->id);
+            $this->column[$c]->addAttribute('column-id', $c + 1);
+            $call[1][1][1] = $this->column[$c]->getAttributes();
+        }
+    }
+
+    /**
+     * Convert raw attributes into column attributes
+     */
+    private function loadBlockAttributes($attribute) {
+        $column = -1;
+        $nextColumn = -1;
+        foreach ($attribute as $a) {
+            list($name, $temp) = $this->parseAttribute($a);
+            if ($name == 'width') {
+                if (($column == -1) && array_key_exists('column-width', 
$temp)) {
+                    $this->column[0]->addAttribute('table-width', 
$temp['column-width']);
+                }
+                $nextColumn = $column + 1;
+            }
+            if (($column >= 0) && ($column < count($this->column))) {
+                $this->column[$column]->addAttributes($temp);
+            }
+            $column = $nextColumn;
+        }
+    }
+
+    /**
+     * Convert raw attributes into column attributes
+     */
+    private function loadColumnAttributes($column, $attribute) {
+        foreach ($attribute as $a) {
+            list($name, $temp) = $this->parseAttribute($a);
+            $this->column[$column]->addAttributes($temp);
+        }
+    }
+
+    /**
+     *
+     */
+    private function parseAttribute($attribute) {
+        static $syntax = array(
+            '/^left|right|center|justify$/' => 'text-align',
+            '/^top|middle|bottom$/' => 'vertical-align',
+            '/^[lrcjtmb]{1,2}$/' => 'align',
+            '/^continue|\.{3}$/' => 'continue',
+            '/^(\*?)((?:-|(?:\d+\.?|\d*\.\d+)(?:%|em|px|cm|mm|in|pt)))(\*?)$/' 
=> 'width'
+        );
+        $result = array();
+        $attributeName = '';
+        foreach ($syntax as $pattern => $name) {
+            if (preg_match($pattern, $attribute, $match) == 1) {
+                $attributeName = $name;
+                break;
+            }
+        }
+        switch ($attributeName) {
+            case 'text-align':
+            case 'vertical-align':
+                $result[$attributeName] = $match[0];
+                break;
+
+            case 'align':
+                $result = $this->parseAlignAttribute($match[0]);
+                break;
+
+            case 'continue':
+                $result[$attributeName] = 'on';
+                break;
+
+            case 'width':
+                $result = $this->parseWidthAttribute($match);
+                break;
+        }
+        return array($attributeName, $result);
+    }
+
+    /**
+     *
+     */
+    private function parseAlignAttribute($syntax) {
+        $result = array();
+        $align1 = $this->getAlignStyle($syntax{0});
+        if (strlen($syntax) == 2) {
+            $align2 = $this->getAlignStyle($syntax{1});
+            if ($align1 != $align2) {
+                $result[$align1] = $this->getAlignment($syntax{0});
+                $result[$align2] = $this->getAlignment($syntax{1});
+            }
+        }
+        else{
+            $result[$align1] = $this->getAlignment($syntax{0});
+        }
+        return $result;
+    }
+
+    /**
+     *
+     */
+    private function getAlignStyle($align) {
+        return preg_match('/[lrcj]/', $align) ? 'text-align' : 
'vertical-align';
+    }
+
+    /**
+     *
+     */
+    private function parseWidthAttribute($syntax) {
+        $result = array();
+        if ($syntax[2] != '-') {
+            $result['column-width'] = $syntax[2];
+        }
+        $align = $syntax[1] . '-' . $syntax[3];
+        if ($align != '-') {
+            $result['text-align'] = $this->getAlignment($align);
+        }
+        return $result;
+    }
+
+    /**
+     * Returns column text alignment
+     */
+    private function getAlignment($syntax) {
+        static $align = array(
+            'l' => 'left', '-*' => 'left',
+            'r' => 'right', '*-' => 'right',
+            'c' => 'center', '*-*' => 'center',
+            'j' => 'justify',
+            't' => 'top',
+            'm' => 'middle',
+            'b' => 'bottom'
+        );
+        if (array_key_exists($syntax, $align)) {
+            return $align[$syntax];
+        }
+        else {
+            return '';
+        }
+    }
+
+    /**
+     * Returns a list of corrections that have to be applied to the 
instruction array
+     */
+    public function getCorrections() {
+        if ($this->closed) {
+            $correction = $this->fixSections();
+        }
+        else {
+            $correction = $this->deleteColumns();
+        }
+        return $correction;
+    }
+
+    /**
+     * Re-write section open/close instructions to produce valid HTML
+     * See columns:design#section_fixing for details
+     */
+    private function fixSections() {
+        $correction = array();
+        foreach ($this->column as $column) {
+            $correction = array_merge($correction, $column->getCorrections());
+        }
+        return $correction;
+    }
+
+    /**
+     *
+     */
+    private function deleteColumns() {
+        $correction = array();
+        foreach ($this->column as $column) {
+            $correction[] = $column->delete();
+        }
+        return $correction;
+    }
+}
+
+class columns_attributes_bag {
+
+    private $attribute;
+
+    /**
+     * Constructor
+     */
+    public function __construct() {
+        $this->attribute = array();
+    }
+
+    /**
+     *
+     */
+    public function addAttribute($name, $value) {
+        $this->attribute[$name] = $value;
+    }
+
+    /**
+     *
+     */
+    public function addAttributes($attribute) {
+        if (is_array($attribute) && (count($attribute) > 0)) {
+            $this->attribute = array_merge($this->attribute, $attribute);
+        }
+    }
+
+    /**
+     *
+     */
+    public function getAttribute($name) {
+        $result = '';
+        if (array_key_exists($name, $this->attribute)) {
+            $result = $this->attribute[$name];
+        }
+        return $result;
+    }
+
+    /**
+     *
+     */
+    public function getAttributes() {
+        return $this->attribute;
+    }
+}
+
+class columns_column extends columns_attributes_bag {
+
+    private $open;
+    private $close;
+    private $sectionLevel;
+    private $sectionOpen;
+    private $sectionClose;
+    private $sectionStart;
+    private $sectionEnd;
+
+    /**
+     * Constructor
+     */
+    public function __construct($open, $sectionLevel) {
+        parent::__construct();
+
+        $this->open = $open;
+        $this->close = -1;
+        $this->sectionLevel = $sectionLevel;
+        $this->sectionOpen = false;
+        $this->sectionClose = -1;
+        $this->sectionStart = null;
+        $this->sectionEnd = null;
+    }
+
+    /**
+     *
+     */
+    public function getOpenCall() {
+        return $this->open;
+    }
+
+    /**
+     *
+     */
+    public function openSection() {
+        $this->sectionOpen = true;
+    }
+
+    /**
+     *
+     */
+    public function closeSection($callIndex) {
+        if ($this->sectionClose == -1) {
+            $this->sectionClose = $callIndex;
+        }
+    }
+
+    /**
+     *
+     */
+    public function startSection($callInfo) {
+        $this->sectionStart = $callInfo;
+    }
+
+    /**
+     *
+     */
+    public function endSection($callInfo) {
+        $this->sectionEnd = $callInfo;
+    }
+
+    /**
+     *
+     */
+    public function close($callIndex) {
+        $this->close = $callIndex;
+    }
+
+    /**
+     *
+     */
+    public function delete() {
+        return new instruction_rewriter_delete($this->open);
+    }
+
+    /**
+     * Re-write section open/close instructions to produce valid HTML
+     * See columns:design#section_fixing for details
+     */
+    public function getCorrections() {
+        $result = array();
+        $deleteSectionClose = ($this->sectionClose != -1);
+        $closeSection = $this->sectionOpen;
+        if ($this->sectionStart != null) {
+            $result = array_merge($result, $this->moveStartSectionEdit());
+        }
+        if (($this->getAttribute('continue') == 'on') && ($this->sectionLevel 
> 0)) {
+            $result[] = $this->openStartSection();
+            /* Ensure that this section will be properly closed */
+            $deleteSectionClose = false;
+            $closeSection = true;
+        }
+        if ($deleteSectionClose) {
+            /* Remove first section_close from the column to prevent </div> in 
the middle of the column */
+            $result[] = new instruction_rewriter_delete($this->sectionClose);
+        }
+        if ($closeSection || ($this->sectionEnd != null)) {
+            $result = array_merge($result, 
$this->closeLastSection($closeSection));
+        }
+        return $result;
+    }
+
+    /**
+     * Moves section_edit at the start of the column out of the column
+     */
+    private function moveStartSectionEdit() {
+        $result = array();
+        $result[0] = new instruction_rewriter_insert($this->open);
+        $result[0]->addPluginCall('columns', array(987, $this->sectionStart - 
1), DOKU_LEXER_MATCHED);
+        return $result;
+    }
+
+    /**
+     * Insert section_open at the start of the column
+     */
+    private function openStartSection() {
+        $insert = new instruction_rewriter_insert($this->open + 1);
+        $insert->addCall('section_open', array($this->sectionLevel));
+        return $insert;
+    }
+
+    /**
+     * Close last open section in the column
+     */
+    private function closeLastSection($closeSection) {
+        $result = array();
+        $result[0] = new instruction_rewriter_insert($this->close);
+        if ($closeSection) {
+            $result[0]->addCall('section_close', array());
+        }
+        if ($this->sectionEnd != null) {
+            $result[0]->addPluginCall('columns', array(987, $this->sectionEnd 
- 1), DOKU_LEXER_MATCHED);
+        }
+        return $result;
+    }
+}
diff --git a/public_html/lib/plugins/columns/conf/default.php 
b/public_html/lib/plugins/columns/conf/default.php
new file mode 100644
index 0000000..e83f6c2
--- /dev/null
+++ b/public_html/lib/plugins/columns/conf/default.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * Plugin Columns: Configuration defaults
+ *
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author     Mykola Ostrovskyy <spambo...@mail.ru>
+ */
+
+$conf['kwcolumns'] = '';
+$conf['kwnewcol'] = '';
+$conf['wrapnewcol'] = 1;
diff --git a/public_html/lib/plugins/columns/conf/metadata.php 
b/public_html/lib/plugins/columns/conf/metadata.php
new file mode 100644
index 0000000..011bdf7
--- /dev/null
+++ b/public_html/lib/plugins/columns/conf/metadata.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * Plugin Columns: Metadata for configuration manager plugin
+ *
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author     Mykola Ostrovskyy <spambo...@mail.ru>
+ */
+
+$meta['kwcolumns'] = array('string');
+$meta['kwnewcol'] = array('string');
+$meta['wrapnewcol'] = array('onoff');
diff --git a/public_html/lib/plugins/columns/lang/en/lang.php 
b/public_html/lib/plugins/columns/lang/en/lang.php
new file mode 100644
index 0000000..7182dd6
--- /dev/null
+++ b/public_html/lib/plugins/columns/lang/en/lang.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * Plugin Columns: English language file
+ *
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author     Mykola Ostrovskyy <spambo...@mail.ru>
+ */
+
+$lang['kwcolumns'] = 'columns';
+$lang['kwnewcol'] = 'newcolumn';
+
diff --git a/public_html/lib/plugins/columns/lang/en/settings.php 
b/public_html/lib/plugins/columns/lang/en/settings.php
new file mode 100644
index 0000000..6fb55e5
--- /dev/null
+++ b/public_html/lib/plugins/columns/lang/en/settings.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * Plugin Columns: English language file
+ *
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author     Mykola Ostrovskyy <spambo...@mail.ru>
+ */
+
+$lang['kwcolumns'] = 'Columns tag (default: columns); must be specified within 
angle brackets (&lt;columns&gt;...&lt;/columns&gt;)';
+$lang['kwnewcol'] = 'New column tag (default: newcolumn)';
+$lang['wrapnewcol'] = 'Wrap the new column tag in angle brackets 
(&lt;newcolumn&gt;)';
diff --git a/public_html/lib/plugins/columns/lang/es/lang.php 
b/public_html/lib/plugins/columns/lang/es/lang.php
new file mode 100644
index 0000000..4e552e1
--- /dev/null
+++ b/public_html/lib/plugins/columns/lang/es/lang.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * Plugin Columns: Spanish language file
+ *
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author     Digna González Otero <digna.gonzalezotero [at] gmail [dot] com>
+ */
+
+$lang['kwcolumns'] = 'columnas';
+$lang['kwnewcol'] = 'nueva_columna';
+
diff --git a/public_html/lib/plugins/columns/lang/es/settings.php 
b/public_html/lib/plugins/columns/lang/es/settings.php
new file mode 100644
index 0000000..a1106b2
--- /dev/null
+++ b/public_html/lib/plugins/columns/lang/es/settings.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * Plugin Columns: Spanish language file
+ *
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author     Digna González Otero <digna.gonzalezotero [at] gmail [dot] com>
+ */
+
+$lang['kwcolumns'] = 'Etiqueta de columnas (por defecto: columnas); Se debe 
especificar entre paréntesis angulares (&lt;columnas&gt;...&lt;/columnas&gt;)';
+$lang['kwnewcol'] = 'Etiqueta de nueva columna (por defecto: nueva_columna)';
+$lang['wrapnewcol'] = 'Encerrar la etiqueta de nueva columna entre paréntesis 
angulares (&lt;nueva_columna&gt;)';
diff --git a/public_html/lib/plugins/columns/lang/ru/lang.php 
b/public_html/lib/plugins/columns/lang/ru/lang.php
new file mode 100644
index 0000000..4f3270f
--- /dev/null
+++ b/public_html/lib/plugins/columns/lang/ru/lang.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * Plugin Columns: Russian language file
+ *
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author     Mykola Ostrovskyy <spambo...@mail.ru>
+ */
+
+$lang['kwcolumns'] = 'колонки';
+$lang['kwnewcol'] = 'новаяколонка';
+
diff --git a/public_html/lib/plugins/columns/lang/ru/settings.php 
b/public_html/lib/plugins/columns/lang/ru/settings.php
new file mode 100644
index 0000000..08dd870
--- /dev/null
+++ b/public_html/lib/plugins/columns/lang/ru/settings.php
@@ -0,0 +1,12 @@
+<?php
+
+/**
+ * Plugin Columns: Russian language file
+ *
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author     Mykola Ostrovskyy <spambo...@mail.ru>
+ */
+
+$lang['kwcolumns'] = 'Тег колонок (по умолчанию: колонки); тег должен быть 
заключен в угловые скобки (&lt;колонки&gt;...&lt;/колонки&gt;)';
+$lang['kwnewcol'] = 'Тег новой колонки (по умолчанию: новаяколонка)';
+$lang['wrapnewcol'] = 'Заключать тег новой колонки в угловые скобки 
(&lt;новаяколонка&gt;)';
diff --git a/public_html/lib/plugins/columns/plugin.info.txt 
b/public_html/lib/plugins/columns/plugin.info.txt
new file mode 100644
index 0000000..4c514f8
--- /dev/null
+++ b/public_html/lib/plugins/columns/plugin.info.txt
@@ -0,0 +1,7 @@
+base   columns
+author Mykola Ostrovskyy
+email  spambo...@mail.ru
+date   2016-09-07
+name   Columns Plugin
+desc   Arrange information in multiple columns.
+url    http://www.dokuwiki.org/plugin:columns
\ No newline at end of file
diff --git a/public_html/lib/plugins/columns/print.css 
b/public_html/lib/plugins/columns/print.css
new file mode 100644
index 0000000..7f07371
--- /dev/null
+++ b/public_html/lib/plugins/columns/print.css
@@ -0,0 +1,24 @@
+div.dokuwiki table.columns-plugin td {
+    vertical-align: top;
+    padding: 0 0.3cm 0 0.3cm;
+}
+
+div.dokuwiki table.columns-plugin td.first {
+    padding-left: 0;
+}
+
+div.dokuwiki table.columns-plugin td.last {
+    padding-right: 0;
+}
+
+div.dokuwiki table.columns-plugin td.left {
+    text-align: left;
+}
+
+div.dokuwiki table.columns-plugin td.center {
+    text-align: center;
+}
+
+div.dokuwiki table.columns-plugin td.right {
+    text-align: right;
+}
diff --git a/public_html/lib/plugins/columns/rewriter.php 
b/public_html/lib/plugins/columns/rewriter.php
new file mode 100644
index 0000000..eaa7296
--- /dev/null
+++ b/public_html/lib/plugins/columns/rewriter.php
@@ -0,0 +1,190 @@
+<?php
+
+/**
+ * Instruction re-writer
+ *
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author     Mykola Ostrovskyy <spambo...@mail.ru>
+ */
+
+if (!class_exists('instruction_rewriter', false)) {
+
+class instruction_rewriter {
+
+    private $correction;
+
+    /**
+     * Constructor
+     */
+    public function __construct() {
+        $this->correction = array();
+    }
+
+    /**
+     *
+     */
+    public function addCorrections($correction) {
+        foreach ($correction as $c) {
+            $this->correction[$c->getIndex()][] = $c;
+        }
+    }
+
+    /**
+     *
+     */
+    public function process(&$instruction) {
+        if (count($this->correction) > 0) {
+            $index = $this->getCorrectionIndex();
+            $corrections = count($index);
+            $instructions = count($instruction);
+            $output = array();
+            for ($c = 0, $i = 0; $c < $corrections; $c++, $i++) {
+                /* Copy all instructions that are before the next correction */
+                for ( ; $i < $index[$c]; $i++) {
+                    $output[] = $instruction[$i];
+                }
+                /* Apply the corrections */
+                $preventDefault = false;
+                foreach ($this->correction[$i] as $correction) {
+                    $preventDefault = ($preventDefault || 
$correction->apply($instruction, $output));
+                }
+                if (!$preventDefault) {
+                    $output[] = $instruction[$i];
+                }
+            }
+            /* Copy the rest of instructions after the last correction */
+            for ( ; $i < $instructions; $i++) {
+                $output[] = $instruction[$i];
+            }
+            /* Handle appends */
+            if (array_key_exists(-1, $this->correction)) {
+                $this->correction[-1]->apply($instruction, $output);
+            }
+            $instruction = $output;
+        }
+    }
+
+    /**
+     *
+     */
+    private function getCorrectionIndex() {
+        $result = array_keys($this->correction);
+        asort($result);
+        /* Remove appends */
+        if (reset($result) == -1) {
+            unset($result[key($result)]);
+        }
+        return array_values($result);
+    }
+}
+
+class instruction_rewriter_correction {
+
+    private $index;
+
+    /**
+     * Constructor
+     */
+    public function __construct($index) {
+        $this->index = $index;
+    }
+
+    /**
+     *
+     */
+    public function getIndex() {
+        return $this->index;
+    }
+}
+
+class instruction_rewriter_delete extends instruction_rewriter_correction {
+
+    /**
+     * Constructor
+     */
+    public function __construct($index) {
+        parent::__construct($index);
+    }
+
+    /**
+     *
+     */
+    public function apply($input, &$output) {
+        return true;
+    }
+}
+
+class instruction_rewriter_call_list extends instruction_rewriter_correction {
+
+    private $call;
+
+    /**
+     * Constructor
+     */
+    public function __construct($index) {
+        parent::__construct($index);
+        $this->call = array();
+    }
+
+    /**
+     *
+     */
+    public function addCall($name, $data) {
+        $this->call[] = array($name, $data);
+    }
+
+    /**
+     *
+     */
+    public function addPluginCall($name, $data, $state, $text = '') {
+        $this->call[] = array('plugin', array($name, $data, $state, $text));
+    }
+
+    /**
+     *
+     */
+    public function appendCalls(&$output, $position) {
+        foreach ($this->call as $call) {
+            $output[] = array($call[0], $call[1], $position);
+        }
+    }
+}
+
+class instruction_rewriter_insert extends instruction_rewriter_call_list {
+
+    /**
+     * Constructor
+     */
+    public function __construct($index) {
+        parent::__construct($index);
+    }
+
+    /**
+     *
+     */
+    public function apply($input, &$output) {
+        $this->appendCalls($output, $input[$this->index][2]);
+        return false;
+    }
+}
+
+class instruction_rewriter_append extends instruction_rewriter_call_list {
+
+    /**
+     * Constructor
+     */
+    public function __construct() {
+        parent::__construct(-1);
+    }
+
+    /**
+     *
+     */
+    public function apply($input, &$output) {
+        $lastCall = end($output);
+        $this->appendCalls($output, $lastCall[2]);
+        return false;
+    }
+}
+
+}
diff --git a/public_html/lib/plugins/columns/style.css 
b/public_html/lib/plugins/columns/style.css
new file mode 100644
index 0000000..eab6bf1
--- /dev/null
+++ b/public_html/lib/plugins/columns/style.css
@@ -0,0 +1,43 @@
+div.dokuwiki table.columns-plugin {
+    border: 0;
+    border-spacing: 0;
+    border-collapse: collapse;
+    margin: 0;
+}
+
+div.dokuwiki table.columns-plugin td.columns-plugin {
+    border: 0;
+    text-align: justify;
+    vertical-align: top;
+    padding: 0 0.5em 0 0.5em;
+}
+
+div.dokuwiki table.columns-plugin td.columns-plugin.first {
+    padding-left: 0;
+}
+
+div.dokuwiki table.columns-plugin td.columns-plugin.last {
+    padding-right: 0;
+}
+
+div.dokuwiki table.columns-plugin td.columns-plugin.left {
+    text-align: left;
+}
+
+div.dokuwiki table.columns-plugin td.columns-plugin.center {
+    text-align: center;
+}
+
+div.dokuwiki table.columns-plugin td.columns-plugin.right {
+    text-align: right;
+}
+
+div.dokuwiki table.columns-plugin td.columns-plugin.center table {
+    margin-left: auto;
+    margin-right: auto;
+}
+
+div.dokuwiki table.columns-plugin td.columns-plugin.right table {
+    margin-left: auto;
+    margin-right: 0;
+}
diff --git a/public_html/lib/plugins/columns/syntax.php 
b/public_html/lib/plugins/columns/syntax.php
new file mode 100644
index 0000000..82ec905
--- /dev/null
+++ b/public_html/lib/plugins/columns/syntax.php
@@ -0,0 +1,611 @@
+<?php
+
+/**
+ * Plugin Columns: Syntax & rendering
+ *
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author     Mykola Ostrovskyy <spambo...@mail.ru>
+ *             Based on plugin by Michael Arlt <michael.arlt [at] 
sk-schwanstetten [dot] de>
+ */
+
+/* Must be run within Dokuwiki */
+if(!defined('DOKU_INC')) die();
+
+if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
+require_once(DOKU_PLUGIN . 'syntax.php');
+
+class syntax_plugin_columns extends DokuWiki_Syntax_Plugin {
+
+    private $mode;
+    private $lexerSyntax;
+    private $syntax;
+    private $xhtmlRenderer;
+    private $odtRenderer;
+
+    /**
+     * Constructor
+     */
+    public function __construct() {
+        $this->mode = substr(get_class($this), 7);
+
+        $columns = $this->getColumnsTagName();
+        $newColumn = $this->getNewColumnTagName();
+        if ($this->getConf('wrapnewcol') == 1) {
+            $newColumnLexer = '<' . $newColumn . '(?:>|\s.*?>)';
+            $newColumnHandler = '<' . $newColumn . '(.*?)>';
+        }
+        else {
+            $newColumnLexer = $newColumn;
+            $newColumnHandler = $newColumn;
+        }
+        $enterLexer = '<' . $columns . '(?:>|\s.*?>)';
+        $enterHandler = '<' . $columns . '(.*?)>';
+        $exit = '<\/' . $columns . '>';
+
+        $this->lexerSyntax['enter'] = $enterLexer;
+        $this->lexerSyntax['newcol'] = $newColumnLexer;
+        $this->lexerSyntax['exit'] = $exit;
+
+        $this->syntax[DOKU_LEXER_ENTER] = '/' . $enterHandler . '/';
+        $this->syntax[DOKU_LEXER_MATCHED] = '/' . $newColumnHandler . '/';
+        $this->syntax[DOKU_LEXER_EXIT] = '/' . $exit . '/';
+    }
+
+    /**
+     * What kind of syntax are we?
+     */
+    public function getType() {
+        return 'substition';
+    }
+
+    public function getPType() {
+        return 'block';
+    }
+
+    /**
+     * Where to sort in?
+     */
+    public function getSort() {
+        return 65;
+    }
+
+    public function connectTo($mode) {
+        $this->Lexer->addSpecialPattern($this->lexerSyntax['enter'], $mode, 
$this->mode);
+        $this->Lexer->addSpecialPattern($this->lexerSyntax['newcol'], $mode, 
$this->mode);
+        $this->Lexer->addSpecialPattern($this->lexerSyntax['exit'], $mode, 
$this->mode);
+    }
+
+    /**
+     * Handle the match
+     */
+    public function handle($match, $state, $pos, Doku_Handler $handler) {
+        foreach ($this->syntax as $state => $pattern) {
+            if (preg_match($pattern, $match, $data) == 1) {
+                break;
+            }
+        }
+        switch ($state) {
+            case DOKU_LEXER_ENTER:
+            case DOKU_LEXER_MATCHED:
+                return array($state, preg_split('/\s+/', $data[1], -1, 
PREG_SPLIT_NO_EMPTY));
+
+            case DOKU_LEXER_EXIT:
+                return array($state);
+        }
+        return false;
+    }
+
+    /**
+     * Create output
+     */
+    public function render($mode, Doku_Renderer $renderer, $data) {
+        $columnsRenderer = $this->getRenderer($mode, $renderer);
+
+        if ($columnsRenderer != NULL) {
+            $columnsRenderer->render($data[0], $renderer, $data[1]);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     *
+     */
+    private function getRenderer($mode, Doku_Renderer $renderer) {
+        switch ($mode) {
+            case 'xhtml':
+                if ($this->xhtmlRenderer == NULL) {
+                    $this->xhtmlRenderer = new columns_renderer_xhtml();
+                }
+                return $this->xhtmlRenderer;
+
+            case 'odt':
+                if ($this->odtRenderer == NULL) {
+                    if (method_exists($renderer, 
'getODTPropertiesFromElement')) {
+                        $this->odtRenderer = new columns_renderer_odt_v2();
+                    }
+                    else {
+                        $this->odtRenderer = new columns_renderer_odt_v1();
+                    }
+                }
+                return $this->odtRenderer;
+        }
+
+        return NULL;
+    }
+
+    /**
+     * Returns columns tag
+     */
+    private function getColumnsTagName() {
+        $tag = $this->getConf('kwcolumns');
+        if ($tag == '') {
+            $tag = $this->getLang('kwcolumns');
+        }
+        return $tag;
+    }
+
+    /**
+     * Returns new column tag
+     */
+    private function getNewColumnTagName() {
+        $tag = $this->getConf('kwnewcol');
+        if ($tag == '') {
+            $tag = $this->getLang('kwnewcol');
+        }
+        return $tag;
+    }
+}
+
+/**
+ * Base class for columns rendering.
+ */
+abstract class columns_renderer {
+    /**
+     *
+     */
+    public function render($state, Doku_Renderer $renderer, $attribute) {
+        switch ($state) {
+            case DOKU_LEXER_ENTER:
+                $this->render_enter($renderer, $attribute);
+                break;
+
+            case DOKU_LEXER_MATCHED:
+                $this->render_matched($renderer, $attribute);
+                break;
+
+            case DOKU_LEXER_EXIT:
+                $this->render_exit($renderer, $attribute);
+                break;
+        }
+    }
+
+    abstract protected function render_enter(Doku_Renderer $renderer, 
$attribute);
+    abstract protected function render_matched(Doku_Renderer $renderer, 
$attribute);
+    abstract protected function render_exit(Doku_Renderer $renderer, 
$attribute);
+
+    /**
+     *
+     */
+    protected function getAttribute($attribute, $name) {
+        $result = '';
+        if (array_key_exists($name, $attribute)) {
+            $result = $attribute[$name];
+        }
+        return $result;
+    }
+
+    /**
+     *
+     */
+    protected function getStyle($attribute, $attributeName, $styleName = '') {
+        $result = $this->getAttribute($attribute, $attributeName);
+        if ($result != '') {
+            if ($styleName == '') {
+                $styleName = $attributeName;
+            }
+            $result = $styleName . ':' . $result . ';';
+        }
+        return $result;
+    }
+}
+
+/**
+ * Class columns_renderer_xhtml
+ * @author LarsDW223
+ */
+class columns_renderer_xhtml extends columns_renderer {
+    /**
+     *
+     */
+    public function render($state, Doku_Renderer $renderer, $attribute) {
+        parent::render($state, $renderer, $attribute);
+
+        if ($state == 987 && method_exists($renderer, 'finishSectionEdit')) {
+            $renderer->finishSectionEdit($attribute);
+        }
+    }
+
+    /**
+     *
+     */
+    protected function render_enter(Doku_Renderer $renderer, $attribute) {
+        $renderer->doc .= $this->renderTable($attribute) . DOKU_LF;
+        $renderer->doc .= '<tr>' . $this->renderTd($attribute) . DOKU_LF;
+    }
+
+    /**
+     *
+     */
+    protected function render_matched(Doku_Renderer $renderer, $attribute) {
+        $renderer->doc .= '</td>' . $this->renderTd($attribute) . DOKU_LF;
+    }
+
+    /**
+     *
+     */
+    protected function render_exit(Doku_Renderer $renderer, $attribute) {
+        $renderer->doc .= '</td></tr></table>' . DOKU_LF;
+    }
+
+    /**
+     *
+     */
+    private function renderTable($attribute) {
+        $width = $this->getAttribute($attribute, 'table-width');
+        if ($width != '') {
+            return '<table class="columns-plugin" style="width:' . $width . 
'">';
+        }
+        else {
+            return '<table class="columns-plugin">';
+        }
+    }
+
+    /**
+     *
+     */
+    private function renderTd($attribute) {
+        $class[] = 'columns-plugin';
+        $class[] = $this->getAttribute($attribute, 'class');
+        $class[] = $this->getAttribute($attribute, 'text-align');
+        $html = '<td class="' . implode(' ', array_filter($class)) . '"';
+        $style = $this->getStyle($attribute, 'column-width', 'width');
+        $style .= $this->getStyle($attribute, 'vertical-align');
+        if ($style != '') {
+            $html .= ' style="' . $style . '"';
+        }
+        return $html . '>';
+    }
+}
+
+/**
+ * Class columns_renderer_odt_v1
+ */
+class columns_renderer_odt_v1 extends columns_renderer {
+    /**
+     *
+     */
+    protected function render_enter(Doku_Renderer $renderer, $attribute) {
+        $this->addOdtTableStyle($renderer, $attribute);
+        $this->addOdtColumnStyles($renderer, $attribute);
+        $this->renderOdtTableEnter($renderer, $attribute);
+        $this->renderOdtColumnEnter($renderer, $attribute);
+    }
+
+    /**
+     *
+     */
+    protected function render_matched(Doku_Renderer $renderer, $attribute) {
+        $this->addOdtColumnStyles($renderer, $attribute);
+        $this->renderOdtColumnExit($renderer);
+        $this->renderOdtColumnEnter($renderer, $attribute);
+    }
+
+    /**
+     *
+     */
+    protected function render_exit(Doku_Renderer $renderer, $attribute) {
+        $this->renderOdtColumnExit($renderer);
+        $this->renderOdtTableExit($renderer);
+    }
+
+    /**
+     *
+     */
+    private function addOdtTableStyle(Doku_Renderer $renderer, $attribute) {
+        $styleName = 
$this->getOdtTableStyleName($this->getAttribute($attribute, 'block-id'));
+        $style = '<style:style style:name="' . $styleName . '" 
style:family="table">';
+        $style .= '<style:table-properties';
+        $width = $this->getAttribute($attribute, 'table-width');
+
+        if (($width != '') && ($width != '100%')) {
+            $metrics = $this->getOdtMetrics($renderer->autostyles);
+            $style .= ' style:width="' . $this->getOdtAbsoluteWidth($metrics, 
$width) . '"';
+        }
+        $align = ($width == '100%') ? 'margins' : 'left';
+        $style .= ' table:align="' . $align . '"/>';
+        $style .= '</style:style>';
+
+        $renderer->autostyles[$styleName] = $style;
+    }
+
+    /**
+     *
+     */
+    private function addOdtColumnStyles(Doku_Renderer $renderer, $attribute) {
+        $blockId = $this->getAttribute($attribute, 'block-id');
+        $columnId = $this->getAttribute($attribute, 'column-id');
+        $styleName = $this->getOdtTableStyleName($blockId, $columnId);
+
+        $style = '<style:style style:name="' . $styleName . '" 
style:family="table-column">';
+        $style .= '<style:table-column-properties';
+        $width = $this->getAttribute($attribute, 'column-width');
+
+        if ($width != '') {
+            $metrics = $this->getOdtMetrics($renderer->autostyles);
+            $style .= ' style:column-width="' . 
$this->getOdtAbsoluteWidth($metrics, $width) . '"';
+        }
+        $style .= '/>';
+        $style .= '</style:style>';
+
+        $renderer->autostyles[$styleName] = $style;
+
+        $styleName = $this->getOdtTableStyleName($blockId, $columnId, 1);
+
+        $style = '<style:style style:name="' . $styleName . '" 
style:family="table-cell">';
+        $style .= '<style:table-cell-properties';
+        $style .= ' fo:border="none"';
+        $style .= ' fo:padding-top="0cm"';
+        $style .= ' fo:padding-bottom="0cm"';
+
+        switch ($this->getAttribute($attribute, 'class')) {
+            case 'first':
+                $style .= ' fo:padding-left="0cm"';
+                $style .= ' fo:padding-right="0.4cm"';
+                break;
+
+            case 'last':
+                $style .= ' fo:padding-left="0.4cm"';
+                $style .= ' fo:padding-right="0cm"';
+                break;
+        }
+
+        /* There seems to be no easy way to control horizontal alignment of 
text within
+           the column as fo:text-align aplies to individual paragraphs. */
+        //TODO: $this->getAttribute($attribute, 'text-align');
+
+        $align = $this->getAttribute($attribute, 'vertical-align');
+        if ($align != '') {
+            $style .= ' style:vertical-align="' . $align . '"';
+        }
+        else {
+            $style .= ' style:vertical-align="top"';
+        }
+
+        $style .= '/>';
+        $style .= '</style:style>';
+
+        $renderer->autostyles[$styleName] = $style;
+    }
+
+    /**
+     *
+     */
+    private function renderOdtTableEnter(Doku_Renderer $renderer, $attribute) {
+        $columns = $this->getAttribute($attribute, 'columns');
+        $blockId = $this->getAttribute($attribute, 'block-id');
+        $styleName = $this->getOdtTableStyleName($blockId);
+
+        $renderer->doc .= '<table:table table:style-name="' . $styleName . 
'">';
+        for ($c = 0; $c < $columns; $c++) {
+            $styleName = $this->getOdtTableStyleName($blockId, $c + 1);
+            $renderer->doc .= '<table:table-column table:style-name="' . 
$styleName . '" />';
+        }
+        $renderer->doc .= '<table:table-row>';
+    }
+
+    /**
+     *
+     */
+    private function renderOdtColumnEnter(Doku_Renderer $renderer, $attribute) 
{
+        $blockId = $this->getAttribute($attribute, 'block-id');
+        $columnId = $this->getAttribute($attribute, 'column-id');
+        $styleName = $this->getOdtTableStyleName($blockId, $columnId, 1);
+        $renderer->doc .= '<table:table-cell table:style-name="' . $styleName 
. '" office:value-type="string">';
+    }
+
+    /**
+     *
+     */
+    private function renderOdtColumnExit(Doku_Renderer $renderer) {
+        $renderer->doc .= '</table:table-cell>';
+    }
+
+    /**
+     *
+     */
+    private function renderOdtTableExit(Doku_Renderer $renderer) {
+        $renderer->doc .= '</table:table-row>';
+        $renderer->doc .= '</table:table>';
+    }
+
+    /**
+     * Convert relative units to absolute
+     */
+    private function getOdtAbsoluteWidth($metrics, $width) {
+        if (preg_match('/([\d\.]+)(.+)/', $width, $match) == 1) {
+            switch ($match[2]) {
+                case '%':
+                    /* Won't work for nested column blocks */
+                    $width = ($match[1] / 100 * $metrics['page-width']) . 
$metrics['page-width-units'];
+                    break;
+                case 'em':
+                    /* Rough estimate */
+                    $width = ($match[1] * 0.8 * $metrics['font-size']) . 
$metrics['font-size-units'];
+                    break;
+            }
+        }
+        return $width;
+    }
+
+    /**
+     *
+     */
+    private function getOdtTableStyleName($blockId, $columnId = 0, $cell = 0) {
+        $result = 'ColumnsBlock' . $blockId;
+        if ($columnId != 0) {
+            if ($columnId <= 26) {
+                $result .= '.' . chr(ord('A') + $columnId - 1);
+            }
+            else {
+                /* To unlikey to handle it properly */
+                $result .= '.a';
+            }
+            if ($cell != 0) {
+                $result .= $cell;
+            }
+        }
+        return $result;
+    }
+
+    /**
+     *
+     */
+    private function getOdtMetrics($autoStyle) {
+        $result = array();
+        if (array_key_exists('pm1', $autoStyle)) {
+            $style = $autoStyle['pm1'];
+            if (preg_match('/fo:page-width="([\d\.]+)(.+?)"/', $style, $match) 
== 1) {
+                $result['page-width'] = floatval($match[1]);
+                $result['page-width-units'] = $match[2];
+                $units = $match[2];
+
+                if (preg_match('/fo:margin-left="([\d\.]+)(.+?)"/', $style, 
$match) == 1) {
+                    // TODO: Unit conversion
+                    if ($match[2] == $units) {
+                        $result['page-width'] -= floatval($match[1]);
+                    }
+                }
+                if (preg_match('/fo:margin-right="([\d\.]+)(.+?)"/', $style, 
$match) == 1) {
+                    if ($match[2] == $units) {
+                        $result['page-width'] -= floatval($match[1]);
+                    }
+                }
+            }
+        }
+        if (!array_key_exists('page-width', $result)) {
+            $result['page-width'] = 17;
+            $result['page-width-units'] = 'cm';
+        }
+
+        /* There seems to be no easy way to get default font size apart from 
loading styles.xml. */
+        $styles = io_readFile(DOKU_PLUGIN . 'odt/styles.xml');
+        if (preg_match('/<style:default-style 
style:family="paragraph">(.+?)<\/style:default-style>/s', $styles, $match) == 
1) {
+            if (preg_match('/<style:text-properties(.+?)>/', $match[1], 
$match) == 1) {
+                if (preg_match('/fo:font-size="([\d\.]+)(.+?)"/', $match[1], 
$match) == 1) {
+                    $result['font-size'] = floatval($match[1]);
+                    $result['font-size-units'] = $match[2];
+                }
+            }
+        }
+        if (!array_key_exists('font-size', $result)) {
+            $result['font-size'] = 12;
+            $result['font-size-units'] = 'pt';
+        }
+        return $result;
+    }
+}
+
+/**
+ * Class columns_renderer_odt_v2
+ * @author LarsDW223
+ */
+class columns_renderer_odt_v2 extends columns_renderer {
+    /**
+     *
+     */
+    protected function render_enter(Doku_Renderer $renderer, $attribute) {
+        $this->renderOdtTableEnter($renderer, $attribute);
+        $this->renderOdtColumnEnter($renderer, $attribute);
+    }
+
+    /**
+     *
+     */
+    protected function render_matched(Doku_Renderer $renderer, $attribute) {
+        $this->renderOdtColumnExit($renderer);
+        $this->renderOdtColumnEnter($renderer, $attribute);
+    }
+
+    /**
+     *
+     */
+    protected function render_exit(Doku_Renderer $renderer, $attribute) {
+        $this->renderOdtColumnExit($renderer);
+        $this->renderOdtTableExit($renderer);
+    }
+
+    /**
+     *
+     */
+    private function renderOdtTableEnter(Doku_Renderer $renderer, $attribute) {
+        $properties = array();
+        $properties ['width'] = $this->getAttribute($attribute, 'table-width');
+        $properties ['align'] = 'left';
+        $renderer->_odtTableOpenUseProperties ($properties);
+        $renderer->tablerow_open();
+    }
+
+    /**
+     *
+     */
+    private function renderOdtColumnEnter(Doku_Renderer $renderer, $attribute) 
{
+        $properties = array();
+        $properties ['width'] = $this->getAttribute($attribute, 
'column-width');
+        $properties ['border'] = 'none';
+        $properties ['padding-top'] = '0cm';
+        $properties ['padding-bottom'] = '0cm';
+        switch ($this->getAttribute($attribute, 'class')) {
+            case 'first':
+                $properties ['padding-left'] = '0cm';
+                $properties ['padding-right'] = '0.4cm';
+                break;
+
+            case 'last':
+                $properties ['padding-left'] = '0.4cm';
+                $properties ['padding-right'] = '0cm';
+                break;
+        }
+        $align = $this->getAttribute($attribute, 'vertical-align');
+        if ($align != '') {
+            $properties ['vertical-align'] = $align;
+        }
+        else {
+            $properties ['vertical-align'] = 'top';
+        }
+        $align = $this->getAttribute($attribute, 'text-align');
+        if ($align != '') {
+            $properties ['text-align'] = $align;
+        }
+        else {
+            $properties ['text-align'] = 'left';
+        }
+
+        $renderer->_odtTableCellOpenUseProperties($properties);
+    }
+
+    /**
+     *
+     */
+    private function renderOdtColumnExit(Doku_Renderer $renderer) {
+        $renderer->tablecell_close();
+    }
+
+    /**
+     *
+     */
+    private function renderOdtTableExit(Doku_Renderer $renderer) {
+        $renderer->tablerow_close();
+        $renderer->table_close();
+    }
+}
diff --git a/public_html/lib/tpl/e/css/modifications.css 
b/public_html/lib/tpl/e/css/modifications.css
index fe4d17e..9cc7377 100644
--- a/public_html/lib/tpl/e/css/modifications.css
+++ b/public_html/lib/tpl/e/css/modifications.css
@@ -90,6 +90,17 @@ h1, h2, h3, h4, h5, h6,
    }
 }
 
+@media screen and (max-width: 768px) {
+   table.columns-plugin {
+      border: none;
+   }
+   table.columns-plugin, table.columns-plugin tbody,
+   table.columns-plugin tr, table.columns-plugin td {
+      display: block;
+      width: 100% !important;
+   }
+}
+
 @media (min-width: 768px) and (max-width: 993px) {
     .page {
         padding: 60px 0;

-- 


Reply via email to