1531e725cSNickeau<?php 2531e725cSNickeau 3531e725cSNickeauuse ComboStrap\CallStack; 4531e725cSNickeauuse ComboStrap\LogUtility; 5531e725cSNickeauuse ComboStrap\PluginUtility; 6531e725cSNickeauuse ComboStrap\TagAttributes; 7531e725cSNickeau 8531e725cSNickeau 9531e725cSNickeau/** 10531e725cSNickeau * Class headingwiki 11531e725cSNickeau * Taking over {@link \dokuwiki\Parsing\ParserMode\Header} 12531e725cSNickeau */ 13531e725cSNickeauclass syntax_plugin_combo_headingwiki extends DokuWiki_Syntax_Plugin 14531e725cSNickeau{ 15531e725cSNickeau 16531e725cSNickeau /** 17531e725cSNickeau * Header pattern 18531e725cSNickeau * * Dokuwiki does not made a space mandatory after and before the opening an closing `=` character 19531e725cSNickeau * * No line break in the look ahead 20531e725cSNickeau * * The capture of the first spaces should be optional otherwise the {@link \dokuwiki\Parsing\ParserMode\Header} is taking over 21531e725cSNickeau * 22531e725cSNickeau * See also for information, 23531e725cSNickeau * the original heading pattern of Dokuwiki {@link \dokuwiki\Parsing\ParserMode\Header} 24531e725cSNickeau */ 25531e725cSNickeau const ENTRY_PATTERN = '[ \t]*={1,6}(?=[^\n]*={1,6}\s*\r??\n)'; 26531e725cSNickeau const EXIT_PATTERN = '={1,6}\s*(?=\r??\n)'; 27531e725cSNickeau const TAG = "headingwiki"; 28531e725cSNickeau 29531e725cSNickeau const CONF_WIKI_HEADING_ENABLE = "headingWikiEnable"; 30531e725cSNickeau const CONF_DEFAULT_WIKI_ENABLE_VALUE = 1; 31531e725cSNickeau 32531e725cSNickeau public function getSort() 33531e725cSNickeau { 34531e725cSNickeau /** 35531e725cSNickeau * It's 49 (on less than the original heading) 36531e725cSNickeau * {@link \dokuwiki\Parsing\ParserMode\Header::getSort()} 37531e725cSNickeau */ 38531e725cSNickeau return 49; 39531e725cSNickeau } 40531e725cSNickeau 41531e725cSNickeau public function getType() 42531e725cSNickeau { 43531e725cSNickeau return syntax_plugin_combo_heading::SYNTAX_TYPE; 44531e725cSNickeau } 45531e725cSNickeau 46531e725cSNickeau 47531e725cSNickeau /** 48531e725cSNickeau * 49531e725cSNickeau * How Dokuwiki will add P element 50531e725cSNickeau * 51531e725cSNickeau * * 'normal' - The plugin can be used inside paragraphs (inline) 52531e725cSNickeau * * 'block' - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs 53531e725cSNickeau * * 'stack' - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs 54531e725cSNickeau * 55531e725cSNickeau * @see DokuWiki_Syntax_Plugin::getPType() 56531e725cSNickeau * 57531e725cSNickeau * This is the equivalent of inline or block for css 58531e725cSNickeau */ 59531e725cSNickeau public function getPType() 60531e725cSNickeau { 61531e725cSNickeau return syntax_plugin_combo_heading::SYNTAX_PTYPE; 62531e725cSNickeau } 63531e725cSNickeau 64531e725cSNickeau /** 65531e725cSNickeau * @return array 66531e725cSNickeau * Allow which kind of plugin inside 67531e725cSNickeau * 68531e725cSNickeau * No one of array('baseonly','container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs') 69531e725cSNickeau * because we manage self the content and we call self the parser 70531e725cSNickeau * 71531e725cSNickeau * Return an array of one or more of the mode types {@link $PARSER_MODES} in Parser.php 72531e725cSNickeau */ 73531e725cSNickeau function getAllowedTypes() 74531e725cSNickeau { 75531e725cSNickeau return array('formatting', 'substition', 'protected', 'disabled'); 76531e725cSNickeau } 77531e725cSNickeau 78531e725cSNickeau 79531e725cSNickeau public function connectTo($mode) 80531e725cSNickeau { 81531e725cSNickeau if ($this->enableWikiHeading($mode)) { 82*9337a630SNickeau $this->Lexer->addEntryPattern(self::ENTRY_PATTERN, $mode, PluginUtility::getModeFromTag($this->getPluginComponent())); 83531e725cSNickeau } 84531e725cSNickeau } 85531e725cSNickeau 86531e725cSNickeau public function postConnect() 87531e725cSNickeau { 88531e725cSNickeau 89*9337a630SNickeau $this->Lexer->addExitPattern(self::EXIT_PATTERN, PluginUtility::getModeFromTag($this->getPluginComponent())); 90531e725cSNickeau 91531e725cSNickeau } 92531e725cSNickeau 93531e725cSNickeau 94531e725cSNickeau /** 95531e725cSNickeau * Handle the syntax 96531e725cSNickeau * 97531e725cSNickeau * At the end of the parser, the `section_open` and `section_close` calls 98531e725cSNickeau * are created in {@link action_plugin_combo_headingpostprocessing} 99531e725cSNickeau * and the text inside for the toc is captured 100531e725cSNickeau * 101531e725cSNickeau * @param string $match 102531e725cSNickeau * @param int $state 103531e725cSNickeau * @param int $pos 104531e725cSNickeau * @param Doku_Handler $handler 105531e725cSNickeau * @return array 106531e725cSNickeau */ 107531e725cSNickeau public function handle($match, $state, $pos, Doku_Handler $handler) 108531e725cSNickeau { 109531e725cSNickeau switch ($state) { 110531e725cSNickeau 111531e725cSNickeau case DOKU_LEXER_ENTER: 112531e725cSNickeau /** 113531e725cSNickeau * Title regexp 114531e725cSNickeau */ 115531e725cSNickeau $attributes[syntax_plugin_combo_heading::LEVEL] = $this->getLevelFromMatch($match); 116531e725cSNickeau $callStack = CallStack::createFromHandler($handler); 117531e725cSNickeau 118*9337a630SNickeau $context = syntax_plugin_combo_heading::getContext($callStack); 119531e725cSNickeau 120531e725cSNickeau return array( 121531e725cSNickeau PluginUtility::STATE => $state, 122531e725cSNickeau PluginUtility::ATTRIBUTES => $attributes, 123531e725cSNickeau PluginUtility::CONTEXT => $context, 124531e725cSNickeau PluginUtility::POSITION => $pos 125531e725cSNickeau ); 126531e725cSNickeau case DOKU_LEXER_UNMATCHED : 127531e725cSNickeau 128531e725cSNickeau return PluginUtility::handleAndReturnUnmatchedData(self::TAG, $match, $handler); 129531e725cSNickeau 130531e725cSNickeau case DOKU_LEXER_EXIT : 131531e725cSNickeau 132531e725cSNickeau $callStack = CallStack::createFromHandler($handler); 133531e725cSNickeau 134531e725cSNickeau $returnedData = syntax_plugin_combo_heading::handleExit($callStack); 135531e725cSNickeau 136531e725cSNickeau 137531e725cSNickeau /** 138531e725cSNickeau * Control of the Number of `=` before and after 139531e725cSNickeau */ 140531e725cSNickeau $callStack->moveToEnd(); 141531e725cSNickeau $openingTag = $callStack->moveToPreviousCorrespondingOpeningCall(); 142531e725cSNickeau $levelFromMatch = $this->getLevelFromMatch($match); 143531e725cSNickeau $levelFromStartTag = $openingTag->getAttribute(syntax_plugin_combo_heading::LEVEL); 144531e725cSNickeau if ($levelFromMatch != $levelFromStartTag) { 145531e725cSNickeau $content = ""; 146531e725cSNickeau while ($actualCall = $callStack->next()) { 147531e725cSNickeau $content .= $actualCall->getCapturedContent(); 148531e725cSNickeau } 149531e725cSNickeau LogUtility::msg("The number of `=` character for a wiki heading is not the same before ($levelFromStartTag) and after ($levelFromMatch) the content ($content).", LogUtility::LVL_MSG_WARNING, syntax_plugin_combo_heading::CANONICAL); 150531e725cSNickeau } 151531e725cSNickeau 152531e725cSNickeau return $returnedData; 153531e725cSNickeau 154531e725cSNickeau } 155531e725cSNickeau return array(); 156531e725cSNickeau } 157531e725cSNickeau 158531e725cSNickeau public function render($format, Doku_Renderer $renderer, $data) 159531e725cSNickeau { 160531e725cSNickeau 161531e725cSNickeau if ($format == "xhtml") { 162531e725cSNickeau /** 163531e725cSNickeau * @var Doku_Renderer_xhtml $renderer 164531e725cSNickeau */ 165531e725cSNickeau $state = $data[PluginUtility::STATE]; 166531e725cSNickeau switch ($state) { 167531e725cSNickeau 168531e725cSNickeau case DOKU_LEXER_ENTER: 169531e725cSNickeau $callStackArray = $data[PluginUtility::ATTRIBUTES]; 170531e725cSNickeau $tagAttributes = TagAttributes::createFromCallStackArray($callStackArray, syntax_plugin_combo_heading::TAG); 171531e725cSNickeau $context = $data[PluginUtility::CONTEXT]; 172531e725cSNickeau $pos = $data[PluginUtility::POSITION]; 173531e725cSNickeau syntax_plugin_combo_heading::renderOpeningTag($context, $tagAttributes, $renderer, $pos); 174531e725cSNickeau return true; 175531e725cSNickeau case DOKU_LEXER_UNMATCHED: 176531e725cSNickeau $renderer->doc .= PluginUtility::renderUnmatched($data); 177531e725cSNickeau return true; 178531e725cSNickeau case DOKU_LEXER_EXIT: 179531e725cSNickeau $callStackArray = $data[PluginUtility::ATTRIBUTES]; 180531e725cSNickeau $tagAttributes = TagAttributes::createFromCallStackArray($callStackArray); 181531e725cSNickeau $renderer->doc .= syntax_plugin_combo_heading::renderClosingTag($tagAttributes); 182531e725cSNickeau return true; 183531e725cSNickeau 184531e725cSNickeau } 185531e725cSNickeau } else if ($format == renderer_plugin_combo_analytics::RENDERER_FORMAT) { 186531e725cSNickeau 187531e725cSNickeau /** 188531e725cSNickeau * @var renderer_plugin_combo_analytics $renderer 189531e725cSNickeau */ 190531e725cSNickeau syntax_plugin_combo_heading::processMetadataAnalytics($data, $renderer); 191531e725cSNickeau 192531e725cSNickeau } else if ($format == "metadata") { 193531e725cSNickeau 194531e725cSNickeau /** 195531e725cSNickeau * @var Doku_Renderer_metadata $renderer 196531e725cSNickeau */ 197531e725cSNickeau syntax_plugin_combo_heading::processHeadingMetadata($data, $renderer); 198531e725cSNickeau 199531e725cSNickeau } 200531e725cSNickeau 201531e725cSNickeau return false; 202531e725cSNickeau } 203531e725cSNickeau 204531e725cSNickeau /** 205531e725cSNickeau * @param $match 206531e725cSNickeau * @return int 207531e725cSNickeau */ 208531e725cSNickeau public 209531e725cSNickeau function getLevelFromMatch($match) 210531e725cSNickeau { 211531e725cSNickeau return 7 - strlen(trim($match)); 212531e725cSNickeau } 213531e725cSNickeau 214531e725cSNickeau 215531e725cSNickeau private 216531e725cSNickeau function enableWikiHeading($mode) 217531e725cSNickeau { 218531e725cSNickeau 219531e725cSNickeau 220531e725cSNickeau /** 221531e725cSNickeau * Basically all mode that are not `base` 222531e725cSNickeau * To not take the dokuwiki heading 223531e725cSNickeau */ 224531e725cSNickeau if (!(in_array($mode, ['base', 'header', 'table']))) { 225531e725cSNickeau return true; 226531e725cSNickeau } else { 227531e725cSNickeau return PluginUtility::getConfValue(self::CONF_WIKI_HEADING_ENABLE, self::CONF_DEFAULT_WIKI_ENABLE_VALUE); 228531e725cSNickeau } 229531e725cSNickeau 230531e725cSNickeau 231531e725cSNickeau } 232531e725cSNickeau 233531e725cSNickeau 234531e725cSNickeau} 235