From 11eb2ac3289ffb276c23dc8d8c80d08c57ce758e Mon Sep 17 00:00:00 2001 From: alistair3149 Date: Tue, 19 Nov 2024 16:01:11 -0500 Subject: [PATCH] refactor: use Mustache to generate HTML --- includes/Tabber.php | 69 ++++++---------------- includes/TabberTransclude.php | 49 +++++++-------- includes/templates/Tabber.mustache | 24 ++++---- includes/templates/TabberTab.mustache | 1 + includes/templates/TabberTabpanel.mustache | 4 ++ 5 files changed, 56 insertions(+), 91 deletions(-) create mode 100644 includes/templates/TabberTab.mustache create mode 100644 includes/templates/TabberTabpanel.mustache diff --git a/includes/Tabber.php b/includes/Tabber.php index 7969eaa..7605122 100644 --- a/includes/Tabber.php +++ b/includes/Tabber.php @@ -88,7 +88,13 @@ class Tabber { */ public static function render( string $input, int $count, Parser $parser, PPFrame $frame ): string { $arr = explode( '|-|', $input ); - $tabs = ''; + $data = [ + 'count' => $count, + 'array-tabs' => [] + ]; + + // For Codex use only + // TODO: Maybe we should redo the whole Codex implementation $tabpanels = ''; foreach ( $arr as $tab ) { @@ -97,13 +103,17 @@ class Tabber { continue; } + $data['array-tabs'][] = [ + 'content' => $tabData['content'], + 'label' => $tabData['label'], + 'tabId' => "tabber-tab-{$tabData['id']}", + 'tabpanelId' => self::$useLegacyId ? $tabData['id'] : "tabber-tabpanel-{$tabData['id']}" + ]; + if ( self::$useCodex && self::$isNested ) { $tabpanels .= self::getCodexNestedTabJSON( $tabData ); continue; } - - $tabs .= self::getTabHTML( $tabData ); - $tabpanels .= self::getTabpanelHTML( $tabData ); } if ( self::$useCodex && self::$isNested ) { @@ -115,11 +125,6 @@ class Tabber { } $templateParser = new TemplateParser( __DIR__ . '/templates' ); - $data = [ - 'count' => $count, - 'html-tabs' => $tabs, - 'html-tabpanels' => $tabpanels - ]; return $templateParser->processTemplate( 'Tabber', $data ); } @@ -212,6 +217,11 @@ class Tabber { } $data['content'] = self::getTabContent( $content, $parser, $frame ); + $isContentHTML = strpos( $content, '<' ) === 0; + if ( $data['content'] && !$isContentHTML ) { + // If $content does not have any HTML element (i.e. just a text node), wrap it in

+ $data['content'] = Html::rawElement( 'p', [], $data['content'] ); + } $id = Sanitizer::escapeIdForAttribute( htmlspecialchars( $data['label'] ) ); if ( self::$useLegacyId === true ) { @@ -231,47 +241,6 @@ class Tabber { 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'] ); - } - - /** - * Get the HTML for a tabpanel. - * - * @param array $tabData Tab data - * - * @return string HTML - */ - private static function getTabpanelHTML( array $tabData ): string { - $content = $tabData['content']; - $isContentHTML = strpos( $content, '<' ) === 0; - if ( $content && !$isContentHTML ) { - // If $content does not have any HTML element (i.e. just a text node), wrap it in

- $content = Html::rawElement( 'p', [], $content ); - } - return Html::rawElement( 'article', [ - 'class' => 'tabber__panel', - 'id' => "tabber-tabpanel-{$tabData['id']}", - 'role' => 'tabpanel', - 'tabindex' => 0, - 'aria-labelledby' => "tabber-tab-{$tabData['id']}" - ], $content ); - } - /** * Get JSON representation of a nested tab for Codex * diff --git a/includes/TabberTransclude.php b/includes/TabberTransclude.php index 22c60a7..19585fe 100644 --- a/includes/TabberTransclude.php +++ b/includes/TabberTransclude.php @@ -15,7 +15,6 @@ declare( strict_types=1 ); namespace MediaWiki\Extension\TabberNeue; use Exception; -use Html; use MediaWiki\MediaWikiServices; use Parser; use PPFrame; @@ -24,6 +23,10 @@ use TemplateParser; use Title; class TabberTransclude { + + /** @var bool */ + private static $useLegacyId = false; + /** * Parser callback for tag * @@ -39,8 +42,11 @@ class TabberTransclude { return ''; } + $config = MediaWikiServices::getInstance()->getMainConfig(); $parserOutput = $parser->getOutput(); + self::$useLegacyId = $config->get( 'TabberNeueUseLegacyTabIds' ); + $count = count( $parserOutput->getExtensionData( 'tabber-count' ) ?? [] ); $html = self::render( $input, $count, $parser, $frame ); @@ -65,29 +71,34 @@ class TabberTransclude { public static function render( string $input, int $count, Parser $parser, PPFrame $frame ): string { $selected = true; $arr = explode( "\n", $input ); - $tabs = ''; - $tabpanels = ''; + $data = [ + 'count' => $count, + 'array-tabs' => [] + ]; foreach ( $arr as $tab ) { $tabData = self::getTabData( $tab ); if ( $tabData === [] ) { continue; } - $tabs .= self::getTabHTML( $tabData ); + + $tabpanelHtml = ''; try { - $tabpanels .= self::buildTabTransclude( $tabData, $parser, $frame, $selected ); + $tabpanelHtml = self::buildTabTransclude( $tabData, $parser, $frame, $selected ); } catch ( Exception $e ) { // This can happen if a $currentTitle is null continue; } + + $data['array-tabs'][] = [ + 'html-tabpanel' => $tabpanelHtml, + 'label' => $tabData['label'], + 'tabId' => "tabber-tab-{$tabData['id']}", + 'tabpanelId' => self::$useLegacyId ? $tabData['id'] : "tabber-tabpanel-{$tabData['id']}" + ]; } $templateParser = new TemplateParser( __DIR__ . '/templates' ); - $data = [ - 'count' => $count, - 'html-tabs' => $tabs, - 'html-tabpanels' => $tabpanels - ]; return $templateParser->processTemplate( 'Tabber', $data ); } @@ -117,24 +128,6 @@ class TabberTransclude { 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::element( 'a', [ - 'class' => 'tabber__tab', - 'id' => "tabber-tab-{$tabData['id']}", - 'href' => "#$tabpanelId", - 'role' => 'tab', - 'aria-controls' => $tabpanelId - ], $tabData['label'] ); - } - /** * Build individual tab. * diff --git a/includes/templates/Tabber.mustache b/includes/templates/Tabber.mustache index c5726d7..1c8899f 100644 --- a/includes/templates/Tabber.mustache +++ b/includes/templates/Tabber.mustache @@ -1,13 +1,11 @@ -{{! - int count Current Tabber count - string html-tabs - string html-tabpanels -}} -

-
- - - -
-
{{{html-tabpanels}}}
-
\ No newline at end of file +
{{! + }}
{{! + }}{{! + }}{{! + }}{{! + }}
{{! + }}
{{>TabberTabpanel}}
{{! +}}
\ No newline at end of file diff --git a/includes/templates/TabberTab.mustache b/includes/templates/TabberTab.mustache new file mode 100644 index 0000000..9e6d803 --- /dev/null +++ b/includes/templates/TabberTab.mustache @@ -0,0 +1 @@ +{{{label}}} \ No newline at end of file diff --git a/includes/templates/TabberTabpanel.mustache b/includes/templates/TabberTabpanel.mustache new file mode 100644 index 0000000..e094f95 --- /dev/null +++ b/includes/templates/TabberTabpanel.mustache @@ -0,0 +1,4 @@ +{{#array-tabs}} +{{^html-tabpanel}}
{{{content}}}
{{/html-tabpanel}} +{{#html-tabpanel}}{{{.}}}{{/html-tabpanel}} +{{/array-tabs}} \ No newline at end of file