jenkins-bot has submitted this change and it was merged.

Change subject: Update the footer in beta
......................................................................


Update the footer in beta

Move mobile.toggle.images to skins.minerva.icons.images.variants
* This allows us to reuse the arrow icon for the last modified bar
* Ship clock and arrow variants
* Make mobile.toggle use this module

Structure footer differently in beta
* Render history-beta template partial instead of history
* Move last modifier bar into new page <footer>
** Desktop switcher is now in links
** Site title / image appears at top of footer
* Bump version number in minerva.mustache to signal partials have changed

* Add feature flag MinervaUseFooterV2
In preparation for pushing to stable
When true adds class feature-footer-v2 to body element
The old footer carries the id footer whereas the new footer
just uses a footer tag. This will help pushing it to stable
without hitting cache issues.

Bug: T141002
Depends-On: Iac11948f8f5fdaad45d51b905bb7494a84775710
Change-Id: I4b17119e1dd6e4866851c7791d9cedea88104335
---
M README.md
M extension.json
M includes/MobileFrontend.hooks.php
M includes/MobileFrontend.skin.hooks.php
M includes/skins/MinervaTemplate.php
M includes/skins/MinervaTemplateBeta.php
M includes/skins/SkinMinerva.php
M includes/skins/SkinMinervaBeta.php
M includes/skins/footer.mustache
A includes/skins/history-beta.mustache
M includes/skins/minerva.mustache
M minerva.less/minerva.variables.less
D resources/mobile.toggle.images/arrow.svg
M resources/skins.minerva.base.styles/footer.less
A resources/skins.minerva.footerV2.styles/common.less
A resources/skins.minerva.icons.images.variants/arrow.svg
A resources/skins.minerva.icons.images.variants/clock.svg
M resources/skins.minerva.scripts/init.js
18 files changed, 248 insertions(+), 45 deletions(-)

Approvals:
  Bmansurov: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/README.md b/README.md
index ed7a4c9..62ab591 100644
--- a/README.md
+++ b/README.md
@@ -266,6 +266,17 @@
 * Type: `Boolean`
 * Default: `true`
 
+#### $wgMinervaUseFooterV2
+
+A temporary configuration variable to control display of a new footer which 
impacts styling
+of the last modified bar and with a slight different arrangement of footer 
icons.
+
+The config variable currently controls whether the styles and template for new 
footer should be invoked.
+Enabling this in current state will break rendering of footer in stable.
+
+* Type: `Boolean`
+* Default: `false`
+
 #### $wgMFRemovableClasses
 
 Make the classes, tags and ids stripped from page content configurable. Each
diff --git a/extension.json b/extension.json
index f24273b..5911ea4 100644
--- a/extension.json
+++ b/extension.json
@@ -198,6 +198,26 @@
                                "language-switcher": 
"resources/skins.minerva.icons.images/languageSwitcher.svg"
                        }
                },
+               "skins.minerva.icons.images.variants": {
+                       "selectorWithoutVariant": ".mw-ui-icon-{name}:before",
+                       "selectorWithVariant": 
".mw-ui-icon-{name}-{variant}:before",
+                       "class": "ResourceLoaderImageModule",
+                       "prefix": "mw-ui",
+                       "variants": {
+                               "gray": {
+                                       "color": "#BBB",
+                                       "global": true
+                               },
+                               "invert": {
+                                       "color": "#FFF",
+                                       "global": true
+                               }
+                       },
+                       "images": {
+                               "clock": 
"resources/skins.minerva.icons.images.variants/clock.svg",
+                               "arrow": 
"resources/skins.minerva.icons.images.variants/arrow.svg"
+                       }
+               },
                "mobile.overlay.images": {
                        "selectorWithoutVariant": ".mw-ui-icon-{name}:before",
                        "selectorWithVariant": 
".mw-ui-icon-{name}-{variant}:before",
@@ -242,14 +262,6 @@
                                "citation": 
"resources/mobile.references.images/cite.svg"
                        }
                },
-               "mobile.toggle.images": {
-                       "class": "ResourceLoaderImageModule",
-                       "prefix": "mw-ui",
-                       "selector": ".mw-ui-icon-{name}:before",
-                       "images": {
-                               "arrow": 
"resources/mobile.toggle.images/arrow.svg"
-                       }
-               },
                "skins.minerva.icons.images.scripts": {
                        "class": "ResourceLoaderImageModule",
                        "prefix": "mw-ui",
@@ -271,6 +283,16 @@
                        "position": "top",
                        "styles": [
                                
"resources/skins.minerva.mainPage.beta.styles/common.less"
+                       ]
+               },
+               "skins.minerva.footerV2.styles": {
+                       "targets": [
+                               "mobile",
+                               "desktop"
+                       ],
+                       "position": "top",
+                       "styles": [
+                               
"resources/skins.minerva.footerV2.styles/common.less"
                        ]
                },
                "skins.minerva.mainPage.styles": {
@@ -1113,7 +1135,7 @@
                        ],
                        "dependencies": [
                                "mobile.settings",
-                               "mobile.toggle.images",
+                               "skins.minerva.icons.images.variants",
                                "mobile.startup"
                        ],
                        "styles": [
@@ -2048,6 +2070,7 @@
                "MFAllowNonJavaScriptEditing": false,
                "MinervaAlwaysShowLanguageButton": true,
                "MinervaBottomLanguageButton": true,
+               "MinervaUseFooterV2": false,
                "MinervaUsePageActionBarV2": false,
                "MFStripResponsiveImages": true,
                "MFResponsiveImageWhitelist": [
diff --git a/includes/MobileFrontend.hooks.php 
b/includes/MobileFrontend.hooks.php
index 6911e0e..477eb6a 100644
--- a/includes/MobileFrontend.hooks.php
+++ b/includes/MobileFrontend.hooks.php
@@ -1276,6 +1276,9 @@
                if ( $config->get( 'MinervaUsePageActionBarV2' ) || 
$context->isBetaGroupMember() ) {
                        $bodyAttributes['class'] .= ' 
feature-page-action-bar-v2';
                }
+               if ( $config->get( 'MinervaUseFooterV2' ) || 
$context->isBetaGroupMember() ) {
+                       $bodyAttributes['class'] .= ' feature-footer-v2';
+               }
        }
 
        /**
diff --git a/includes/MobileFrontend.skin.hooks.php 
b/includes/MobileFrontend.skin.hooks.php
index 374891a..134c84e 100644
--- a/includes/MobileFrontend.skin.hooks.php
+++ b/includes/MobileFrontend.skin.hooks.php
@@ -205,6 +205,8 @@
        protected static function mobileFooter( Skin $sk, QuickTemplate $tpl, 
MobileContext $ctx,
                Title $title, WebRequest $req
        ) {
+               $inBeta = $ctx->isBetaGroupMember();
+
                $url = $sk->getOutput()->getProperty( 'desktopUrl' );
                if ( $url ) {
                        $url = wfAppendQuery( $url, 
'mobileaction=toggle_view_desktop' );
@@ -213,18 +215,18 @@
                                $req->appendQueryValue( 'mobileaction', 
'toggle_view_desktop', true )
                        );
                }
-               $url = htmlspecialchars(
-                       $ctx->getDesktopUrl( wfExpandUrl( $url, PROTO_RELATIVE 
) )
-               );
+               $desktopUrl = $ctx->getDesktopUrl( wfExpandUrl( $url, 
PROTO_RELATIVE ) );
 
                $desktop = $ctx->msg( 'mobile-frontend-view-desktop' 
)->escaped();
                $mobile = $ctx->msg( 'mobile-frontend-view-mobile' )->escaped();
-
+               $desktopToggler = Html::element( 'a',
+                       [ 'id' => "mw-mf-display-toggle", "href" => $desktopUrl 
], $desktop );
                $sitename = self::getSitename( true );
+               $siteheading = Html::rawElement( 'h2', [], $sitename );
                $switcherHtml = <<<HTML
-<h2>{$sitename}</h2>
+{$siteheading}
 <ul>
-       <li>{$mobile}</li><li><a id="mw-mf-display-toggle" 
href="{$url}">{$desktop}</a></li>
+       <li>{$mobile}</li><li>{$desktopToggler}</li>
 </ul>
 HTML;
 
@@ -243,20 +245,32 @@
                Hooks::run( 'SkinMinervaOutputPageBeforeExec', [ &$sk, &$tpl ], 
'1.26' );
 
                $tpl->set( 'mobile-switcher', $switcherHtml );
+               $tpl->set( 'footer-site-heading-html', $sitename );
+               $tpl->set( 'desktop-toggle', $desktopToggler );
                $tpl->set( 'mobile-license', $licenseText );
                $tpl->set( 'privacy', $sk->footerLink( 
'mobile-frontend-privacy-link-text', 'privacypage' ) );
                $tpl->set( 'terms-use', self::getTermsLink( $sk ) );
 
-               $tpl->set( 'footerlinks', [
-                       'info' => [
-                               'mobile-switcher',
-                               'mobile-license',
-                       ],
-                       'places' => [
-                               'terms-use',
-                               'privacy',
-                       ],
-               ] );
+               $places = [
+                       'terms-use',
+                       'privacy',
+               ];
+
+               if ( $inBeta ) {
+                       $places[] = 'desktop-toggle';
+                       $footerlinks = [
+                               'places' => $places,
+                       ];
+               } else {
+                       $footerlinks = [
+                               'info' => [
+                                       'mobile-switcher',
+                                       'mobile-license',
+                               ],
+                               'places' => $places,
+                       ];
+               }
+               $tpl->set( 'footerlinks', $footerlinks );
                return $tpl;
        }
 
diff --git a/includes/skins/MinervaTemplate.php 
b/includes/skins/MinervaTemplate.php
index 366b6a0..0eb5507 100644
--- a/includes/skins/MinervaTemplate.php
+++ b/includes/skins/MinervaTemplate.php
@@ -91,6 +91,7 @@
                        ];
                }
                return [
+                       'v1' => !$this->getSkin()->isFooterV2(),
                        'lists' => $groups,
                ];
        }
@@ -146,6 +147,9 @@
                if ( isset( $data['historyLink'] ) && $action === 'view' ) {
                        $historyLink = $data['historyLink'];
                        $args = [
+                               'clockIconClass' => MobileUI::iconClass( 
'clock-gray', 'before' ),
+                               'arrowIconClass' => MobileUI::iconClass(
+                                       'arrow-gray', 'element', 
'mw-ui-icon-small indicator' ),
                                'isMainPage' => 
$this->getSkin()->getTitle()->isMainPage(),
                                'link' => $historyLink['href'],
                                'text' => $historyLink['text'],
@@ -154,7 +158,8 @@
                                'timestamp' => $historyLink['data-timestamp']
                        ];
                        $templateParser = new TemplateParser( __DIR__ );
-                       return $templateParser->processTemplate( 'history', 
$args );
+                       $templateName = $this->getSkin()->isFooterV2() ? 
'history-beta' : 'history';
+                       return $templateParser->processTemplate( $templateName, 
$args );
                } else {
                        return '';
                }
diff --git a/includes/skins/MinervaTemplateBeta.php 
b/includes/skins/MinervaTemplateBeta.php
index 9710a0e..b346416 100644
--- a/includes/skins/MinervaTemplateBeta.php
+++ b/includes/skins/MinervaTemplateBeta.php
@@ -19,6 +19,33 @@
        }
 
        /**
+        * Gets template data for rendering
+        *
+        * @inheritdoc
+        */
+       protected function getFooterTemplateData( $data ) {
+               $tmpData = parent::getFooterTemplateData( $data );
+               // This turns off the footer id and allows us to distinguish 
the old footer with the new design
+
+               $tmpData = array_merge( $tmpData, [
+                       'lastmodified' => $this->getHistoryLinkHtml( $data ),
+                       'headinghtml' => $data['footer-site-heading-html'],
+                       'licensehtml' => $data['mobile-license']
+               ] );
+               return $tmpData;
+       }
+
+       /**
+        * Removes the last modified bar from the post content area
+        * so that it can instead be placed in the footer
+        *
+        * @inheritdoc
+        */
+       protected function getPostContentHtml( $data ) {
+               return $this->getSecondaryActionsHtml();
+       }
+
+       /**
         * Get category button if categories are present
         * @return array A map of the button's friendly name, "categories" to 
its
         *   spec if the button can be displayed.
diff --git a/includes/skins/SkinMinerva.php b/includes/skins/SkinMinerva.php
index fb71872..453ce2c 100644
--- a/includes/skins/SkinMinerva.php
+++ b/includes/skins/SkinMinerva.php
@@ -45,6 +45,14 @@
        }
 
        /**
+        * Whether the new footer is to be used
+        * @return boolean
+        */
+       public function isFooterV2() {
+               return $this->getMFConfig()->get( 'MinervaUseFooterV2' );
+       }
+
+       /**
         * initialize various variables and generate the template
         * @return QuickTemplate
         */
diff --git a/includes/skins/SkinMinervaBeta.php 
b/includes/skins/SkinMinervaBeta.php
index d632fe1..ab4deae 100644
--- a/includes/skins/SkinMinervaBeta.php
+++ b/includes/skins/SkinMinervaBeta.php
@@ -18,6 +18,14 @@
        protected $shouldSecondaryActionsIncludeLanguageBtn = true;
 
        /**
+        * Whether the new footer is to be used
+        * @return boolean
+        */
+       public function isFooterV2() {
+               return true;
+       }
+
+       /**
         * The "switch-language" is always allowed in MFBeta.
         *
         * @inheritdoc
@@ -98,6 +106,10 @@
                        $styles[] = 'skins.minerva.mainPage.beta.styles';
                }
                $styles[] = 'skins.minerva.content.styles.beta';
+               $styles[] = 'skins.minerva.icons.images.variants';
+               if ( self::isFooterV2() ) {
+                       $styles[] = 'skins.minerva.footerV2.styles';
+               }
 
                return $styles;
        }
diff --git a/includes/skins/footer.mustache b/includes/skins/footer.mustache
index 02e038a..4ddcd78 100644
--- a/includes/skins/footer.mustache
+++ b/includes/skins/footer.mustache
@@ -1,12 +1,17 @@
 {{#footer}}
-<div id="footer" class="post-content">
-{{#lists}}
-<ul class="footer-{{name}}">
-       {{! "." means "current context", which allows us to iterate over Plain 
Old PHP Arrays™. }}
-       {{#items}}
-               <li id="footer-{{category}}-{{name}}">{{{linkhtml}}}</li>
-       {{/items}}
-</ul>
-{{/lists}}
+<footer {{#v1}}id="footer"{{/v1}}>
+{{{lastmodified}}}
+<div class="post-content footer-content">
+       <h2>{{{headinghtml}}}</h2>
+       <div>{{{licensehtml}}}</div>
+       {{#lists}}
+       <ul class="footer-{{name}} hlist">
+               {{! "." means "current context", which allows us to iterate 
over Plain Old PHP Arrays™. }}
+               {{#items}}
+                       <li 
id="footer-{{category}}-{{name}}">{{{linkhtml}}}</li>
+               {{/items}}
+       </ul>
+       {{/lists}}
+</div>
 </div>
 {{/footer}}
diff --git a/includes/skins/history-beta.mustache 
b/includes/skins/history-beta.mustache
new file mode 100644
index 0000000..c2e1728
--- /dev/null
+++ b/includes/skins/history-beta.mustache
@@ -0,0 +1,12 @@
+<div class="last-modified-bar view-border-box footer-element">
+       <div class="content">
+               <div class="last-modifier-tagline truncated-text 
{{clockIconClass}}">
+                       <div class="{{arrowIconClass}}"></div><a href="{{link}}"
+                               data-user-name="{{username}}"
+                               data-user-gender="{{userGender}}"
+                               data-timestamp="{{timestamp}}">
+                               {{text}}
+                       </a>
+               </div>
+       </div>
+</div>
\ No newline at end of file
diff --git a/includes/skins/minerva.mustache b/includes/skins/minerva.mustache
index 77489c6..7a24721 100644
--- a/includes/skins/minerva.mustache
+++ b/includes/skins/minerva.mustache
@@ -1,4 +1,4 @@
-<!-- v:1 -->
+<!-- v:2 -->
 {{{headelement}}}
 <div id="mw-mf-viewport">
        {{>ie8Html5Support}}
diff --git a/minerva.less/minerva.variables.less 
b/minerva.less/minerva.variables.less
index 9891334..8446bc3 100644
--- a/minerva.less/minerva.variables.less
+++ b/minerva.less/minerva.variables.less
@@ -109,3 +109,12 @@
 @tocFontSize: 0.8em;
 // indicators
 @indicatorFontSize: 0.4em;
+
+@lastModifiedBarBgColor: @grayLightest;
+@lastModifiedBarActiveBgColor: @lastModifiedBarActiveBackgroundColor;
+@lastModifiedBarTextColor: @colorGray6;
+
+@footerBgColor: @lastModifiedBarBgColor;
+
+@footerBgColor: @grayLightest;
+@footerBorderColor: @grayLight;
diff --git a/resources/mobile.toggle.images/arrow.svg 
b/resources/mobile.toggle.images/arrow.svg
deleted file mode 100644
index 818c3e8..0000000
--- a/resources/mobile.toggle.images/arrow.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg xmlns="http://www.w3.org/2000/svg"; viewBox="0 -407 24 24">
-    <g id="g4">
-        <path d="M21.348-401.268q.94 0 1.61.668l.92.922-11.858 
11.86L.198-399.66l.922-.94q.65-.686 1.59-.686.94 0 1.61.668l7.718 7.7 
7.7-7.682q.67-.668 1.61-.668z" id="path6" fill="currentColor"/>
-    </g>
-</svg>
diff --git a/resources/skins.minerva.base.styles/footer.less 
b/resources/skins.minerva.base.styles/footer.less
index 1341b8a..75c1fcd 100644
--- a/resources/skins.minerva.base.styles/footer.less
+++ b/resources/skins.minerva.base.styles/footer.less
@@ -28,6 +28,7 @@
                li {
                        line-height: 1.2;
                        padding: 0 0 0.7em;
+                       display: block;
                }
 
                ul {
diff --git a/resources/skins.minerva.footerV2.styles/common.less 
b/resources/skins.minerva.footerV2.styles/common.less
new file mode 100644
index 0000000..0d06738
--- /dev/null
+++ b/resources/skins.minerva.footerV2.styles/common.less
@@ -0,0 +1,71 @@
+@import 'minerva.variables';
+@import 'minerva.mixins';
+
+.feature-footer-v2 footer {
+       margin-top: 32px;
+       overflow: auto;
+       background-color: @footerBgColor;
+
+       .last-modified-bar {
+               border-top: solid 1px @footerBorderColor;
+               border-bottom: solid 1px @footerBorderColor;
+               background-color: @lastModifiedBarBgColor;
+               display: block;
+               color: @lastModifiedBarTextColor;
+               line-height: 1.5em;
+               transition: background-color 0.2s ease, color 0.2s ease;
+
+               &.active {
+                       background-color: @lastModifiedBarActiveBackgroundColor;
+                       color: #fff;
+               }
+       }
+
+       .last-modifier-tagline {
+               display: block;
+               width: 100%;
+               font-size: 0.9em;
+               padding: 7px 2em 7px 0;
+       }
+
+       .indicator {
+               position: absolute;
+               right: -1em;
+
+               &:before {
+                       transform: rotateZ( -90deg );
+               }
+       }
+
+       > .post-content {
+               overflow: auto;
+               margin-top: 42px;
+
+               > * {
+                       font-size: 0.875em;
+                       margin-bottom: 9px;
+               }
+
+               > h2 {
+                       border-bottom: solid 1px @footerBorderColor;
+                       padding-bottom: 10px;
+                       margin-top: 42px;
+                       font-size: 1em;
+                       font-weight: bold;
+
+                       &:first-child {
+                               margin-top: 0;
+                       }
+               }
+       }
+}
+
+@media ( min-width: @deviceWidthTablet ) {
+       .feature-footer-v2 footer {
+               .last-modified-bar {
+                       padding-left: 0;
+                       padding-right: 0;
+                       font-size: 1em;
+               }
+       }
+}
diff --git a/resources/skins.minerva.icons.images.variants/arrow.svg 
b/resources/skins.minerva.icons.images.variants/arrow.svg
new file mode 100644
index 0000000..1b32a2b
--- /dev/null
+++ b/resources/skins.minerva.icons.images.variants/arrow.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"; viewBox="0 -407 24 24"><g 
id="g4"><path d="M21.348-401.268q.94 0 1.61.668l.92.922-11.858 
11.86L.198-399.66l.922-.94q.65-.686 1.59-.686.94 0 1.61.668l7.718 7.7 
7.7-7.682q.67-.668 1.61-.668z" id="path6"/></g></svg>
\ No newline at end of file
diff --git a/resources/skins.minerva.icons.images.variants/clock.svg 
b/resources/skins.minerva.icons.images.variants/clock.svg
new file mode 100644
index 0000000..bcc8a36
--- /dev/null
+++ b/resources/skins.minerva.icons.images.variants/clock.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg width="19" 
height="17" viewBox="0 0 19 17" 
xmlns="http://www.w3.org/2000/svg";><title>60D09D03-11C8-45CE-89FD-0CDCF810A626</title><g
 id="Page-1"><g id="footer-recently-edited"><g id="Group-2"><path d="M10.853 
0a8.137 8.137 0 0 0-8.14 8.143H0l3.524 3.524.063.13 3.65-3.654H4.525a6.334 
6.334 0 0 1 12.666 0 6.334 6.334 0 0 1-6.333 6.333c-1.75 
0-3.33-.715-4.474-1.86l-1.28 1.28a8.09 8.09 0 0 0 5.75 2.39c4.5 0 8.147-3.646 
8.147-8.143A8.144 8.144 0 0 0 10.853 0zm-.9 4.524v4.524l3.872 
2.298.65-1.1L11.31 8.37V4.523H9.952z" id="Page-1"/></g></g></g></svg>
\ No newline at end of file
diff --git a/resources/skins.minerva.scripts/init.js 
b/resources/skins.minerva.scripts/init.js
index 8b0c166..5aa14e2 100644
--- a/resources/skins.minerva.scripts/init.js
+++ b/resources/skins.minerva.scripts/init.js
@@ -311,7 +311,7 @@
         * @param {JQuery.Object} [$lastModifiedLink]
         */
        function initHistoryLink( $lastModifiedLink ) {
-               var delta, historyUrl, msg,
+               var delta, historyUrl, msg, $bar,
                        ts, username, gender;
 
                historyUrl = $lastModifiedLink.attr( 'href' );
@@ -322,7 +322,12 @@
                if ( ts ) {
                        delta = time.getTimeAgoDelta( parseInt( ts, 10 ) );
                        if ( time.isRecent( delta ) ) {
-                               $lastModifiedLink.closest( '.last-modified-bar' 
).addClass( 'active' );
+                               $bar = $lastModifiedLink.closest( 
'.last-modified-bar' );
+                               $bar.addClass( 'active' );
+                               // in beta update icons to be inverted
+                               $bar.find( '.mw-ui-icon' ).each( function () {
+                                       $( this ).attr( 'class', $( this 
).attr( 'class' ).replace( '-gray', '-invert' ) );
+                               } );
                        }
                        msg = time.getLastModifiedMessage( ts, username, 
gender, historyUrl );
                        $lastModifiedLink.replaceWith( msg );
@@ -346,6 +351,7 @@
        $( function () {
                // Update anything else that needs enhancing (e.g. watchlist)
                initModifiedInfo();
-               initHistoryLink( $( '#mw-mf-last-modified a' ) );
+               // FIXME: Drop id selector when footer v2 in stable (T141002)
+               initHistoryLink( $( '#mw-mf-last-modified a, 
.last-modifier-tagline a' ) );
        } );
 }( mw.mobileFrontend, jQuery ) );

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I4b17119e1dd6e4866851c7791d9cedea88104335
Gerrit-PatchSet: 15
Gerrit-Project: mediawiki/extensions/MobileFrontend
Gerrit-Branch: master
Gerrit-Owner: Jdlrobson <jrob...@wikimedia.org>
Gerrit-Reviewer: Bmansurov <bmansu...@wikimedia.org>
Gerrit-Reviewer: Jdlrobson <jrob...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to