Fix some typescript issues

This commit is contained in:
Nils Maier 2019-08-20 23:08:48 +02:00
parent 6c197d8353
commit 1513f0b022
26 changed files with 161 additions and 133 deletions

View File

@ -51,7 +51,7 @@ export const DB = new class DB {
const store = transaction.objectStore(STORE); const store = transaction.objectStore(STORE);
const index = store.index("by_position"); const index = store.index("by_position");
index.openCursor().onsuccess = event => { index.openCursor().onsuccess = event => {
const cursor = (<IDBRequest<IDBCursorWithValue>> event.target).result; const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result;
if (!cursor) { if (!cursor) {
resolve(items); resolve(items);
return; return;

View File

@ -78,7 +78,7 @@ const SIZE_SCALE = 875;
const SIZE_KILO = 1024; const SIZE_KILO = 1024;
export const formatSize = memoize(function formatSize( export const formatSize = memoize(function formatSize(
size: number, fractions: boolean = true) { size: number, fractions = true) {
const neg = size < 0; const neg = size < 0;
size = Math.abs(size); size = Math.abs(size);
let i = 0; let i = 0;

View File

@ -3,6 +3,50 @@
import {memoize} from "./memoize"; import {memoize} from "./memoize";
function load() {
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const {i18n} = require("webextension-polyfill");
return i18n;
}
catch (ex) {
// We might be running under node for tests
// eslint-disable-next-line @typescript-eslint/no-var-requires
const messages = require("../_locales/en/messages.json");
const map = new Map();
for (const [k, v] of Object.entries<any>(messages)) {
const {placeholders = {}} = v;
let {message = ""} = v;
for (const [pname, pval] of Object.entries<any>(placeholders)) {
message = message.replace(`$${pname.toUpperCase()}$`, `${pval.content}$`);
}
map.set(k, message);
}
return {
getMessage(id: string, subst: string[]) {
const m = map.get(id);
if (typeof subst === undefined) {
return m;
}
if (!Array.isArray(subst)) {
subst = [subst];
}
return m.replace(/\$\d+\$/g, (r: string) => {
const idx = parseInt(r.substr(1, r.length - 2), 10) - 1;
return subst[idx] || "";
});
}
};
}
}
const i18n = load();
const memoGetMessage = memoize(i18n.getMessage, 10 * 1000, 0);
/** /**
* Localize a message * Localize a message
* @param {string} id Identifier of the string to localize * @param {string} id Identifier of the string to localize
@ -58,46 +102,5 @@ function localize(elem: HTMLElement) {
return elem; return elem;
} }
function load() {
try {
const {i18n} = require("webextension-polyfill");
return i18n;
}
catch (ex) {
// We might be running under node for tests
const messages = require("../_locales/en/messages.json");
const map = new Map();
for (const [k, v] of Object.entries<any>(messages)) {
const {placeholders = {}} = v;
let {message = ""} = v;
for (const [pname, pval] of Object.entries<any>(placeholders)) {
message = message.replace(`$${pname.toUpperCase()}$`, `${pval.content}$`);
}
map.set(k, message);
}
return {
getMessage(id: string, subst: string[]) {
const m = map.get(id);
if (typeof subst === undefined) {
return m;
}
if (!Array.isArray(subst)) {
subst = [subst];
}
return m.replace(/\$\d+\$/g, (r: string) => {
const idx = parseInt(r.substr(1, r.length - 2), 10) - 1;
return subst[idx] || "";
});
}
};
}
}
const i18n = load();
const memoGetMessage = memoize(i18n.getMessage, 10 * 1000, 0);
export {localize, _}; export {localize, _};

View File

@ -95,14 +95,15 @@ export class BaseDownload {
} }
assign(options: any) { assign(options: any) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self: any = this; const self: any = this;
for (const prop of SAVEDPROPS) { for (const prop of SAVEDPROPS) {
if (prop in options) { if (prop in options) {
self[prop] = options[prop]; self[prop] = options[prop];
} }
} }
this.uURL = <URLd> new URL(this.url); this.uURL = new URL(this.url) as URLd;
this.uReferrer = <URLd> (this.referrer && new URL(this.referrer)); this.uReferrer = (this.referrer && new URL(this.referrer)) as URLd;
this.startDate = new Date(options.startDate || Date.now()); this.startDate = new Date(options.startDate || Date.now());
if (options.paused) { if (options.paused) {
this.state = PAUSED; this.state = PAUSED;
@ -133,6 +134,7 @@ export class BaseDownload {
} }
toJSON() { toJSON() {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self: any = this; const self: any = this;
const rv: any = {}; const rv: any = {};
for (const prop of SAVEDPROPS) { for (const prop of SAVEDPROPS) {

View File

@ -74,7 +74,7 @@ export const Limits = new class Limits extends EventEmitter {
this.concurrent = await Prefs.get("concurrent", this.concurrent); this.concurrent = await Prefs.get("concurrent", this.concurrent);
const rawlimits = await Prefs.get("limits"); const rawlimits = await Prefs.get("limits");
this.limits = new Map(rawlimits.map((e: any) => [e.domain, new Limit(e)])); this.limits = new Map(rawlimits.map((e: any) => [e.domain, new Limit(e)]));
this.load = <() => Promise<void>> <unknown> (() => {}); this.load = (() => {}) as unknown as () => Promise<void>;
this.emit("changed"); this.emit("changed");
} }

View File

@ -7,7 +7,10 @@ import { API } from "../api";
import { BaseDownload } from "./basedownload"; import { BaseDownload } from "./basedownload";
type SID = {sid: number}; type SID = {sid: number};
type SIDS = {sids: number[], forced?: boolean}; type SIDS = {
sids: number[];
forced?: boolean;
};
export class ManagerPort { export class ManagerPort {
private manager: any; private manager: any;

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/camelcase */
"use strict"; "use strict";
// License: MIT // License: MIT
@ -169,6 +170,7 @@ export default class Renamer {
toString() { toString() {
const {mask} = this.d; const {mask} = this.d;
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self: any = this; const self: any = this;
// XXX flat // XXX flat
return sanitizePath(mask.replace(REPLACE_EXPR, function(type: string) { return sanitizePath(mask.replace(REPLACE_EXPR, function(type: string) {
@ -230,7 +232,7 @@ function makeHTMLMap() {
export function hookButton(maskButton: HTMLElement) { export function hookButton(maskButton: HTMLElement) {
let maskMap: HTMLElement; let maskMap: HTMLElement;
maskButton.addEventListener("click", (evt : MouseEvent) => { maskButton.addEventListener("click", (evt: MouseEvent) => {
evt.preventDefault(); evt.preventDefault();
evt.stopPropagation(); evt.stopPropagation();

View File

@ -31,14 +31,14 @@ type MemoizeFun<T> = (...args: any[]) => T;
* *
* @param {Function} func The function to be memoized * @param {Function} func The function to be memoized
* @param {Number} [limit] Optional. Cache size (default: 3000) * @param {Number} [limit] Optional. Cache size (default: 3000)
* @param {Number} [num_args] Options. Number of arguments the function expects * @param {Number} [numArgs] Options. Number of arguments the function expects
* (default: func.length) * (default: func.length)
* @returns {Function} Memoized function * @returns {Function} Memoized function
*/ */
export function memoize<T>( export function memoize<T>(
func: MemoizeFun<T>, limit?: number, num_args?: number): MemoizeFun<T> { func: MemoizeFun<T>, limit?: number, numArgs?: number): MemoizeFun<T> {
const climit = limit && limit > 0 ? limit : DEFAULT_LIMIT; const climit = limit && limit > 0 ? limit : DEFAULT_LIMIT;
num_args = num_args || func.length; numArgs = numArgs || func.length;
const cache = new Map(); const cache = new Map();
memoes.push(cache); memoes.push(cache);
@ -46,12 +46,12 @@ export function memoize<T>(
const args: any[] = []; const args: any[] = [];
let key; let result; let key; let result;
switch (num_args) { switch (numArgs) {
case 0: case 0:
throw new Error("memoize does not support functions without arguments"); throw new Error("memoize does not support functions without arguments");
case 1: case 1:
return function memoize_one_arg(a: any) { return function memoizeOne(a: any) {
key = a.spec || a; key = a.spec || a;
if (cache.has(key)) { if (cache.has(key)) {
return cache.get(key); return cache.get(key);
@ -66,7 +66,7 @@ export function memoize<T>(
}; };
case 2: case 2:
return function memoize_two_args(a: any, b: any) { return function memoizeTwo(a: any, b: any) {
args[0] = a; args[1] = b; args[0] = a; args[1] = b;
key = JSON.stringify(args); key = JSON.stringify(args);
args.length = 0; args.length = 0;
@ -84,7 +84,7 @@ export function memoize<T>(
}; };
case 3: case 3:
return function memoize_three_args(a: any, b: any, c: any) { return function memoizeThree(a: any, b: any, c: any) {
args[0] = a; args[1] = b; args[2] = c; args[0] = a; args[1] = b; args[2] = c;
key = JSON.stringify(args); key = JSON.stringify(args);
args.length = 0; args.length = 0;
@ -102,7 +102,7 @@ export function memoize<T>(
}; };
case 4: case 4:
return function memoize_four_args(a: any, b: any, c: any, d: any) { return function memoizeFour(a: any, b: any, c: any, d: any) {
args[0] = a; args[1] = b; args[2] = c; args[3] = d; args[0] = a; args[1] = b; args[2] = c; args[3] = d;
key = JSON.stringify(args); key = JSON.stringify(args);
args.length = 0; args.length = 0;

View File

@ -5,7 +5,7 @@ const RUNNING = Symbol();
const LIMIT = Symbol(); const LIMIT = Symbol();
const ITEMS = Symbol(); const ITEMS = Symbol();
function nothing() {} function nothing() { /* ignored */ }
type Wrapped<T> = (...args: any[]) => Promise<T>; type Wrapped<T> = (...args: any[]) => Promise<T>;
@ -79,7 +79,7 @@ export class PromiseSerializer {
return this.scheduled + this.running; return this.scheduled + this.running;
} }
static wrapNew<T>(limit: number, ctx: any, fn: Function) : Wrapped<T> { static wrapNew<T>(limit: number, ctx: any, fn: Function): Wrapped<T> {
return new PromiseSerializer(limit).wrap(ctx, fn); return new PromiseSerializer(limit).wrap(ctx, fn);
} }

View File

@ -1,9 +1,9 @@
"use strict"; "use strict";
// License: MIT // License: MIT
const re_tokenize = /(0x[0-9a-f]+|[+-]?[0-9]+(?:\.[0-9]*(?:e[+-]?[0-9]+)?)?|\d+)/i; const RE_TOKENIZE = /(0x[0-9a-f]+|[+-]?[0-9]+(?:\.[0-9]*(?:e[+-]?[0-9]+)?)?|\d+)/i;
const re_hex = /^0x[0-9a-z]+$/i; const RE_HEX = /^0x[0-9a-z]+$/i;
const re_trimmore = /\s+/g; const RE_TRIMMORE = /\s+/g;
type KeyFunc<T> = (v: T) => any; type KeyFunc<T> = (v: T) => any;
type CompareFunc<T> = (a: T, b: T) => number; type CompareFunc<T> = (a: T, b: T) => number;
@ -14,31 +14,29 @@ type CompareFunc<T> = (a: T, b: T) => number;
* @param {*} b Second value * @param {*} b Second value
* @returns {number} Comparision result * @returns {number} Comparision result
*/ */
export function default_compare(a: any, b: any) { export function defaultCompare(a: any, b: any) {
return a < b ? -1 : (a > b ? 1 : 0); return a < b ? -1 : (a > b ? 1 : 0);
} }
function parseToken(chunk: string) { function parseToken(chunk: string) {
chunk = chunk.replace(re_trimmore, " ").trim(); chunk = chunk.replace(RE_TRIMMORE, " ").trim();
if (re_hex.test(chunk)) { if (RE_HEX.test(chunk)) {
return parseInt(chunk.slice(2), 16); return parseInt(chunk.slice(2), 16);
} }
const val = parseFloat(chunk); const val = parseFloat(chunk);
return Number.isNaN(val) ? chunk : val; return Number.isNaN(val) ? chunk : val;
} }
function filterTokens(str: string) {
function token_filter(str: string) {
return str && str.trim(); return str && str.trim();
} }
function tokenize(val: any) { function tokenize(val: any) {
if (typeof val === "number") { if (typeof val === "number") {
return [[`${val}`], [val]]; return [[`${val}`], [val]];
} }
const tokens = `${val}`.split(re_tokenize).filter(token_filter); const tokens = `${val}`.split(RE_TOKENIZE).filter(filterTokens);
const numeric = tokens.map(parseToken); const numeric = tokens.map(parseToken);
return [tokens, numeric]; return [tokens, numeric];
} }
@ -76,8 +74,8 @@ export function naturalCompare(a: any, b: any): number {
if (xisnum) { if (xisnum) {
// both are numbers // both are numbers
// Compare the numbers and if they are the same, the tokens too // Compare the numbers and if they are the same, the tokens too
const res = default_compare(xnum, ynum) || const res = defaultCompare(xnum, ynum) ||
default_compare(xTokens[i], yTokens[i]); defaultCompare(xTokens[i], yTokens[i]);
if (!res) { if (!res) {
continue; continue;
} }
@ -86,13 +84,13 @@ export function naturalCompare(a: any, b: any): number {
// both must be stringey // both must be stringey
// Compare the actual tokens. // Compare the actual tokens.
const res = default_compare(xTokens[i], yTokens[i]); const res = defaultCompare(xTokens[i], yTokens[i]);
if (!res) { if (!res) {
continue; continue;
} }
return res; return res;
} }
return default_compare(xTokenLen, yTokenLen); return defaultCompare(xTokenLen, yTokenLen);
} }
/** /**
@ -114,19 +112,19 @@ export function naturalCaseCompare(a: any, b: any) {
* @param {cmpf} [cmp] Compare function or default_compare * @param {cmpf} [cmp] Compare function or default_compare
* @returns {number} Comparison result * @returns {number} Comparison result
*/ */
export function array_compare(a: any, b: any, cmp: CompareFunc<any>): number { export function arrayCompare(a: any, b: any, cmp: CompareFunc<any>): number {
cmp = cmp || default_compare; cmp = cmp || defaultCompare;
if (Array.isArray(a) && Array.isArray(b)) { if (Array.isArray(a) && Array.isArray(b)) {
const {length: alen} = a; const {length: alen} = a;
const {length: blen} = b; const {length: blen} = b;
const len = Math.min(alen, blen); const len = Math.min(alen, blen);
for (let i = 0; i < len; ++i) { for (let i = 0; i < len; ++i) {
const rv = array_compare(a[i], b[i], cmp); const rv = arrayCompare(a[i], b[i], cmp);
if (rv) { if (rv) {
return rv; return rv;
} }
} }
return default_compare(alen, blen); return defaultCompare(alen, blen);
} }
return cmp(a, b); return cmp(a, b);
} }
@ -137,12 +135,12 @@ interface MapValue {
value: any; value: any;
} }
function mapped_compare( function mappedCompare(
fn: CompareFunc<any>, a: MapValue, b: MapValue) : number { fn: CompareFunc<any>, a: MapValue, b: MapValue): number {
const {key: ka} = a; const {key: ka} = a;
const {key: kb} = b; const {key: kb} = b;
return array_compare(ka, kb, fn) || return arrayCompare(ka, kb, fn) ||
/* stable */ default_compare(a.index, b.index); /* stable */ defaultCompare(a.index, b.index);
} }
/** /**
@ -169,8 +167,8 @@ function mapped_compare(
* @returns {*[]} New sorted array * @returns {*[]} New sorted array
*/ */
export function sort<T>(arr: T[], key?: KeyFunc<T>, cmp?: CompareFunc<T>) { export function sort<T>(arr: T[], key?: KeyFunc<T>, cmp?: CompareFunc<T>) {
cmp = cmp || default_compare; cmp = cmp || defaultCompare;
const carr = <MapValue[]> <unknown> arr; const carr = arr as unknown as MapValue[];
if (key) { if (key) {
arr.forEach((value, index) => { arr.forEach((value, index) => {
carr[index] = {value, key: key(value), index}; carr[index] = {value, key: key(value), index};
@ -181,7 +179,7 @@ export function sort<T>(arr: T[], key?: KeyFunc<T>, cmp?: CompareFunc<T>) {
carr[index] = {value, key: value, index}; carr[index] = {value, key: value, index};
}); });
} }
arr.sort(mapped_compare.bind(null, cmp)); arr.sort(mappedCompare.bind(null, cmp));
carr.forEach((i, idx) => { carr.forEach((i, idx) => {
arr[idx] = i.value; arr[idx] = i.value;
}); });
@ -198,7 +196,7 @@ export function sort<T>(arr: T[], key?: KeyFunc<T>, cmp?: CompareFunc<T>) {
* @returns {*[]} New sorted array * @returns {*[]} New sorted array
*/ */
export function sorted<T>(arr: T[], key?: KeyFunc<T>, cmp?: CompareFunc<T>) { export function sorted<T>(arr: T[], key?: KeyFunc<T>, cmp?: CompareFunc<T>) {
cmp = cmp || default_compare; cmp = cmp || defaultCompare;
let carr: MapValue[]; let carr: MapValue[];
if (key) { if (key) {
carr = arr.map((value, index) => { carr = arr.map((value, index) => {
@ -210,6 +208,6 @@ export function sorted<T>(arr: T[], key?: KeyFunc<T>, cmp?: CompareFunc<T>) {
return {value, key: value, index}; return {value, key: value, index};
}); });
} }
carr.sort(mapped_compare.bind(null, cmp)); carr.sort(mappedCompare.bind(null, cmp));
return carr.map(v => v.value); return carr.map(v => v.value);
} }

View File

@ -73,6 +73,7 @@ export class FakeLink {
} }
getAttribute(attr: string) { getAttribute(attr: string) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self: any = this; const self: any = this;
return (attr in self) ? self[attr] : null; return (attr in self) ? self[attr] : null;
} }

View File

@ -47,7 +47,21 @@ export function lazy<T>(object: any, name: string, fun: (...any: any[]) => T) {
return object; return object;
} }
export function none() { } export function none() { /* ignored */ }
export const sanitizePath = identity(function sanitizePath(path: string) {
return path.
replace(/:+/g, "ː").
replace(/\?+/g, "_").
replace(/\*+/g, "_").
replace(/<+/g, "◄").
replace(/>+/g, "▶").
replace(/"+/g, "'").
replace(/\|+/g, "¦").
replace(/#+/g, "♯").
replace(/[.\s]+$/g, "").
trim();
});
// XXX cleanup + test // XXX cleanup + test
export const parsePath = memoize(function parsePath(path: string | URL) { export const parsePath = memoize(function parsePath(path: string | URL) {
@ -89,21 +103,6 @@ export const parsePath = memoize(function parsePath(path: string | URL) {
}; };
}); });
export const sanitizePath = identity(function sanitizePath(path: string) {
return path.
replace(/:+/g, "ː").
replace(/\?+/g, "_").
replace(/\*+/g, "_").
replace(/<+/g, "◄").
replace(/>+/g, "▶").
replace(/"+/g, "'").
replace(/\|+/g, "¦").
replace(/#+/g, "♯").
replace(/[.\s]+$/g, "").
trim();
});
export class CoalescedUpdate<T> extends Set<T> { export class CoalescedUpdate<T> extends Set<T> {
private readonly to: number; private readonly to: number;
@ -141,7 +140,7 @@ export class CoalescedUpdate<T> extends Set<T> {
export const hostToDomain = memoize(psl.get, 1000); export const hostToDomain = memoize(psl.get, 1000);
export interface URLd extends URL { export interface URLd extends URL {
domain: string domain: string;
} }
Object.defineProperty(URL.prototype, "domain", { Object.defineProperty(URL.prototype, "domain", {
@ -188,7 +187,8 @@ export function filterInSitu<T>(arr: T[], cb: (value: T) => boolean, tp?: any) {
*/ */
export function mapInSitu<TRes, T>(arr: T[], cb: (value: T) => TRes, tp?: any) { export function mapInSitu<TRes, T>(arr: T[], cb: (value: T) => TRes, tp?: any) {
tp = tp || null; tp = tp || null;
const carr = <TRes[]> <unknown> arr; const carr = arr as unknown as TRes[];
for (let i = 0, e = arr.length; i < e; i++) { for (let i = 0, e = arr.length; i < e; i++) {
carr[i] = cb.call(tp, arr[i], i, arr); carr[i] = cb.call(tp, arr[i], i, arr);
} }
@ -209,7 +209,7 @@ export function filterMapInSitu<TRes, T>(
mapStep: (value: T) => TRes, mapStep: (value: T) => TRes,
tp?: any) { tp?: any) {
tp = tp || null; tp = tp || null;
const carr = <TRes[]> <unknown> arr; const carr = arr as unknown as TRes[];
let i; let k; let e; let i; let k; let e;
for (i = 0, k = 0, e = arr.length; i < e; i++) { for (i = 0, k = 0, e = arr.length; i < e; i++) {
@ -238,7 +238,7 @@ export function mapFilterInSitu<TRes, T>(
filterStep: (value: T) => boolean, filterStep: (value: T) => boolean,
tp?: any) { tp?: any) {
tp = tp || null; tp = tp || null;
const carr = <TRes[]> <unknown> arr; const carr = arr as unknown as TRes[];
let i; let k; let e; let i; let k; let e;
for (i = 0, k = 0, e = arr.length; i < e; i++) { for (i = 0, k = 0, e = arr.length; i < e; i++) {

View File

@ -12,6 +12,7 @@ try {
}; };
} }
catch (ex) { catch (ex) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const cr = require("crypto"); const cr = require("crypto");
return function(size: number) { return function(size: number) {

View File

@ -67,6 +67,7 @@ export class AbstractTable extends EventEmitter {
*/ */
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
setCellCheck(rowid: number, colid: number, value: boolean) { setCellCheck(rowid: number, colid: number, value: boolean) {
// ignored
} }
/** /**

View File

@ -113,6 +113,7 @@ export class AnimationPool {
* Your newly bound function. * Your newly bound function.
*/ */
wrap(fn: Function) { wrap(fn: Function) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self = this; const self = this;
return function wrapped(...args: any[]) { return function wrapped(...args: any[]) {
return self.schedule(this, fn, ...args); return self.schedule(this, fn, ...args);

View File

@ -79,7 +79,7 @@ export class BaseTable extends AbstractTable {
[COLS]: Columns; [COLS]: Columns;
constructor(elem : any, config: any, version?: number) { constructor(elem: any, config: any, version?: number) {
config = (config && config.version === version && config) || {}; config = (config && config.version === version && config) || {};
super(); super();
@ -168,6 +168,7 @@ export class BaseTable extends AbstractTable {
} }
init() { init() {
// ignored
} }
/* do not override unless you know what you're doing */ /* do not override unless you know what you're doing */
@ -471,7 +472,7 @@ export class BaseTable extends AbstractTable {
} }
isCheckClick(evt: MouseEvent) { isCheckClick(evt: MouseEvent) {
return /virtualtable-check/.test((<HTMLElement> evt.target).className) && return /virtualtable-check/.test((evt.target as HTMLElement).className) &&
!evt.ctrlKey && !evt.shiftKey && !evt.metaKey; !evt.ctrlKey && !evt.shiftKey && !evt.metaKey;
} }

View File

@ -29,8 +29,8 @@ function toKeyText(key: string) {
} }
export interface MenuPosition { export interface MenuPosition {
clientX: number, clientX: number;
clientY: number, clientY: number;
} }
export class MenuItemBase { export class MenuItemBase {
@ -137,6 +137,7 @@ export class SubMenuItem extends MenuItemBase {
this.elem.setAttribute("aria-role", "menuitem"); this.elem.setAttribute("aria-role", "menuitem");
this.elem.setAttribute("aria-haspopup", "true"); this.elem.setAttribute("aria-haspopup", "true");
// eslint-disable-next-line @typescript-eslint/no-use-before-define
this.menu = new ContextMenu(); this.menu = new ContextMenu();
this.expandElem = document.createElement("span"); this.expandElem = document.createElement("span");
@ -177,7 +178,7 @@ export class SubMenuItem extends MenuItemBase {
entered(event: MouseEvent) { entered(event: MouseEvent) {
const {target} = event; const {target} = event;
const htarget = <HTMLElement> target; const htarget = target as HTMLElement;
if (htarget.classList.contains("context-menu")) { if (htarget.classList.contains("context-menu")) {
return; return;
} }
@ -307,7 +308,7 @@ export class ContextMenu extends EventEmitter {
Math.abs(event.clientY - origEvent.clientY) < CLICK_DIFF) { Math.abs(event.clientY - origEvent.clientY) < CLICK_DIFF) {
return; return;
} }
let el = <HTMLElement> event.target; let el = event.target as HTMLElement;
while (el) { while (el) {
if (el.classList.contains("context-menu")) { if (el.classList.contains("context-menu")) {
return; return;
@ -386,7 +387,7 @@ export class ContextMenu extends EventEmitter {
el.parentElement.removeChild(el); el.parentElement.removeChild(el);
} }
if (el.localName === "template") { if (el.localName === "template") {
el = <HTMLElement> (<HTMLTemplateElement> el).content.firstElementChild; el = (el as HTMLTemplateElement).content.firstElementChild as HTMLElement;
} }
if (el.className) { if (el.className) {
this.elem.className = el.className; this.elem.className = el.className;
@ -408,24 +409,24 @@ export class ContextMenu extends EventEmitter {
if (sub) { if (sub) {
throw new Error("Already has a submenu"); throw new Error("Already has a submenu");
} }
if ((<HTMLElement> sc).localName !== "ul") { if ((sc as HTMLElement).localName !== "ul") {
throw new Error("Not a valid submenu"); throw new Error("Not a valid submenu");
} }
sub = sc; sub = sc;
break; break;
default: default:
throw new Error(`Invalid node: ${(<HTMLElement> sc).localName}`); throw new Error(`Invalid node: ${(sc as HTMLElement).localName}`);
} }
} }
const joined = text.join(" ").trim(); const joined = text.join(" ").trim();
let item = null; let item = null;
const ce = <HTMLElement> child; const ce = child as HTMLElement;
if (joined === "-") { if (joined === "-") {
item = new MenuSeperatorItem(this, child.id); item = new MenuSeperatorItem(this, child.id);
} }
else if (sub) { else if (sub) {
item = new SubMenuItem(this, child.id, joined, ce.dataset); item = new SubMenuItem(this, child.id, joined, ce.dataset);
item.constructFromTemplate(<HTMLElement> sub); item.constructFromTemplate(sub as HTMLElement);
} }
else { else {
item = new MenuItem(this, child.id, joined, ce.dataset); item = new MenuItem(this, child.id, joined, ce.dataset);

View File

@ -63,6 +63,7 @@ export class EventEmitter {
once(event: string, cb: (...args: any[]) => any) { once(event: string, cb: (...args: any[]) => any) {
const wrapped = (...args: any[]) => { const wrapped = (...args: any[]) => {
try { try {
// eslint-disable-next-line prefer-spread
return cb.apply(null, args); return cb.apply(null, args);
} }
finally { finally {
@ -102,6 +103,7 @@ export class EventEmitter {
} }
for (const e of Array.from(handlers)) { for (const e of Array.from(handlers)) {
try { try {
// eslint-disable-next-line prefer-spread
handled = handled || !!e.apply(null, args); handled = handled || !!e.apply(null, args);
} }
catch (ex) { catch (ex) {

View File

@ -87,7 +87,7 @@ export default class ModalDialog {
return el; return el;
} }
get content() : DocumentFragment | HTMLElement { get content(): DocumentFragment | HTMLElement {
throw new Error("Not implemented"); throw new Error("Not implemented");
} }
@ -119,13 +119,14 @@ export default class ModalDialog {
} }
shown() { shown() {
// ignored
} }
focusDefault() { focusDefault() {
this._default && this._default.focus(); this._default && this._default.focus();
} }
convertValue(value: string) : any { convertValue(value: string): any {
return value; return value;
} }
@ -148,7 +149,7 @@ export default class ModalDialog {
if (e.key !== "Enter") { if (e.key !== "Enter") {
return; return;
} }
const {localName} = <HTMLElement> e.target; const {localName} = e.target as HTMLElement;
if (localName === "textarea" && !e.metaKey) { if (localName === "textarea" && !e.metaKey) {
return; return;
} }

View File

@ -303,7 +303,7 @@ export class TableSelection extends EventEmitter {
newSelection._add(pos, r.end + offset); newSelection._add(pos, r.end + offset);
} }
this.ranges.length = 0; this.ranges.length = 0;
this.ranges.push.apply(this.ranges, newSelection.ranges); this.ranges.push(...newSelection.ranges);
} }
clear() { clear() {

View File

@ -38,7 +38,7 @@ export class Broadcaster {
} }
onkey(evt: KeyboardEvent) { onkey(evt: KeyboardEvent) {
const {localName} = <HTMLElement> evt.target; const {localName} = evt.target as HTMLElement;
if (localName === "input" || localName === "textarea") { if (localName === "input" || localName === "textarea") {
return undefined; return undefined;
} }

View File

@ -24,7 +24,7 @@ export class Dropdown extends EventEmitter {
this.container.classList.add("dropdown"); this.container.classList.add("dropdown");
input = input.parentElement.replaceChild(this.container, input); input = input.parentElement.replaceChild(this.container, input);
this.input = <HTMLInputElement> input; this.input = input as HTMLInputElement;
this.container.appendChild(this.input); this.container.appendChild(this.input);
this.select = document.createElement("select"); this.select = document.createElement("select");

View File

@ -8,7 +8,7 @@ export class Icons extends Map {
constructor(el: HTMLStyleElement) { constructor(el: HTMLStyleElement) {
super(); super();
this.sheet = <CSSStyleSheet> el.sheet; this.sheet = el.sheet as CSSStyleSheet;
this.running = 0; this.running = 0;
} }

View File

@ -15,7 +15,7 @@ export class Buttons extends EventEmitter {
} }
clicked(evt: MouseEvent) { clicked(evt: MouseEvent) {
let target = <HTMLElement | null> evt.target; let target = evt.target as HTMLElement | null;
while (target && target !== this.parent) { while (target && target !== this.parent) {
if (target.classList.contains("button")) { if (target.classList.contains("button")) {
const {id} = target; const {id} = target;

View File

@ -12,8 +12,9 @@ import {
MenuPosition, MenuPosition,
} from "../../uikit/lib/contextmenu"; } from "../../uikit/lib/contextmenu";
import {EventEmitter} from "../../lib/events"; import {EventEmitter} from "../../lib/events";
import {filters, Matcher} from "../../lib/filters"; // eslint-disable-next-line no-unused-vars
import {sort, default_compare, naturalCaseCompare} from "../../lib/sorting"; import {filters, Matcher, Filter} from "../../lib/filters";
import {sort, defaultCompare, naturalCaseCompare} from "../../lib/sorting";
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
import {DownloadItem, DownloadTable} from "./table"; import {DownloadItem, DownloadTable} from "./table";
import {formatSize} from "../../lib/formatters"; import {formatSize} from "../../lib/formatters";
@ -162,7 +163,10 @@ export class MenuFilter extends ItemFilter {
if (!callback) { if (!callback) {
continue; continue;
} }
this.toggleItem(<MenuItem> item); if (!(item instanceof MenuItem)) {
continue;
}
this.toggleItem(item);
callback.apply(this); callback.apply(this);
} }
} }
@ -188,7 +192,10 @@ export class MenuFilter extends ItemFilter {
if (!item) { if (!item) {
return; return;
} }
this.toggleItem(<MenuItem> item); if (!(item instanceof MenuItem)) {
return;
}
this.toggleItem(item);
if (callback) { if (callback) {
callback.call(this); callback.call(this);
} }
@ -300,7 +307,7 @@ export class SizeMenuFilter extends FixedMenuFilter {
export class UrlMenuFilter extends MenuFilter { export class UrlMenuFilter extends MenuFilter {
collection: FilteredCollection; collection: FilteredCollection;
filters: Set<any>; filters: Set<Filter>;
domains: Set<string>; domains: Set<string>;
@ -364,7 +371,7 @@ export class UrlMenuFilter extends MenuFilter {
} }
else { else {
const exprs = Array.from(this.filters).map(f => Array.from(f)).flat(); const exprs = Array.from(this.filters).map(f => Array.from(f)).flat();
this.matcher = new Matcher(<RegExp[]> exprs); this.matcher = new Matcher(exprs);
} }
this.collection.addFilter(this); this.collection.addFilter(this);
@ -570,7 +577,7 @@ export class FilteredCollection extends EventEmitter {
* @param {boolean} [natural] Sort naturally * @param {boolean} [natural] Sort naturally
*/ */
sort(keyfn: (i: DownloadItem) => any, descending = false, natural = false) { sort(keyfn: (i: DownloadItem) => any, descending = false, natural = false) {
const cmp = natural ? naturalCaseCompare : default_compare; const cmp = natural ? naturalCaseCompare : defaultCompare;
let cmpfn = cmp; let cmpfn = cmp;
if (descending) { if (descending) {
cmpfn = (a, b) => -cmp(a, b); cmpfn = (a, b) => -cmp(a, b);

View File

@ -147,7 +147,10 @@ export class Tooltip {
this.update = this.update.bind(this); this.update = this.update.bind(this);
this.item = item; this.item = item;
const tmpl = ( const tmpl = (
<HTMLTemplateElement> document.querySelector("#tooltip-template")); document.querySelector<HTMLTemplateElement>("#tooltip-template"));
if (!tmpl) {
throw new Error("template failed");
}
const el = tmpl.content.firstElementChild; const el = tmpl.content.firstElementChild;
if (!el) { if (!el) {
throw new Error("invalid template"); throw new Error("invalid template");
@ -155,8 +158,9 @@ export class Tooltip {
this.elem = localize(el.cloneNode(true) as HTMLElement); this.elem = localize(el.cloneNode(true) as HTMLElement);
this.adjust(pos); this.adjust(pos);
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self: any = this;
ELEMS.forEach(e => { ELEMS.forEach(e => {
const self: any = this;
self[e] = this.elem.querySelector(`#tooltip-${e}`); self[e] = this.elem.querySelector(`#tooltip-${e}`);
}); });
document.body.appendChild(this.elem); document.body.appendChild(this.elem);