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