1*531e725cSNickeau<?php 2*531e725cSNickeau 3*531e725cSNickeau 4*531e725cSNickeauuse ComboStrap\CallStack; 5*531e725cSNickeauuse ComboStrap\LogUtility; 6*531e725cSNickeauuse ComboStrap\PluginUtility; 7*531e725cSNickeauuse ComboStrap\TagAttributes; 8*531e725cSNickeau 9*531e725cSNickeau 10*531e725cSNickeauif (!defined('DOKU_INC')) die(); 11*531e725cSNickeau 12*531e725cSNickeau/** 13*531e725cSNickeau * Atx headings 14*531e725cSNickeau * https://github.github.com/gfm/#atx-headings 15*531e725cSNickeau * https://spec.commonmark.org/0.29/#atx-heading 16*531e725cSNickeau * http://www.aaronsw.com/2002/atx/intro 17*531e725cSNickeau */ 18*531e725cSNickeauclass syntax_plugin_combo_headingatx extends DokuWiki_Syntax_Plugin 19*531e725cSNickeau{ 20*531e725cSNickeau 21*531e725cSNickeau 22*531e725cSNickeau const TAG = "headingatx"; 23*531e725cSNickeau const LEVEL = 'level'; 24*531e725cSNickeau const EXIT_PATTERN = "\r??\n"; 25*531e725cSNickeau 26*531e725cSNickeau 27*531e725cSNickeau function getType() 28*531e725cSNickeau { 29*531e725cSNickeau return 'formatting'; 30*531e725cSNickeau } 31*531e725cSNickeau 32*531e725cSNickeau /** 33*531e725cSNickeau * 34*531e725cSNickeau * How Dokuwiki will add P element 35*531e725cSNickeau * 36*531e725cSNickeau * * 'normal' - The plugin can be used inside paragraphs (inline) 37*531e725cSNickeau * * 'block' - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs 38*531e725cSNickeau * * 'stack' - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs 39*531e725cSNickeau * 40*531e725cSNickeau * @see DokuWiki_Syntax_Plugin::getPType() 41*531e725cSNickeau * 42*531e725cSNickeau */ 43*531e725cSNickeau function getPType() 44*531e725cSNickeau { 45*531e725cSNickeau return 'block'; 46*531e725cSNickeau } 47*531e725cSNickeau 48*531e725cSNickeau /** 49*531e725cSNickeau * @return array 50*531e725cSNickeau * Allow which kind of plugin inside 51*531e725cSNickeau * 52*531e725cSNickeau * No one of array('baseonly','container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs') 53*531e725cSNickeau * because we manage self the content and we call self the parser 54*531e725cSNickeau * 55*531e725cSNickeau * Return an array of one or more of the mode types {@link $PARSER_MODES} in Parser.php 56*531e725cSNickeau */ 57*531e725cSNickeau function getAllowedTypes() 58*531e725cSNickeau { 59*531e725cSNickeau return array('formatting', 'substition', 'protected', 'disabled'); 60*531e725cSNickeau } 61*531e725cSNickeau 62*531e725cSNickeau /** 63*531e725cSNickeau * 64*531e725cSNickeau * @return int 65*531e725cSNickeau */ 66*531e725cSNickeau function getSort() 67*531e725cSNickeau { 68*531e725cSNickeau return 49; 69*531e725cSNickeau } 70*531e725cSNickeau 71*531e725cSNickeau 72*531e725cSNickeau function connectTo($mode) 73*531e725cSNickeau { 74*531e725cSNickeau 75*531e725cSNickeau $pattern = '\r??\n\s*#{1,6}\s?(?=.*' . self::EXIT_PATTERN . ')'; 76*531e725cSNickeau $this->Lexer->addSpecialPattern($pattern, $mode, PluginUtility::getModeForComponent($this->getPluginComponent())); 77*531e725cSNickeau 78*531e725cSNickeau } 79*531e725cSNickeau 80*531e725cSNickeau 81*531e725cSNickeau function handle($match, $state, $pos, Doku_Handler $handler) 82*531e725cSNickeau { 83*531e725cSNickeau 84*531e725cSNickeau switch ($state) { 85*531e725cSNickeau 86*531e725cSNickeau case DOKU_LEXER_SPECIAL : 87*531e725cSNickeau 88*531e725cSNickeau $attributes = [syntax_plugin_combo_heading::LEVEL => strlen(trim($match))]; 89*531e725cSNickeau $callStack = CallStack::createFromHandler($handler); 90*531e725cSNickeau 91*531e725cSNickeau // Determine the type 92*531e725cSNickeau $parent = $callStack->moveToParent(); 93*531e725cSNickeau $context = syntax_plugin_combo_heading::getContext($parent); 94*531e725cSNickeau 95*531e725cSNickeau /** 96*531e725cSNickeau * The context is needed: 97*531e725cSNickeau * * to add the bootstrap class if it's a card title for instance 98*531e725cSNickeau * * and to delete {@link syntax_plugin_combo_heading::TYPE_OUTLINE} call 99*531e725cSNickeau * in the {@link action_plugin_combo_headingpostprocess} (The rendering is done via Dokuwiki, 100*531e725cSNickeau * see the exit processing for more info on the handling of outline headings) 101*531e725cSNickeau * 102*531e725cSNickeau */ 103*531e725cSNickeau return array( 104*531e725cSNickeau PluginUtility::STATE => $state, 105*531e725cSNickeau PluginUtility::ATTRIBUTES => $attributes, 106*531e725cSNickeau PluginUtility::CONTEXT => $context, 107*531e725cSNickeau PluginUtility::POSITION => $pos 108*531e725cSNickeau ); 109*531e725cSNickeau 110*531e725cSNickeau 111*531e725cSNickeau } 112*531e725cSNickeau return array(); 113*531e725cSNickeau 114*531e725cSNickeau } 115*531e725cSNickeau 116*531e725cSNickeau /** 117*531e725cSNickeau * Render the output 118*531e725cSNickeau * @param string $format 119*531e725cSNickeau * @param Doku_Renderer $renderer 120*531e725cSNickeau * @param array $data - what the function handle() return'ed 121*531e725cSNickeau * @return boolean - rendered correctly? (however, returned value is not used at the moment) 122*531e725cSNickeau * @see DokuWiki_Syntax_Plugin::render() 123*531e725cSNickeau * 124*531e725cSNickeau * 125*531e725cSNickeau */ 126*531e725cSNickeau function render($format, Doku_Renderer $renderer, $data) 127*531e725cSNickeau { 128*531e725cSNickeau 129*531e725cSNickeau /** 130*531e725cSNickeau * 131*531e725cSNickeau * The atx special call is transformed by the {@link action_plugin_combo_headingpostprocess} 132*531e725cSNickeau * into enter and exit call 133*531e725cSNickeau */ 134*531e725cSNickeau if ($format == 'xhtml') { 135*531e725cSNickeau 136*531e725cSNickeau /** @var Doku_Renderer_xhtml $renderer */ 137*531e725cSNickeau $state = $data[PluginUtility::STATE]; 138*531e725cSNickeau switch ($state) { 139*531e725cSNickeau 140*531e725cSNickeau case DOKU_LEXER_ENTER: 141*531e725cSNickeau 142*531e725cSNickeau $attributes = $data[PluginUtility::ATTRIBUTES]; 143*531e725cSNickeau $context = $data[PluginUtility::CONTEXT]; 144*531e725cSNickeau $tagAttributes = TagAttributes::createFromCallStackArray($attributes, syntax_plugin_combo_heading::TAG); 145*531e725cSNickeau $pos = $data[PluginUtility::POSITION]; 146*531e725cSNickeau syntax_plugin_combo_heading::renderOpeningTag($context, $tagAttributes, $renderer, $pos); 147*531e725cSNickeau return true; 148*531e725cSNickeau 149*531e725cSNickeau 150*531e725cSNickeau case DOKU_LEXER_EXIT: 151*531e725cSNickeau 152*531e725cSNickeau $attributes = $data[PluginUtility::ATTRIBUTES]; 153*531e725cSNickeau $tagAttributes = TagAttributes::createFromCallStackArray($attributes); 154*531e725cSNickeau $level = $tagAttributes->getValue(syntax_plugin_combo_heading::LEVEL); 155*531e725cSNickeau $renderer->doc .= "</h$level>" . DOKU_LF; 156*531e725cSNickeau return true; 157*531e725cSNickeau 158*531e725cSNickeau } 159*531e725cSNickeau } else if ($format == renderer_plugin_combo_analytics::RENDERER_FORMAT) { 160*531e725cSNickeau 161*531e725cSNickeau /** 162*531e725cSNickeau * @var renderer_plugin_combo_analytics $renderer 163*531e725cSNickeau */ 164*531e725cSNickeau syntax_plugin_combo_heading::processMetadataAnalytics($data, $renderer); 165*531e725cSNickeau 166*531e725cSNickeau } else if ($format == "metadata") { 167*531e725cSNickeau 168*531e725cSNickeau /** 169*531e725cSNickeau * @var Doku_Renderer_metadata $renderer 170*531e725cSNickeau */ 171*531e725cSNickeau syntax_plugin_combo_heading::processHeadingMetadata($data, $renderer); 172*531e725cSNickeau 173*531e725cSNickeau } 174*531e725cSNickeau 175*531e725cSNickeau return false; 176*531e725cSNickeau } 177*531e725cSNickeau 178*531e725cSNickeau 179*531e725cSNickeau} 180*531e725cSNickeau 181