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