diff --git a/includes/Tabber.php b/includes/Tabber.php index f4cf9af..3cf3ada 100644 --- a/includes/Tabber.php +++ b/includes/Tabber.php @@ -48,6 +48,10 @@ class Tabber { * @return string HTML */ public static function parserHook( ?string $input, array $args, Parser $parser, PPFrame $frame ) { + if ( $input === null ) { + return ''; + } + $config = MediaWikiServices::getInstance()->getMainConfig(); $parserOutput = $parser->getOutput(); @@ -57,11 +61,7 @@ class Tabber { $count = count( $parserOutput->getExtensionData( 'tabber-count' ) ?? [] ); - $html = self::render( $input ?? '', $count, $parser, $frame ); - - if ( $input === null ) { - return ''; - } + $html = self::render( $input, $count, $parser, $frame ); $parserOutput->appendExtensionData( 'tabber-count', $count++ ); diff --git a/includes/TabberTransclude.php b/includes/TabberTransclude.php index 5db22b7..4df855e 100644 --- a/includes/TabberTransclude.php +++ b/includes/TabberTransclude.php @@ -15,9 +15,12 @@ declare( strict_types=1 ); namespace MediaWiki\Extension\TabberNeue; use Exception; +use Html; use MediaWiki\MediaWikiServices; use Parser; use PPFrame; +use Sanitizer; +use TemplateParser; use Title; class TabberTransclude { @@ -32,14 +35,18 @@ class TabberTransclude { * @return string HTML */ public static function parserHook( ?string $input, array $args, Parser $parser, PPFrame $frame ) { - $html = self::render( $input, $parser, $frame ); - if ( $input === null ) { return ''; } + $parserOutput = $parser->getOutput(); + + $count = count( $parserOutput->getExtensionData( 'tabber-count' ) ?? [] ); + + $html = self::render( $input, $count, $parser, $frame ); + $parser->getOutput()->addModuleStyles( [ 'ext.tabberNeue.init.styles' ] ); - // $parser->getOutput()->addModules( [ 'ext.tabberNeue' ] ); + $parser->getOutput()->addModules( [ 'ext.tabberNeue' ] ); $parser->addTrackingCategory( 'tabberneue-tabbertransclude-category' ); return $html; @@ -49,31 +56,39 @@ class TabberTransclude { * Renders the necessary HTML for a tag. * * @param string $input The input URL between the beginning and ending tags. + * @param int $count Current Tabber count * @param Parser $parser Mediawiki Parser Object * @param PPFrame $frame Mediawiki PPFrame Object * * @return string HTML */ - public static function render( string $input, Parser $parser, PPFrame $frame ): string { + public static function render( string $input, int $count, Parser $parser, PPFrame $frame ): string { $selected = true; $arr = explode( "\n", $input ); - $htmlTabs = ''; + $tabs = ''; + $tabpanels = ''; + foreach ( $arr as $tab ) { $tabData = self::getTabData( $tab ); if ( $tabData === [] ) { continue; } + $tabs .= self::getTabHTML( $tabData ); try { - $htmlTabs .= self::buildTabTransclude( $tabData, $parser, $frame, $selected ); + $tabpanels .= self::buildTabTransclude( $tabData, $parser, $frame, $selected ); } catch ( Exception $e ) { // This can happen if a $currentTitle is null continue; } } - return '
' . - '
' . - '
' . $htmlTabs . '
'; + $templateParser = new TemplateParser( __DIR__ . '/templates' ); + $data = [ + 'count' => $count, + 'html-tabs' => $tabs, + 'html-tabpanels' => $tabpanels + ]; + return $templateParser->processTemplate( 'Tabber', $data ); } /** @@ -91,11 +106,35 @@ class TabberTransclude { // Transclude uses a different syntax: Page name|Tab label // Use array_pad to make sure at least 2 array values are always returned [ $content, $label ] = array_pad( explode( '|', $tab, 2 ), 2, '' ); + $data['label'] = trim( $label ); + // Label is empty, we cannot generate tabber + if ( $data['label'] === '' ) { + return $data; + } $data['content'] = trim( $content ); + $data['id'] = Sanitizer::escapeIdForAttribute( htmlspecialchars( $data['label'] ) ); return $data; } + /** + * Get the HTML for a tab. + * + * @param array $tabData Tab data + * + * @return string HTML + */ + private static function getTabHTML( array $tabData ): string { + $tabpanelId = "tabber-tabpanel-{$tabData['id']}"; + return Html::rawElement( 'a', [ + 'class' => 'tabber__tab', + 'id' => "tabber-tab-{$tabData['id']}", + 'href' => "#$tabpanelId", + 'role' => 'tab', + 'aria-controls' => $tabpanelId + ], $tabData['label'] ); + } + /** * Build individual tab. * @@ -166,7 +205,7 @@ class TabberTransclude { ); } - $tab = '