Commit 23cdae8e authored by gfyoung's avatar gfyoung

Enable "prefer-destructuring" in JS files

Partially addresses #47006.
parent d38eb9bb
......@@ -69,5 +69,3 @@ rules:
FunctionExpression:
parameters: 1
body: 1
## Destructuring: https://eslint.org/docs/rules/prefer-destructuring
prefer-destructuring: off
......@@ -26,7 +26,7 @@ export default class AjaxLoadingSpinner {
}
static toggleLoadingIcon(iconElement) {
const classList = iconElement.classList;
const { classList } = iconElement;
classList.toggle(iconElement.dataset.icon);
classList.toggle('fa-spinner');
classList.toggle('fa-spin');
......
......@@ -52,7 +52,7 @@ export default function initCopyToClipboard() {
* data types to the intended values.
*/
$(document).on('copy', 'body > textarea[readonly]', (e) => {
const clipboardData = e.originalEvent.clipboardData;
const { clipboardData } = e.originalEvent;
if (!clipboardData) return;
const text = e.target.value;
......
......@@ -321,7 +321,7 @@ export class CopyAsGFM {
}
static copyAsGFM(e, transformer) {
const clipboardData = e.originalEvent.clipboardData;
const { clipboardData } = e.originalEvent;
if (!clipboardData) return;
const documentFragment = getSelectedFragment();
......@@ -338,7 +338,7 @@ export class CopyAsGFM {
}
static pasteGFM(e) {
const clipboardData = e.originalEvent.clipboardData;
const { clipboardData } = e.originalEvent;
if (!clipboardData) return;
const text = clipboardData.getData('text/plain');
......
......@@ -84,7 +84,7 @@ class BalsamiqViewer {
renderTemplate(preview) {
const resource = this.getResource(preview.resourceID);
const name = BalsamiqViewer.parseTitle(resource);
const image = preview.image;
const { image } = preview;
const template = PREVIEW_TEMPLATE({
name,
......
......@@ -12,7 +12,7 @@ export default function loadBalsamiqFile() {
if (!(viewer instanceof Element)) return;
const endpoint = viewer.dataset.endpoint;
const { endpoint } = viewer.dataset;
const balsamiqViewer = new BalsamiqViewer(viewer);
balsamiqViewer.loadFile(endpoint).catch(onError);
......
......@@ -5,7 +5,7 @@ export default () => {
[].slice.call(document.querySelectorAll('.js-material-changer')).forEach((el) => {
el.addEventListener('click', (e) => {
const target = e.target;
const { target } = e;
e.preventDefault();
......
......@@ -23,7 +23,7 @@
},
methods: {
removeIssue() {
const issue = this.issue;
const { issue } = this;
const lists = issue.getLists();
const listLabelIds = lists.map(list => list.label.id);
......
......@@ -121,7 +121,7 @@ export default () => {
this.filterManager.updateTokens();
},
updateDetailIssue(newIssue) {
const sidebarInfoEndpoint = newIssue.sidebarInfoEndpoint;
const { sidebarInfoEndpoint } = newIssue;
if (sidebarInfoEndpoint && newIssue.subscribed === undefined) {
newIssue.setFetchingState('subscriptions', true);
BoardService.getIssueInfo(sidebarInfoEndpoint)
......@@ -144,7 +144,7 @@ export default () => {
Store.detail.issue = {};
},
toggleSubscription(id) {
const issue = Store.detail.issue;
const { issue } = Store.detail;
if (issue.id === id && issue.toggleSubscriptionEndpoint) {
issue.setFetchingState('subscriptions', true);
BoardService.toggleIssueSubscription(issue.toggleSubscriptionEndpoint)
......
......@@ -26,7 +26,7 @@ class ModalStore {
toggleIssue(issueObj) {
const issue = issueObj;
const selected = issue.selected;
const { selected } = issue;
issue.selected = !selected;
......
......@@ -81,7 +81,7 @@ export default class Clusters {
}
initApplications() {
const store = this.store;
const { store } = this;
const el = document.querySelector('#js-cluster-applications');
this.applications = new Vue({
......
......@@ -122,7 +122,7 @@ export default class ImageFile {
return $('.swipe.view', this.file).each((function(_this) {
return function(index, view) {
var $swipeWrap, $swipeBar, $swipeFrame, wrapPadding, ref;
ref = _this.prepareFrames(view), maxWidth = ref[0], maxHeight = ref[1];
ref = _this.prepareFrames(view), [maxWidth, maxHeight] = ref;
$swipeFrame = $('.swipe-frame', view);
$swipeWrap = $('.swipe-wrap', view);
$swipeBar = $('.swipe-bar', view);
......@@ -159,7 +159,7 @@ export default class ImageFile {
return $('.onion-skin.view', this.file).each((function(_this) {
return function(index, view) {
var $frame, $track, $dragger, $frameAdded, framePadding, ref, dragging = false;
ref = _this.prepareFrames(view), maxWidth = ref[0], maxHeight = ref[1];
ref = _this.prepareFrames(view), [maxWidth, maxHeight] = ref;
$frame = $('.onion-skin-frame', view);
$frameAdded = $('.frame.added', view);
$track = $('.drag-track', view);
......
......@@ -281,7 +281,7 @@ export default class CreateMergeRequestDropdown {
if (event.target === this.branchInput) {
target = 'branch';
value = this.branchInput.value;
({ value } = this.branchInput);
} else if (event.target === this.refInput) {
target = 'ref';
value =
......
......@@ -111,7 +111,7 @@ const DiffNoteAvatars = Vue.extend({
});
},
addNoCommentClass() {
const notesCount = this.notesCount;
const { notesCount } = this;
$(this.$el).closest('.js-avatar-container')
.toggleClass('no-comment-btn', notesCount > 0)
......
......@@ -73,7 +73,7 @@ const JumpToDiscussion = Vue.extend({
}).toArray();
};
const discussions = this.discussions;
const { discussions } = this;
if (activeTab === 'diffs') {
discussionsSelector = '.diffs .notes[data-discussion-id]';
......
......@@ -18,7 +18,7 @@ import './components/new_issue_for_discussion';
export default () => {
const projectPathHolder =
document.querySelector('.merge-request') || document.querySelector('.commit-box');
const projectPath = projectPathHolder.dataset.projectPath;
const { projectPath } = projectPathHolder.dataset;
const COMPONENT_SELECTOR =
'resolve-btn, resolve-discussion-btn, jump-to-discussion, comment-and-resolve-btn, new-issue-for-discussion-btn';
......
......@@ -47,7 +47,7 @@ export default {
methods: {
...mapActions(['toggleDiscussion']),
getTooltipText(noteData) {
let note = noteData.note;
let { note } = noteData;
if (note.length > LENGTH_OF_AVATAR_TOOLTIP) {
note = truncate(note, LENGTH_OF_AVATAR_TOOLTIP);
......
......@@ -124,7 +124,7 @@ export default {
const newLineNumber = this.metaData.newPos || 0;
const offset = newLineNumber - oldLineNumber;
const bottom = this.isBottom;
const fileHash = this.fileHash;
const { fileHash } = this;
const view = this.diffViewType;
let unfold = true;
let lineNumber = newLineNumber - 1;
......
......@@ -89,7 +89,7 @@ export default {
return isLeftExpanded || isRightExpanded;
},
getLineCode(line, side) {
const lineCode = side.lineCode;
const { lineCode } = side;
if (lineCode) {
return lineCode;
}
......
......@@ -292,7 +292,7 @@
if (this.model &&
this.model.last_deployment &&
this.model.last_deployment.deployable) {
const deployable = this.model.last_deployment.deployable;
const { deployable } = this.model.last_deployment;
return `${deployable.name} #${deployable.id}`;
}
return '';
......
......@@ -146,7 +146,7 @@ export default class EnvironmentsStore {
* @return {Array}
*/
updateEnvironmentProp(environment, prop, newValue) {
const environments = this.state.environments;
const { environments } = this.state;
const updatedEnvironments = environments.map((env) => {
const updateEnv = Object.assign({}, env);
......@@ -161,7 +161,7 @@ export default class EnvironmentsStore {
}
getOpenFolders() {
const environments = this.state.environments;
const { environments } = this.state;
return environments.filter(env => env.isFolder && env.isOpen);
}
......
......@@ -35,7 +35,7 @@ export default class DropdownUtils {
// Remove the symbol for filter
if (value[0] === filterSymbol) {
symbol = value[0];
[symbol] = value;
value = value.slice(1);
}
......@@ -162,7 +162,7 @@ export default class DropdownUtils {
// Determines the full search query (visual tokens + input)
static getSearchQuery(untilInput = false) {
const container = FilteredSearchContainer.container;
const { container } = FilteredSearchContainer;
const tokens = [].slice.call(container.querySelectorAll('.tokens-container li'));
const values = [];
......@@ -220,7 +220,7 @@ export default class DropdownUtils {
}
static getInputSelectionPosition(input) {
const selectionStart = input.selectionStart;
const { selectionStart } = input;
let inputValue = input.value;
// Replace all spaces inside quote marks with underscores
// (will continue to match entire string until an end quote is found if any)
......
......@@ -159,7 +159,7 @@ export default class FilteredSearchDropdownManager {
load(key, firstLoad = false) {
const mappingKey = this.mapping[key];
const glClass = mappingKey.gl;
const element = mappingKey.element;
const { element } = mappingKey;
let forceShowList = false;
if (!mappingKey.reference) {
......
......@@ -235,7 +235,7 @@ export default class FilteredSearchManager {
checkForEnter(e) {
if (e.keyCode === 38 || e.keyCode === 40) {
const selectionStart = this.filteredSearchInput.selectionStart;
const { selectionStart } = this.filteredSearchInput;
e.preventDefault();
this.filteredSearchInput.setSelectionRange(selectionStart, selectionStart);
......@@ -496,7 +496,7 @@ export default class FilteredSearchManager {
// Replace underscore with hyphen in the sanitizedkey.
// e.g. 'my_reaction' => 'my-reaction'
sanitizedKey = sanitizedKey.replace('_', '-');
const symbol = match.symbol;
const { symbol } = match;
let quotationsToUse = '';
if (sanitizedValue.indexOf(' ') !== -1) {
......
......@@ -101,7 +101,7 @@ export default class FilteredSearchVisualTokens {
static updateLabelTokenColor(tokenValueContainer, tokenValue) {
const filteredSearchInput = FilteredSearchContainer.container.querySelector('.filtered-search');
const baseEndpoint = filteredSearchInput.dataset.baseEndpoint;
const { baseEndpoint } = filteredSearchInput.dataset;
const labelsEndpoint = FilteredSearchVisualTokens.getEndpointWithQueryParams(
`${baseEndpoint}/labels.json`,
filteredSearchInput.dataset.endpointQueryParams,
......@@ -215,7 +215,7 @@ export default class FilteredSearchVisualTokens {
static addFilterVisualToken(tokenName, tokenValue, canEdit) {
const { lastVisualToken, isLastVisualTokenValid }
= FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
const addVisualTokenElement = FilteredSearchVisualTokens.addVisualTokenElement;
const { addVisualTokenElement } = FilteredSearchVisualTokens;
if (isLastVisualTokenValid) {
addVisualTokenElement(tokenName, tokenValue, false, canEdit);
......
......@@ -29,7 +29,7 @@ class RecentSearchesRoot {
}
render() {
const state = this.store.state;
const { state } = this.store;
this.vm = new Vue({
el: this.wrapperElement,
components: {
......
......@@ -80,7 +80,7 @@ class GfmAutoComplete {
let tpl = '/${name} ';
let referencePrefix = null;
if (value.params.length > 0) {
referencePrefix = value.params[0][0];
[[referencePrefix]] = value.params;
if (/^[@%~]/.test(referencePrefix)) {
tpl += '<%- referencePrefix %>';
}
......@@ -458,7 +458,7 @@ class GfmAutoComplete {
static isLoading(data) {
let dataToInspect = data;
if (data && data.length > 0) {
dataToInspect = data[0];
[dataToInspect] = data;
}
const loadingState = GfmAutoComplete.defaultLoadingData[0];
......
......@@ -613,7 +613,7 @@ GitLabDropdown = (function() {
};
GitLabDropdown.prototype.renderItem = function(data, group, index) {
var field, fieldName, html, selected, text, url, value, rowHidden;
var field, html, selected, text, url, value, rowHidden;
if (!this.options.renderRow) {
value = this.options.id ? this.options.id(data) : data.id;
......@@ -651,7 +651,7 @@ GitLabDropdown = (function() {
html = this.options.renderRow.call(this.options, data, this);
} else {
if (!selected) {
fieldName = this.options.fieldName;
const { fieldName } = this.options;
if (value) {
field = this.dropdown.parent().find(`input[name='${fieldName}'][value='${value}']`);
......@@ -705,7 +705,8 @@ GitLabDropdown = (function() {
GitLabDropdown.prototype.highlightTextMatches = function(text, term) {
const occurrences = fuzzaldrinPlus.match(text, term);
const indexOf = [].indexOf;
const { indexOf } = [];
return text.split('').map(function(character, i) {
if (indexOf.call(occurrences, i) !== -1) {
return "<b>" + character + "</b>";
......@@ -721,9 +722,9 @@ GitLabDropdown = (function() {
};
GitLabDropdown.prototype.rowClicked = function(el) {
var field, fieldName, groupName, isInput, selectedIndex, selectedObject, value, isMarking;
var field, groupName, isInput, selectedIndex, selectedObject, value, isMarking;
fieldName = this.options.fieldName;
const { fieldName } = this.options;
isInput = $(this.el).is('input');
if (this.renderedData) {
groupName = el.data('group');
......
......@@ -29,7 +29,7 @@ export default () => {
groupsApp,
},
data() {
const dataset = this.$options.el.dataset;
const { dataset } = this.$options.el;
const hideProjects = dataset.hideProjects === 'true';
const store = new GroupsStore(hideProjects);
const service = new GroupsService(dataset.endpoint);
......@@ -42,7 +42,7 @@ export default () => {
};
},
beforeMount() {
const dataset = this.$options.el.dataset;
const { dataset } = this.$options.el;
let groupFilterList = null;
const form = document.querySelector(dataset.formSel);
const filter = document.querySelector(dataset.filterSel);
......
......@@ -30,7 +30,7 @@ export default {
},
computed: {
pathWithEllipsis() {
const path = this.file.path;
const { path } = this.file;
return path.length < MAX_PATH_LENGTH
? path
......
......@@ -23,6 +23,7 @@
let { result } = target;
if (!isText) {
// eslint-disable-next-line prefer-destructuring
result = result.split('base64,')[1];
}
......
......@@ -2,7 +2,7 @@ import { computeDiff } from './diff';
// eslint-disable-next-line no-restricted-globals
self.addEventListener('message', (e) => {
const data = e.data;
const { data } = e;
// eslint-disable-next-line no-restricted-globals
self.postMessage({
......
......@@ -8,7 +8,7 @@ import { setPageTitle } from '../utils';
import { viewerTypes } from '../../constants';
export const closeFile = ({ commit, state, dispatch }, file) => {
const path = file.path;
const { path } = file;
const indexOfClosedFile = state.openFiles.findIndex(f => f.key === file.key);
const fileWasActive = file.active;
......
......@@ -2,7 +2,8 @@ export function setPositionDataAttribute(el, options) {
// Update position data attribute so that the
// new comment form can use this data for ajax request
const { x, y, width, height } = options;
const position = el.dataset.position;
const { position } = el.dataset;
const positionObject = Object.assign({}, JSON.parse(position), {
x,
y,
......
......@@ -40,8 +40,7 @@ export function getTargetSelection(event) {
const x = event.offsetX;
const y = event.offsetY;
const width = imageEl.width;
const height = imageEl.height;
const { width, height } = imageEl;
const actualWidth = imageEl.naturalWidth;
const actualHeight = imageEl.naturalHeight;
......
......@@ -10,7 +10,7 @@ class AutoWidthDropdownSelect {
}
init() {
const dropdownClass = this.dropdownClass;
const { dropdownClass } = this;
this.$selectElement.select2({
dropdownCssClass: dropdownClass,
...AutoWidthDropdownSelect.selectOptions(this.dropdownClass),
......
......@@ -4,7 +4,7 @@ import jobHeader from './components/header.vue';
import detailsBlock from './components/sidebar_details_block.vue';
export default () => {
const dataset = document.getElementById('js-job-details-vue').dataset;
const { dataset } = document.getElementById('js-job-details-vue');
const mediator = new JobMediator({ endpoint: dataset.endpoint });
mediator.fetchJob();
......
......@@ -56,7 +56,7 @@ export default class LabelsSelect {
.map(function () {
return this.value;
}).get();
const handleClick = options.handleClick;
const { handleClick } = options;
$sidebarLabelTooltip.tooltip();
......@@ -215,7 +215,7 @@ export default class LabelsSelect {
}
else {
if (label.color != null) {
color = label.color[0];
[color] = label.color;
}
}
if (color) {
......@@ -243,7 +243,8 @@ export default class LabelsSelect {
var $dropdownParent = $dropdown.parent();
var $dropdownInputField = $dropdownParent.find('.dropdown-input-field');
var isSelected = el !== null ? el.hasClass('is-active') : false;
var title = selected.title;
var { title } = selected;
var selectedLabels = this.selected;
if ($dropdownInputField.length && $dropdownInputField.val().length) {
......@@ -382,7 +383,7 @@ export default class LabelsSelect {
}));
}
else {
var labels = gl.issueBoards.BoardsStore.detail.issue.labels;
var { labels } = gl.issueBoards.BoardsStore.detail.issue;
labels = labels.filter(function (selectedLabel) {
return selectedLabel.id !== label.id;
});
......
......@@ -164,7 +164,7 @@ export const scrollToElement = element => {
if (!(element instanceof $)) {
$el = $(element);
}
const top = $el.offset().top;
const { top } = $el.offset();
return $('body, html').animate(
{
......@@ -203,9 +203,7 @@ export const getSelectedFragment = () => {
export const insertText = (target, text) => {
// Firefox doesn't support `document.execCommand('insertText', false, text)` on textareas
const selectionStart = target.selectionStart;
const selectionEnd = target.selectionEnd;
const value = target.value;
const { selectionStart, selectionEnd, value } = target;
const textBefore = value.substring(0, selectionStart);
const textAfter = value.substring(selectionEnd, value.length);
......@@ -245,7 +243,8 @@ export const nodeMatchesSelector = (node, selector) => {
// IE11 doesn't support `node.matches(selector)`
let parentNode = node.parentNode;
let { parentNode } = node;
if (!parentNode) {
parentNode = document.createElement('div');
// eslint-disable-next-line no-param-reassign
......@@ -281,6 +280,8 @@ export const normalizeCRLFHeaders = headers => {
headersArray.forEach(header => {
const keyValue = header.split(': ');
// eslint-disable-next-line prefer-destructuring
headersObject[keyValue[0]] = keyValue[1];
});
......
......@@ -13,7 +13,7 @@ export function formatRelevantDigits(number) {
let relevantDigits = 0;
let formattedNumber = '';
if (!Number.isNaN(Number(number))) {
digitsLeft = number.toString().split('.')[0];
[digitsLeft] = number.toString().split('.');
switch (digitsLeft.length) {
case 1:
relevantDigits = 3;
......
......@@ -156,7 +156,7 @@ import Cookies from 'js-cookie';
return 0;
}
const files = this.state.conflictsData.files;
const { files } = this.state.conflictsData;
let count = 0;
files.forEach((file) => {
......@@ -313,7 +313,7 @@ import Cookies from 'js-cookie';
},
isReadyToCommit() {
const files = this.state.conflictsData.files;
const { files } = this.state.conflictsData;
const hasCommitMessage = $.trim(this.state.conflictsData.commitMessage).length;
let unresolved = 0;
......
......@@ -12,7 +12,7 @@ import syntaxHighlight from '../syntax_highlight';
export default function initMergeConflicts() {
const INTERACTIVE_RESOLVE_MODE = 'interactive';
const conflictsEl = document.querySelector('#conflicts');
const mergeConflictsStore = gl.mergeConflicts.mergeConflictsStore;
const { mergeConflictsStore } = gl.mergeConflicts;
const mergeConflictsService = new MergeConflictsService({
conflictsPath: conflictsEl.dataset.conflictsPath,
resolveConflictsPath: conflictsEl.dataset.resolveConflictsPath,
......
......@@ -64,7 +64,7 @@ import Notes from './notes';
/* eslint-enable max-len */
// Store the `location` object, allowing for easier stubbing in tests
let location = window.location;
let { location } = window;
export default class MergeRequestTabs {
constructor({ action, setUrl, stubLocation } = {}) {
......@@ -279,7 +279,7 @@ export default class MergeRequestTabs {
mountPipelinesView() {
const pipelineTableViewEl = document.querySelector('#commit-pipeline-table-view');
const CommitPipelinesTable = gl.CommitPipelinesTable;
const { CommitPipelinesTable } = gl;
this.commitPipelinesTable = new CommitPipelinesTable({
propsData: {
endpoint: pipelineTableViewEl.dataset.endpoint,
......
......@@ -41,10 +41,10 @@ function queryTimeSeries(query, graphWidth, graphHeight, graphHeightOffset, xDom
} else {
const unusedColors = _.difference(defaultColorOrder, usedColors);
if (unusedColors.length > 0) {
pick = unusedColors[0];
[pick] = unusedColors;
} else {
usedColors = [];
pick = defaultColorOrder[0];
[pick] = defaultColorOrder;
}
}
usedColors.push(pick);
......
......@@ -101,8 +101,8 @@ export default (function() {
};
BranchGraph.prototype.buildGraph = function() {
var cuday, cumonth, day, j, len, mm, r, ref;
r = this.r;
var cuday, cumonth, day, j, len, mm, ref;
const { r } = this;
cuday = 0;
cumonth = "";
r.rect(0, 0, 40, this.barHeight).attr({
......@@ -121,7 +121,7 @@ export default (function() {
font: "12px Monaco, monospace",
fill: "#BBB"
});
cuday = day[0];
[cuday] = day;
}