1<?php 2 3namespace ComboStrap; 4 5 6use ComboStrap\Tag\AdTag; 7use ComboStrap\Tag\BackgroundTag; 8use ComboStrap\Tag\BarTag; 9use ComboStrap\Tag\BoxTag; 10use ComboStrap\Tag\FollowTag; 11use ComboStrap\Tag\MermaidTag; 12use ComboStrap\Tag\RelatedTag; 13use ComboStrap\Tag\ShareTag; 14use ComboStrap\Tag\SubscribeTag; 15use ComboStrap\Tag\TableTag; 16use ComboStrap\Tag\WebCodeTag; 17use ComboStrap\TagAttribute\Hero; 18use Doku_Handler; 19use Doku_Renderer; 20use Doku_Renderer_metadata; 21use Doku_Renderer_xhtml; 22use DokuWiki_Syntax_Plugin; 23use Mpdf\Tag\Sub; 24use renderer_plugin_combo_analytics; 25use renderer_plugin_combo_xml; 26use syntax_plugin_combo_code; 27 28 29class XmlTagProcessing 30{ 31 32 33 /** 34 * The start tag pattern does not allow > or / 35 * in the data to not compete with the empty tag pattern (ie <empty/> 36 * 37 * No numbers to not have a greater than `<1200` as tag 38 */ 39 public const START_TAG_PATTERN = '<[A-Za-z-]+[^/><]*>'; 40 41 42 public static function renderStaticExitXhtml(TagAttributes $tagAttributes, Doku_Renderer_xhtml $renderer, array $data, DokuWiki_Syntax_Plugin $plugin): bool 43 { 44 $logicalTag = $tagAttributes->getLogicalTag(); 45 switch ($logicalTag) { 46 case BlockquoteTag::TAG: 47 BlockquoteTag::renderExitXhtml($tagAttributes, $renderer, $data); 48 return true; 49 case BoxTag::TAG: 50 $renderer->doc .= BoxTag::renderExitXhtml($tagAttributes); 51 return true; 52 case ButtonTag::LOGICAL_TAG: 53 $renderer->doc .= ButtonTag::renderExitXhtml($data); 54 return true; 55 case CardTag::LOGICAL_TAG: 56 CardTag::handleExitXhtml($data, $renderer); 57 return true; 58 case BarTag::LOGICAL_TAG: 59 $renderer->doc .= BarTag::renderExitXhtml($data); 60 return true; 61 case CarrouselTag::TAG: 62 $renderer->doc .= CarrouselTag::renderExitXhtml(); 63 return true; 64 case PrismTags::CONSOLE_TAG: 65 case PrismTags::FILE_TAG: 66 PrismTags::processExitXhtml($tagAttributes, $renderer); 67 return true; 68 case ContainerTag::TAG: 69 $renderer->doc .= ContainerTag::renderExitXhtml(); 70 return true; 71 case GridTag::LOGICAL_TAG: 72 $renderer->doc .= GridTag::renderExitXhtml($tagAttributes); 73 return true; 74 case PipelineTag::TAG: 75 case DateTag::TAG: 76 case PageExplorerTag::LOGICAL_TAG: 77 case PermalinkTag::TAG: 78 case IconTag::TAG: 79 case MermaidTag::LOGICAL_TAG: 80 return true; 81 case DropDownTag::TAG: 82 $renderer->doc .= DropDownTag::renderExitXhtml(); 83 return true; 84 case HeadingTag::LOGICAL_TAG: 85 $context = $data[PluginUtility::CONTEXT]; 86 $renderer->doc .= HeadingTag::renderClosingTag($tagAttributes, $context); 87 return true; 88 case NoteTag::TAG_INOTE: 89 $renderer->doc .= NoteTag::renderClosingInlineNote(); 90 return true; 91 case JumbotronTag::TAG: 92 $renderer->doc .= JumbotronTag::renderExitHtml(); 93 return true; 94 case MasonryTag::LOGICAL_TAG: 95 $renderer->doc .= MasonryTag::renderExitHtml(); 96 return true; 97 case SectionTag::TAG: 98 $renderer->doc .= SectionTag::renderExitXhtml(); 99 return true; 100 case TabsTag::TAG: 101 $renderer->doc .= TabsTag::renderExitXhtml($tagAttributes, $data); 102 return true; 103 case PanelTag::PANEL_LOGICAL_MARKUP: 104 $renderer->doc .= PanelTag::renderExitXhtml($data); 105 return true; 106 case BackgroundTag::LOGICAL_TAG: 107 $renderer->doc .= BackgroundTag::renderExitSpecialHtml($data); 108 return true; 109 case WebCodeTag::TAG: 110 $renderer->doc .= WebCodeTag::renderExit($tagAttributes, $data); 111 return true; 112 case ShareTag::MARKUP: 113 $renderer->doc .= ShareTag::renderExit($tagAttributes); 114 return true; 115 case FollowTag::MARKUP: 116 $renderer->doc .= FollowTag::renderExit(); 117 return true; 118 default: 119 LogUtility::warning("The exit tag (" . $logicalTag . ") was not processed."); 120 return false; 121 } 122 123 } 124 125 /** 126 * Static because it handle inline and block tag 127 * @param string $match 128 * @param int $state 129 * @param int $pos 130 * @param Doku_Handler $handler 131 * @param DokuWiki_Syntax_Plugin $plugin 132 * @return array 133 */ 134 public static function handleStatic(string $match, int $state, int $pos, Doku_Handler $handler, DokuWiki_Syntax_Plugin $plugin): array 135 { 136 /** 137 * Logical Tag Building 138 */ 139 switch ($state) { 140 141 case DOKU_LEXER_ENTER: 142 143 return self::handleStaticEnter($match, $pos, $handler, $plugin); 144 145 case DOKU_LEXER_UNMATCHED : 146 147 $data = PluginUtility::handleAndReturnUnmatchedData(null, $match, $handler); 148 /** 149 * Attribute of parent are send for context 150 * (example `display = none`) 151 */ 152 $callStack = CallStack::createFromHandler($handler); 153 $parentTag = $callStack->moveToParent(); 154 if ($parentTag !== false) { 155 $tagAttributes = $parentTag->getAttributes(); 156 $data[PluginUtility::ATTRIBUTES] = $tagAttributes; 157 } 158 return $data; 159 160 case DOKU_LEXER_EXIT : 161 162 return self::handleStaticExit($match, $pos, $handler, $plugin); 163 164 165 default: 166 throw new ExceptionRuntimeInternal("Should not happen"); 167 } 168 } 169 170 public static function renderStaticEnterXhtml(TagAttributes $tagAttributes, Doku_Renderer_xhtml $renderer, array $data, DokuWiki_Syntax_Plugin $plugin): bool 171 { 172 173 $context = $data[PluginUtility::CONTEXT] ?? null; 174 $pos = $data[PluginUtility::POSITION] ?? null; 175 $logicalTag = $tagAttributes->getLogicalTag(); 176 switch ($logicalTag) { 177 case BlockquoteTag::TAG: 178 $renderer->doc .= BlockquoteTag::renderEnterXhtml($tagAttributes, $data, $renderer); 179 return true; 180 case BoxTag::TAG: 181 $renderer->doc .= BoxTag::renderEnterXhtml($tagAttributes); 182 return true; 183 case ButtonTag::LOGICAL_TAG: 184 $renderer->doc .= ButtonTag::renderEnterXhtml($tagAttributes, $plugin, $data); 185 return true; 186 case CardTag::LOGICAL_TAG: 187 $renderer->doc .= CardTag::renderEnterXhtml($tagAttributes, $renderer, $data); 188 return true; 189 case BarTag::LOGICAL_TAG: 190 $renderer->doc .= BarTag::renderEnterXhtml($tagAttributes, $data); 191 return true; 192 case CarrouselTag::TAG: 193 $renderer->doc .= CarrouselTag::renderEnterXhtml($tagAttributes, $data); 194 return true; 195 case PrismTags::CONSOLE_TAG: 196 case PrismTags::FILE_TAG: 197 PrismTags::processEnterXhtml($tagAttributes, $plugin, $renderer); 198 return true; 199 case ContainerTag::TAG: 200 $renderer->doc .= ContainerTag::renderEnterXhtml($tagAttributes); 201 return true; 202 case GridTag::LOGICAL_TAG: 203 $renderer->doc .= GridTag::renderEnterXhtml($tagAttributes); 204 return true; 205 case PipelineTag::TAG: 206 $renderer->doc .= PipelineTag::renderEnterXhtml($tagAttributes); 207 return true; 208 case DateTag::TAG: 209 $renderer->doc .= DateTag::renderHtml($tagAttributes); 210 return true; 211 case DropDownTag::TAG: 212 $renderer->doc .= DropDownTag::renderEnterXhtml($tagAttributes); 213 return true; 214 case HeadingTag::LOGICAL_TAG: 215 HeadingTag::processRenderEnterXhtml($context, $tagAttributes, $renderer, $pos); 216 return true; 217 case NoteTag::TAG_INOTE: 218 $renderer->doc .= NoteTag::renderEnterInlineNote($tagAttributes); 219 return true; 220 case JumbotronTag::TAG: 221 $renderer->doc .= JumbotronTag::renderEnterXhtml($tagAttributes); 222 return true; 223 case MasonryTag::LOGICAL_TAG: 224 $renderer->doc .= MasonryTag::renderEnterTag(); 225 return true; 226 case PageExplorerTag::LOGICAL_TAG: 227 $renderer->doc .= PageExplorerTag::renderEnterTag($tagAttributes, $data); 228 return true; 229 case SectionTag::TAG: 230 $renderer->doc .= SectionTag::renderEnterXhtml($tagAttributes); 231 return true; 232 case TabsTag::TAG: 233 $renderer->doc .= TabsTag::renderEnterXhtml($tagAttributes, $data); 234 return true; 235 case PanelTag::PANEL_LOGICAL_MARKUP: 236 $renderer->doc .= PanelTag::renderEnterXhtml($tagAttributes, $data); 237 return true; 238 case PermalinkTag::TAG: 239 $renderer->doc .= PermalinkTag::renderEnterSpecialXhtml($data); 240 return true; 241 case HrTag::TAG: 242 $renderer->doc .= HrTag::render($tagAttributes); 243 return true; 244 case IconTag::TAG: 245 $renderer->doc .= IconTag::renderEnterTag($tagAttributes); 246 return true; 247 case BackgroundTag::LOGICAL_TAG: 248 $renderer->doc .= BackgroundTag::renderEnterTag(); 249 return true; 250 case MermaidTag::LOGICAL_TAG: 251 $renderer->doc .= MermaidTag::renderEnter($tagAttributes); 252 return true; 253 case WebCodeTag::TAG: 254 return true; 255 case ShareTag::MARKUP: 256 $renderer->doc .= ShareTag::renderSpecialEnter($tagAttributes, DOKU_LEXER_ENTER); 257 return true; 258 case FollowTag::MARKUP: 259 $renderer->doc .= FollowTag::renderSpecialEnterNode($tagAttributes, DOKU_LEXER_ENTER); 260 return true; 261 case TableTag::TAG: 262 TableTag::renderEnterXhtml($tagAttributes, $renderer); 263 return true; 264 case RelatedTag::TAG: 265 LogUtility::warning("The related tag should be closed. You should write <related/> and not <related>."); 266 $renderer->doc .= RelatedTag::render($tagAttributes); 267 return true; 268 default: 269 LogUtility::warning("The enter tag (" . $logicalTag . ") was not processed."); 270 return false; 271 } 272 } 273 274 public static function handleStaticEnter(string $match, int $pos, Doku_Handler $handler, DokuWiki_Syntax_Plugin $plugin): array 275 { 276 // context data 277 $executionContext = ExecutionContext::getActualOrCreateFromEnv(); 278 279 // Normalize Trim and delete eol to start clean 280 $match = trim($match); 281 $match = str_replace("\n", " ", $match); 282 283 // Markup 284 $markupTag = PluginUtility::getMarkupTag($match); 285 $logicalTag = $markupTag; 286 $defaultAttributes = []; 287 $knownTypes = []; 288 $allowAnyFirstBooleanAttributesAsType = false; 289 290 // code block allow a second attribute value as file name 291 $hasTwoBooleanAttribute = false; 292 $secondBooleanAttribute = null; 293 294 switch ($markupTag) { 295 case BlockquoteTag::TAG: 296 // Suppress the component name 297 $defaultAttributes = array("type" => BlockquoteTag::CARD_TYPE); 298 $knownTypes = [BlockquoteTag::TYPO_TYPE, BlockquoteTag::CARD_TYPE];; 299 break; 300 case BoxTag::TAG: 301 $defaultAttributes[BoxTag::HTML_TAG_ATTRIBUTE] = BoxTag::DEFAULT_HTML_TAG; 302 $defaultAttributes[BoxTag::LOGICAL_TAG_ATTRIBUTE] = BoxTag::LOGICAL_TAG_DEFAUT; 303 break; 304 case ButtonTag::MARKUP_SHORT: 305 case ButtonTag::MARKUP_LONG: 306 $logicalTag = ButtonTag::LOGICAL_TAG; 307 $knownTypes = ButtonTag::TYPES; 308 $defaultAttributes = array( 309 Skin::SKIN_ATTRIBUTE => Skin::FILLED_VALUE, 310 TagAttributes::TYPE_KEY => ColorRgb::PRIMARY_VALUE 311 ); 312 break; 313 case CardTag::CARD_TAG: 314 case CardTag::TEASER_TAG: 315 $logicalTag = CardTag::LOGICAL_TAG; 316 break; 317 case BarTag::BAR_TAG: 318 case BarTag::SLIDE_TAG: 319 $logicalTag = BarTag::LOGICAL_TAG; 320 $defaultAttributes[Hero::ATTRIBUTE] = "sm"; 321 break; 322 case PrismTags::CONSOLE_TAG: 323 case PrismTags::FILE_TAG: 324 $hasTwoBooleanAttribute = true; 325 $secondBooleanAttribute = syntax_plugin_combo_code::FILE_PATH_KEY; 326 $allowAnyFirstBooleanAttributesAsType = true; 327 break; 328 case ContainerTag::TAG: 329 $knownTypes = ContainerTag::CONTAINER_VALUES; 330 $defaultAttributes[TagAttributes::TYPE_KEY] = $executionContext->getConfig()->getValue(ContainerTag::DEFAULT_LAYOUT_CONTAINER_CONF, ContainerTag::DEFAULT_LAYOUT_CONTAINER_DEFAULT_VALUE); 331 break; 332 case GridTag::ROW_TAG: 333 case GridTag::GRID_TAG: 334 $logicalTag = GridTag::LOGICAL_TAG; 335 $knownTypes = GridTag::KNOWN_TYPES; 336 break; 337 case HeadingTag::HEADING_TAG: 338 case HeadingTag::TITLE_TAG: 339 $logicalTag = HeadingTag::LOGICAL_TAG; 340 $knownTypes = HeadingTag::getAllTypes(); 341 break; 342 case NoteTag::TAG_INOTE: 343 $defaultConfValue = $plugin->getConf(NoteTag::INOTE_CONF_DEFAULT_ATTRIBUTES_KEY); 344 $defaultAttributes = PluginUtility::parseAttributes($defaultConfValue); 345 if (!isset($defaultAttributes[TagAttributes::TYPE_KEY])) { 346 $defaultAttributes[TagAttributes::TYPE_KEY] = "info"; 347 } 348 $knownTypes = NoteTag::KNOWN_TYPES; 349 break; 350 case JumbotronTag::TAG: 351 $defaultAttributes = JumbotronTag::getDefault(); 352 break; 353 case MasonryTag::CARD_COLUMNS_TAG: 354 case MasonryTag::TEASER_COLUMNS_TAG: 355 case MasonryTag::MASONRY_TAG: 356 $logicalTag = MasonryTag::LOGICAL_TAG; 357 break; 358 case PageExplorerTag::NTOC_MARKUP: 359 case PageExplorerTag::PAGE_EXPLORER_MARKUP: 360 $logicalTag = PageExplorerTag::LOGICAL_TAG; 361 $defaultAttributes = [TagAttributes::TYPE_KEY => PageExplorerTag::LIST_TYPE]; 362 $knownTypes = [PageExplorerTag::TYPE_TREE, PageExplorerTag::LIST_TYPE]; 363 break; 364 case PageExplorerTag::INDEX_HOME_TAG: 365 case PageExplorerTag::INDEX_TAG: 366 $logicalTag = PageExplorerTag::LOGICAL_INDEX_TAG; 367 break; 368 case PageExplorerTag::NAMESPACE_ITEM_TAG: 369 case PageExplorerTag::NAMESPACE_LONG_TAG: 370 case PageExplorerTag::NAMESPACE_SHORT_TAG: 371 $logicalTag = PageExplorerTag::NAMESPACE_LOGICAL_TAG; 372 break; 373 case PageExplorerTag::PAGE_ITEM_TAG: 374 case PageExplorerTag::PAGE_TAG: 375 $logicalTag = PageExplorerTag::PAGE_LOGICAL_TAG; 376 break; 377 case TabsTag::TAG: 378 $knownTypes = [TabsTag::ENCLOSED_PILLS_TYPE, TabsTag::ENCLOSED_TABS_TYPE, TabsTag::PILLS_TYPE, TabsTag::TABS_TYPE]; 379 break; 380 case PanelTag::PANEL_MARKUP: 381 case PanelTag::TAB_PANEL_MARKUP: 382 $logicalTag = PanelTag::PANEL_LOGICAL_MARKUP; 383 break; 384 case PermalinkTag::TAG: 385 $knownTypes = PermalinkTag::getKnownTypes(); 386 $defaultAttributes = [TagAttributes::TYPE_KEY => PermalinkTag::GENERATED_TYPE]; 387 break; 388 case BackgroundTag::MARKUP_LONG: 389 case BackgroundTag::MARKUP_SHORT: 390 $logicalTag = BackgroundTag::LOGICAL_TAG; 391 break; 392 case MermaidTag::MARKUP_MERMAID: 393 case WebCodeTag::TAG: 394 $logicalTag = Tag\WebCodeTag::TAG; 395 $defaultAttributes = WebCodeTag::getDefaultAttributes(); 396 break; 397 case MermaidTag::MARKUP_SEQUENCE_DIAGRAM: 398 case MermaidTag::MARKUP_CLASS_DIAGRAM: 399 case MermaidTag::MARKUP_FLOWCHART: 400 case MermaidTag::MARKUP_GANTT: 401 case MermaidTag::MARKUP_ERD: 402 case MermaidTag::MARKUP_JOURNEY: 403 case MermaidTag::MARKUP_PIECHART: 404 case MermaidTag::MARKUP_STATE_DIAGRAM: 405 $logicalTag = MermaidTag::LOGICAL_TAG; 406 break; 407 case ShareTag::MARKUP: 408 $knownTypes = ShareTag::getKnownTypes(); 409 break; 410 case FollowTag::MARKUP: 411 $knownTypes = FollowTag::getKnownTypes(); 412 break; 413 } 414 415 /** 416 * Build tag Attributes 417 */ 418 if (!$hasTwoBooleanAttribute) { 419 $tagAttributes = TagAttributes::createFromTagMatch($match, $defaultAttributes, $knownTypes, $allowAnyFirstBooleanAttributesAsType); 420 } else { 421 $tagAttributes = TagAttributes::createEmpty(); 422 $attributesArray = PluginUtility::getQualifiedTagAttributes($match, true, $secondBooleanAttribute, $knownTypes, $allowAnyFirstBooleanAttributesAsType); 423 foreach ($attributesArray as $key => $value) { 424 $tagAttributes->addComponentAttributeValue($key, $value); 425 } 426 } 427 $tagAttributes->setLogicalTag($logicalTag); 428 429 /** 430 * Calculate extra returned key in the table 431 */ 432 $returnedArray = []; 433 switch ($logicalTag) { 434 case BlockquoteTag::TAG: 435 $returnedArray = BlockquoteTag::handleEnter($handler); 436 break; 437 case BoxTag::TAG: 438 BoxTag::handleEnter($tagAttributes); 439 break; 440 case ButtonTag::LOGICAL_TAG: 441 $returnedArray = ButtonTag::handleEnter($tagAttributes, $handler); 442 break; 443 case CardTag::CARD_TAG: 444 $returnedArray = CardTag::handleEnter($tagAttributes, $handler); 445 break; 446 case BarTag::LOGICAL_TAG: 447 $returnedArray = BarTag::handleEnter($tagAttributes); 448 break; 449 case CarrouselTag::TAG: 450 $returnedArray = CarrouselTag::handleEnter($handler); 451 break; 452 case GridTag::LOGICAL_TAG: 453 GridTag::processEnter($tagAttributes, $handler, $match); 454 break; 455 case DateTag::TAG: 456 DateTag::handleEnterAndSpecial(); 457 break; 458 case HeadingTag::LOGICAL_TAG: 459 $returnedArray = HeadingTag::handleEnter($handler, $tagAttributes, $markupTag); 460 break; 461 case PanelTag::PANEL_LOGICAL_MARKUP: 462 $returnedArray = PanelTag::handleEnter($tagAttributes, $handler, $markupTag); 463 break; 464 case PermalinkTag::TAG: 465 $returnedArray = PermalinkTag::handleEnterSpecial($tagAttributes, DOKU_LEXER_ENTER, $handler); 466 break; 467 case IconTag::TAG: 468 $returnedArray = IconTag::handleEnter($tagAttributes, $handler); 469 break; 470 case BackgroundTag::LOGICAL_TAG: 471 BackgroundTag::handleEnterAndSpecial($tagAttributes); 472 break; 473 } 474 475 /** 476 * Common default 477 */ 478 $defaultReturnedArray[PluginUtility::STATE] = DOKU_LEXER_ENTER; 479 $defaultReturnedArray[PluginUtility::TAG] = $logicalTag; 480 $defaultReturnedArray[PluginUtility::MARKUP_TAG] = $markupTag; 481 $defaultReturnedArray[PluginUtility::POSITION] = $pos; 482 $defaultReturnedArray[PluginUtility::ATTRIBUTES] = $tagAttributes->toCallStackArray(); 483 484 return array_merge($defaultReturnedArray, $returnedArray); 485 486 } 487 488 public static function renderStatic(string $format, Doku_Renderer $renderer, array $data, DokuWiki_Syntax_Plugin $plugin): bool 489 { 490 $logicalTag = $data[PluginUtility::TAG] ?? null; 491 $attributes = $data[PluginUtility::ATTRIBUTES] ?? null; 492 $context = $data[PluginUtility::CONTEXT] ?? null; 493 $state = $data[PluginUtility::STATE] ?? null; 494 $pos = $data[PluginUtility::POSITION] ?? null; 495 $tagAttributes = TagAttributes::createFromCallStackArray($attributes)->setLogicalTag($logicalTag); 496 switch ($format) { 497 case "xhtml": 498 /** @var Doku_Renderer_xhtml $renderer */ 499 switch ($state) { 500 case DOKU_LEXER_ENTER: 501 return self::renderStaticEnterXhtml($tagAttributes, $renderer, $data, $plugin); 502 case DOKU_LEXER_UNMATCHED: 503 504 $renderer->doc .= PluginUtility::renderUnmatched($data); 505 return true; 506 507 case DOKU_LEXER_EXIT: 508 509 return XmlTagProcessing::renderStaticExitXhtml($tagAttributes, $renderer, $data, $plugin); 510 } 511 break; 512 case 'metadata': 513 /** @var Doku_Renderer_metadata $renderer */ 514 if (!in_array($state, [DOKU_LEXER_ENTER, DOKU_LEXER_SPECIAL])) { 515 return true; 516 } 517 return XmlTagProcessing::renderStaticEnterSpecialMetadata($tagAttributes, $renderer, $data, $plugin); 518 case 'xml': 519 /** @var renderer_plugin_combo_xml $renderer */ 520 switch ($state) { 521 case DOKU_LEXER_ENTER: 522 switch ($logicalTag) { 523 default: 524 case BarTag::LOGICAL_TAG: 525 $renderer->doc .= "<$logicalTag>"; 526 return true; 527 } 528 case DOKU_LEXER_UNMATCHED : 529 $renderer->doc .= PluginUtility::renderUnmatched($data); 530 break; 531 case DOKU_LEXER_EXIT : 532 switch ($logicalTag) { 533 default: 534 case BarTag::LOGICAL_TAG: 535 $renderer->doc .= "</$logicalTag>"; 536 return true; 537 } 538 } 539 return false; 540 case renderer_plugin_combo_analytics::RENDERER_FORMAT: 541 /** 542 * @var renderer_plugin_combo_analytics $renderer 543 */ 544 switch ($logicalTag) { 545 default: 546 case HeadingTag::LOGICAL_TAG: 547 HeadingTag::processMetadataAnalytics($data, $renderer); 548 return true; 549 } 550 551 } 552 553 // unsupported $mode 554 return false; 555 } 556 557 public static function handleStaticExit(string $match, int $pos, Doku_Handler $handler, DokuWiki_Syntax_Plugin $plugin): array 558 { 559 $markupTag = PluginUtility::getMarkupTag($match); 560 $logicalTag = $markupTag; 561 $returnedArray = []; 562 switch ($markupTag) { 563 case BlockquoteTag::TAG: 564 $returnedArray = BlockquoteTag::handleExit($handler); 565 break; 566 case BoxTag::TAG: 567 $returnedArray = BoxTag::handleExit($handler); 568 break; 569 case ButtonTag::MARKUP_SHORT: 570 case ButtonTag::MARKUP_LONG: 571 $logicalTag = ButtonTag::LOGICAL_TAG; 572 $returnedArray = ButtonTag::handleExit($handler); 573 break; 574 case CardTag::CARD_TAG: 575 case CardTag::TEASER_TAG: 576 $logicalTag = CardTag::LOGICAL_TAG; 577 $returnedArray = CardTag::handleExit($handler, $pos, $match); 578 break; 579 case BarTag::BAR_TAG: 580 case BarTag::SLIDE_TAG: 581 $logicalTag = BarTag::LOGICAL_TAG; 582 $returnedArray = BarTag::handleExit($handler, $pos, $match); 583 break; 584 case CarrouselTag::TAG: 585 $returnedArray = CarrouselTag::handleExit($handler); 586 break; 587 case PrismTags::CONSOLE_TAG: 588 case PrismTags::FILE_TAG: 589 $returnedArray = PrismTags::handleExit($handler); 590 break; 591 case PipelineTag::TAG: 592 PipelineTag::processExit($handler); 593 break; 594 case GridTag::GRID_TAG: 595 case GridTag::ROW_TAG: 596 $logicalTag = GridTag::LOGICAL_TAG; 597 $returnedArray = GridTag::handleExit($handler); 598 break; 599 case DateTag::TAG: 600 DateTag::handleExit($handler); 601 break; 602 case HeadingTag::TITLE_TAG: 603 case HeadingTag::HEADING_TAG: 604 $logicalTag = HeadingTag::LOGICAL_TAG; 605 $returnedArray = HeadingTag::handleExit($handler); 606 break; 607 case MasonryTag::CARD_COLUMNS_TAG: 608 case MasonryTag::TEASER_COLUMNS_TAG: 609 case MasonryTag::MASONRY_TAG: 610 $logicalTag = MasonryTag::LOGICAL_TAG; 611 MasonryTag::handleExit($handler); 612 break; 613 case PageExplorerTag::NTOC_MARKUP: 614 case PageExplorerTag::PAGE_EXPLORER_MARKUP: 615 $logicalTag = PageExplorerTag::LOGICAL_TAG; 616 PageExplorerTag::handleExit($handler); 617 break; 618 case PageExplorerTag::INDEX_HOME_TAG: 619 case PageExplorerTag::INDEX_TAG: 620 $logicalTag = PageExplorerTag::LOGICAL_INDEX_TAG; 621 break; 622 case PageExplorerTag::NAMESPACE_ITEM_TAG: 623 case PageExplorerTag::NAMESPACE_LONG_TAG: 624 case PageExplorerTag::NAMESPACE_SHORT_TAG: 625 $logicalTag = PageExplorerTag::NAMESPACE_LOGICAL_TAG; 626 break; 627 case PageExplorerTag::PAGE_ITEM_TAG: 628 case PageExplorerTag::PAGE_TAG: 629 $logicalTag = PageExplorerTag::PAGE_LOGICAL_TAG; 630 break; 631 case PageExplorerTag::PARENT_TAG: 632 // nothing as the content is captured and deleted by page-explorer 633 break; 634 case TabsTag::TAG: 635 $returnedArray = TabsTag::handleExit($handler); 636 break; 637 case PanelTag::PANEL_MARKUP: 638 case PanelTag::TAB_PANEL_MARKUP: 639 $logicalTag = PanelTag::PANEL_LOGICAL_MARKUP; 640 $returnedArray = PanelTag::handleExit($handler, $pos, $markupTag, $match); 641 break; 642 case PermalinkTag::TAG: 643 PermalinkTag::handeExit($handler); 644 break; 645 case IconTag::TAG: 646 $returnedArray = IconTag::handleExit($handler); 647 break; 648 case BackgroundTag::MARKUP_SHORT: 649 case BackgroundTag::MARKUP_LONG: 650 $logicalTag = BackgroundTag::LOGICAL_TAG; 651 $returnedArray = BackgroundTag::handleExit($handler); 652 break; 653 case MermaidTag::MARKUP_SEQUENCE_DIAGRAM: 654 case MermaidTag::MARKUP_CLASS_DIAGRAM: 655 case MermaidTag::MARKUP_FLOWCHART: 656 case MermaidTag::MARKUP_GANTT: 657 case MermaidTag::MARKUP_ERD: 658 case MermaidTag::MARKUP_JOURNEY: 659 case MermaidTag::MARKUP_PIECHART: 660 case MermaidTag::MARKUP_STATE_DIAGRAM: 661 $logicalTag = MermaidTag::LOGICAL_TAG; 662 MermaidTag::handleExit($handler); 663 break; 664 case MermaidTag::MARKUP_MERMAID: // bug 665 case WebCodeTag::TAG: 666 $logicalTag = WebCodeTag::TAG; 667 $returnedArray = WebCodeTag::handleExit($handler); 668 break; 669 case ShareTag::MARKUP: 670 $returnedArray = ShareTag::handleExit($handler); 671 672 break; 673 674 } 675 /** 676 * Common exit attributes 677 */ 678 $defaultReturnedArray[PluginUtility::STATE] = DOKU_LEXER_EXIT; 679 $defaultReturnedArray[PluginUtility::TAG] = $logicalTag; 680 $defaultReturnedArray[PluginUtility::MARKUP_TAG] = $markupTag; 681 return array_merge($defaultReturnedArray, $returnedArray); 682 } 683 684 /** 685 * @param $tag 686 * @return string 687 * 688 * Create a lookahead pattern for a container tag used to enter in a mode 689 */ 690 public static function getContainerTagPattern($tag): string 691 { 692 // this pattern ensure that the tag 693 // `accordion` will not intercept also the tag `accordionitem` 694 // where: 695 // ?: means non capturing group (to not capture the last >) 696 // (\s.*?): is a capturing group that starts with a space 697 $pattern = "(?:\s.*?>|>)"; 698 return '<' . $tag . $pattern . '(?=.*?<\/' . $tag . '>)'; 699 } 700 701 public static function handleStaticEmptyTag(string $match, int $state, int $pos, Doku_Handler $handler, DokuWiki_Syntax_Plugin $plugin): array 702 { 703 /** 704 * Logical Tag Building 705 */ 706 $logicalTag = PluginUtility::getMarkupTag($match); 707 $defaultAttributes = []; 708 $knownTypes = []; 709 $allowAnyFirstBooleanAttributesAsType = false; 710 switch ($logicalTag) { 711 case SearchTag::TAG: 712 $defaultAttributes = array( 713 'ajax' => true, 714 'autocomplete' => false 715 ); 716 break; 717 case PageImageTag::MARKUP: 718 $knownTypes = PageImageTag::TYPES; 719 $defaultAttributes = PageImageTag::getDefaultAttributes(); 720 break; 721 case ShareTag::MARKUP: 722 $knownTypes = ShareTag::getKnownTypes(); 723 break; 724 case FollowTag::MARKUP: 725 $knownTypes = FollowTag::getKnownTypes(); 726 break; 727 case BrandListTag::MARKUP: 728 $knownTypes = BrandButton::TYPE_BUTTONS; 729 $defaultAttributes = [TagAttributes::TYPE_KEY => BrandButton::TYPE_BUTTON_BRAND]; 730 break; 731 case BrandTag::MARKUP: 732 $defaultAttributes = [TagAttributes::TYPE_KEY => Brand::CURRENT_BRAND]; 733 $allowAnyFirstBooleanAttributesAsType = true; 734 break; 735 case PermalinkTag::TAG: 736 $knownTypes = PermalinkTag::getKnownTypes(); 737 $defaultAttributes = [TagAttributes::TYPE_KEY => PermalinkTag::GENERATED_TYPE]; 738 break; 739 case BreadcrumbTag::MARKUP_BLOCK: 740 $logicalTag = BreadcrumbTag::LOGICAL_TAG; 741 $knownTypes = BreadcrumbTag::TYPES; 742 $defaultAttributes = BreadcrumbTag::getDefaultBlockAttributes(); 743 break; 744 } 745 $tagAttributes = TagAttributes::createFromTagMatch($match, $defaultAttributes, $knownTypes, $allowAnyFirstBooleanAttributesAsType) 746 ->setLogicalTag($logicalTag); 747 748 /** 749 * Calculate extra returned key in the table 750 */ 751 $returnedArray = []; 752 switch ($logicalTag) { 753 case IconTag::TAG: 754 $returnedArray = IconTag::handleSpecial($tagAttributes, $handler); 755 break; 756 case PageImageTag::MARKUP: 757 $returnedArray = PageImageTag::handle($tagAttributes, $handler); 758 break; 759 case BrandTag::MARKUP: 760 $returnedArray = BrandTag::handleSpecialEnter($tagAttributes, $handler); 761 break; 762 case CacheTag::MARKUP: 763 $returnedArray = CacheTag::handle($tagAttributes); 764 break; 765 case BackgroundTag::MARKUP_SHORT: 766 case BackgroundTag::MARKUP_LONG: 767 BackgroundTag::handleEnterAndSpecial($tagAttributes); 768 $callStack = CallStack::createFromHandler($handler); 769 $returnedArray = BackgroundTag::setAttributesToParentAndReturnData($callStack, $tagAttributes, $state); 770 break; 771 case DateTag::TAG: 772 DateTag::handleEnterAndSpecial(); 773 break; 774 case PermalinkTag::TAG: 775 $returnedArray = PermalinkTag::handleEnterSpecial($tagAttributes, $state, $handler); 776 break; 777 case BreadcrumbTag::MARKUP_BLOCK: 778 $returnedArray = BreadcrumbTag::handleEnter($tagAttributes); 779 break; 780 case HrTag::TAG: 781 /** 782 * Block tag 783 */ 784 $returnedArray = [PluginUtility::DISPLAY => HrTag::getDisplay()]; 785 break; 786 } 787 788 /** 789 * Common default 790 * {@link PluginUtility::DISPLAY} should be set on handle 791 */ 792 $defaultReturnedArray[PluginUtility::STATE] = $state; 793 $defaultReturnedArray[PluginUtility::TAG] = $logicalTag; 794 $defaultReturnedArray[PluginUtility::ATTRIBUTES] = $tagAttributes->toCallStackArray(); 795 796 return array_merge($defaultReturnedArray, $returnedArray); 797 } 798 799 public static function renderStaticEmptyTag(string $format, Doku_Renderer $renderer, array $data, DokuWiki_Syntax_Plugin $plugin): bool 800 { 801 802 $tag = $data[PluginUtility::TAG]; 803 $attributes = $data[PluginUtility::ATTRIBUTES]; 804 $state = DOKU_LEXER_SPECIAL; 805 $tagAttributes = TagAttributes::createFromCallStackArray($attributes)->setLogicalTag($tag); 806 switch ($format) { 807 case "xhtml": 808 /** @var Doku_Renderer_xhtml $renderer */ 809 switch ($tag) { 810 case HrTag::TAG: 811 $renderer->doc .= HrTag::render($tagAttributes); 812 break; 813 case SearchTag::TAG: 814 $renderer->doc .= SearchTag::render($tagAttributes); 815 break; 816 case IconTag::TAG: 817 $renderer->doc .= IconTag::renderEmptyTag($tagAttributes); 818 break; 819 case BreadcrumbTag::LOGICAL_TAG: 820 $renderer->doc .= BreadcrumbTag::render($tagAttributes); 821 break; 822 case PageImageTag::MARKUP: 823 $renderer->doc .= PageImageTag::render($tagAttributes, $data); 824 break; 825 case ShareTag::MARKUP: 826 $renderer->doc .= ShareTag::renderSpecialEnter($tagAttributes, $state); 827 break; 828 case BrandListTag::MARKUP: 829 $renderer->doc .= BrandListTag::render($tagAttributes); 830 break; 831 case BrandTag::MARKUP: 832 $renderer->doc .= BrandTag::render($tagAttributes, $state, $data); 833 break; 834 case CacheTag::MARKUP: 835 $renderer->doc .= CacheTag::renderXhtml($data); 836 break; 837 case BackgroundTag::MARKUP_LONG: 838 case BackgroundTag::MARKUP_SHORT: 839 $renderer->doc .= BackgroundTag::renderExitSpecialHtml($data); 840 break; 841 case DateTag::TAG: 842 $renderer->doc .= DateTag::renderHtml($tagAttributes); 843 return true; 844 case PermalinkTag::TAG: 845 $renderer->doc .= PermalinkTag::renderEnterSpecialXhtml($data); 846 return true; 847 case QualityTag::MARKUP_TAG: 848 $renderer->doc .= QualityTag::renderXhtml($tagAttributes); 849 return true; 850 case FollowTag::MARKUP: 851 $renderer->doc .= FollowTag::renderSpecialEnterNode($tagAttributes, DOKU_LEXER_SPECIAL); 852 return true; 853 case MediaMarkup::TAG: 854 $renderer->doc .= MediaMarkup::renderSpecial($data, $renderer); 855 return true; 856 case SubscribeTag::LOGICAL_TAG: 857 $renderer->doc .= SubscribeTag::renderEnterXhtml($tagAttributes); 858 return true; 859 case AdTag::MARKUP: 860 $renderer->doc .= AdTag::render($tagAttributes); 861 return true; 862 case RelatedTag::TAG: 863 $renderer->doc .= RelatedTag::render($tagAttributes); 864 return true; 865 default: 866 LogUtility::errorIfDevOrTest("The empty tag (" . $tag . ") was not processed."); 867 } 868 break; 869 case 'metadata': 870 /** @var Doku_Renderer_metadata $renderer */ 871 switch ($tag) { 872 case IconTag::TAG: 873 IconTag::metadata($renderer, $tagAttributes); 874 return true; 875 case CacheTag::MARKUP: 876 CacheTag::metadata($data); 877 return true; 878 case MediaMarkup::TAG: 879 MediaMarkup::metadata($data, $renderer); 880 return true; 881 } 882 break; 883 case renderer_plugin_combo_analytics::RENDERER_FORMAT: 884 885 } 886 // unsupported $mode 887 return false; 888 } 889 890 private static function renderStaticEnterSpecialMetadata(TagAttributes $tagAttributes, Doku_Renderer_metadata $renderer, array $data, DokuWiki_Syntax_Plugin $plugin): bool 891 { 892 $logicalTag = $tagAttributes->getLogicalTag(); 893 switch ($logicalTag) { 894 case HeadingTag::LOGICAL_TAG: 895 HeadingTag::processHeadingEnterMetadata($data, $renderer); 896 return true; 897 case IconTag::TAG: 898 IconTag::metadata($renderer, $tagAttributes); 899 return true; 900 case BackgroundTag::LOGICAL_TAG: 901 BackgroundTag::renderMeta($data, $renderer); 902 return true; 903 } 904 return false; 905 } 906} 907 908