lint: Fix some straightforward ESLint errors

This commit is contained in:
Richard Hansen 2020-12-13 18:34:11 -05:00 committed by John McLear
parent e66e8a4eb2
commit ca01856f94
3 changed files with 139 additions and 113 deletions

View file

@ -20,13 +20,15 @@
* limitations under the License. * limitations under the License.
*/ */
'use strict';
const Security = require('./security'); const Security = require('./security');
/** /**
* Generates a random String with the given length. Is needed to generate the Author, Group, readonly, session Ids * Generates a random String with the given length. Is needed to generate the Author, Group,
* readonly, session Ids
*/ */
const randomString = (len) => {
function randomString(len) {
const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
let randomstring = ''; let randomstring = '';
len = len || 20; len = len || 20;
@ -35,41 +37,69 @@ function randomString(len) {
randomstring += chars.substring(rnum, rnum + 1); randomstring += chars.substring(rnum, rnum + 1);
} }
return randomstring; return randomstring;
} };
var padutils = { const padutils = {
escapeHtml(x) { escapeHtml: (x) => Security.escapeHTML(String(x)),
return Security.escapeHTML(String(x)); uniqueId: () => {
},
uniqueId() {
const pad = require('./pad').pad; // Sidestep circular dependency const pad = require('./pad').pad; // Sidestep circular dependency
function encodeNum(n, width) { // returns string that is exactly 'width' chars, padding with zeros and taking rightmost digits
// returns string that is exactly 'width' chars, padding with zeros const encodeNum =
// and taking rightmost digits (n, width) => (Array(width + 1).join('0') + Number(n).toString(35)).slice(-width);
return (Array(width + 1).join('0') + Number(n).toString(35)).slice(-width); return [
} pad.getClientIp(),
return [pad.getClientIp(), encodeNum(+new Date(), 7), encodeNum(Math.floor(Math.random() * 1e9), 4)].join('.'); encodeNum(+new Date(), 7),
encodeNum(Math.floor(Math.random() * 1e9), 4),
].join('.');
}, },
// e.g. "Thu Jun 18 2009 13:09" // e.g. "Thu Jun 18 2009 13:09"
simpleDateTime(date) { simpleDateTime: (date) => {
const d = new Date(+date); // accept either number or date const d = new Date(+date); // accept either number or date
const dayOfWeek = (['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'])[d.getDay()]; const dayOfWeek = (['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'])[d.getDay()];
const month = (['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'])[d.getMonth()]; const month = ([
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec',
])[d.getMonth()];
const dayOfMonth = d.getDate(); const dayOfMonth = d.getDate();
const year = d.getFullYear(); const year = d.getFullYear();
const hourmin = `${d.getHours()}:${(`0${d.getMinutes()}`).slice(-2)}`; const hourmin = `${d.getHours()}:${(`0${d.getMinutes()}`).slice(-2)}`;
return `${dayOfWeek} ${month} ${dayOfMonth} ${year} ${hourmin}`; return `${dayOfWeek} ${month} ${dayOfMonth} ${year} ${hourmin}`;
}, },
findURLs(text) { findURLs: (text) => {
// copied from ACE // copied from ACE
const _REGEX_WORDCHAR = /[\u0030-\u0039\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u1FFF\u3040-\u9FFF\uF900-\uFDFF\uFE70-\uFEFE\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFDC]/; const _REGEX_WORDCHAR = new RegExp(`[${[
const _REGEX_URLCHAR = new RegExp(`(${/[-:@a-zA-Z0-9_.,~%+\/?=&#;()$]/.source}|${_REGEX_WORDCHAR.source})`); '\u0030-\u0039',
const _REGEX_URL = new RegExp(`${/(?:(?:https?|s?ftp|ftps|file|nfs):\/\/|(about|geo|mailto|tel):)/.source + _REGEX_URLCHAR.source}*(?![:.,;])${_REGEX_URLCHAR.source}`, 'g'); '\u0041-\u005A',
'\u0061-\u007A',
'\u00C0-\u00D6',
'\u00D8-\u00F6',
'\u00F8-\u00FF',
'\u0100-\u1FFF',
'\u3040-\u9FFF',
'\uF900-\uFDFF',
'\uFE70-\uFEFE',
'\uFF10-\uFF19',
'\uFF21-\uFF3A',
'\uFF41-\uFF5A',
'\uFF66-\uFFDC',
].join('')}]`);
const _REGEX_URLCHAR = new RegExp(`([-:@a-zA-Z0-9_.,~%+/?=&#;()$]|${_REGEX_WORDCHAR.source})`);
const _REGEX_URL = new RegExp(
'(?:(?:https?|s?ftp|ftps|file|nfs)://|(about|geo|mailto|tel):)' +
`${_REGEX_URLCHAR.source}*(?![:.,;])${_REGEX_URLCHAR.source}`, 'g');
// returns null if no URLs, or [[startIndex1, url1], [startIndex2, url2], ...] // returns null if no URLs, or [[startIndex1, url1], [startIndex2, url2], ...]
const _findURLs = (text) => {
function _findURLs(text) {
_REGEX_URL.lastIndex = 0; _REGEX_URL.lastIndex = 0;
let urls = null; let urls = null;
let execResult; let execResult;
@ -81,34 +111,39 @@ var padutils = {
} }
return urls; return urls;
} };
return _findURLs(text); return _findURLs(text);
}, },
escapeHtmlWithClickableLinks(text, target) { escapeHtmlWithClickableLinks: (text, target) => {
let idx = 0; let idx = 0;
const pieces = []; const pieces = [];
const urls = padutils.findURLs(text); const urls = padutils.findURLs(text);
function advanceTo(i) { const advanceTo = (i) => {
if (i > idx) { if (i > idx) {
pieces.push(Security.escapeHTML(text.substring(idx, i))); pieces.push(Security.escapeHTML(text.substring(idx, i)));
idx = i; idx = i;
} }
} };
if (urls) { if (urls) {
for (let j = 0; j < urls.length; j++) { for (let j = 0; j < urls.length; j++) {
const startIndex = urls[j][0]; const startIndex = urls[j][0];
const href = urls[j][1]; const href = urls[j][1];
advanceTo(startIndex); advanceTo(startIndex);
// Using rel="noreferrer" stops leaking the URL/location of the pad when clicking links in the document. // Using rel="noreferrer" stops leaking the URL/location of the pad when clicking links in
// Not all browsers understand this attribute, but it's part of the HTML5 standard. // the document. Not all browsers understand this attribute, but it's part of the HTML5
// https://html.spec.whatwg.org/multipage/links.html#link-type-noreferrer // standard. https://html.spec.whatwg.org/multipage/links.html#link-type-noreferrer
// Additionally, we do rel="noopener" to ensure a higher level of referrer security. // Additionally, we do rel="noopener" to ensure a higher level of referrer security.
// https://html.spec.whatwg.org/multipage/links.html#link-type-noopener // https://html.spec.whatwg.org/multipage/links.html#link-type-noopener
// https://mathiasbynens.github.io/rel-noopener/ // https://mathiasbynens.github.io/rel-noopener/
// https://github.com/ether/etherpad-lite/pull/3636 // https://github.com/ether/etherpad-lite/pull/3636
pieces.push('<a ', (target ? `target="${Security.escapeHTMLAttribute(target)}" ` : ''), 'href="', Security.escapeHTMLAttribute(href), '" rel="noreferrer noopener">'); pieces.push(
'<a ',
(target ? `target="${Security.escapeHTMLAttribute(target)}" ` : ''),
'href="',
Security.escapeHTMLAttribute(href),
'" rel="noreferrer noopener">');
advanceTo(startIndex + href.length); advanceTo(startIndex + href.length);
pieces.push('</a>'); pieces.push('</a>');
} }
@ -116,14 +151,14 @@ var padutils = {
advanceTo(text.length); advanceTo(text.length);
return pieces.join(''); return pieces.join('');
}, },
bindEnterAndEscape(node, onEnter, onEscape) { bindEnterAndEscape: (node, onEnter, onEscape) => {
// Use keypress instead of keyup in bindEnterAndEscape // Use keypress instead of keyup in bindEnterAndEscape. Keyup event is fired on enter in IME
// Keyup event is fired on enter in IME (Input Method Editor), But // (Input Method Editor), But keypress is not. So, I changed to use keypress instead of keyup.
// keypress is not. So, I changed to use keypress instead of keyup. // It is work on Windows (IE8, Chrome 6.0.472), CentOs (Firefox 3.0) and Mac OSX (Firefox
// It is work on Windows (IE8, Chrome 6.0.472), CentOs (Firefox 3.0) and Mac OSX (Firefox 3.6.10, Chrome 6.0.472, Safari 5.0). // 3.6.10, Chrome 6.0.472, Safari 5.0).
if (onEnter) { if (onEnter) {
node.keypress((evt) => { node.keypress((evt) => {
if (evt.which == 13) { if (evt.which === 13) {
onEnter(evt); onEnter(evt);
} }
}); });
@ -131,18 +166,18 @@ var padutils = {
if (onEscape) { if (onEscape) {
node.keydown((evt) => { node.keydown((evt) => {
if (evt.which == 27) { if (evt.which === 27) {
onEscape(evt); onEscape(evt);
} }
}); });
} }
}, },
timediff(d) { timediff: (d) => {
const pad = require('./pad').pad; // Sidestep circular dependency const pad = require('./pad').pad; // Sidestep circular dependency
function format(n, word) { const format = (n, word) => {
n = Math.round(n); n = Math.round(n);
return (`${n} ${word}${n != 1 ? 's' : ''} ago`); return (`${n} ${word}${n !== 1 ? 's' : ''} ago`);
} };
d = Math.max(0, (+(new Date()) - (+d) - pad.clientTimeOffset) / 1000); d = Math.max(0, (+(new Date()) - (+d) - pad.clientTimeOffset) / 1000);
if (d < 60) { if (d < 60) {
return format(d, 'second'); return format(d, 'second');
@ -158,14 +193,14 @@ var padutils = {
d /= 24; d /= 24;
return format(d, 'day'); return format(d, 'day');
}, },
makeAnimationScheduler(funcToAnimateOneStep, stepTime, stepsAtOnce) { makeAnimationScheduler: (funcToAnimateOneStep, stepTime, stepsAtOnce) => {
if (stepsAtOnce === undefined) { if (stepsAtOnce === undefined) {
stepsAtOnce = 1; stepsAtOnce = 1;
} }
let animationTimer = null; let animationTimer = null;
function scheduleAnimation() { const scheduleAnimation = () => {
if (!animationTimer) { if (!animationTimer) {
animationTimer = window.setTimeout(() => { animationTimer = window.setTimeout(() => {
animationTimer = null; animationTimer = null;
@ -181,43 +216,16 @@ var padutils = {
} }
}, stepTime * stepsAtOnce); }, stepTime * stepsAtOnce);
} }
}
return {
scheduleAnimation,
}; };
return {scheduleAnimation};
}, },
makeShowHideAnimator(funcToArriveAtState, initiallyShown, fps, totalMs) { makeShowHideAnimator: (funcToArriveAtState, initiallyShown, fps, totalMs) => {
let animationState = (initiallyShown ? 0 : -2); // -2 hidden, -1 to 0 fade in, 0 to 1 fade out let animationState = (initiallyShown ? 0 : -2); // -2 hidden, -1 to 0 fade in, 0 to 1 fade out
const animationFrameDelay = 1000 / fps; const animationFrameDelay = 1000 / fps;
const animationStep = animationFrameDelay / totalMs; const animationStep = animationFrameDelay / totalMs;
const scheduleAnimation = padutils.makeAnimationScheduler(animateOneStep, animationFrameDelay).scheduleAnimation; const animateOneStep = () => {
if (animationState < -1 || animationState === 0) {
function doShow() {
animationState = -1;
funcToArriveAtState(animationState);
scheduleAnimation();
}
function doQuickShow() { // start showing without losing any fade-in progress
if (animationState < -1) {
animationState = -1;
} else if (animationState > 0) {
animationState = Math.max(-1, Math.min(0, -animationState));
}
funcToArriveAtState(animationState);
scheduleAnimation();
}
function doHide() {
if (animationState >= -1 && animationState <= 0) {
animationState = 1e-6;
scheduleAnimation();
}
}
function animateOneStep() {
if (animationState < -1 || animationState == 0) {
return false; return false;
} else if (animationState < 0) { } else if (animationState < 0) {
// animate show // animate show
@ -243,17 +251,37 @@ var padutils = {
return true; return true;
} }
} }
} };
const scheduleAnimation =
padutils.makeAnimationScheduler(animateOneStep, animationFrameDelay).scheduleAnimation;
return { return {
show: doShow, show: () => {
hide: doHide, animationState = -1;
quickShow: doQuickShow, funcToArriveAtState(animationState);
scheduleAnimation();
},
quickShow: () => { // start showing without losing any fade-in progress
if (animationState < -1) {
animationState = -1;
} else if (animationState > 0) {
animationState = Math.max(-1, Math.min(0, -animationState));
}
funcToArriveAtState(animationState);
scheduleAnimation();
},
hide: () => {
if (animationState >= -1 && animationState <= 0) {
animationState = 1e-6;
scheduleAnimation();
}
},
}; };
}, },
_nextActionId: 1, _nextActionId: 1,
uncanceledActions: {}, uncanceledActions: {},
getCancellableAction(actionType, actionFunc) { getCancellableAction: (actionType, actionFunc) => {
let o = padutils.uncanceledActions[actionType]; let o = padutils.uncanceledActions[actionType];
if (!o) { if (!o) {
o = {}; o = {};
@ -261,27 +289,27 @@ var padutils = {
} }
const actionId = (padutils._nextActionId++); const actionId = (padutils._nextActionId++);
o[actionId] = true; o[actionId] = true;
return function () { return () => {
const p = padutils.uncanceledActions[actionType]; const p = padutils.uncanceledActions[actionType];
if (p && p[actionId]) { if (p && p[actionId]) {
actionFunc(); actionFunc();
} }
}; };
}, },
cancelActions(actionType) { cancelActions: (actionType) => {
const o = padutils.uncanceledActions[actionType]; const o = padutils.uncanceledActions[actionType];
if (o) { if (o) {
// clear it // clear it
delete padutils.uncanceledActions[actionType]; delete padutils.uncanceledActions[actionType];
} }
}, },
makeFieldLabeledWhenEmpty(field, labelText) { makeFieldLabeledWhenEmpty: (field, labelText) => {
field = $(field); field = $(field);
function clear() { const clear = () => {
field.addClass('editempty'); field.addClass('editempty');
field.val(labelText); field.val(labelText);
} };
field.focus(() => { field.focus(() => {
if (field.hasClass('editempty')) { if (field.hasClass('editempty')) {
field.val(''); field.val('');
@ -297,34 +325,28 @@ var padutils = {
clear, clear,
}; };
}, },
getCheckbox(node) { getCheckbox: (node) => $(node).is(':checked'),
return $(node).is(':checked'); setCheckbox: (node, value) => {
},
setCheckbox(node, value) {
if (value) { if (value) {
$(node).attr('checked', 'checked'); $(node).attr('checked', 'checked');
} else { } else {
$(node).removeAttr('checked'); $(node).removeAttr('checked');
} }
}, },
bindCheckboxChange(node, func) { bindCheckboxChange: (node, func) => {
$(node).change(func); $(node).change(func);
}, },
encodeUserId(userId) { encodeUserId: (userId) => userId.replace(/[^a-y0-9]/g, (c) => {
return userId.replace(/[^a-y0-9]/g, (c) => { if (c === '.') return '-';
if (c == '.') return '-'; return `z${c.charCodeAt(0)}z`;
return `z${c.charCodeAt(0)}z`; }),
}); decodeUserId: (encodedUserId) => encodedUserId.replace(/[a-y0-9]+|-|z.+?z/g, (cc) => {
}, if (cc === '-') { return '.'; } else if (cc.charAt(0) === 'z') {
decodeUserId(encodedUserId) { return String.fromCharCode(Number(cc.slice(1, -1)));
return encodedUserId.replace(/[a-y0-9]+|-|z.+?z/g, (cc) => { } else {
if (cc == '-') { return '.'; } else if (cc.charAt(0) == 'z') { return cc;
return String.fromCharCode(Number(cc.slice(1, -1))); }
} else { }),
return cc;
}
});
},
}; };
let globalExceptionHandler = null; let globalExceptionHandler = null;
@ -402,13 +424,13 @@ padutils.setupGlobalExceptionHandler = () => {
padutils.binarySearch = require('./ace2_common').binarySearch; padutils.binarySearch = require('./ace2_common').binarySearch;
// https://stackoverflow.com/a/42660748 // https://stackoverflow.com/a/42660748
function inThirdPartyIframe() { const inThirdPartyIframe = () => {
try { try {
return (!window.top.location.hostname); return (!window.top.location.hostname);
} catch (e) { } catch (e) {
return true; return true;
} }
} };
// This file is included from Node so that it can reuse randomString, but Node doesn't have a global // This file is included from Node so that it can reuse randomString, but Node doesn't have a global
// window object. // window object.

View file

@ -1,3 +1,5 @@
'use strict';
/** /**
* Spys on socket.io messages and saves them into several arrays * Spys on socket.io messages and saves them into several arrays
* that are visible in tests * that are visible in tests

View file

@ -1,3 +1,5 @@
'use strict';
describe('timeslider follow', function () { describe('timeslider follow', function () {
// create a new pad before each test run // create a new pad before each test run
beforeEach(function (cb) { beforeEach(function (cb) {
@ -23,7 +25,7 @@ describe('timeslider follow', function () {
helper.contentWindow().$('#playpause_button_icon').click(); helper.contentWindow().$('#playpause_button_icon').click();
let newTop; let newTop;
return helper.waitForPromise(() => { await helper.waitForPromise(() => {
newTop = helper.contentWindow().$('#innerdocbody').offset(); newTop = helper.contentWindow().$('#innerdocbody').offset();
return newTop.top < originalTop.top; return newTop.top < originalTop.top;
}); });
@ -96,9 +98,9 @@ describe('timeslider follow', function () {
* @param {number} lineNum * @param {number} lineNum
* @returns {boolean} scrolled to the lineOffset? * @returns {boolean} scrolled to the lineOffset?
*/ */
function hasFollowedToLine(lineNum) { const hasFollowedToLine = (lineNum) => {
const scrollPosition = helper.contentWindow().$('#editorcontainerbox')[0].scrollTop; const scrollPosition = helper.contentWindow().$('#editorcontainerbox')[0].scrollTop;
const lineOffset = helper.contentWindow().$('#innerdocbody').find(`div:nth-child(${lineNum})`)[0].offsetTop; const lineOffset =
helper.contentWindow().$('#innerdocbody').find(`div:nth-child(${lineNum})`)[0].offsetTop;
return Math.abs(scrollPosition - lineOffset) < 1; return Math.abs(scrollPosition - lineOffset) < 1;
} };