Types on src/share

jh-changes
Shin'ya Ueoka 6 years ago
parent 2b8c37e57f
commit 0cffb09e24
  1. 4
      src/shared/blacklists.ts
  2. 15
      src/shared/messages.ts
  3. 4
      src/shared/operations.ts
  4. 6
      src/shared/settings/properties.ts
  5. 6
      src/shared/settings/storage.ts
  6. 12
      src/shared/settings/validator.ts
  7. 24
      src/shared/settings/values.ts
  8. 6
      src/shared/urls.ts
  9. 41
      src/shared/utils/dom.ts
  10. 22
      src/shared/utils/keys.ts
  11. 2
      src/shared/utils/re.ts

@ -1,6 +1,6 @@
import * as re from 'shared/utils/re'; import * as re from './utils/re';
const includes = (blacklist, url) => { const includes = (blacklist: string[], url: string): boolean => {
let u = new URL(url); let u = new URL(url);
return blacklist.some((item) => { return blacklist.some((item) => {
if (!item.includes('/')) { if (!item.includes('/')) {

@ -1,5 +1,8 @@
const onWebMessage = (listener) => { type WebMessageSender = Window | MessagePort | ServiceWorker | null;
window.addEventListener('message', (event) => { type WebMessageListener = (msg: any, sender: WebMessageSender | null) => void;
const onWebMessage = (listener: WebMessageListener) => {
window.addEventListener('message', (event: MessageEvent) => {
let sender = event.source; let sender = event.source;
let message = null; let message = null;
try { try {
@ -12,11 +15,15 @@ const onWebMessage = (listener) => {
}); });
}; };
const onBackgroundMessage = (listener) => { const onBackgroundMessage = (
listener: (msg: any, sender: browser.runtime.MessageSender,
) => void) => {
browser.runtime.onMessage.addListener(listener); browser.runtime.onMessage.addListener(listener);
}; };
const onMessage = (listener) => { const onMessage = (
listener: (msg: any, sender: WebMessageSender | browser.runtime.MessageSender,
) => void) => {
onWebMessage(listener); onWebMessage(listener);
onBackgroundMessage(listener); onBackgroundMessage(listener);
}; };

@ -1,4 +1,4 @@
export default { const operations: { [key: string]: string } = {
// Hide console, or cancel some user actions // Hide console, or cancel some user actions
CANCEL: 'cancel', CANCEL: 'cancel',
@ -76,3 +76,5 @@ export default {
MARK_SET_PREFIX: 'mark.set.prefix', MARK_SET_PREFIX: 'mark.set.prefix',
MARK_JUMP_PREFIX: 'mark.jump.prefix', MARK_JUMP_PREFIX: 'mark.jump.prefix',
}; };
export default operations;

@ -2,20 +2,20 @@
// mystr: 'string', // mystr: 'string',
// mynum: 'number', // mynum: 'number',
// mybool: 'boolean', // mybool: 'boolean',
const types = { const types: { [key: string]: string } = {
hintchars: 'string', hintchars: 'string',
smoothscroll: 'boolean', smoothscroll: 'boolean',
complete: 'string', complete: 'string',
}; };
// describe default values of a property // describe default values of a property
const defaults = { const defaults: { [key: string]: string | number | boolean } = {
hintchars: 'abcdefghijklmnopqrstuvwxyz', hintchars: 'abcdefghijklmnopqrstuvwxyz',
smoothscroll: false, smoothscroll: false,
complete: 'sbh', complete: 'sbh',
}; };
const docs = { const docs: { [key: string]: string } = {
hintchars: 'hint characters on follow mode', hintchars: 'hint characters on follow mode',
smoothscroll: 'smooth scroll', smoothscroll: 'smooth scroll',
complete: 'which are completed at the open page', complete: 'which are completed at the open page',

@ -1,12 +1,12 @@
import DefaultSettings from './default'; import DefaultSettings from './default';
import * as settingsValues from './values'; import * as settingsValues from './values';
const loadRaw = async() => { const loadRaw = async(): Promise<any> => {
let { settings } = await browser.storage.local.get('settings'); let { settings } = await browser.storage.local.get('settings');
if (!settings) { if (!settings) {
return DefaultSettings; return DefaultSettings;
} }
return { ...DefaultSettings, ...settings }; return { ...DefaultSettings, ...settings as object };
}; };
const loadValue = async() => { const loadValue = async() => {
@ -23,7 +23,7 @@ const loadValue = async() => {
return { ...settingsValues.valueFromJson(DefaultSettings.json), ...value }; return { ...settingsValues.valueFromJson(DefaultSettings.json), ...value };
}; };
const save = (settings) => { const save = (settings: any): Promise<any> => {
return browser.storage.local.set({ return browser.storage.local.set({
settings, settings,
}); });

@ -1,4 +1,4 @@
import operations from 'shared/operations'; import operations from '../operations';
import * as properties from './properties'; import * as properties from './properties';
const VALID_TOP_KEYS = ['keymaps', 'search', 'blacklist', 'properties']; const VALID_TOP_KEYS = ['keymaps', 'search', 'blacklist', 'properties'];
@ -6,7 +6,7 @@ const VALID_OPERATION_VALUES = Object.keys(operations).map((key) => {
return operations[key]; return operations[key];
}); });
const validateInvalidTopKeys = (settings) => { const validateInvalidTopKeys = (settings: any): void => {
let invalidKey = Object.keys(settings).find((key) => { let invalidKey = Object.keys(settings).find((key) => {
return !VALID_TOP_KEYS.includes(key); return !VALID_TOP_KEYS.includes(key);
}); });
@ -15,7 +15,7 @@ const validateInvalidTopKeys = (settings) => {
} }
}; };
const validateKeymaps = (keymaps) => { const validateKeymaps = (keymaps: any): void => {
for (let key of Object.keys(keymaps)) { for (let key of Object.keys(keymaps)) {
let value = keymaps[key]; let value = keymaps[key];
if (!VALID_OPERATION_VALUES.includes(value.type)) { if (!VALID_OPERATION_VALUES.includes(value.type)) {
@ -24,7 +24,7 @@ const validateKeymaps = (keymaps) => {
} }
}; };
const validateSearch = (search) => { const validateSearch = (search: any): void => {
let engines = search.engines; let engines = search.engines;
for (let key of Object.keys(engines)) { for (let key of Object.keys(engines)) {
if ((/\s/).test(key)) { if ((/\s/).test(key)) {
@ -49,7 +49,7 @@ const validateSearch = (search) => {
} }
}; };
const validateProperties = (props) => { const validateProperties = (props: any): void => {
for (let name of Object.keys(props)) { for (let name of Object.keys(props)) {
if (!properties.types[name]) { if (!properties.types[name]) {
throw new Error(`Unknown property name: "${name}"`); throw new Error(`Unknown property name: "${name}"`);
@ -60,7 +60,7 @@ const validateProperties = (props) => {
} }
}; };
const validate = (settings) => { const validate = (settings: any): void => {
validateInvalidTopKeys(settings); validateInvalidTopKeys(settings);
if (settings.keymaps) { if (settings.keymaps) {
validateKeymaps(settings.keymaps); validateKeymaps(settings.keymaps);

@ -1,6 +1,6 @@
import * as properties from './properties'; import * as properties from './properties';
const operationFromFormName = (name) => { const operationFromFormName = (name: string): any => {
let [type, argStr] = name.split('?'); let [type, argStr] = name.split('?');
let args = {}; let args = {};
if (argStr) { if (argStr) {
@ -9,7 +9,7 @@ const operationFromFormName = (name) => {
return { type, ...args }; return { type, ...args };
}; };
const operationToFormName = (op) => { const operationToFormName = (op: any): string => {
let type = op.type; let type = op.type;
let args = { ...op }; let args = { ...op };
delete args.type; delete args.type;
@ -20,12 +20,12 @@ const operationToFormName = (op) => {
return op.type + '?' + JSON.stringify(args); return op.type + '?' + JSON.stringify(args);
}; };
const valueFromJson = (json) => { const valueFromJson = (json: string): object => {
return JSON.parse(json); return JSON.parse(json);
}; };
const valueFromForm = (form) => { const valueFromForm = (form: any): object => {
let keymaps = undefined; let keymaps: any = undefined;
if (form.keymaps) { if (form.keymaps) {
keymaps = {}; keymaps = {};
for (let name of Object.keys(form.keymaps)) { for (let name of Object.keys(form.keymaps)) {
@ -34,7 +34,7 @@ const valueFromForm = (form) => {
} }
} }
let search = undefined; let search: any = undefined;
if (form.search) { if (form.search) {
search = { default: form.search.default }; search = { default: form.search.default };
@ -54,12 +54,12 @@ const valueFromForm = (form) => {
}; };
}; };
const jsonFromValue = (value) => { const jsonFromValue = (value: any): string => {
return JSON.stringify(value, undefined, 2); return JSON.stringify(value, undefined, 2);
}; };
const formFromValue = (value, allowedOps) => { const formFromValue = (value: any, allowedOps: any[]): any => {
let keymaps = undefined; let keymaps: any = undefined;
if (value.keymaps) { if (value.keymaps) {
let allowedSet = new Set(allowedOps); let allowedSet = new Set(allowedOps);
@ -73,7 +73,7 @@ const formFromValue = (value, allowedOps) => {
} }
} }
let search = undefined; let search: any = undefined;
if (value.search) { if (value.search) {
search = { default: value.search.default }; search = { default: value.search.default };
if (value.search.engines) { if (value.search.engines) {
@ -93,11 +93,11 @@ const formFromValue = (value, allowedOps) => {
}; };
}; };
const jsonFromForm = (form) => { const jsonFromForm = (form: any): string => {
return jsonFromValue(valueFromForm(form)); return jsonFromValue(valueFromForm(form));
}; };
const formFromJson = (json, allowedOps) => { const formFromJson = (json: string, allowedOps: any[]): any => {
let value = valueFromJson(json); let value = valueFromJson(json);
return formFromValue(value, allowedOps); return formFromValue(value, allowedOps);
}; };

@ -1,11 +1,11 @@
const trimStart = (str) => { const trimStart = (str: string): string => {
// NOTE String.trimStart is available on Firefox 61 // NOTE String.trimStart is available on Firefox 61
return str.replace(/^\s+/, ''); return str.replace(/^\s+/, '');
}; };
const SUPPORTED_PROTOCOLS = ['http:', 'https:', 'ftp:', 'mailto:', 'about:']; const SUPPORTED_PROTOCOLS = ['http:', 'https:', 'ftp:', 'mailto:', 'about:'];
const searchUrl = (keywords, searchSettings) => { const searchUrl = (keywords: string, searchSettings: any): string => {
try { try {
let u = new URL(keywords); let u = new URL(keywords);
if (SUPPORTED_PROTOCOLS.includes(u.protocol.toLowerCase())) { if (SUPPORTED_PROTOCOLS.includes(u.protocol.toLowerCase())) {
@ -28,7 +28,7 @@ const searchUrl = (keywords, searchSettings) => {
return template.replace('{}', encodeURIComponent(query)); return template.replace('{}', encodeURIComponent(query));
}; };
const normalizeUrl = (url) => { const normalizeUrl = (url: string): string => {
try { try {
let u = new URL(url); let u = new URL(url);
if (SUPPORTED_PROTOCOLS.includes(u.protocol.toLowerCase())) { if (SUPPORTED_PROTOCOLS.includes(u.protocol.toLowerCase())) {

@ -1,16 +1,24 @@
const isContentEditable = (element) => { const isContentEditable = (element: Element): boolean => {
return element.hasAttribute('contenteditable') && ( let value = element.getAttribute('contenteditable');
element.getAttribute('contenteditable').toLowerCase() === 'true' || if (value === null) {
element.getAttribute('contenteditable').toLowerCase() === '' return false;
); }
return value.toLowerCase() === 'true' || value.toLowerCase() === '';
}; };
const rectangleCoordsRect = (coords) => { interface Rect {
left: number;
top: number;
right: number;
bottom: number;
}
const rectangleCoordsRect = (coords: string): Rect => {
let [left, top, right, bottom] = coords.split(',').map(n => Number(n)); let [left, top, right, bottom] = coords.split(',').map(n => Number(n));
return { left, top, right, bottom }; return { left, top, right, bottom };
}; };
const circleCoordsRect = (coords) => { const circleCoordsRect = (coords: string): Rect => {
let [x, y, r] = coords.split(',').map(n => Number(n)); let [x, y, r] = coords.split(',').map(n => Number(n));
return { return {
left: x - r, left: x - r,
@ -20,7 +28,7 @@ const circleCoordsRect = (coords) => {
}; };
}; };
const polygonCoordsRect = (coords) => { const polygonCoordsRect = (coords: string): Rect => {
let params = coords.split(','); let params = coords.split(',');
let minx = Number(params[0]), let minx = Number(params[0]),
maxx = Number(params[0]), maxx = Number(params[0]),
@ -46,18 +54,24 @@ const polygonCoordsRect = (coords) => {
return { left: minx, top: miny, right: maxx, bottom: maxy }; return { left: minx, top: miny, right: maxx, bottom: maxy };
}; };
const viewportRect = (e) => { const viewportRect = (e: Element): Rect => {
if (e.tagName !== 'AREA') { if (e.tagName !== 'AREA') {
return e.getBoundingClientRect(); return e.getBoundingClientRect();
} }
let mapElement = e.parentNode; let mapElement = e.parentNode as HTMLMapElement;
let imgElement = document.querySelector(`img[usemap="#${mapElement.name}"]`); let imgElement = document.querySelector(
`img[usemap="#${mapElement.name}"]`
) as HTMLImageElement;
let { let {
left: mapLeft, left: mapLeft,
top: mapTop top: mapTop
} = imgElement.getBoundingClientRect(); } = imgElement.getBoundingClientRect();
let coords = e.getAttribute('coords'); let coords = e.getAttribute('coords');
if (!coords) {
return e.getBoundingClientRect();
}
let rect = { left: 0, top: 0, right: 0, bottom: 0 }; let rect = { left: 0, top: 0, right: 0, bottom: 0 };
switch (e.getAttribute('shape')) { switch (e.getAttribute('shape')) {
case 'rect': case 'rect':
@ -81,7 +95,7 @@ const viewportRect = (e) => {
}; };
}; };
const isVisible = (element) => { const isVisible = (element: Element): boolean => {
let rect = element.getBoundingClientRect(); let rect = element.getBoundingClientRect();
let style = window.getComputedStyle(element); let style = window.getComputedStyle(element);
@ -94,7 +108,8 @@ const isVisible = (element) => {
if (window.innerWidth < rect.left && window.innerHeight < rect.top) { if (window.innerWidth < rect.left && window.innerHeight < rect.top) {
return false; return false;
} }
if (element.nodeName === 'INPUT' && element.type.toLowerCase() === 'hidden') { if (element instanceof HTMLInputElement &&
element.type.toLowerCase() === 'hidden') {
return false; return false;
} }

@ -1,4 +1,12 @@
const modifiedKeyName = (name) => { interface Key {
key: string;
shiftKey: boolean | undefined;
ctrlKey: boolean | undefined;
altKey: boolean | undefined;
metaKey: boolean | undefined;
}
const modifiedKeyName = (name: string): string => {
if (name === ' ') { if (name === ' ') {
return 'Space'; return 'Space';
} }
@ -10,7 +18,7 @@ const modifiedKeyName = (name) => {
return name; return name;
}; };
const fromKeyboardEvent = (e) => { const fromKeyboardEvent = (e: KeyboardEvent): Key => {
let key = modifiedKeyName(e.key); let key = modifiedKeyName(e.key);
let shift = e.shiftKey; let shift = e.shiftKey;
if (key.length === 1 && key.toUpperCase() === key.toLowerCase()) { if (key.length === 1 && key.toUpperCase() === key.toLowerCase()) {
@ -28,7 +36,7 @@ const fromKeyboardEvent = (e) => {
}; };
}; };
const fromMapKey = (key) => { const fromMapKey = (key: string): Key => {
if (key.startsWith('<') && key.endsWith('>')) { if (key.startsWith('<') && key.endsWith('>')) {
let inner = key.slice(1, -1); let inner = key.slice(1, -1);
let shift = inner.includes('S-'); let shift = inner.includes('S-');
@ -55,8 +63,10 @@ const fromMapKey = (key) => {
}; };
}; };
const fromMapKeys = (keys) => { const fromMapKeys = (keys: string): Key[] => {
const fromMapKeysRecursive = (remainings, mappedKeys) => { const fromMapKeysRecursive = (
remainings: string, mappedKeys: Key[],
): Key[] => {
if (remainings.length === 0) { if (remainings.length === 0) {
return mappedKeys; return mappedKeys;
} }
@ -78,7 +88,7 @@ const fromMapKeys = (keys) => {
return fromMapKeysRecursive(keys, []); return fromMapKeysRecursive(keys, []);
}; };
const equals = (e1, e2) => { const equals = (e1: Key, e2: Key): boolean => {
return e1.key === e2.key && return e1.key === e2.key &&
e1.ctrlKey === e2.ctrlKey && e1.ctrlKey === e2.ctrlKey &&
e1.metaKey === e2.metaKey && e1.metaKey === e2.metaKey &&

@ -1,4 +1,4 @@
const fromWildcard = (pattern) => { const fromWildcard = (pattern: string): RegExp => {
let regexStr = '^' + pattern.replace(/\*/g, '.*') + '$'; let regexStr = '^' + pattern.replace(/\*/g, '.*') + '$';
return new RegExp(regexStr); return new RegExp(regexStr);
}; };