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