Use eslint rule "no-var": "error" and replace all var

Change-Id: I67acf88e1b8de55054248d7cf8ca622d5772ea6f
This commit is contained in:
Fomafix 2024-03-24 20:53:43 +00:00
parent a73e2d2d19
commit effd4fe133
28 changed files with 396 additions and 441 deletions

View file

@ -35,7 +35,7 @@
}
],
"no-underscore-dangle": "off",
"no-var": "off",
"no-var": "error",
"object-property-newline": "error",
"unit-disallowed-list": "off"
},

View file

@ -5,7 +5,7 @@
* a predefined bucket ("unsampled", "control", or "treatment") and starts an AB-test.
*/
( function ( mwExperiments ) {
var bucket = {
const bucket = {
UNSAMPLED: 'unsampled', // Old treatment: not sampled and not instrumented.
CONTROL: 'control', // Old treatment: sampled and instrumented.
TREATMENT: 'treatment' // New treatment: sampled and instrumented.
@ -21,19 +21,18 @@
* @constructor
*/
function AB( config ) {
var
testName = config.testName,
samplingRate = config.samplingRate,
sessionId = config.sessionId,
test = {
name: testName,
enabled: !!samplingRate,
buckets: {
unsampled: 1 - samplingRate,
control: samplingRate / 2,
treatment: samplingRate / 2
}
};
const testName = config.testName;
const samplingRate = config.samplingRate;
const sessionId = config.sessionId;
const test = {
name: testName,
enabled: !!samplingRate,
buckets: {
unsampled: 1 - samplingRate,
control: samplingRate / 2,
treatment: samplingRate / 2
}
};
/**
* Gets the users AB-test bucket.

View file

@ -1,7 +1,6 @@
var scrollLeftStyle = null;
let scrollLeftStyle = null;
function testScrollLeftStyle() {
var definer, $definer;
if ( scrollLeftStyle !== null ) {
return scrollLeftStyle;
}
@ -9,12 +8,12 @@ function testScrollLeftStyle() {
// Adapted from <https://github.com/othree/jquery.rtl-scroll-type>.
// Original code copyright 2012 Wei-Ko Kao, licensed under the MIT License.
// Adaptation copied from OO.ui.Element.static.getScrollLeft
$definer = $( '<div>' ).attr( {
const $definer = $( '<div>' ).attr( {
dir: 'rtl',
style: 'font-size: 14px; width: 4px; height: 1px; position: absolute; top: -1000px; overflow: scroll;'
} ).text( 'ABCD' );
$definer.appendTo( document.body );
definer = $definer[ 0 ];
const definer = $definer[ 0 ];
if ( definer.scrollLeft > 0 ) {
// Safari, Chrome
scrollLeftStyle = 'default';
@ -36,10 +35,16 @@ function testScrollLeftStyle() {
* When tabs are present and one is selected, scroll the selected tab into view.
*/
function initTabsScrollPosition() {
var selectedTab, tabContainer, $tabContainer, maxScrollLeft, leftMostChild, rightMostChild,
dir, widthDiff, tabPosition, containerPosition, left, increaseScrollLeft,
// eslint-disable-next-line no-jquery/no-global-selector
$selectedTab = $( '.minerva__tab.selected' );
// eslint-disable-next-line no-jquery/no-global-selector
const $selectedTab = $( '.minerva__tab.selected' );
if ( $selectedTab.length !== 1 ) {
return;
}
const selectedTab = $selectedTab.get( 0 );
const $tabContainer = $selectedTab.closest( '.minerva__tab-container' );
const tabContainer = $tabContainer.get( 0 );
const maxScrollLeft = tabContainer.scrollWidth - tabContainer.clientWidth;
const dir = $tabContainer.css( 'direction' ) || 'ltr';
/**
* Set tabContainer.scrollLeft, with adjustments for browser inconsistencies in RTL
@ -60,18 +65,10 @@ function initTabsScrollPosition() {
tabContainer.scrollLeft = sl;
}
if ( $selectedTab.length !== 1 ) {
return;
}
selectedTab = $selectedTab.get( 0 );
$tabContainer = $selectedTab.closest( '.minerva__tab-container' );
tabContainer = $tabContainer.get( 0 );
maxScrollLeft = tabContainer.scrollWidth - tabContainer.clientWidth;
dir = $tabContainer.css( 'direction' ) || 'ltr';
leftMostChild = dir === 'ltr' ? tabContainer.firstElementChild : tabContainer.lastElementChild;
rightMostChild = dir === 'ltr' ? tabContainer.lastElementChild : tabContainer.firstElementChild;
const leftMostChild = dir === 'ltr' ? tabContainer.firstElementChild : tabContainer.lastElementChild;
const rightMostChild = dir === 'ltr' ? tabContainer.lastElementChild : tabContainer.firstElementChild;
// If the tab is wider than the container (doesn't fit), this value will be negative
widthDiff = tabContainer.clientWidth - selectedTab.clientWidth;
const widthDiff = tabContainer.clientWidth - selectedTab.clientWidth;
if ( selectedTab === leftMostChild ) {
// The left-most tab is selected. If the tab fits, scroll all the way to the left.
@ -91,14 +88,15 @@ function initTabsScrollPosition() {
}
} else {
// The selected tab is not the left-most or right-most, it's somewhere in the middle
tabPosition = $selectedTab.position();
containerPosition = $tabContainer.position();
const tabPosition = $selectedTab.position();
const containerPosition = $tabContainer.position();
// Position of the left edge of $selectedTab relative to the left edge of $tabContainer
left = tabPosition.left - containerPosition.left;
const left = tabPosition.left - containerPosition.left;
// Because the calculations above use the existing .scrollLeft from the browser,
// we should not use setScrollLeft() here. Instead, we rely on the fact that scrollLeft
// increases to the left in the 'default' and 'negative' modes, and to the right in
// the 'reverse' mode, so we can add/subtract a delta to/from scrollLeft accordingly.
let increaseScrollLeft;
if ( widthDiff >= 0 ) {
// The tab fits, center it
increaseScrollLeft = left - widthDiff / 2;

View file

@ -4,7 +4,7 @@
// implementation where each copy can deviate but deletion is easy. See additional discussion in
// T218358 and I95b08e77eece5cd4dae62f6f237d492d6b0fe42b.
( function () {
var UriUtil = require( './UriUtil.js' );
const UriUtil = require( './UriUtil.js' );
/**
* Returns the decoded wiki page title referenced by the passed link as a string when parsable.
@ -46,11 +46,8 @@
* @return {mw.Title|null} A Title or `null`.
*/
function newFromUri( uri, options ) {
var
mwUri,
regExp,
matches,
title;
let mwUri;
let title;
try {
// uri may or may not be a Uri but the Uri constructor accepts a Uri parameter.
@ -70,11 +67,11 @@
if ( mwUri.query.title ) {
// True if input starts with wgScriptPath.
regExp = new RegExp( '^' + mw.util.escapeRegExp( mw.config.get( 'wgScriptPath' ) ) + '/' );
const regExp = new RegExp( '^' + mw.util.escapeRegExp( mw.config.get( 'wgScriptPath' ) ) + '/' );
// URL has a nonempty `title` query parameter like `/w/index.php?title=Foo`. The script
// path should match.
matches = regExp.test( mwUri.path );
const matches = regExp.test( mwUri.path );
if ( !matches ) {
return null;
}
@ -84,12 +81,12 @@
} else {
// True if input starts with wgArticlePath and ends with a nonempty page title. The
// first matching group (index 1) is the page title.
regExp = new RegExp( '^' + mw.util.escapeRegExp( mw.config.get( 'wgArticlePath' ) ).replace( '\\$1', '(.+)' ) );
const regExp = new RegExp( '^' + mw.util.escapeRegExp( mw.config.get( 'wgArticlePath' ) ).replace( '\\$1', '(.+)' ) );
// No title query parameter is present so the URL may be "pretty" like `/wiki/Foo`.
// `Uri.path` should not contain query parameters or a fragment, as is assumed in
// `Uri.getRelativePath()`. Try to isolate the title.
matches = regExp.exec( mwUri.path );
const matches = regExp.exec( mwUri.path );
if ( !matches || !matches[ 1 ] ) {
return null;
}
@ -128,7 +125,7 @@
* @return {boolean} True if uri has no query parameters or only known parameters for reading.
*/
function isReadOnlyUri( uri ) {
var length = Object.keys( uri.query ).length;
const length = Object.keys( uri.query ).length;
return length === ( ( 'oldid' in uri.query ? 1 : 0 ) + ( 'title' in uri.query ? 1 : 0 ) );
}

View file

@ -3,13 +3,13 @@
* @return {Object} of arrays with mandatory class names for list item elements.
*/
function getClassesForItem( $item ) {
const $parent = $item.parent(),
// eslint-disable-next-line no-jquery/no-class-state
isPageActionList = $parent.hasClass( 'page-actions-menu__list' ),
// eslint-disable-next-line no-jquery/no-class-state
isTabContainer = $parent.hasClass( 'minerva__tab-container' ),
// eslint-disable-next-line no-jquery/no-class-state
isToggleList = $parent.hasClass( 'toggle-list__list' );
const $parent = $item.parent();
// eslint-disable-next-line no-jquery/no-class-state
const isPageActionList = $parent.hasClass( 'page-actions-menu__list' );
// eslint-disable-next-line no-jquery/no-class-state
const isTabContainer = $parent.hasClass( 'minerva__tab-container' );
// eslint-disable-next-line no-jquery/no-class-state
const isToggleList = $parent.hasClass( 'toggle-list__list' );
if ( isToggleList ) {
return {
@ -52,8 +52,8 @@ function getClassesForItem( $item ) {
* @param {string|undefined} id for icon
*/
function insertIcon( $link, id ) {
var icon = document.createElement( 'span' ),
classes = 'minerva-icon';
const icon = document.createElement( 'span' );
let classes = 'minerva-icon';
if ( id ) {
classes += ` minerva-icon-portletlink-${ id }`;
// FIXME: Please remove when following URL returns zero results:
@ -69,16 +69,14 @@ function insertIcon( $link, id ) {
* @param {Object} data
*/
function hookHandler( listItem, data ) {
var $item, $a, classes,
id = data.id;
if ( listItem && !listItem.dataset.minervaPortlet ) {
$item = $( listItem );
const id = data.id;
const $item = $( listItem );
// add the corresponding classes
classes = getClassesForItem( $item );
const classes = getClassesForItem( $item );
$item.addClass( classes.li );
$a = $item.find( 'a' );
const $a = $item.find( 'a' );
$a.addClass( classes.a );
$item.find( 'a > span' ).addClass( classes.span );

View file

@ -1,6 +1,6 @@
var mobile = require( 'mobile.startup' ),
drawers = require( './drawers.js' ),
CtaDrawer = mobile.CtaDrawer;
const mobile = require( 'mobile.startup' );
const drawers = require( './drawers.js' );
const CtaDrawer = mobile.CtaDrawer;
/**
* Initialize red links call-to-action
@ -23,7 +23,7 @@ var mobile = require( 'mobile.startup' ),
*/
function initRedlinksCta( $redLinks ) {
$redLinks.on( 'click', function ( ev ) {
var drawerOptions = {
const drawerOptions = {
progressiveButton: {
progressive: true,
label: mw.msg( 'mobile-frontend-editor-redlink-create' ),
@ -53,7 +53,7 @@ function initRedlinksCta( $redLinks ) {
* @param {jQuery} $watchstar
*/
function initWatchstarCta( $watchstar ) {
var watchCtaDrawer;
let watchCtaDrawer;
// show a CTA for anonymous users
$watchstar.on( 'click', function ( ev ) {
if ( !watchCtaDrawer ) {

View file

@ -1,7 +1,7 @@
( function ( track ) {
var MAX_PRINT_TIMEOUT = 3000,
printSetTimeoutReference = 0,
mobile = require( 'mobile.startup' );
const MAX_PRINT_TIMEOUT = 3000;
let printSetTimeoutReference = 0;
const mobile = require( 'mobile.startup' );
/**
* Helper function to detect iOs
@ -22,7 +22,7 @@
* @return {number|boolean} Integer version number, or false if not found
*/
function getAndroidVersion( userAgent ) {
var match = userAgent.toLowerCase().match( /android\s(\d\.]*)/ );
const match = userAgent.toLowerCase().match( /android\s(\d\.]*)/ );
return match ? parseInt( match[ 1 ] ) : false;
}
@ -34,7 +34,7 @@
* @return {number|boolean} Integer version number, or false if not found
*/
function getChromeVersion( userAgent ) {
var match = userAgent.toLowerCase().match( /chrom(e|ium)\/(\d+)\./ );
const match = userAgent.toLowerCase().match( /chrom(e|ium)\/(\d+)\./ );
return match ? parseInt( match[ 2 ] ) : false;
}
@ -50,8 +50,8 @@
* @return {boolean}
*/
function isAvailable( windowObj, page, userAgent, supportedNamespaces ) {
var androidVersion = getAndroidVersion( userAgent ),
chromeVersion = getChromeVersion( userAgent );
const androidVersion = getAndroidVersion( userAgent );
const chromeVersion = getChromeVersion( userAgent );
if ( typeof window.print !== 'function' ) {
// T309591: No window.print support
@ -86,7 +86,7 @@
* @param {Function} [loadAllImagesInPage]
*/
function onClick( portletItem, spinner, loadAllImagesInPage ) {
var icon = portletItem.querySelector( '.minerva-icon--download' );
const icon = portletItem.querySelector( '.minerva-icon--download' );
function doPrint() {
printSetTimeoutReference = clearTimeout( printSetTimeoutReference );
track( 'minerva.downloadAsPDF', {
@ -131,12 +131,10 @@
* @return {jQuery|null}
*/
function downloadPageAction( page, supportedNamespaces, windowObj, overflowList ) {
var
portletLink, iconElement,
spinner = ( overflowList ) ? mobile.spinner( {
label: '',
isIconOnly: false
} ) : mobile.spinner();
const spinner = ( overflowList ) ? mobile.spinner( {
label: '',
isIconOnly: false
} ) : mobile.spinner();
if (
isAvailable(
@ -146,7 +144,7 @@
) {
// FIXME: Use p-views when cache has cleared.
const actionID = document.querySelector( '#p-views' ) ? 'p-views' : 'page-actions';
portletLink = mw.util.addPortletLink(
const portletLink = mw.util.addPortletLink(
overflowList ? 'page-actions-overflow' : actionID,
'#',
mw.msg( 'minerva-download' ),
@ -162,7 +160,7 @@
portletLink.addEventListener( 'click', function () {
onClick( portletLink, spinner, mobile.loadAllImagesInPage );
} );
iconElement = portletLink.querySelector( '.minerva-icon' );
const iconElement = portletLink.querySelector( '.minerva-icon' );
if ( iconElement ) {
iconElement.classList.add( 'minerva-icon--download' );
}

View file

@ -1,5 +1,5 @@
var $drawerContainer = $( document.body ),
BODY_CLASS_SCROLL_LOCKED = 'has-drawer--with-scroll-locked';
const $drawerContainer = $( document.body );
const BODY_CLASS_SCROLL_LOCKED = 'has-drawer--with-scroll-locked';
/**
* Discard a drawer from display on the page.

View file

@ -40,12 +40,12 @@ module.exports = function () {
return;
}
var el = ev.target.closest( PageHTMLParser.THUMB_SELECTOR );
const el = ev.target.closest( PageHTMLParser.THUMB_SELECTOR );
if ( !el ) {
return;
}
var thumb = currentPageHTMLParser.getThumbnail( $( el ) );
const thumb = currentPageHTMLParser.getThumbnail( $( el ) );
if ( !thumb ) {
return;
}
@ -82,7 +82,7 @@ module.exports = function () {
function initButton() {
// This catches language selectors in page actions and in secondary actions (e.g. Main Page)
// eslint-disable-next-line no-jquery/no-global-selector
var $primaryBtn = $( '.language-selector' );
const $primaryBtn = $( '.language-selector' );
if ( $primaryBtn.length ) {
// We only bind the click event to the first language switcher in page
@ -160,21 +160,17 @@ module.exports = function () {
* @param {jQuery} $lastModifiedLink
*/
function initHistoryLink( $lastModifiedLink ) {
var delta, $msg, $bar,
ts, username, gender;
ts = $lastModifiedLink.data( 'timestamp' );
username = $lastModifiedLink.data( 'user-name' ) || false;
gender = $lastModifiedLink.data( 'user-gender' );
const ts = $lastModifiedLink.data( 'timestamp' );
if ( ts ) {
delta = time.getTimeAgoDelta( parseInt( ts, 10 ) );
const username = $lastModifiedLink.data( 'user-name' ) || false;
const gender = $lastModifiedLink.data( 'user-gender' );
const delta = time.getTimeAgoDelta( parseInt( ts, 10 ) );
if ( time.isRecent( delta ) ) {
$bar = $lastModifiedLink.closest( '.last-modified-bar' );
const $bar = $lastModifiedLink.closest( '.last-modified-bar' );
$bar.addClass( 'active' );
}
$msg = $( '<span>' )
const $msg = $( '<span>' )
// The new element should maintain the non-js element's CSS classes.
.attr( 'class', $lastModifiedLink.attr( 'class' ) )
.html(
@ -192,15 +188,14 @@ module.exports = function () {
* @param {jQuery.Event} ev
*/
function amcHistoryClickHandler( ev ) {
var
self = this,
amcOutreach = ms.amcOutreach,
amcCampaign = amcOutreach.loadCampaign(),
onDismiss = function () {
notifyOnPageReload( mw.msg( 'mobile-frontend-amc-outreach-dismissed-message' ) );
window.location = self.href;
},
drawer = amcCampaign.showIfEligible( amcOutreach.ACTIONS.onHistoryLink, onDismiss, currentPage.title, 'action=history' );
const self = this;
const amcOutreach = ms.amcOutreach;
const amcCampaign = amcOutreach.loadCampaign();
const onDismiss = function () {
notifyOnPageReload( mw.msg( 'mobile-frontend-amc-outreach-dismissed-message' ) );
window.location = self.href;
};
const drawer = amcCampaign.showIfEligible( amcOutreach.ACTIONS.onHistoryLink, onDismiss, currentPage.title, 'action=history' );
if ( drawer ) {
ev.preventDefault();
@ -272,12 +267,10 @@ module.exports = function () {
* @param {jQuery} [$tagline]
*/
function initRegistrationDate( $tagline ) {
var msg, ts;
ts = $tagline.data( 'userpage-registration-date' );
const ts = $tagline.data( 'userpage-registration-date' );
if ( ts ) {
msg = time.getRegistrationMessage( ts, $tagline.data( 'userpage-gender' ) );
const msg = time.getRegistrationMessage( ts, $tagline.data( 'userpage-gender' ) );
$tagline.text( msg );
}
}
@ -318,9 +311,8 @@ module.exports = function () {
* @return {boolean}
*/
function isUserUri( url ) {
var
title = TitleUtil.newFromUri( url ),
namespace = title ? title.getNamespaceId() : undefined;
const title = TitleUtil.newFromUri( url );
const namespace = title ? title.getNamespaceId() : undefined;
return namespace === namespaceIDs.user;
}
@ -334,7 +326,7 @@ module.exports = function () {
// Filter out non-User namespace pages.
return isUserUri( element.href );
} ).each( function ( _, element ) {
var uri = new mw.Uri( element.href );
const uri = new mw.Uri( element.href );
if ( uri.query.action !== 'edit' ) {
// Nothing to strip.
return;
@ -371,12 +363,11 @@ module.exports = function () {
}
$( function () {
var
// eslint-disable-next-line no-jquery/no-global-selector
$watch = $( '#page-actions-watch' ),
toolbarElement = document.querySelector( Toolbar.selector ),
userMenu = document.querySelector( '.minerva-user-menu' ), // See UserMenuDirector.
navigationDrawer = document.querySelector( '.navigation-drawer' );
// eslint-disable-next-line no-jquery/no-global-selector
const $watch = $( '#page-actions-watch' );
const toolbarElement = document.querySelector( Toolbar.selector );
const userMenu = document.querySelector( '.minerva-user-menu' ); // See UserMenuDirector.
const navigationDrawer = document.querySelector( '.navigation-drawer' );
// The `minerva-animations-ready` class can be used by clients to prevent unwanted
// CSS transitions from firing on page load in some browsers (see
@ -388,7 +379,7 @@ module.exports = function () {
// eslint-disable-next-line no-jquery/no-global-selector
$( '.mw-mf-page-center__mask' ).on( 'click', function ( ev ) {
var path = router.getPath();
const path = router.getPath();
// avoid jumping to the top of the page and polluting history by avoiding the
// resetting of the hash unless the hash is being utilised (T237015).
if ( !path ) {
@ -423,7 +414,7 @@ module.exports = function () {
}
if ( navigationDrawer ) {
ToggleList.bind( window, navigationDrawer );
var navigationDrawerMask = navigationDrawer.querySelector( '.main-menu-mask' );
const navigationDrawerMask = navigationDrawer.querySelector( '.main-menu-mask' );
// The 'for' attribute is used to close the drawer when the mask is clicked without JS
// Since we are using JS to enhance the drawer behavior, we need to
// remove the attribute to prevent the drawer from being toggled twice
@ -454,12 +445,12 @@ module.exports = function () {
}
// Mutate TOC.
var $toctitle = $container.find( '.toctitle' );
const $toctitle = $container.find( '.toctitle' );
$( '<span>' ).addClass( 'toc-title-icon' ).prependTo( $toctitle );
$( '<span>' ).addClass( 'toc-title-state-icon' ).appendTo( $toctitle );
// Init red links.
var $redLinks = currentPageHTMLParser.getRedLinks();
const $redLinks = currentPageHTMLParser.getRedLinks();
ctaDrawers.initRedlinksCta(
$redLinks.filter( function ( _, element ) {
// Filter out local User namespace pages.

View file

@ -1,4 +1,4 @@
var BODY_NOTIFICATIONS_REVEAL_CLASS = 'navigation-enabled secondary-navigation-enabled';
const BODY_NOTIFICATIONS_REVEAL_CLASS = 'navigation-enabled secondary-navigation-enabled';
/**
* Wire up the main menu

View file

@ -1,4 +1,4 @@
var drawers = require( './drawers.js' );
const drawers = require( './drawers.js' );
/*
* Warn people if they're trying to switch to desktop but have cookies disabled.
@ -52,24 +52,23 @@ module.exports = function ( amcOutreach, currentPage ) {
* @return {boolean|undefined}
*/
function amcDesktopClickHandler( ev ) {
var
self = this,
executeWrappedEvent = function () {
if ( desktopViewClick() === false ) {
return false;
}
const self = this;
const executeWrappedEvent = function () {
if ( desktopViewClick() === false ) {
return false;
}
window.location = self.href;
},
amcCampaign = amcOutreach.loadCampaign(),
onDismiss = function () {
executeWrappedEvent();
},
drawer = amcCampaign.showIfEligible(
amcOutreach.ACTIONS.onDesktopLink,
onDismiss,
currentPage.title
);
window.location = self.href;
};
const amcCampaign = amcOutreach.loadCampaign();
const onDismiss = function () {
executeWrappedEvent();
};
const drawer = amcCampaign.showIfEligible(
amcOutreach.ACTIONS.onDesktopLink,
onDismiss,
currentPage.title
);
if ( drawer ) {
ev.preventDefault();

View file

@ -1,19 +1,19 @@
/** @typedef {Object.<string, IssueSummary[]>} IssueSummaryMap */
var PageHTMLParser = require( 'mobile.startup' ).PageHTMLParser,
KEYWORD_ALL_SECTIONS = 'all',
config = mw.config,
NS_MAIN = 0,
NS_CATEGORY = 14,
CURRENT_NS = config.get( 'wgNamespaceNumber' ),
features = mw.config.get( 'wgMinervaFeatures', {} ),
pageIssuesParser = require( './parser.js' ),
pageIssuesOverlay = require( './overlay/pageIssuesOverlay.js' ),
pageIssueFormatter = require( './page/pageIssueFormatter.js' ),
// When the query string flag is set force on new treatment.
// When wgMinervaPageIssuesNewTreatment is the default this line can be removed.
QUERY_STRING_FLAG = mw.util.getParamValue( 'minerva-issues' ),
newTreatmentEnabled = features.pageIssues || QUERY_STRING_FLAG;
const PageHTMLParser = require( 'mobile.startup' ).PageHTMLParser;
const KEYWORD_ALL_SECTIONS = 'all';
const config = mw.config;
const NS_MAIN = 0;
const NS_CATEGORY = 14;
const CURRENT_NS = config.get( 'wgNamespaceNumber' );
const features = mw.config.get( 'wgMinervaFeatures', {} );
const pageIssuesParser = require( './parser.js' );
const pageIssuesOverlay = require( './overlay/pageIssuesOverlay.js' );
const pageIssueFormatter = require( './page/pageIssueFormatter.js' );
// When the query string flag is set force on new treatment.
// When wgMinervaPageIssuesNewTreatment is the default this line can be removed.
const QUERY_STRING_FLAG = mw.util.getParamValue( 'minerva-issues' );
const newTreatmentEnabled = features.pageIssues || QUERY_STRING_FLAG;
/**
* Render a banner in a containing element.
@ -36,26 +36,21 @@ var PageHTMLParser = require( 'mobile.startup' ).PageHTMLParser,
* @return {{ambox: jQuery, issueSummaries: IssueSummary[]}}
*/
function insertBannersOrNotice( pageHTMLParser, labelText, section, inline, overlayManager ) {
var
$metadata,
issueUrl = section === KEYWORD_ALL_SECTIONS ? '#/issues/' + KEYWORD_ALL_SECTIONS : '#/issues/' + section,
selector = [ '.ambox', '.tmbox', '.cmbox', '.fmbox' ].join( ',' ),
issueSummaries = [];
const issueUrl = section === KEYWORD_ALL_SECTIONS ? '#/issues/' + KEYWORD_ALL_SECTIONS : '#/issues/' + section;
const selector = [ '.ambox', '.tmbox', '.cmbox', '.fmbox' ].join( ',' );
const issueSummaries = [];
if ( section === KEYWORD_ALL_SECTIONS ) {
$metadata = pageHTMLParser.$el.find( selector );
} else {
const $metadata = section === KEYWORD_ALL_SECTIONS ?
pageHTMLParser.$el.find( selector ) :
// find heading associated with the section
$metadata = pageHTMLParser.findChildInSectionLead( parseInt( section, 10 ), selector );
}
pageHTMLParser.findChildInSectionLead( parseInt( section, 10 ), selector );
// clean it up a little
$metadata.find( '.NavFrame' ).remove();
$metadata.each( function () {
var issueSummary,
$this = $( this );
const $this = $( this );
if ( $this.find( selector ).length === 0 ) {
issueSummary = pageIssuesParser.extract( $this );
const issueSummary = pageIssuesParser.extract( $this );
// Some issues after "extract" has been run will have no text.
// For example in Template:Talk header the table will be removed and no issue found.
// These should not be rendered.
@ -67,10 +62,10 @@ function insertBannersOrNotice( pageHTMLParser, labelText, section, inline, over
if ( inline ) {
issueSummaries.forEach( function ( issueSummary, i ) {
var isGrouped = issueSummary.issue.grouped,
lastIssueIsGrouped = issueSummaries[ i - 1 ] &&
issueSummaries[ i - 1 ].issue.grouped,
multiple = isGrouped && !lastIssueIsGrouped;
const isGrouped = issueSummary.issue.grouped;
const lastIssueIsGrouped = issueSummaries[ i - 1 ] &&
issueSummaries[ i - 1 ].issue.grouped;
const multiple = isGrouped && !lastIssueIsGrouped;
// only render the first grouped issue of each group
pageIssueFormatter.insertPageIssueBanner(
issueSummary,
@ -122,14 +117,12 @@ function getIssues( allIssues, section ) {
* @param {PageHTMLParser} pageHTMLParser
*/
function initPageIssues( overlayManager, pageHTMLParser ) {
var
section,
issueSummaries = [],
allIssues = {},
label,
$lead = pageHTMLParser.getLeadSectionElement(),
issueOverlayShowAll = CURRENT_NS === NS_CATEGORY || !$lead,
inline = newTreatmentEnabled && CURRENT_NS === 0;
let section;
let issueSummaries = [];
const allIssues = {};
const $lead = pageHTMLParser.getLeadSectionElement();
const issueOverlayShowAll = CURRENT_NS === NS_CATEGORY || !$lead;
const inline = newTreatmentEnabled && CURRENT_NS === 0;
// set A-B test class.
// When wgMinervaPageIssuesNewTreatment is the default this can be removed.
@ -144,7 +137,7 @@ function initPageIssues( overlayManager, pageHTMLParser ) {
section, inline, overlayManager ).issueSummaries;
allIssues[ section ] = issueSummaries;
} else if ( CURRENT_NS === NS_MAIN ) {
label = mw.msg( 'mobile-frontend-meta-data-issues-header' );
const label = mw.msg( 'mobile-frontend-meta-data-issues-header' );
if ( issueOverlayShowAll ) {
section = KEYWORD_ALL_SECTIONS;
issueSummaries = insertBannersOrNotice(
@ -163,10 +156,10 @@ function initPageIssues( overlayManager, pageHTMLParser ) {
// for sections.
pageHTMLParser.$el.find( PageHTMLParser.HEADING_SELECTOR ).each(
function ( i, headingEl ) {
var $headingEl = $( headingEl ),
// section number is absent on protected pages, when this is the case
// use i, otherwise icon will not show (T340910)
sectionNum = $headingEl.find( '.edit-page' ).data( 'section' ) || i;
const $headingEl = $( headingEl );
// section number is absent on protected pages, when this is the case
// use i, otherwise icon will not show (T340910)
const sectionNum = $headingEl.find( '.edit-page' ).data( 'section' ) || i;
// Note certain headings matched using
// PageHTMLParser.HEADING_SELECTOR may not be headings and will

View file

@ -1,9 +1,8 @@
const
Overlay = require( 'mobile.startup' ).Overlay,
IssueList = require( './IssueList.js' ),
KEYWORD_ALL_SECTIONS = 'all',
NS_MAIN = 0,
NS_CATEGORY = 14;
const Overlay = require( 'mobile.startup' ).Overlay;
const IssueList = require( './IssueList.js' );
const KEYWORD_ALL_SECTIONS = 'all';
const NS_MAIN = 0;
const NS_CATEGORY = 14;
/**
* Overlay for displaying page issues
@ -14,15 +13,14 @@ const
* @return {Overlay}
*/
function pageIssuesOverlay( issues, section, namespaceID ) {
var overlay,
// Note only the main namespace is expected to make use of section issues, so the
// heading will always be minerva-meta-data-issues-section-header regardless of
// namespace.
headingText = section === '0' || section === KEYWORD_ALL_SECTIONS ?
getNamespaceHeadingText( namespaceID ) :
mw.msg( 'minerva-meta-data-issues-section-header' );
// Note only the main namespace is expected to make use of section issues, so the
// heading will always be minerva-meta-data-issues-section-header regardless of
// namespace.
const headingText = section === '0' || section === KEYWORD_ALL_SECTIONS ?
getNamespaceHeadingText( namespaceID ) :
mw.msg( 'minerva-meta-data-issues-section-header' );
overlay = new Overlay( {
const overlay = new Overlay( {
className: 'overlay overlay-issues',
heading: '<strong>' + headingText + '</strong>'
} );

View file

@ -1,7 +1,6 @@
( function () {
var
newPageIssueLink = require( './PageIssueLink.js' ),
newPageIssueLearnMoreLink = require( './PageIssueLearnMoreLink.js' );
const newPageIssueLink = require( './PageIssueLink.js' );
const newPageIssueLearnMoreLink = require( './PageIssueLearnMoreLink.js' );
/**
* Modifies the `issue` DOM to create a banner designed for single / multiple issue templates,
@ -14,11 +13,11 @@
* @param {boolean} [multiple]
*/
function insertPageIssueBanner( issue, msg, overlayUrl, overlayManager, multiple ) {
var $learnMoreEl = newPageIssueLearnMoreLink( msg ),
$issueContainer = multiple ?
issue.$el.parents( '.mbox-text-span, .mbox-text-div' ) :
issue.$el.find( '.mbox-text' ),
$clickContainer = multiple ? issue.$el.parents( '.mbox-text' ) : issue.$el;
const $learnMoreEl = newPageIssueLearnMoreLink( msg );
const $issueContainer = multiple ?
issue.$el.parents( '.mbox-text-span, .mbox-text-div' ) :
issue.$el.find( '.mbox-text' );
const $clickContainer = multiple ? issue.$el.parents( '.mbox-text' ) : issue.$el;
$issueContainer.prepend( issue.issue.iconElement );
$issueContainer.prepend( $learnMoreEl );
@ -38,7 +37,7 @@
* @param {string} section
*/
function insertPageIssueNotice( labelText, section ) {
var $link = newPageIssueLink( labelText );
const $link = newPageIssueLink( labelText );
$link.attr( 'href', '#/issues/' + section );
// eslint-disable-next-line no-jquery/no-global-selector
$link.insertAfter( $( 'h1.mw-first-heading' ) );

View file

@ -14,102 +14,101 @@
* @property {string} text HTML string.
*/
var
// Icons are matching the type selector below use a TYPE_* icon. When unmatched, the icon is
// chosen by severity. Their color is always determined by severity, too.
ICON_NAME = {
// Generic severity icons.
SEVERITY: {
DEFAULT: 'issue-generic',
LOW: 'issue-severity-low',
MEDIUM: 'issue-severity-medium',
HIGH: 'issue-generic'
},
// Icons are matching the type selector below use a TYPE_* icon. When unmatched, the icon is
// chosen by severity. Their color is always determined by severity, too.
const ICON_NAME = {
// Generic severity icons.
SEVERITY: {
DEFAULT: 'issue-generic',
LOW: 'issue-severity-low',
MEDIUM: 'issue-severity-medium',
HIGH: 'issue-generic'
},
// Icons customized by type.
TYPE: {
MOVE: 'issue-type-move',
POINT_OF_VIEW: 'issue-type-point-of-view'
}
},
ICON_COLOR = {
DEFAULT: 'defaultColor',
LOW: 'lowColor',
MEDIUM: 'mediumColor',
HIGH: 'highColor'
},
// How severities order and compare from least to greatest. For the multiple issues
// template, severity should be considered the maximum of all its contained issues.
SEVERITY_LEVEL = {
DEFAULT: 0,
LOW: 1,
MEDIUM: 2,
HIGH: 3
},
// Match the template's color CSS selector to a severity level concept. Derived via the
// Ambox templates and sub-templates for the top five wikis and tested on page issues
// inventory:
// - https://people.wikimedia.org/~jdrewniak/page_issues_inventory
// - https://en.wikipedia.org/wiki/Template:Ambox
// - https://es.wikipedia.org/wiki/Plantilla:Metaplantilla_de_avisos
// - https://ja.wikipedia.org/wiki/Template:Ambox
// - https://ru.wikipedia.org/wiki/Шаблон:Ambox
// - https://it.wikipedia.org/wiki/Template:Avviso
// Severity is the class associated with the color. The ResourceLoader config mimics the
// idea by using severity for color variants. Severity is determined independently of icons.
// These selectors should be migrated to their templates.
SEVERITY_REGEX = {
// recommended (T206177), en, it
LOW: /mobile-issue-severity-low|ambox-style|avviso-stile/,
// recommended, en, it
MEDIUM: /mobile-issue-severity-medium|ambox-content|avviso-contenuto/,
// recommended, en, en, es / ru, it
HIGH: /mobile-issue-severity-high|ambox-speedy|ambox-delete|ambox-serious|avviso-importante/
// ..And everything else that doesn't match should be considered DEFAULT.
},
// As above but used to identify specific templates requiring icon customization.
TYPE_REGEX = {
// recommended (opt-in) / en, es / ru, it (long term only recommended should be used)
MOVE: /mobile-issue-move|ambox-converted|ambox-move|ambox-merge|avviso-struttura/,
POINT_OF_VIEW: new RegExp( [
// recommended (opt-in)
'mobile-issue-pov',
// FIXME: en classes: plan to remove these provided can get adoption of recommended
'ambox-Advert',
'ambox-autobiography',
'ambox-believerpov',
'ambox-COI',
'ambox-coverage',
'ambox-criticism',
'ambox-fanpov',
'ambox-fringe-theories',
'ambox-geographical-imbalance',
'ambox-globalize',
'ambox-npov-language',
'ambox-POV',
'ambox-pseudo',
'ambox-systemic-bias',
'ambox-unbalanced',
'ambox-usgovtpov'
].join( '|' ) )
// ..And everything else that doesn't match is mapped to a "SEVERITY" type.
},
GROUPED_PARENT_REGEX = /mw-collapsible-content/,
// Variants supported by specific types. The "severity icon" supports all severities but the
// type icons only support one each by ResourceLoader.
TYPE_SEVERITY = {
MOVE: 'DEFAULT',
POINT_OF_VIEW: 'MEDIUM'
};
// Icons customized by type.
TYPE: {
MOVE: 'issue-type-move',
POINT_OF_VIEW: 'issue-type-point-of-view'
}
};
const ICON_COLOR = {
DEFAULT: 'defaultColor',
LOW: 'lowColor',
MEDIUM: 'mediumColor',
HIGH: 'highColor'
};
// How severities order and compare from least to greatest. For the multiple issues
// template, severity should be considered the maximum of all its contained issues.
const SEVERITY_LEVEL = {
DEFAULT: 0,
LOW: 1,
MEDIUM: 2,
HIGH: 3
};
// Match the template's color CSS selector to a severity level concept. Derived via the
// Ambox templates and sub-templates for the top five wikis and tested on page issues
// inventory:
// - https://people.wikimedia.org/~jdrewniak/page_issues_inventory
// - https://en.wikipedia.org/wiki/Template:Ambox
// - https://es.wikipedia.org/wiki/Plantilla:Metaplantilla_de_avisos
// - https://ja.wikipedia.org/wiki/Template:Ambox
// - https://ru.wikipedia.org/wiki/Шаблон:Ambox
// - https://it.wikipedia.org/wiki/Template:Avviso
// Severity is the class associated with the color. The ResourceLoader config mimics the
// idea by using severity for color variants. Severity is determined independently of icons.
// These selectors should be migrated to their templates.
const SEVERITY_REGEX = {
// recommended (T206177), en, it
LOW: /mobile-issue-severity-low|ambox-style|avviso-stile/,
// recommended, en, it
MEDIUM: /mobile-issue-severity-medium|ambox-content|avviso-contenuto/,
// recommended, en, en, es / ru, it
HIGH: /mobile-issue-severity-high|ambox-speedy|ambox-delete|ambox-serious|avviso-importante/
// ..And everything else that doesn't match should be considered DEFAULT.
};
// As above but used to identify specific templates requiring icon customization.
const TYPE_REGEX = {
// recommended (opt-in) / en, es / ru, it (long term only recommended should be used)
MOVE: /mobile-issue-move|ambox-converted|ambox-move|ambox-merge|avviso-struttura/,
POINT_OF_VIEW: new RegExp( [
// recommended (opt-in)
'mobile-issue-pov',
// FIXME: en classes: plan to remove these provided can get adoption of recommended
'ambox-Advert',
'ambox-autobiography',
'ambox-believerpov',
'ambox-COI',
'ambox-coverage',
'ambox-criticism',
'ambox-fanpov',
'ambox-fringe-theories',
'ambox-geographical-imbalance',
'ambox-globalize',
'ambox-npov-language',
'ambox-POV',
'ambox-pseudo',
'ambox-systemic-bias',
'ambox-unbalanced',
'ambox-usgovtpov'
].join( '|' ) )
// ..And everything else that doesn't match is mapped to a "SEVERITY" type.
};
const GROUPED_PARENT_REGEX = /mw-collapsible-content/;
// Variants supported by specific types. The "severity icon" supports all severities but the
// type icons only support one each by ResourceLoader.
const TYPE_SEVERITY = {
MOVE: 'DEFAULT',
POINT_OF_VIEW: 'MEDIUM'
};
/**
* @param {Element} box
* @return {string} An SEVERITY_SELECTOR key.
*/
function parseSeverity( box ) {
var severity, identified;
identified = Object.keys( SEVERITY_REGEX ).some( function ( key ) {
var regex = SEVERITY_REGEX[ key ];
let severity;
const identified = Object.keys( SEVERITY_REGEX ).some( function ( key ) {
const regex = SEVERITY_REGEX[ key ];
severity = key;
return regex.test( box.className );
} );
@ -122,9 +121,9 @@
* @return {{name: string, severity: string}} An ICON_NAME.
*/
function parseType( box, severity ) {
var identified, identifiedType;
identified = Object.keys( TYPE_REGEX ).some( function ( type ) {
var regex = TYPE_REGEX[ type ];
let identifiedType;
const identified = Object.keys( TYPE_REGEX ).some( function ( type ) {
const regex = TYPE_REGEX[ type ];
identifiedType = type;
return regex.test( box.className );
} );
@ -148,7 +147,7 @@
* @return {string} A severity or type ISSUE_ICON.
*/
function iconName( box, severity ) {
var nameSeverity = parseType( box, severity );
const nameSeverity = parseType( box, severity );
// The icon with color variant as expected by ResourceLoader,
// {iconName}-{severityColorVariant}.
return nameSeverity.name + '-' + ICON_COLOR[ nameSeverity.severity ];
@ -187,23 +186,21 @@
* @return {IssueSummary}
*/
function extract( $box ) {
var SELECTOR = '.mbox-text, .ambox-text',
$container = $( '<div>' ),
pageIssue;
const SELECTOR = '.mbox-text, .ambox-text';
const $container = $( '<div>' );
$box.find( SELECTOR ).each( function () {
var contents,
$this = $( this );
const $this = $( this );
// Clean up talk page boxes
$this.find( 'table, .noprint' ).remove();
contents = $this.html();
const contents = $this.html();
if ( contents ) {
$( '<p>' ).html( contents ).appendTo( $container );
}
} );
pageIssue = parse( $box.get( 0 ) );
const pageIssue = parse( $box.get( 0 ) );
return {
issue: pageIssue,

View file

@ -1,5 +1,5 @@
module.exports = function () {
var menus = require( './menu.js' );
const menus = require( './menu.js' );
// setup main menu
menus.init();
@ -8,18 +8,16 @@ module.exports = function () {
// If the user has been redirected, then show them a toast message (see
// https://phabricator.wikimedia.org/T146596).
var redirectedFrom, $msg, title;
if ( wgRedirectedFrom === null ) {
return;
}
redirectedFrom = mw.Title.newFromText( wgRedirectedFrom );
const redirectedFrom = mw.Title.newFromText( wgRedirectedFrom );
if ( redirectedFrom ) {
// mw.Title.getPrefixedText includes the human-readable namespace prefix.
title = redirectedFrom.getPrefixedText();
$msg = $( '<div>' ).html(
const title = redirectedFrom.getPrefixedText();
const $msg = $( '<div>' ).html(
mw.message( 'mobile-frontend-redirected-from', title ).parse()
);
$msg.find( 'a' ).attr( 'href', mw.util.getUrl( title, { redirect: 'no' } ) );

View file

@ -1,13 +1,13 @@
var drawers = require( './drawers.js' );
const drawers = require( './drawers.js' );
module.exports = function () {
var mobile = require( 'mobile.startup' ),
references = mobile.references,
currentPage = mobile.currentPage(),
currentPageHTMLParser = mobile.currentPageHTMLParser(),
ReferencesHtmlScraperGateway = mobile.references.ReferencesHtmlScraperGateway,
gateway = new ReferencesHtmlScraperGateway( new mw.Api() );
const mobile = require( 'mobile.startup' );
const references = mobile.references;
const currentPage = mobile.currentPage();
const currentPageHTMLParser = mobile.currentPageHTMLParser();
const ReferencesHtmlScraperGateway = mobile.references.ReferencesHtmlScraperGateway;
const gateway = new ReferencesHtmlScraperGateway( new mw.Api() );
/**
* Event handler to show reference when a reference link is clicked
@ -16,14 +16,14 @@ module.exports = function () {
* @param {jQuery.Event} ev Click event of the reference element
*/
function showReference( ev ) {
var $dest = $( ev.currentTarget ),
href = $dest.attr( 'href' );
const $dest = $( ev.currentTarget );
let href = $dest.attr( 'href' );
ev.preventDefault();
// If necessary strip the URL portion of the href so we are left with the
// fragment
var i = href.indexOf( '#' );
const i = href.indexOf( '#' );
if ( i > 0 ) {
href = href.slice( i );
}

View file

@ -1,17 +1,16 @@
module.exports = function () {
var
mobile = require( 'mobile.startup' ),
SearchOverlay = mobile.search.SearchOverlay,
SearchGateway = mobile.search.SearchGateway,
overlayManager = mobile.getOverlayManager(),
// eslint-disable-next-line no-jquery/no-global-selector
$searchInput = $( '#searchInput' ),
placeholder = $searchInput.attr( 'placeholder' ),
defaultSearchPage = $searchInput.siblings( 'input[name=title]' ).val(),
// eslint-disable-next-line no-jquery/no-global-selector
$searchBar = $( '#searchInput, #searchIcon, .skin-minerva-search-trigger' ),
searchRoute = new RegExp( /\/search/ ),
searchOverlayInstance;
const mobile = require( 'mobile.startup' );
const SearchOverlay = mobile.search.SearchOverlay;
const SearchGateway = mobile.search.SearchGateway;
const overlayManager = mobile.getOverlayManager();
// eslint-disable-next-line no-jquery/no-global-selector
const $searchInput = $( '#searchInput' );
const placeholder = $searchInput.attr( 'placeholder' );
const defaultSearchPage = $searchInput.siblings( 'input[name=title]' ).val();
// eslint-disable-next-line no-jquery/no-global-selector
const $searchBar = $( '#searchInput, #searchIcon, .skin-minerva-search-trigger' );
const searchRoute = new RegExp( /\/search/ );
let searchOverlayInstance;
// Only continue on mobile devices as it breaks desktop search
// See https://phabricator.wikimedia.org/T108432

View file

@ -1,11 +1,11 @@
var SEARCH_CLASS = 'search-enabled';
const SEARCH_CLASS = 'search-enabled';
module.exports = function () {
// eslint-disable-next-line no-jquery/no-global-selector
$( '#searchIcon' ).on( 'click', function () {
// eslint-disable-next-line no-jquery/no-global-selector
var $input = $( '#searchInput' ),
$body = $( document.body );
const $input = $( '#searchInput' );
const $body = $( document.body );
// eslint-disable-next-line no-jquery/no-sizzle
if ( !$input.is( ':visible' ) ) {

View file

@ -2,15 +2,15 @@
* This setups the Minerva skin.
* It should run without errors even if MobileFrontend is not installed.
*/
var ms = require( 'mobile.startup' ),
reportIfNightModeWasDisabledOnPage = require( './reportIfNightModeWasDisabledOnPage.js' ),
addPortletLink = require( './addPortletLink.js' ),
teleportTarget = require( 'mediawiki.page.ready' ).teleportTarget;
const ms = require( 'mobile.startup' );
const reportIfNightModeWasDisabledOnPage = require( './reportIfNightModeWasDisabledOnPage.js' );
const addPortletLink = require( './addPortletLink.js' );
const teleportTarget = require( 'mediawiki.page.ready' ).teleportTarget;
function init() {
var permissions = mw.config.get( 'wgMinervaPermissions' ) || {},
// eslint-disable-next-line no-jquery/no-global-selector
$watch = $( '#page-actions-watch' );
const permissions = mw.config.get( 'wgMinervaPermissions' ) || {};
// eslint-disable-next-line no-jquery/no-global-selector
const $watch = $( '#page-actions-watch' );
if ( permissions.watch ) {
require( './watchstar.js' ).init( $watch );

View file

@ -1,11 +1,10 @@
var watchstar = require( 'mediawiki.page.watch.ajax' ).watchstar;
const watchstar = require( 'mediawiki.page.watch.ajax' ).watchstar;
( function () {
var
WATCHED_ICON_CLASS = 'minerva-icon--unStar-progressive',
TEMP_WATCHED_ICON_CLASS = 'minerva-icon--halfStar-progressive',
UNWATCHED_ICON_CLASS = 'minerva-icon--star-base20';
const WATCHED_ICON_CLASS = 'minerva-icon--unStar-progressive';
const TEMP_WATCHED_ICON_CLASS = 'minerva-icon--halfStar-progressive';
const UNWATCHED_ICON_CLASS = 'minerva-icon--star-base20';
/**
* Tweaks the global watchstar handler in core to use the correct classes for Minerva.
@ -13,7 +12,7 @@ var watchstar = require( 'mediawiki.page.watch.ajax' ).watchstar;
* @param {jQuery} $icon
*/
function init( $icon ) {
var $watchlink = $icon.find( 'a' );
const $watchlink = $icon.find( 'a' );
watchstar( $watchlink, mw.config.get( 'wgRelevantPageName' ), toggleClasses );
}
@ -23,10 +22,10 @@ var watchstar = require( 'mediawiki.page.watch.ajax' ).watchstar;
* @param {string} expiry
*/
function toggleClasses( $link, isWatched, expiry ) {
var $icon = $link.find( '.minerva-icon' );
const $icon = $link.find( '.minerva-icon' );
$icon.removeClass( [ WATCHED_ICON_CLASS, UNWATCHED_ICON_CLASS, TEMP_WATCHED_ICON_CLASS ] )
.addClass( function () {
var classes = UNWATCHED_ICON_CLASS;
let classes = UNWATCHED_ICON_CLASS;
if ( isWatched ) {
if ( expiry !== null && expiry !== undefined && expiry !== 'infinity' ) {
classes = TEMP_WATCHED_ICON_CLASS;

View file

@ -7,6 +7,6 @@
"rules": {
"no-jquery/no-parse-html-literal": "off",
"no-restricted-properties": "off",
"no-var": "off"
"no-var": "error"
}
}

View file

@ -1,30 +1,27 @@
( function () {
var AB = require( '../../../resources/skins.minerva.scripts/AB.js' ),
defaultConfig = {
testName: 'WME.MinervaABTest',
samplingRate: 0.5,
sessionId: mw.user.generateRandomSessionId()
};
const AB = require( '../../../resources/skins.minerva.scripts/AB.js' );
const defaultConfig = {
testName: 'WME.MinervaABTest',
samplingRate: 0.5,
sessionId: mw.user.generateRandomSessionId()
};
QUnit.module( 'Minerva AB-test' );
QUnit.test( 'Bucketing test', function ( assert ) {
var userBuckets = {
unsampled: 0,
control: 0,
treatment: 0
},
maxUsers = 1000,
bucketingTest,
config,
i;
const userBuckets = {
unsampled: 0,
control: 0,
treatment: 0
};
const maxUsers = 1000;
for ( i = 0; i < maxUsers; i++ ) {
config = Object.assign( {}, defaultConfig, {
for ( let i = 0; i < maxUsers; i++ ) {
const config = Object.assign( {}, defaultConfig, {
sessionId: mw.user.generateRandomSessionId()
} );
bucketingTest = new AB( config );
const bucketingTest = new AB( config );
if ( bucketingTest.isControl() ) {
++userBuckets.control;
} else if ( bucketingTest.isTreatment() ) {

View file

@ -1,6 +1,6 @@
( function () {
var TitleUtil = require( '../../../resources/skins.minerva.scripts/TitleUtil.js' );
var mwUriOrg = mw.Uri;
const TitleUtil = require( '../../../resources/skins.minerva.scripts/TitleUtil.js' );
const mwUriOrg = mw.Uri;
QUnit.module( 'Minerva TitleUtil', QUnit.newMwEnvironment( {
beforeEach: function () {
@ -76,7 +76,7 @@
empty: '',
metawiki: 'https://meta.wikimedia.org'
}, function ( assert, authority ) {
var validateReadOnlyLink = { validateReadOnlyLink: true };
const validateReadOnlyLink = { validateReadOnlyLink: true };
assert.strictEqual(
TitleUtil.newFromUri( authority + '/w/index.php?title=Title' ).getPrefixedDb(),
'Title',

View file

@ -1,6 +1,6 @@
( function () {
var UriUtil = require( '../../../resources/skins.minerva.scripts/UriUtil.js' );
var mwUriOrg = mw.Uri;
const UriUtil = require( '../../../resources/skins.minerva.scripts/UriUtil.js' );
const mwUriOrg = mw.Uri;
QUnit.module( 'Minerva UriUtil', {
beforeEach: function () {

View file

@ -1,15 +1,15 @@
( function () {
var VALID_UA = 'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Mobile Safari/537.36',
VALID_SUPPORTED_NAMESPACES = [ 0 ],
spinner = () => ( {
$el: $( '<span>' )
} ),
Deferred = $.Deferred,
windowChrome = { chrome: true },
windowNotChrome = {},
downloadAction = require( '../../../resources/skins.minerva.scripts/downloadPageAction.js' ),
onClick = downloadAction.test.onClick,
isAvailable = downloadAction.test.isAvailable;
const VALID_UA = 'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Mobile Safari/537.36';
const VALID_SUPPORTED_NAMESPACES = [ 0 ];
const spinner = () => ( {
$el: $( '<span>' )
} );
const Deferred = $.Deferred;
const windowChrome = { chrome: true };
const windowNotChrome = {};
const downloadAction = require( '../../../resources/skins.minerva.scripts/downloadPageAction.js' );
const onClick = downloadAction.test.onClick;
const isAvailable = downloadAction.test.isAvailable;
class Page {
constructor( options ) {
@ -28,7 +28,7 @@
QUnit.module( 'Minerva DownloadIcon', {
beforeEach: function () {
this.getOnClickHandler = function ( onLoadAllImages ) {
var portletLink = document.createElement( 'li' );
const portletLink = document.createElement( 'li' );
return function () {
onClick( portletLink, spinner(), onLoadAllImages );
@ -91,7 +91,7 @@
QUnit.module( 'isAvailable()', {
beforeEach: function () {
var page = new Page( {
const page = new Page( {
id: 0,
title: 'Test',
isMissing: false,
@ -118,7 +118,7 @@
} );
QUnit.test( 'isAvailable() handles missing pages', function ( assert ) {
var page = new Page( {
const page = new Page( {
id: 0,
title: 'Missing',
isMissing: true
@ -127,7 +127,7 @@
} );
QUnit.test( 'isAvailable() handles properly main page', function ( assert ) {
var page = new Page( {
const page = new Page( {
id: 0,
title: 'Test',
isMissing: false,

View file

@ -11,7 +11,7 @@
* @return {Element}
*/
function newBox( className ) {
var box = document.createElement( 'div' );
const box = document.createElement( 'div' );
box.className = className;
return box;
}
@ -58,7 +58,7 @@
} );
QUnit.test( 'parseSeverity', function ( assert ) {
var tests = [
const tests = [
[ '', 'DEFAULT', 'empty' ],
[ 'foo', 'DEFAULT', 'unknown' ],
[ 'ambox-style', 'LOW', 'style' ],
@ -72,11 +72,10 @@
// Mixed severities such as 'ambox-style ambox-content' are not prioritized.
];
tests.forEach( function ( params, i ) {
var
className = params[ 0 ],
expect = params[ 1 ],
test = params[ 2 ],
box = newBox( className );
const className = params[ 0 ];
const expect = params[ 1 ];
const test = params[ 2 ];
const box = newBox( className );
assert.strictEqual(
pageIssuesParser.test.parseSeverity( box ),
expect,
@ -86,7 +85,7 @@
} );
QUnit.test( 'parseType', function ( assert ) {
var tests = [
const tests = [
[ '', 'DEFAULT', 'issue-generic', 'empty' ],
[ 'foo', 'DEFAULT', 'issue-generic', 'unknown' ],
[ 'ambox-move', 'DEFAULT', 'issue-type-move', 'move' ],
@ -97,15 +96,14 @@
[ '', 'HIGH', 'issue-generic', 'HIGH severity' ]
];
tests.forEach( function ( params, i ) {
var
className = params[ 0 ],
severity = params[ 1 ],
expect = {
name: params[ 2 ],
severity: severity
},
test = params[ 3 ],
box = newBox( className );
const className = params[ 0 ];
const severity = params[ 1 ];
const expect = {
name: params[ 2 ],
severity: severity
};
const test = params[ 3 ];
const box = newBox( className );
assert.propEqual(
pageIssuesParser.test.parseType( box, severity ),
expect,
@ -115,20 +113,18 @@
} );
QUnit.test( 'parseGroup', function ( assert ) {
var tests = [
const tests = [
[ undefined, false, 'orphaned' ],
[ '', false, 'ungrouped' ],
[ 'mw-collapsible-content', true, 'grouped' ]
];
tests.forEach( function ( params, i ) {
var
parentClassName = params[ 0 ],
expect = params[ 1 ],
test = params[ 2 ],
parent,
box = newBox( '' );
const parentClassName = params[ 0 ];
const expect = params[ 1 ];
const test = params[ 2 ];
const box = newBox( '' );
if ( parentClassName !== undefined ) {
parent = document.createElement( 'div' );
const parent = document.createElement( 'div' );
parent.className = parentClassName;
parent.appendChild( box );
}
@ -141,7 +137,7 @@
} );
QUnit.test( 'iconName', function ( assert ) {
var tests = [
const tests = [
[ '', 'DEFAULT', 'issue-generic-defaultColor' ],
[ '', 'LOW', 'issue-severity-low-lowColor' ],
[ '', 'MEDIUM', 'issue-severity-medium-mediumColor' ],
@ -154,11 +150,10 @@
[ 'ambox-content ambox-move', 'MEDIUM', 'issue-type-move-defaultColor' ]
];
tests.forEach( function ( params, i ) {
var
className = params[ 0 ],
severity = params[ 1 ],
expect = params[ 2 ],
box = newBox( className );
const className = params[ 0 ];
const severity = params[ 1 ];
const expect = params[ 2 ];
const box = newBox( className );
assert.strictEqual(
pageIssuesParser.iconName( box, severity ),
expect,
@ -168,7 +163,7 @@
} );
QUnit.test( 'maxSeverity', function ( assert ) {
var tests = [
const tests = [
[ [], 'DEFAULT' ],
[ [ 'DEFAULT' ], 'DEFAULT' ],
[ [ 'DEFAULT', 'LOW' ], 'LOW' ],
@ -178,8 +173,8 @@
[ [ 'DEFAULT', 'HIGH', 'LOW', 'MEDIUM' ], 'HIGH' ]
];
tests.forEach( function ( params, i ) {
var severities = params[ 0 ],
expect = params[ 1 ];
const severities = params[ 0 ];
const expect = params[ 1 ];
assert.strictEqual(
pageIssuesParser.maxSeverity( severities ),

View file

@ -1,10 +1,10 @@
/* eslint-disable no-jquery/no-class-state */
( function () {
var watchstar = require( '../../../resources/skins.minerva.scripts/watchstar.js' ),
toggleClasses = watchstar.test.toggleClasses,
WATCHED_CLASS = watchstar.test.WATCHED_ICON_CLASS,
TEMP_WATCHED_CLASS = watchstar.test.TEMP_WATCHED_ICON_CLASS,
UNWATCHED_CLASS = watchstar.test.UNWATCHED_ICON_CLASS;
const watchstar = require( '../../../resources/skins.minerva.scripts/watchstar.js' );
const toggleClasses = watchstar.test.toggleClasses;
const WATCHED_CLASS = watchstar.test.WATCHED_ICON_CLASS;
const TEMP_WATCHED_CLASS = watchstar.test.TEMP_WATCHED_ICON_CLASS;
const UNWATCHED_CLASS = watchstar.test.UNWATCHED_ICON_CLASS;
QUnit.module( 'Minerva Watchstar' );
@ -14,25 +14,25 @@
}
QUnit.test( 'toggleClasses() from watched to unwatched', function ( assert ) {
var $elem = createElemWithClass( WATCHED_CLASS );
const $elem = createElemWithClass( WATCHED_CLASS );
toggleClasses( $elem, false );
assert.true( $elem.find( '.minerva-icon' ).hasClass( UNWATCHED_CLASS ) );
} );
QUnit.test( 'toggleClasses() from unwatched to watched', function ( assert ) {
var $elem = createElemWithClass( UNWATCHED_CLASS );
const $elem = createElemWithClass( UNWATCHED_CLASS );
toggleClasses( $elem, true, null );
assert.true( $elem.find( '.minerva-icon' ).hasClass( WATCHED_CLASS ) );
} );
QUnit.test( 'toggleClasses() from unwatched to temp watched', function ( assert ) {
var $elem = createElemWithClass( UNWATCHED_CLASS );
const $elem = createElemWithClass( UNWATCHED_CLASS );
toggleClasses( $elem, true, 'expiry' );
assert.true( $elem.find( '.minerva-icon' ).hasClass( TEMP_WATCHED_CLASS ) );
} );
QUnit.test( 'toggleClasses() from temp watched to watched', function ( assert ) {
var $elem = createElemWithClass( TEMP_WATCHED_CLASS );
const $elem = createElemWithClass( TEMP_WATCHED_CLASS );
toggleClasses( $elem, true, null );
assert.true( $elem.find( '.minerva-icon' ).hasClass( WATCHED_CLASS ) );
} );