Add column plugin and re-flow columns on mobile
This commit is contained in:
parent
ca37d68e4b
commit
62069b6490
|
@ -0,0 +1,675 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Plugin Columns: Layout parser
|
||||
*
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
* @author Mykola Ostrovskyy <spambox03@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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Plugin Columns: Configuration defaults
|
||||
*
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
* @author Mykola Ostrovskyy <spambox03@mail.ru>
|
||||
*/
|
||||
|
||||
$conf['kwcolumns'] = '';
|
||||
$conf['kwnewcol'] = '';
|
||||
$conf['wrapnewcol'] = 1;
|
|
@ -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 <spambox03@mail.ru>
|
||||
*/
|
||||
|
||||
$meta['kwcolumns'] = array('string');
|
||||
$meta['kwnewcol'] = array('string');
|
||||
$meta['wrapnewcol'] = array('onoff');
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Plugin Columns: English language file
|
||||
*
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
* @author Mykola Ostrovskyy <spambox03@mail.ru>
|
||||
*/
|
||||
|
||||
$lang['kwcolumns'] = 'columns';
|
||||
$lang['kwnewcol'] = 'newcolumn';
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Plugin Columns: English language file
|
||||
*
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
* @author Mykola Ostrovskyy <spambox03@mail.ru>
|
||||
*/
|
||||
|
||||
$lang['kwcolumns'] = 'Columns tag (default: columns); must be specified within angle brackets (<columns>...</columns>)';
|
||||
$lang['kwnewcol'] = 'New column tag (default: newcolumn)';
|
||||
$lang['wrapnewcol'] = 'Wrap the new column tag in angle brackets (<newcolumn>)';
|
|
@ -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';
|
||||
|
|
@ -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 (<columnas>...</columnas>)';
|
||||
$lang['kwnewcol'] = 'Etiqueta de nueva columna (por defecto: nueva_columna)';
|
||||
$lang['wrapnewcol'] = 'Encerrar la etiqueta de nueva columna entre paréntesis angulares (<nueva_columna>)';
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Plugin Columns: Russian language file
|
||||
*
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
* @author Mykola Ostrovskyy <spambox03@mail.ru>
|
||||
*/
|
||||
|
||||
$lang['kwcolumns'] = 'колонки';
|
||||
$lang['kwnewcol'] = 'новаяколонка';
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Plugin Columns: Russian language file
|
||||
*
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
* @author Mykola Ostrovskyy <spambox03@mail.ru>
|
||||
*/
|
||||
|
||||
$lang['kwcolumns'] = 'Тег колонок (по умолчанию: колонки); тег должен быть заключен в угловые скобки (<колонки>...</колонки>)';
|
||||
$lang['kwnewcol'] = 'Тег новой колонки (по умолчанию: новаяколонка)';
|
||||
$lang['wrapnewcol'] = 'Заключать тег новой колонки в угловые скобки (<новаяколонка>)';
|
|
@ -0,0 +1,7 @@
|
|||
base columns
|
||||
author Mykola Ostrovskyy
|
||||
email spambox03@mail.ru
|
||||
date 2016-09-07
|
||||
name Columns Plugin
|
||||
desc Arrange information in multiple columns.
|
||||
url http://www.dokuwiki.org/plugin:columns
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Instruction re-writer
|
||||
*
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
* @author Mykola Ostrovskyy <spambox03@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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,611 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Plugin Columns: Syntax & rendering
|
||||
*
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
* @author Mykola Ostrovskyy <spambox03@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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue