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