Bartosz Dziewoński has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/249452

Change subject: Implement <button> tag in wikitext for OOjs UI clickable buttons
......................................................................

Implement <button> tag in wikitext for OOjs UI clickable buttons

Bug: T101666
Change-Id: I91467297de4b7c532448a4c20b9a0dc8216c7200
---
M includes/parser/CoreTagHooks.php
M includes/parser/Parser.php
2 files changed, 140 insertions(+), 19 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/52/249452/1

diff --git a/includes/parser/CoreTagHooks.php b/includes/parser/CoreTagHooks.php
index 9755ea9..59b4391 100644
--- a/includes/parser/CoreTagHooks.php
+++ b/includes/parser/CoreTagHooks.php
@@ -36,6 +36,7 @@
                $parser->setHook( 'nowiki', array( __CLASS__, 'nowiki' ) );
                $parser->setHook( 'gallery', array( __CLASS__, 'gallery' ) );
                $parser->setHook( 'indicator', array( __CLASS__, 'indicator' ) 
);
+               $parser->setHook( 'button', array( __CLASS__, 'button' ) );
                if ( $wgRawHtml ) {
                        $parser->setHook( 'html', array( __CLASS__, 'html' ) );
                }
@@ -146,4 +147,96 @@
 
                return '';
        }
+
+       /**
+        * XML-style tag for OOjs UI clickable button links.
+        *
+        * A button must have a valid `link` attribute, and content or valid 
`icon` (or both).
+        * All other attributes are optional.
+        *
+        * @param string $content Button label
+        * @param array $attributes
+        *   - `link`: any internal or external link target, treated like the 
'link' parameter in image syntax
+        *   - `title`: link tooltip, default is generated from `link`
+        *   - `icon`: name of the icon to display next to button label
+        *   - `flags`: space-separated list of flags to apply, 
progressive/constructive/destructive/primary
+        *   - `frameless`: whether to show a covert button that pretends not 
to be one (boolean)
+        * @param Parser $parser
+        * @param PPFrame $frame
+        * @return string
+        * @since 1.27
+        */
+       public static function button( $content, array $attributes, Parser 
$parser, PPFrame $frame ) {
+               $parser->enableOOUI();
+
+               $config = array();
+
+               if ( $content ) {
+                       $parsed = $parser->recursiveTagParseFully( $content, 
$frame );
+                       $stripped = Parser::stripOuterParagraph( $parsed );
+                       if ( $parsed === $stripped ) {
+                               return '<span class="error">' .
+                                       wfMessage( 
'tag-button-must-be-single-line' )->inContentLanguage()->parse() .
+                                       '</span>';
+                       }
+                       if ( strpos( $stripped, '<a ') !== false ) {
+                               return '<span class="error">' .
+                                       wfMessage( 
'tag-button-must-not-nest-links' )->inContentLanguage()->parse() .
+                                       '</span>';
+                       }
+                       $config['label'] = new OOUI\HtmlSnippet( $stripped );
+               }
+               if ( isset( $attributes['icon'] ) ) {
+                       // TODO Validate and load required additional modules
+                       $config['icon'] = $attributes['icon'];
+               }
+               if ( !isset( $config['label'] ) && !isset( $config['icon'] ) ) {
+                       return '<span class="error">' .
+                               wfMessage( 'tag-button-must-have-content' 
)->inContentLanguage()->parse() .
+                               '</span>';
+               }
+
+               if ( isset( $attributes['link'] ) ) {
+                       list( $type, $target ) = $parser->parseLinkParameter( 
$attributes['link'] );
+                       // We intentionally do not add any classes like 'new' 
or 'redirect' to button links
+                       if ( $type === 'link-url' ) {
+                               $config['href'] = $target;
+                               if ( $parser->mOptions->getExternalLinkTarget() 
) {
+                                       $config['target'] = 
$parser->mOptions->getExternalLinkTarget();
+                               }
+                               $config['noFollow'] = 
Parser::getExternalLinkRel( $target ) === 'nofollow';
+                       } elseif ( $type === 'link-title' ) {
+                               $config['href'] = $target->getLinkURL();
+                               $config['title'] = $target->getPrefixedText();
+                               $config['noFollow'] = false;
+                       }
+               }
+               if ( !isset( $config['href'] ) ) {
+                       return '<span class="error">' .
+                               wfMessage( 'tag-button-must-have-link' 
)->inContentLanguage()->parse() .
+                               '</span>';
+               }
+               if ( isset( $attributes['title'] ) ) {
+                       // Overwrites the default from 'link', if any
+                       $config['title'] = $attributes['title'];
+               }
+
+               if ( isset( $attributes['frameless'] ) ) {
+                       $config['framed'] = false;
+               }
+               if ( isset( $attributes['flags'] ) ) {
+                       $config['flags'] = array_filter( array_map( 'trim', 
explode( ' ', $attributes['flags'] ) ) );
+               }
+
+               $button = new OOUI\ButtonWidget( $config );
+               // Prevent paragraphs breaking on the <div> tag
+               $prop = new ReflectionProperty( 'OOUI\\ButtonWidget', 'tag' );
+               $prop->setAccessible( true );
+               $prop->setValue( $button, 'span' );
+               $button = $button->toString();
+               // Prevent Tidy from removing empty <span> tags (used to 
display the icon)
+               $button = str_replace( '></span>', '><!-- --></span>', $button 
);
+               // Prevent further parsing
+               return array( $button, 'markerType' => 'nowiki' );
+       }
 }
diff --git a/includes/parser/Parser.php b/includes/parser/Parser.php
index 9060756..fd02128 100644
--- a/includes/parser/Parser.php
+++ b/includes/parser/Parser.php
@@ -5610,29 +5610,16 @@
                                                        $value = 
$this->stripAltText( $value, $holders );
                                                        break;
                                                case 'link':
-                                                       $chars = 
self::EXT_LINK_URL_CLASS;
-                                                       $addr = 
self::EXT_LINK_ADDR;
-                                                       $prots = 
$this->mUrlProtocols;
-                                                       if ( $value === '' ) {
-                                                               $paramName = 
'no-link';
-                                                               $value = true;
+                                                       list( $paramName, 
$value ) = $this->parseLinkParameter( $value );
+                                                       if ( $paramName ) {
                                                                $validated = 
true;
-                                                       } elseif ( preg_match( 
"/^((?i)$prots)/", $value ) ) {
-                                                               if ( 
preg_match( "/^((?i)$prots)$addr$chars*$/u", $value, $m ) ) {
-                                                                       
$paramName = 'link-url';
-                                                                       
$this->mOutput->addExternalLink( $value );
+                                                               if ( $paramName 
=== 'no-link' ) {
+                                                                       $value 
= true;
+                                                               }
+                                                               if ( $paramName 
=== 'link-url' ) {
                                                                        if ( 
$this->mOptions->getExternalLinkTarget() ) {
                                                                                
$params[$type]['link-target'] = $this->mOptions->getExternalLinkTarget();
                                                                        }
-                                                                       
$validated = true;
-                                                               }
-                                                       } else {
-                                                               $linkTitle = 
Title::newFromText( $value );
-                                                               if ( $linkTitle 
) {
-                                                                       
$paramName = 'link-title';
-                                                                       $value 
= $linkTitle;
-                                                                       
$this->mOutput->addLink( $linkTitle );
-                                                                       
$validated = true;
                                                                }
                                                        }
                                                        break;
@@ -5730,6 +5717,47 @@
        }
 
        /**
+        * Parse the value of 'link' parameter in image syntax 
(`[[File:Foo.jpg|link=<val>]]`).
+        *
+        * Adds an entry to appropriate link tables.
+        *
+        * @return array `array( type, target )`, where:
+        *   - `type` is one of:
+        *     - `null`: Given value is not a valid link target, use default
+        *     - `'no-link'`: Given value is empty, do not generate a link
+        *     - `'link-url'`: Given value is a valid external link
+        *     - `'link-title'`: Given value is a valid internal link
+        *   - `target` is:
+        *     - When `type` is `null` or `'no-link'`: `false`
+        *     - When `type` is `'link-url'`: URL string corresponding to given 
value
+        *     - When `type` is `'link-title'`: Title object corresponding to 
given value
+        */
+       public function parseLinkParameter( $value ) {
+               $chars = self::EXT_LINK_URL_CLASS;
+               $addr = self::EXT_LINK_ADDR;
+               $prots = $this->mUrlProtocols;
+               $type = null;
+               $target = false;
+               if ( $value === '' ) {
+                       $type = 'no-link';
+               } elseif ( preg_match( "/^((?i)$prots)/", $value ) ) {
+                       if ( preg_match( "/^((?i)$prots)$addr$chars*$/u", 
$value, $m ) ) {
+                               $this->mOutput->addExternalLink( $value );
+                               $type = 'link-url';
+                               $target = $value;
+                       }
+               } else {
+                       $linkTitle = Title::newFromText( $value );
+                       if ( $linkTitle ) {
+                               $this->mOutput->addLink( $linkTitle );
+                               $type = 'link-title';
+                               $target = $linkTitle;
+                       }
+               }
+               return array( $type, $target );
+       }
+
+       /**
         * @param string $caption
         * @param LinkHolderArray|bool $holders
         * @return mixed|string

-- 
To view, visit https://gerrit.wikimedia.org/r/249452
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I91467297de4b7c532448a4c20b9a0dc8216c7200
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Bartosz Dziewoński <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to