1<?php 2 3 4// must be run within Dokuwiki 5use ComboStrap\CallStack; 6use ComboStrap\Dimension; 7use ComboStrap\PluginUtility; 8use ComboStrap\TagAttributes; 9 10if (!defined('DOKU_INC')) die(); 11 12/** 13 * Class syntax_plugin_combo_text 14 * A text block that permits to style 15 * paragraph at once 16 * 17 * The output will be a series of {@link syntax_plugin_combo_para paragraph} 18 * with the same properties 19 * 20 * It permits to have several paragraph 21 */ 22class syntax_plugin_combo_text extends DokuWiki_Syntax_Plugin 23{ 24 25 const TAG = "text"; 26 const TAGS = ["typo", self::TAG]; 27 28 /** 29 * Syntax Type. 30 * 31 * Needs to return one of the mode types defined in {@link $PARSER_MODES} in parser.php 32 * @see DokuWiki_Syntax_Plugin::getType() 33 */ 34 function getType(): string 35 { 36 return 'paragraphs'; 37 } 38 39 /** 40 * How Dokuwiki will add P element 41 * 42 * * 'normal' - The plugin can be used inside paragraphs 43 * * 'block' - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs 44 * * 'stack' - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs 45 * 46 * @see DokuWiki_Syntax_Plugin::getPType() 47 */ 48 function getPType(): string 49 { 50 return 'stack'; 51 } 52 53 /** 54 * @return array 55 * Allow which kind of plugin inside 56 * 57 * No one of array('baseonly','container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs') 58 * because we manage self the content and we call self the parser 59 * 60 * Return an array of one or more of the mode types {@link $PARSER_MODES} in Parser.php 61 */ 62 function getAllowedTypes(): array 63 { 64 return array('formatting', 'substition', 'paragraphs'); 65 } 66 67 public function accepts($mode): bool 68 { 69 70 return syntax_plugin_combo_preformatted::disablePreformatted($mode); 71 72 } 73 74 75 function getSort(): int 76 { 77 /** 78 * Less than {@link syntax_plugin_typography_base} 79 */ 80 return 65; 81 } 82 83 84 function connectTo($mode) 85 { 86 87 foreach (self::TAGS as $tag) { 88 $pattern = PluginUtility::getContainerTagPattern($tag); 89 $this->Lexer->addEntryPattern($pattern, $mode, PluginUtility::getModeFromTag($this->getPluginComponent())); 90 } 91 } 92 93 94 function postConnect() 95 { 96 foreach (self::TAGS as $tag) { 97 $this->Lexer->addExitPattern('</' . $tag . '>', PluginUtility::getModeFromTag($this->getPluginComponent())); 98 } 99 100 } 101 102 function handle($match, $state, $pos, Doku_Handler $handler) 103 { 104 105 switch ($state) { 106 107 case DOKU_LEXER_ENTER : 108 109 $attributes = TagAttributes::createFromTagMatch($match); 110 $callStackArray = $attributes->toCallStackArray(); 111 112 return array( 113 PluginUtility::STATE => $state, 114 PluginUtility::ATTRIBUTES => $callStackArray 115 ); 116 117 case DOKU_LEXER_UNMATCHED : 118 return PluginUtility::handleAndReturnUnmatchedData(self::TAG, $match, $handler); 119 120 case DOKU_LEXER_EXIT : 121 /** 122 * Transform all paragraphs 123 * with the type as class 124 */ 125 $callStack = CallStack::createFromHandler($handler); 126 $openingCall = $callStack->moveToPreviousCorrespondingOpeningCall(); 127 $attributes = $openingCall->getAttributes(); 128 // if there is no EOL, we add one to create at minimal a paragraph 129 $callStack->insertEolIfNextCallIsNotEolOrBlock(); 130 $callStack->processEolToEndStack($attributes); 131 132 /** 133 * Check and add a scroll toggle if the 134 * text is constrained by height 135 */ 136 Dimension::addScrollToggleOnClickIfNoControl($callStack); 137 138 return array(PluginUtility::STATE => $state); 139 140 141 } 142 return array(); 143 144 } 145 146 /** 147 * Render the output 148 * @param string $format 149 * @param Doku_Renderer $renderer 150 * @param array $data - what the function handle() return'ed 151 * @return boolean - rendered correctly? (however, returned value is not used at the moment) 152 * @see DokuWiki_Syntax_Plugin::render() 153 * 154 * 155 */ 156 function render($format, Doku_Renderer $renderer, $data): bool 157 { 158 if ($format == 'xhtml') { 159 160 /** @var Doku_Renderer_xhtml $renderer */ 161 $state = $data[PluginUtility::STATE]; 162 switch ($state) { 163 case DOKU_LEXER_EXIT : 164 case DOKU_LEXER_ENTER : 165 /** 166 * The {@link DOKU_LEXER_EXIT} of the {@link syntax_plugin_combo_text::handle()} 167 * has already created in the callstack the {@link syntax_plugin_combo_para} call 168 */ 169 $renderer->doc .= ""; 170 break; 171 case DOKU_LEXER_UNMATCHED : 172 $renderer->doc .= PluginUtility::renderUnmatched($data); 173 break; 174 } 175 return true; 176 } 177 178 // unsupported $mode 179 return false; 180 } 181 182 183} 184 185