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