104fd306cSNickeau<?php 204fd306cSNickeau 304fd306cSNickeau 404fd306cSNickeaunamespace ComboStrap\Tag; 504fd306cSNickeau 604fd306cSNickeau 704fd306cSNickeauuse ComboStrap\CallStack; 804fd306cSNickeauuse ComboStrap\ExceptionBadArgument; 904fd306cSNickeauuse ComboStrap\ExceptionBadSyntax; 1004fd306cSNickeauuse ComboStrap\LogUtility; 1104fd306cSNickeauuse ComboStrap\PluginUtility; 1204fd306cSNickeauuse ComboStrap\Web\Sanitizer; 1304fd306cSNickeauuse ComboStrap\TagAttributes; 1404fd306cSNickeau 1504fd306cSNickeauclass MermaidTag 1604fd306cSNickeau{ 1704fd306cSNickeau 1804fd306cSNickeau 1904fd306cSNickeau const CANONICAL = "mermaid"; 2004fd306cSNickeau public const CLASS_NAME = "mermaid"; 2104fd306cSNickeau const LOGICAL_TAG = "mermaid"; 2204fd306cSNickeau public const MARKUP_MERMAID = 'mermaid'; 2304fd306cSNickeau public const MARKUP_SEQUENCE_DIAGRAM = 'sequence-diagram'; 2404fd306cSNickeau const MARKUP_CONTENT_ATTRIBUTE = "mermaid-markup"; 2504fd306cSNickeau const MERMAID_CODE = "mermaid"; 2604fd306cSNickeau public const MARKUP_CLASS_DIAGRAM = 'class-diagram'; 2704fd306cSNickeau public const MARKUP_FLOWCHART = 'flowchart'; 2804fd306cSNickeau public const MARKUP_GANTT = 'gantt'; 2904fd306cSNickeau public const MARKUP_ERD = 'erd'; 3004fd306cSNickeau public const MARKUP_JOURNEY = 'journey'; 3104fd306cSNickeau public const MARKUP_PIECHART = 'piechart'; 3204fd306cSNickeau public const MARKUP_STATE_DIAGRAM = 'state-diagram'; 3304fd306cSNickeau 3404fd306cSNickeau public static function addSnippet() 3504fd306cSNickeau { 3604fd306cSNickeau $snippetManager = PluginUtility::getSnippetManager(); 3704fd306cSNickeau $snippetId = self::CANONICAL; 3804fd306cSNickeau $snippetManager->attachJavascriptFromComponentId($snippetId); 3904fd306cSNickeau try { 4004fd306cSNickeau $snippetManager->attachRemoteJavascriptLibrary( 4104fd306cSNickeau $snippetId, 42*711d6bd2SNicolas GERARD "https://cdn.jsdelivr.net/npm/mermaid@11.6.0/dist/mermaid.min.js", 43*711d6bd2SNicolas GERARD "sha256-OpMBanPcgrqJDZGfm7sXbz2p2YNBZQwLUX8llcxo/vg=" 4404fd306cSNickeau ); 4504fd306cSNickeau } catch (ExceptionBadArgument|ExceptionBadSyntax $e) { 4604fd306cSNickeau LogUtility::internalError("The url should be good", self::CANONICAL,$e); 4704fd306cSNickeau } 4804fd306cSNickeau } 4904fd306cSNickeau 5004fd306cSNickeau /** 5104fd306cSNickeau * The enter tag 5204fd306cSNickeau * @param TagAttributes $tagAttributes 5304fd306cSNickeau * @return string 5404fd306cSNickeau */ 5504fd306cSNickeau public static function renderEnter(TagAttributes $tagAttributes): string 5604fd306cSNickeau { 5704fd306cSNickeau 5804fd306cSNickeau $content = $tagAttributes->getValueAndRemoveIfPresent(self::MARKUP_CONTENT_ATTRIBUTE); 5904fd306cSNickeau 6004fd306cSNickeau $tagAttributes->addClassName(MermaidTag::CLASS_NAME); 6104fd306cSNickeau $html = $tagAttributes->toHtmlEnterTag("div"); 6204fd306cSNickeau /** 6304fd306cSNickeau * The mermaid markup code is replaced at runtime by the diagram 6404fd306cSNickeau */ 6504fd306cSNickeau MermaidTag::addSnippet(); 6604fd306cSNickeau 6704fd306cSNickeau $html .= MermaidTag::sanitize($content); 6804fd306cSNickeau $html .= '</div>'; 6904fd306cSNickeau return $html; 7004fd306cSNickeau 7104fd306cSNickeau } 7204fd306cSNickeau 7304fd306cSNickeau /** 7404fd306cSNickeau * The closing tag 7504fd306cSNickeau * 7604fd306cSNickeau * @return string 7704fd306cSNickeau * @deprecated 7804fd306cSNickeau */ 7904fd306cSNickeau public static function close(): string 8004fd306cSNickeau { 8104fd306cSNickeau return "</div>"; 8204fd306cSNickeau } 8304fd306cSNickeau 8404fd306cSNickeau /** 8504fd306cSNickeau * The content cannot be HTML escaped 8604fd306cSNickeau * 8704fd306cSNickeau * because 8804fd306cSNickeau * `->>` would become `→>` 8904fd306cSNickeau * or <br/> would not work 9004fd306cSNickeau * 9104fd306cSNickeau * There is a parameter 9204fd306cSNickeau * @param $content 9304fd306cSNickeau * @return mixed 9404fd306cSNickeau */ 9504fd306cSNickeau public static function sanitize($content) 9604fd306cSNickeau { 9704fd306cSNickeau 9804fd306cSNickeau return Sanitizer::sanitize($content, " in a mermaid language", self::CANONICAL); 9904fd306cSNickeau 10004fd306cSNickeau } 10104fd306cSNickeau 10204fd306cSNickeau 10304fd306cSNickeau /** 10404fd306cSNickeau * @param $data 10504fd306cSNickeau * @param $renderer 10604fd306cSNickeau * @return void 10704fd306cSNickeau * @deprecated 10804fd306cSNickeau */ 10904fd306cSNickeau public static function render($data, &$renderer) 11004fd306cSNickeau { 11104fd306cSNickeau $state = $data [PluginUtility::STATE]; 11204fd306cSNickeau switch ($state) { 11304fd306cSNickeau case DOKU_LEXER_ENTER : 11404fd306cSNickeau $tagAttributes = TagAttributes::createFromCallStackArray($data[PluginUtility::ATTRIBUTES]); 11504fd306cSNickeau $renderer->doc .= MermaidTag::renderEnter($tagAttributes); 11604fd306cSNickeau break; 11704fd306cSNickeau case DOKU_LEXER_UNMATCHED : 11804fd306cSNickeau case DOKU_LEXER_EXIT : 11904fd306cSNickeau break; 12004fd306cSNickeau 12104fd306cSNickeau } 12204fd306cSNickeau } 12304fd306cSNickeau 12404fd306cSNickeau public static function handleExit($handler){ 12504fd306cSNickeau 12604fd306cSNickeau $callStack = CallStack::createFromHandler($handler); 12704fd306cSNickeau $openingCall = $callStack->moveToPreviousCorrespondingOpeningCall(); 12804fd306cSNickeau $contentCall = $callStack->next(); 12904fd306cSNickeau $content = $contentCall->getCapturedContent(); 13004fd306cSNickeau $openingCall->setAttribute(self::MARKUP_CONTENT_ATTRIBUTE, $content); 13104fd306cSNickeau $callStack->deleteAllCallsAfter($openingCall); 13204fd306cSNickeau 13304fd306cSNickeau } 13404fd306cSNickeau 13504fd306cSNickeau /** 13604fd306cSNickeau * @param $state 13704fd306cSNickeau * @param $match 13804fd306cSNickeau * @param $handler 13904fd306cSNickeau * @return array 14004fd306cSNickeau */ 14104fd306cSNickeau public static function handle($state, $match, &$handler): array 14204fd306cSNickeau { 14304fd306cSNickeau switch ($state) { 14404fd306cSNickeau 14504fd306cSNickeau case DOKU_LEXER_ENTER : 14604fd306cSNickeau $tagAttributes = TagAttributes::createFromTagMatch($match); 14704fd306cSNickeau return array( 14804fd306cSNickeau PluginUtility::STATE => $state, 14904fd306cSNickeau PluginUtility::ATTRIBUTES => $tagAttributes->toCallStackArray() 15004fd306cSNickeau ); 15104fd306cSNickeau 15204fd306cSNickeau case DOKU_LEXER_UNMATCHED : 15304fd306cSNickeau 15404fd306cSNickeau return PluginUtility::handleAndReturnUnmatchedData("", $match, $handler); 15504fd306cSNickeau 15604fd306cSNickeau 15704fd306cSNickeau case DOKU_LEXER_EXIT : 15804fd306cSNickeau self::handleExit($handler); 15904fd306cSNickeau return array( 16004fd306cSNickeau PluginUtility::STATE => $state 16104fd306cSNickeau ); 16204fd306cSNickeau 16304fd306cSNickeau 16404fd306cSNickeau } 16504fd306cSNickeau return array(); 16604fd306cSNickeau } 16704fd306cSNickeau 16804fd306cSNickeau 16904fd306cSNickeau} 170