1<?php 2 3namespace ComboStrap; 4 5 6use Doku_Handler; 7use Doku_Renderer; 8 9 10/** 11 * 12 * TODO: when level 3 of grid 13 * https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Masonry_Layout 14 * 15 */ 16class MasonryTag 17{ 18 public const TEASER_COLUMNS_TAG = 'teaser-columns'; 19 /** 20 * The Tag constant should be the exact same last name of the class 21 * This is how we recognize a tag in the {@link \ComboStrap\CallStack} 22 */ 23 public const MASONRY_TAG = "masonry"; 24 public const LOGICAL_TAG = "masonry"; 25 /** 26 * The syntax tags 27 */ 28 public const CARD_COLUMNS_TAG = "card-columns"; 29 /** 30 * Same as commercial 31 * https://isotope.metafizzy.co/ 32 * 33 */ 34 public const MASONRY_SCRIPT_ID = "masonry"; 35 36 37 /** 38 * In Bootstrap5, to support card-columns, we need masonry javascript and 39 * a column 40 * We close it as seen here: 41 * https://getbootstrap.com/docs/5.0/examples/masonry/ 42 * 43 * The column is open with the function {@link MasonryTag::addColIfBootstrap5AndCardColumns()} 44 * @param Doku_Renderer $renderer 45 * @param $context 46 */ 47 public static function endColIfBootstrap5AnCardColumns(Doku_Renderer $renderer, $context) 48 { 49 50 /** 51 * Bootstrap five does not include masonry 52 * directly, we need to add a column 53 * and we close it here 54 */ 55 $bootstrapVersion = Bootstrap::getBootStrapMajorVersion(); 56 if ($bootstrapVersion == Bootstrap::BootStrapFiveMajorVersion) { 57 $renderer->doc .= '</div>'; 58 } 59 60 } 61 62 public static function getSyntaxTags(): array 63 { 64 return array(self::MASONRY_TAG, self::CARD_COLUMNS_TAG, self::TEASER_COLUMNS_TAG); 65 } 66 67 /** 68 * @param $renderer 69 * @param $context Doku_Renderer 70 * 71 * Bootstrap five does not include masonry 72 * directly, we need to add a column around the children {@link syntax_plugin_combo_card} and 73 * {@link BlockquoteTag} 74 * https://getbootstrap.com/docs/5.0/examples/masonry/ 75 * 76 * The column is open with the function {@link syntax_plugin_combo_masonry::endColIfBootstrap5AndCardColumns()} 77 * 78 * TODO: do it programmatically by adding call with {@link \ComboStrap\CallStack} 79 */ 80 public static function addColIfBootstrap5AndCardColumns(&$renderer, $context) 81 { 82 $bootstrapVersion = Bootstrap::getBootStrapMajorVersion(); 83 if ($bootstrapVersion == Bootstrap::BootStrapFiveMajorVersion && $context == MasonryTag::MASONRY_TAG) { 84 $renderer->doc .= '<div class="col-sm-6 col-lg-4 mb-4">'; 85 } 86 } 87 88 public static function handleExit(Doku_Handler $handler) 89 { 90 /** 91 * When the masonry is used in an iterator, the direct 92 * context is lost 93 */ 94 $callStack = CallStack::createFromHandler($handler); 95 $callStack->moveToPreviousCorrespondingOpeningCall(); 96 while ($actualCall = $callStack->next()) { 97 if ( 98 in_array($actualCall->getTagName(), [CardTag::CARD_TAG, BlockquoteTag::TAG]) 99 && in_array($actualCall->getState(), [DOKU_LEXER_ENTER, DOKU_LEXER_EXIT]) 100 ) { 101 $actualCall->setContext(MasonryTag::MASONRY_TAG); 102 } 103 } 104 105 } 106 107 public static function renderEnterTag(): string 108 { 109 $bootstrapVersion = Bootstrap::getBootStrapMajorVersion(); 110 switch ($bootstrapVersion) { 111 case 5: 112 // No support for 5, we use Bs with their example 113 // https://getbootstrap.com/docs/5.0/examples/masonry/ 114 // https://masonry.desandro.com/layout.html#responsive-layouts 115 // https://masonry.desandro.com/extras.html#bootstrap 116 // https://masonry.desandro.com/#initialize-with-vanilla-javascript 117 PluginUtility::getSnippetManager()->attachRemoteJavascriptLibrary( 118 MasonryTag::MASONRY_SCRIPT_ID, 119 "https://cdn.jsdelivr.net/npm/masonry-layout@4.2.2/dist/masonry.pkgd.min.js", 120 "sha384-GNFwBvfVxBkLMJpYMOABq3c+d3KnQxudP/mGPkzpZSTYykLBNsZEnG2D9G/X/+7D" 121 ); 122 PluginUtility::getSnippetManager()->attachJavascriptFromComponentId(MasonryTag::MASONRY_SCRIPT_ID); 123 $masonryClass = MasonryTag::MASONRY_SCRIPT_ID; 124 return "<div class=\"row $masonryClass\">"; 125 default: 126 return '<div class="card-columns">' ; 127 } 128 } 129 130 public static function renderExitHtml(): string 131 { 132 return '</div>'; 133 } 134} 135 136