1<?php 2 3use ComboStrap\BrandColors; 4use ComboStrap\ColorRgb; 5use ComboStrap\ExceptionCombo; 6use ComboStrap\LogUtility; 7use ComboStrap\PluginUtility; 8use ComboStrap\Site; 9use ComboStrap\TagAttributes; 10 11 12/** 13 * 14 * Taking over {@link \dokuwiki\Parsing\ParserMode\Formatting monospace} 15 * 16 * Known as code 17 * https://spec.commonmark.org/0.30/#code-spans 18 * 19 * note supported but specific highlight is done with two `==` 20 * in some processor 21 * https://www.markdownguide.org/extended-syntax/#highlight 22 * 23 */ 24class syntax_plugin_combo_highlightwiki extends DokuWiki_Syntax_Plugin 25{ 26 27 28 const TAG = "highlightwiki"; 29 // Only on one line 30 const ENTRY_PATTERN = "\x27\x27(?=[^\n]*\x27\x27)(?!\n)"; 31 32 33 const CONF_HIGHLIGHT_WIKI_ENABLE = "highlightWikiEnable"; 34 const CONF_DEFAULT_HIGHLIGHT_WIKI_ENABLE_VALUE = 1; 35 const EXIT_PATTERN = "\x27\x27"; 36 37 const CANONICAL = self::TAG; 38 39 const HTML_TAG = "mark"; 40 41 public static function getOpenTagHighlight(string $tag): string 42 { 43 $htmlTag = self::HTML_TAG; 44 if (!Site::isBrandingColorInheritanceEnabled()) { 45 return "<$htmlTag>"; 46 } 47 $primaryColor = Site::getPrimaryColor(); 48 if ($primaryColor === null) { 49 return "<$htmlTag>"; 50 } 51 $tagAttributes = TagAttributes::createEmpty($tag); 52 try { 53 $colorRgb = BrandColors::toBackgroundColor($primaryColor); 54 $tagAttributes->addComponentAttributeValue(ColorRgb::BACKGROUND_COLOR, $colorRgb 55 ->toRgbHex()); 56 } catch (ExceptionCombo $e) { 57 LogUtility::msg("Error on highlight color calculation"); 58 } 59 return $tagAttributes->toHtmlEnterTag($htmlTag); 60 } 61 62 public function getSort(): int 63 { 64 /** 65 * It's 49 (on less than the original of 100) named monospace 66 * {@link \dokuwiki\Parsing\ParserMode\Formatting} 67 */ 68 return 49; 69 } 70 71 public function getType(): string 72 { 73 return 'formatting'; 74 } 75 76 77 /** 78 * 79 * How Dokuwiki will add P element 80 * 81 * * 'normal' - The plugin can be used inside paragraphs (inline) 82 * * 'block' - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs 83 * * 'stack' - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs 84 * 85 * @see DokuWiki_Syntax_Plugin::getPType() 86 * 87 * This is the equivalent of inline or block for css 88 */ 89 public function getPType(): string 90 { 91 return 'normal'; 92 } 93 94 /** 95 * @return array 96 * Allow which kind of plugin inside 97 * 98 * No one of array('baseonly','container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs') 99 * because we manage self the content and we call self the parser 100 * 101 * Return an array of one or more of the mode types {@link $PARSER_MODES} in Parser.php 102 */ 103 function getAllowedTypes(): array 104 { 105 return array('formatting', 'substition', 'protected', 'disabled'); 106 } 107 108 109 public function connectTo($mode) 110 { 111 $enabled = PluginUtility::getConfValue(self::CONF_HIGHLIGHT_WIKI_ENABLE, self::CONF_DEFAULT_HIGHLIGHT_WIKI_ENABLE_VALUE); 112 if ($enabled) { 113 $this->Lexer->addEntryPattern(self::ENTRY_PATTERN, $mode, PluginUtility::getModeFromTag($this->getPluginComponent())); 114 } 115 116 } 117 118 public function postConnect() 119 { 120 121 $this->Lexer->addExitPattern(self::EXIT_PATTERN, PluginUtility::getModeFromTag($this->getPluginComponent())); 122 123 } 124 125 126 /** 127 * Handle the syntax 128 * 129 * At the end of the parser, the `section_open` and `section_close` calls 130 * are created in {@link action_plugin_combo_headingpostprocessing} 131 * and the text inside for the toc is captured 132 * 133 * @param string $match 134 * @param int $state 135 * @param int $pos 136 * @param Doku_Handler $handler 137 * @return array 138 */ 139 public function handle($match, $state, $pos, Doku_Handler $handler): array 140 { 141 switch ($state) { 142 143 case DOKU_LEXER_EXIT: 144 case DOKU_LEXER_ENTER: 145 return array( 146 PluginUtility::STATE => $state 147 ); 148 case DOKU_LEXER_UNMATCHED : 149 150 return PluginUtility::handleAndReturnUnmatchedData(self::TAG, $match, $handler); 151 152 } 153 return array(); 154 } 155 156 public function render($format, $renderer, $data): bool 157 { 158 159 switch($format) { 160 case "xhtml": 161 { 162 /** 163 * @var Doku_Renderer_xhtml $renderer 164 */ 165 $state = $data[PluginUtility::STATE]; 166 switch ($state) { 167 168 case DOKU_LEXER_ENTER: 169 $renderer->doc .= self::getOpenTagHighlight(self::TAG); 170 return true; 171 case DOKU_LEXER_UNMATCHED: 172 $renderer->doc .= PluginUtility::renderUnmatched($data); 173 return true; 174 case DOKU_LEXER_EXIT: 175 $htmlTag = self::HTML_TAG; 176 $renderer->doc .= "</$htmlTag>"; 177 return true; 178 179 } 180 break; 181 } 182 case "metadata": 183 /** 184 * @var Doku_Renderer_metadata $renderer 185 */ 186 $state = $data[PluginUtility::STATE]; 187 switch ($state) { 188 case DOKU_LEXER_UNMATCHED: 189 $renderer->doc .= PluginUtility::renderUnmatched($data); 190 } 191 break; 192 } 193 194 return false; 195 } 196 197 198} 199