Files
dokuwiki-plugins/lib/plugins/odt/syntax.php

396 lines
15 KiB
PHP
Raw Normal View History

2025-10-09 15:04:29 +11:00
<?php
/**
* ODT Plugin: Exports to ODT
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Andreas Gohr <andi@splitbrain.org>
* @author Aurelien Bompard <aurelien@bompard.org>
*/
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();
/**
* Class syntax_plugin_odt
*
* @package DokuWiki\Syntax
*/
class syntax_plugin_odt extends DokuWiki_Syntax_Plugin {
protected $config = NULL;
/**
* What kind of syntax are we?
*/
public function getType() {
return 'substition';
}
/**
* What about paragraphs?
*/
public function getPType() {
return 'normal';
}
/**
* Where to sort in?
*/
public function getSort() {
return 319; // Before image detection, which uses {{...}} and is 320
}
/**
* Connect pattern to lexer
*
* @param string $mode
*/
public function connectTo($mode) {
$this->Lexer->addSpecialPattern('~~ODT~~', $mode, 'plugin_odt');
$this->Lexer->addSpecialPattern('{{odt>.+?}}', $mode, 'plugin_odt');
}
/**
* Handler to prepare matched data for the rendering process
*
* @param string $match The text matched by the patterns
* @param int $state The lexer state for the match
* @param int $pos The character position of the matched text
* @param Doku_Handler $handler The Doku_Handler object
* @return bool|array Return an array with all data you want to use in render, false don't add an instruction
*/
public function handle($match, $state, $pos, Doku_Handler $handler) {
// Export button
if($match == '~~ODT~~') {
return array();
}
// Extended info
$match = substr($match, 6, -2); //strip markup
$extinfo = explode(':', $match);
$info_type = $extinfo[0];
if(count($extinfo) < 2) { // no value
$info_value = '';
} elseif(count($extinfo) == 2) {
$info_value = $extinfo[1];
} else { // value may contain colons
$info_value = implode(array_slice($extinfo, 1), ':');
}
return array($info_type, $info_value, $pos);
}
/**
* Handles the actual output creation.
*
* @param string $format output format being rendered
* @param Doku_Renderer $renderer the current renderer object
* @param array $data data created by handler()
* @return boolean rendered correctly? (however, returned value is not used at the moment)
*/
public function render($format, Doku_Renderer $renderer, $data) {
global $ID, $REV;
if(!$data) { // Export button
if($format != 'xhtml') return false;
$renderer->doc .= '<a href="' . exportlink($ID, 'odt', ($REV != '' ? 'rev=' . $REV : '')) . '" title="' . $this->getLang('view') . '">';
$renderer->doc .= '<img src="' . DOKU_BASE . 'lib/plugins/odt/odt.png" align="right" alt="' . $this->getLang('view') . '" width="48" height="48" />';
$renderer->doc .= '</a>';
return true;
} else { // Extended info
// Load config helper if not done yet
if ( $this->config == NULL ) {
$this->config = plugin_load('helper', 'odt_config');
}
list($info_type, $info_value, $pos) = $data;
// If it is a config option store it in the meta data
// and set the config parameter in the renderer.
if ( $this->config->isParam($info_type) ) {
if($format == 'odt') {
/** @var renderer_plugin_odt_page $renderer */
$renderer->setConfigParam($info_type, $info_value);
} elseif($format == 'metadata') {
if ($this->config->addingToMetaIsAllowed($info_type, $pos)) {
/** @var Doku_Renderer_metadata $renderer */
$renderer->meta['relation']['odt'][$info_type] = $info_value;
}
}
}
// Do some more work for the tags which are not just a config parameter setter
switch($info_type)
{
case 'toc': // Insert TOC in exported ODT file
if($format == 'odt') {
/** @var renderer_plugin_odt_page $renderer */
$renderer->render_index('toc', $info_value);
} elseif($format == 'metadata') {
/** @var Doku_Renderer_metadata $renderer */
$renderer->meta['relation']['odt']['toc'] = $info_value;
} elseif($format == 'xhtml') {
$this->insert_index_preview ($renderer, 'toc');
}
break;
case 'chapter-index': // Insert chapter index in exported ODT file
if($format == 'odt') {
/** @var renderer_plugin_odt_page $renderer */
$renderer->render_index('chapter', $info_value);
} elseif($format == 'xhtml') {
$this->insert_index_preview ($renderer, 'chapter');
}
break;
case 'disablelinks': // Disable creating links and only show the text instead
if($format == 'odt') {
$renderer->disable_links();
}
break;
case 'enablelinks': // Re-enable creating links
if($format == 'odt') {
$renderer->enable_links();
}
break;
case 'page':
if($format == 'odt') {
/** @var renderer_plugin_odt_page $renderer */
$params = explode(',', $info_value);
$format = trim ($params [0]);
$orientation = trim ($params [1]);
for ( $index = 2 ; $index < 6 ; $index++ ) {
if ( empty($params [$index]) ) {
$params [$index] = 2;
}
}
$renderer->setPageFormat($format, $orientation, $params [2], $params [3], $params [4], $params [5]);
}
break;
case 'format':
if($format == 'odt') {
/** @var renderer_plugin_odt_page $renderer */
$format = trim ($info_value);
$renderer->setPageFormat($format);
}
break;
case 'orientation':
if($format == 'odt') {
/** @var renderer_plugin_odt_page $renderer */
$orientation = trim ($info_value);
$renderer->setPageFormat(NULL,$orientation);
}
break;
case 'margin_top':
if($format == 'odt') {
/** @var renderer_plugin_odt_page $renderer */
$margin = trim ($info_value);
$renderer->setPageFormat(NULL,NULL,$margin);
}
break;
case 'margin_right':
if($format == 'odt') {
/** @var renderer_plugin_odt_page $renderer */
$margin = trim ($info_value);
$renderer->setPageFormat(NULL,NULL,NULL,$margin);
}
break;
case 'margin_bottom':
if($format == 'odt') {
/** @var renderer_plugin_odt_page $renderer */
$margin = trim ($info_value);
$renderer->setPageFormat(NULL,NULL,NULL,NULL,$margin);
}
break;
case 'margin_left':
if($format == 'odt') {
/** @var renderer_plugin_odt_page $renderer */
$margin = trim ($info_value);
$renderer->setPageFormat(NULL,NULL,NULL,NULL,NULL,$margin);
}
break;
case 'templatepage': // Take wiki page content as additional CSS input
if($format == 'odt' || $format == 'xhtml' ) {
if ($this->check_templatepage ($info_value, $format) == true &&
$format == 'odt' ) {
/** @var renderer_plugin_odt_page $renderer */
$renderer->read_templatepage($info_value);
}
}
break;
case 'frame-open': // Insert/Open ODT frame
if($format == 'odt' ) {
/** @var renderer_plugin_odt_page $renderer */
$this->frame_open($renderer, $info_value);
}
break;
case 'frame-close': // Close ODT frame
if($format == 'odt' ) {
/** @var renderer_plugin_odt_page $renderer */
$this->frame_close($renderer);
}
break;
}
}
return false;
}
/**
* Insert a browser preview for an index.
*
* @param Doku_Renderer $renderer The current renderer
* @param string $type The index type ('toc' or 'chapter)'
*/
function insert_index_preview ($renderer, $type='toc') {
if ($this->config->getParam ('index_in_browser') == 'hide') {
return;
}
switch ($type) {
case 'toc':
$msg = $this->getLang('toc_msg');
$reminder = $this->getLang('update_toc_msg');
break;
case 'chapter':
$msg = $this->getLang('chapter_msg');
$reminder = $this->getLang('update_chapter_msg');
break;
}
$renderer->doc .= '<p class="index_preview_odt">';
$renderer->doc .= '<span id="text" class="index_preview_odt">'.$msg.'</span><br>';
$renderer->doc .= '<span id="reminder" class="index_preview_odt">'.$reminder.'</span>';
$renderer->doc .= '</p>';
}
/**
* Checl existance of the template page and display error
* message in case of xhtml rendering.
*
* @param string $pagename The page to check
* @param string $format The render format ('xhtml' or 'odt')
*/
protected function check_templatepage ($pagename, $format) {
$exists = false;
if (empty($pagename)) {
if ($format == 'xhtml') {
msg(sprintf("No page specified!", html_wikilink($pagename)), -1);
}
return (false);
}
resolve_pageid($INFO['namespace'], $pagename, $exists);
if(!$exists) {
if ($format == 'xhtml') {
msg(sprintf("Page not found!", html_wikilink($pagename)), -1);
}
return (false);
}
return (true);
}
/**
* Open a frame with a text box.
*
* @param Doku_Renderer $renderer The current renderer object
* @param string $params Parameters for the frame
*/
protected function frame_open ($renderer, $params) {
// Get inline CSS for ODT frame
$odt_css = '';
if ( preg_match('/odt-css="[^"]+";/', $params, $matches) === 1 ) {
$quote = strpos ($matches [0], '"');
$temp = substr ($matches [0], $quote+1);
$temp = trim ($temp, '";');
$odt_css = $temp.';';
}
$odt_css_id = '';
if ( preg_match('/odt-css-id="[^"]+";/', $params, $matches) === 1 ) {
$quote = strpos ($matches [0], '"');
$temp = substr ($matches [0], $quote+1);
$temp = trim ($temp, '";');
$odt_css_id = $temp;
}
$properties = array();
$renderer->getODTPropertiesNew ($properties, NULL, 'id="'.$odt_css_id.'" style="'.$odt_css.'"');
if (empty($properties ['page'])) {
$properties ['anchor-type'] = 'page';
}
if (empty($properties ['wrap'])) {
$properties ['wrap'] = 'run-through';
}
if (empty($properties ['number-wrapped-paragraphs'])) {
$properties ['number-wrapped-paragraphs'] = 'no-limit';
}
if (empty($properties ['vertical-pos'])) {
$properties ['vertical-pos'] = 'from-top';
}
if (empty($properties ['vertical-rel'])) {
$properties ['vertical-rel'] = 'page';
}
if (empty($properties ['horizontal-pos'])) {
$properties ['horizontal-pos'] = 'from-left';
}
if (empty($properties ['horizontal-rel'])) {
$properties ['horizontal-rel'] = 'page';
}
if (empty($properties ['wrap-influence-on-position'])) {
$properties ['wrap-influence-on-position'] = 'once-concurrent';
}
if (empty($properties ['flow-with-text'])) {
$properties ['flow-with-text'] = 'false';
}
if (empty($properties ['margin-top'])) {
$properties ['margin-top'] = '0cm';
}
if (empty($properties ['margin-right'])) {
$properties ['margin-right'] = '0cm';
}
if (empty($properties ['margin-bottom'])) {
$properties ['margin-bottom'] = '0cm';
}
if (empty($properties ['margin-left'])) {
$properties ['margin-left'] = '0cm';
}
if (empty($properties ['padding-top'])) {
$properties ['padding-top'] = '0cm';
}
if (empty($properties ['padding-right'])) {
$properties ['padding-right'] = '0cm';
}
if (empty($properties ['padding-bottom'])) {
$properties ['padding-bottom'] = '0cm';
}
if (empty($properties ['padding-left'])) {
$properties ['padding-left'] = '0cm';
}
if (empty($properties ['border-top'])) {
$properties ['border-top'] = 'none';
}
if (empty($properties ['border-right'])) {
$properties ['border-right'] = 'none';
}
if (empty($properties ['border-bottom'])) {
$properties ['border-bottom'] = 'none';
}
if (empty($properties ['border-left'])) {
$properties ['border-left'] = 'none';
}
if (empty($properties ['horizontal-align'])) {
$properties ['horizontal-align'] = 'left';
}
$renderer->_odtOpenTextBoxUseProperties ($properties);
$renderer->p_open();
}
/**
* Close a frame with a text box.
*
* @param Doku_Renderer $renderer The current renderer object
*/
protected function frame_close ($renderer) {
$renderer->p_close();
$renderer->_odtCloseTextBox ();
}
}