From c60d0e7392fc708e961614d6b756a045de74f458 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Tue, 30 Apr 2019 14:00:07 +0900 Subject: Rename .js/.jsx to .ts/.tsx --- src/shared/blacklists.js | 13 ----- src/shared/blacklists.ts | 13 +++++ src/shared/messages.js | 71 ------------------------- src/shared/messages.ts | 71 +++++++++++++++++++++++++ src/shared/operations.js | 78 --------------------------- src/shared/operations.ts | 78 +++++++++++++++++++++++++++ src/shared/settings/default.js | 85 ------------------------------ src/shared/settings/default.ts | 85 ++++++++++++++++++++++++++++++ src/shared/settings/properties.js | 24 --------- src/shared/settings/properties.ts | 24 +++++++++ src/shared/settings/storage.js | 32 ----------- src/shared/settings/storage.ts | 32 +++++++++++ src/shared/settings/validator.js | 76 --------------------------- src/shared/settings/validator.ts | 76 +++++++++++++++++++++++++++ src/shared/settings/values.js | 108 -------------------------------------- src/shared/settings/values.ts | 108 ++++++++++++++++++++++++++++++++++++++ src/shared/urls.js | 43 --------------- src/shared/urls.ts | 43 +++++++++++++++ src/shared/utils/dom.js | 108 -------------------------------------- src/shared/utils/dom.ts | 108 ++++++++++++++++++++++++++++++++++++++ src/shared/utils/keys.js | 89 ------------------------------- src/shared/utils/keys.ts | 89 +++++++++++++++++++++++++++++++ src/shared/utils/re.js | 6 --- src/shared/utils/re.ts | 6 +++ 24 files changed, 733 insertions(+), 733 deletions(-) delete mode 100644 src/shared/blacklists.js create mode 100644 src/shared/blacklists.ts delete mode 100644 src/shared/messages.js create mode 100644 src/shared/messages.ts delete mode 100644 src/shared/operations.js create mode 100644 src/shared/operations.ts delete mode 100644 src/shared/settings/default.js create mode 100644 src/shared/settings/default.ts delete mode 100644 src/shared/settings/properties.js create mode 100644 src/shared/settings/properties.ts delete mode 100644 src/shared/settings/storage.js create mode 100644 src/shared/settings/storage.ts delete mode 100644 src/shared/settings/validator.js create mode 100644 src/shared/settings/validator.ts delete mode 100644 src/shared/settings/values.js create mode 100644 src/shared/settings/values.ts delete mode 100644 src/shared/urls.js create mode 100644 src/shared/urls.ts delete mode 100644 src/shared/utils/dom.js create mode 100644 src/shared/utils/dom.ts delete mode 100644 src/shared/utils/keys.js create mode 100644 src/shared/utils/keys.ts delete mode 100644 src/shared/utils/re.js create mode 100644 src/shared/utils/re.ts (limited to 'src/shared') diff --git a/src/shared/blacklists.js b/src/shared/blacklists.js deleted file mode 100644 index 61720c3..0000000 --- a/src/shared/blacklists.js +++ /dev/null @@ -1,13 +0,0 @@ -import * as re from 'shared/utils/re'; - -const includes = (blacklist, url) => { - let u = new URL(url); - return blacklist.some((item) => { - if (!item.includes('/')) { - return re.fromWildcard(item).test(u.host); - } - return re.fromWildcard(item).test(u.host + u.pathname); - }); -}; - -export { includes }; diff --git a/src/shared/blacklists.ts b/src/shared/blacklists.ts new file mode 100644 index 0000000..61720c3 --- /dev/null +++ b/src/shared/blacklists.ts @@ -0,0 +1,13 @@ +import * as re from 'shared/utils/re'; + +const includes = (blacklist, url) => { + let u = new URL(url); + return blacklist.some((item) => { + if (!item.includes('/')) { + return re.fromWildcard(item).test(u.host); + } + return re.fromWildcard(item).test(u.host + u.pathname); + }); +}; + +export { includes }; diff --git a/src/shared/messages.js b/src/shared/messages.js deleted file mode 100644 index ddf3368..0000000 --- a/src/shared/messages.js +++ /dev/null @@ -1,71 +0,0 @@ -const onWebMessage = (listener) => { - window.addEventListener('message', (event) => { - let sender = event.source; - let message = null; - try { - message = JSON.parse(event.data); - } catch (e) { - // ignore unexpected message - return; - } - listener(message, sender); - }); -}; - -const onBackgroundMessage = (listener) => { - browser.runtime.onMessage.addListener(listener); -}; - -const onMessage = (listener) => { - onWebMessage(listener); - onBackgroundMessage(listener); -}; - -export default { - BACKGROUND_OPERATION: 'background.operation', - - CONSOLE_UNFOCUS: 'console.unfocus', - CONSOLE_ENTER_COMMAND: 'console.enter.command', - CONSOLE_ENTER_FIND: 'console.enter.find', - CONSOLE_QUERY_COMPLETIONS: 'console.query.completions', - CONSOLE_SHOW_COMMAND: 'console.show.command', - CONSOLE_SHOW_ERROR: 'console.show.error', - CONSOLE_SHOW_INFO: 'console.show.info', - CONSOLE_SHOW_FIND: 'console.show.find', - CONSOLE_HIDE: 'console.hide', - - FOLLOW_START: 'follow.start', - FOLLOW_REQUEST_COUNT_TARGETS: 'follow.request.count.targets', - FOLLOW_RESPONSE_COUNT_TARGETS: 'follow.response.count.targets', - FOLLOW_CREATE_HINTS: 'follow.create.hints', - FOLLOW_SHOW_HINTS: 'follow.update.hints', - FOLLOW_REMOVE_HINTS: 'follow.remove.hints', - FOLLOW_ACTIVATE: 'follow.activate', - FOLLOW_KEY_PRESS: 'follow.key.press', - - MARK_SET_GLOBAL: 'mark.set.global', - MARK_JUMP_GLOBAL: 'mark.jump.global', - - TAB_SCROLL_TO: 'tab.scroll.to', - - FIND_NEXT: 'find.next', - FIND_PREV: 'find.prev', - FIND_GET_KEYWORD: 'find.get.keyword', - FIND_SET_KEYWORD: 'find.set.keyword', - - ADDON_ENABLED_QUERY: 'addon.enabled.query', - ADDON_ENABLED_RESPONSE: 'addon.enabled.response', - ADDON_TOGGLE_ENABLED: 'addon.toggle.enabled', - - OPEN_URL: 'open.url', - - SETTINGS_CHANGED: 'settings.changed', - SETTINGS_QUERY: 'settings.query', - - WINDOW_TOP_MESSAGE: 'window.top.message', - CONSOLE_FRAME_MESSAGE: 'console.frame.message', - - onWebMessage, - onBackgroundMessage, - onMessage, -}; diff --git a/src/shared/messages.ts b/src/shared/messages.ts new file mode 100644 index 0000000..ddf3368 --- /dev/null +++ b/src/shared/messages.ts @@ -0,0 +1,71 @@ +const onWebMessage = (listener) => { + window.addEventListener('message', (event) => { + let sender = event.source; + let message = null; + try { + message = JSON.parse(event.data); + } catch (e) { + // ignore unexpected message + return; + } + listener(message, sender); + }); +}; + +const onBackgroundMessage = (listener) => { + browser.runtime.onMessage.addListener(listener); +}; + +const onMessage = (listener) => { + onWebMessage(listener); + onBackgroundMessage(listener); +}; + +export default { + BACKGROUND_OPERATION: 'background.operation', + + CONSOLE_UNFOCUS: 'console.unfocus', + CONSOLE_ENTER_COMMAND: 'console.enter.command', + CONSOLE_ENTER_FIND: 'console.enter.find', + CONSOLE_QUERY_COMPLETIONS: 'console.query.completions', + CONSOLE_SHOW_COMMAND: 'console.show.command', + CONSOLE_SHOW_ERROR: 'console.show.error', + CONSOLE_SHOW_INFO: 'console.show.info', + CONSOLE_SHOW_FIND: 'console.show.find', + CONSOLE_HIDE: 'console.hide', + + FOLLOW_START: 'follow.start', + FOLLOW_REQUEST_COUNT_TARGETS: 'follow.request.count.targets', + FOLLOW_RESPONSE_COUNT_TARGETS: 'follow.response.count.targets', + FOLLOW_CREATE_HINTS: 'follow.create.hints', + FOLLOW_SHOW_HINTS: 'follow.update.hints', + FOLLOW_REMOVE_HINTS: 'follow.remove.hints', + FOLLOW_ACTIVATE: 'follow.activate', + FOLLOW_KEY_PRESS: 'follow.key.press', + + MARK_SET_GLOBAL: 'mark.set.global', + MARK_JUMP_GLOBAL: 'mark.jump.global', + + TAB_SCROLL_TO: 'tab.scroll.to', + + FIND_NEXT: 'find.next', + FIND_PREV: 'find.prev', + FIND_GET_KEYWORD: 'find.get.keyword', + FIND_SET_KEYWORD: 'find.set.keyword', + + ADDON_ENABLED_QUERY: 'addon.enabled.query', + ADDON_ENABLED_RESPONSE: 'addon.enabled.response', + ADDON_TOGGLE_ENABLED: 'addon.toggle.enabled', + + OPEN_URL: 'open.url', + + SETTINGS_CHANGED: 'settings.changed', + SETTINGS_QUERY: 'settings.query', + + WINDOW_TOP_MESSAGE: 'window.top.message', + CONSOLE_FRAME_MESSAGE: 'console.frame.message', + + onWebMessage, + onBackgroundMessage, + onMessage, +}; diff --git a/src/shared/operations.js b/src/shared/operations.js deleted file mode 100644 index 8674f4d..0000000 --- a/src/shared/operations.js +++ /dev/null @@ -1,78 +0,0 @@ -export default { - // Hide console, or cancel some user actions - CANCEL: 'cancel', - - // Addons - ADDON_ENABLE: 'addon.enable', - ADDON_DISABLE: 'addon.disable', - ADDON_TOGGLE_ENABLED: 'addon.toggle.enabled', - - // Command - COMMAND_SHOW: 'command.show', - COMMAND_SHOW_OPEN: 'command.show.open', - COMMAND_SHOW_TABOPEN: 'command.show.tabopen', - COMMAND_SHOW_WINOPEN: 'command.show.winopen', - COMMAND_SHOW_BUFFER: 'command.show.buffer', - COMMAND_SHOW_ADDBOOKMARK: 'command.show.addbookmark', - - // Scrolls - SCROLL_VERTICALLY: 'scroll.vertically', - SCROLL_HORIZONALLY: 'scroll.horizonally', - SCROLL_PAGES: 'scroll.pages', - SCROLL_TOP: 'scroll.top', - SCROLL_BOTTOM: 'scroll.bottom', - SCROLL_HOME: 'scroll.home', - SCROLL_END: 'scroll.end', - - // Follows - FOLLOW_START: 'follow.start', - - // Navigations - NAVIGATE_HISTORY_PREV: 'navigate.history.prev', - NAVIGATE_HISTORY_NEXT: 'navigate.history.next', - NAVIGATE_LINK_PREV: 'navigate.link.prev', - NAVIGATE_LINK_NEXT: 'navigate.link.next', - NAVIGATE_PARENT: 'navigate.parent', - NAVIGATE_ROOT: 'navigate.root', - - // Focus - FOCUS_INPUT: 'focus.input', - - // Page - PAGE_SOURCE: 'page.source', - PAGE_HOME: 'page.home', - - // Tabs - TAB_CLOSE: 'tabs.close', - TAB_CLOSE_FORCE: 'tabs.close.force', - TAB_CLOSE_RIGHT: 'tabs.close.right', - TAB_REOPEN: 'tabs.reopen', - TAB_PREV: 'tabs.prev', - TAB_NEXT: 'tabs.next', - TAB_FIRST: 'tabs.first', - TAB_LAST: 'tabs.last', - TAB_PREV_SEL: 'tabs.prevsel', - TAB_RELOAD: 'tabs.reload', - TAB_PIN: 'tabs.pin', - TAB_UNPIN: 'tabs.unpin', - TAB_TOGGLE_PINNED: 'tabs.pin.toggle', - TAB_DUPLICATE: 'tabs.duplicate', - - // Zooms - ZOOM_IN: 'zoom.in', - ZOOM_OUT: 'zoom.out', - ZOOM_NEUTRAL: 'zoom.neutral', - - // Url yank/paste - URLS_YANK: 'urls.yank', - URLS_PASTE: 'urls.paste', - - // Find - FIND_START: 'find.start', - FIND_NEXT: 'find.next', - FIND_PREV: 'find.prev', - - // Mark - MARK_SET_PREFIX: 'mark.set.prefix', - MARK_JUMP_PREFIX: 'mark.jump.prefix', -}; diff --git a/src/shared/operations.ts b/src/shared/operations.ts new file mode 100644 index 0000000..8674f4d --- /dev/null +++ b/src/shared/operations.ts @@ -0,0 +1,78 @@ +export default { + // Hide console, or cancel some user actions + CANCEL: 'cancel', + + // Addons + ADDON_ENABLE: 'addon.enable', + ADDON_DISABLE: 'addon.disable', + ADDON_TOGGLE_ENABLED: 'addon.toggle.enabled', + + // Command + COMMAND_SHOW: 'command.show', + COMMAND_SHOW_OPEN: 'command.show.open', + COMMAND_SHOW_TABOPEN: 'command.show.tabopen', + COMMAND_SHOW_WINOPEN: 'command.show.winopen', + COMMAND_SHOW_BUFFER: 'command.show.buffer', + COMMAND_SHOW_ADDBOOKMARK: 'command.show.addbookmark', + + // Scrolls + SCROLL_VERTICALLY: 'scroll.vertically', + SCROLL_HORIZONALLY: 'scroll.horizonally', + SCROLL_PAGES: 'scroll.pages', + SCROLL_TOP: 'scroll.top', + SCROLL_BOTTOM: 'scroll.bottom', + SCROLL_HOME: 'scroll.home', + SCROLL_END: 'scroll.end', + + // Follows + FOLLOW_START: 'follow.start', + + // Navigations + NAVIGATE_HISTORY_PREV: 'navigate.history.prev', + NAVIGATE_HISTORY_NEXT: 'navigate.history.next', + NAVIGATE_LINK_PREV: 'navigate.link.prev', + NAVIGATE_LINK_NEXT: 'navigate.link.next', + NAVIGATE_PARENT: 'navigate.parent', + NAVIGATE_ROOT: 'navigate.root', + + // Focus + FOCUS_INPUT: 'focus.input', + + // Page + PAGE_SOURCE: 'page.source', + PAGE_HOME: 'page.home', + + // Tabs + TAB_CLOSE: 'tabs.close', + TAB_CLOSE_FORCE: 'tabs.close.force', + TAB_CLOSE_RIGHT: 'tabs.close.right', + TAB_REOPEN: 'tabs.reopen', + TAB_PREV: 'tabs.prev', + TAB_NEXT: 'tabs.next', + TAB_FIRST: 'tabs.first', + TAB_LAST: 'tabs.last', + TAB_PREV_SEL: 'tabs.prevsel', + TAB_RELOAD: 'tabs.reload', + TAB_PIN: 'tabs.pin', + TAB_UNPIN: 'tabs.unpin', + TAB_TOGGLE_PINNED: 'tabs.pin.toggle', + TAB_DUPLICATE: 'tabs.duplicate', + + // Zooms + ZOOM_IN: 'zoom.in', + ZOOM_OUT: 'zoom.out', + ZOOM_NEUTRAL: 'zoom.neutral', + + // Url yank/paste + URLS_YANK: 'urls.yank', + URLS_PASTE: 'urls.paste', + + // Find + FIND_START: 'find.start', + FIND_NEXT: 'find.next', + FIND_PREV: 'find.prev', + + // Mark + MARK_SET_PREFIX: 'mark.set.prefix', + MARK_JUMP_PREFIX: 'mark.jump.prefix', +}; diff --git a/src/shared/settings/default.js b/src/shared/settings/default.js deleted file mode 100644 index 6523a74..0000000 --- a/src/shared/settings/default.js +++ /dev/null @@ -1,85 +0,0 @@ -export default { - source: 'json', - json: `{ - "keymaps": { - "0": { "type": "scroll.home" }, - ":": { "type": "command.show" }, - "o": { "type": "command.show.open", "alter": false }, - "O": { "type": "command.show.open", "alter": true }, - "t": { "type": "command.show.tabopen", "alter": false }, - "T": { "type": "command.show.tabopen", "alter": true }, - "w": { "type": "command.show.winopen", "alter": false }, - "W": { "type": "command.show.winopen", "alter": true }, - "b": { "type": "command.show.buffer" }, - "a": { "type": "command.show.addbookmark", "alter": true }, - "k": { "type": "scroll.vertically", "count": -1 }, - "j": { "type": "scroll.vertically", "count": 1 }, - "h": { "type": "scroll.horizonally", "count": -1 }, - "l": { "type": "scroll.horizonally", "count": 1 }, - "": { "type": "scroll.pages", "count": -0.5 }, - "": { "type": "scroll.pages", "count": 0.5 }, - "": { "type": "scroll.pages", "count": -1 }, - "": { "type": "scroll.pages", "count": 1 }, - "gg": { "type": "scroll.top" }, - "G": { "type": "scroll.bottom" }, - "$": { "type": "scroll.end" }, - "d": { "type": "tabs.close" }, - "D": { "type": "tabs.close.right" }, - "!d": { "type": "tabs.close.force" }, - "u": { "type": "tabs.reopen" }, - "K": { "type": "tabs.prev", "count": 1 }, - "J": { "type": "tabs.next", "count": 1 }, - "gT": { "type": "tabs.prev", "count": 1 }, - "gt": { "type": "tabs.next", "count": 1 }, - "g0": { "type": "tabs.first" }, - "g$": { "type": "tabs.last" }, - "": { "type": "tabs.prevsel" }, - "r": { "type": "tabs.reload", "cache": false }, - "R": { "type": "tabs.reload", "cache": true }, - "zp": { "type": "tabs.pin.toggle" }, - "zd": { "type": "tabs.duplicate" }, - "zi": { "type": "zoom.in" }, - "zo": { "type": "zoom.out" }, - "zz": { "type": "zoom.neutral" }, - "f": { "type": "follow.start", "newTab": false }, - "F": { "type": "follow.start", "newTab": true, "background": false }, - "m": { "type": "mark.set.prefix" }, - "'": { "type": "mark.jump.prefix" }, - "H": { "type": "navigate.history.prev" }, - "L": { "type": "navigate.history.next" }, - "[[": { "type": "navigate.link.prev" }, - "]]": { "type": "navigate.link.next" }, - "gu": { "type": "navigate.parent" }, - "gU": { "type": "navigate.root" }, - "gi": { "type": "focus.input" }, - "gf": { "type": "page.source" }, - "gh": { "type": "page.home" }, - "gH": { "type": "page.home", "newTab": true }, - "y": { "type": "urls.yank" }, - "p": { "type": "urls.paste", "newTab": false }, - "P": { "type": "urls.paste", "newTab": true }, - "/": { "type": "find.start" }, - "n": { "type": "find.next" }, - "N": { "type": "find.prev" }, - "": { "type": "addon.toggle.enabled" } - }, - "search": { - "default": "google", - "engines": { - "google": "https://google.com/search?q={}", - "yahoo": "https://search.yahoo.com/search?p={}", - "bing": "https://www.bing.com/search?q={}", - "duckduckgo": "https://duckduckgo.com/?q={}", - "twitter": "https://twitter.com/search?q={}", - "wikipedia": "https://en.wikipedia.org/w/index.php?search={}" - } - }, - "properties": { - "hintchars": "abcdefghijklmnopqrstuvwxyz", - "smoothscroll": false, - "complete": "sbh" - }, - "blacklist": [ - ] -}`, -}; diff --git a/src/shared/settings/default.ts b/src/shared/settings/default.ts new file mode 100644 index 0000000..6523a74 --- /dev/null +++ b/src/shared/settings/default.ts @@ -0,0 +1,85 @@ +export default { + source: 'json', + json: `{ + "keymaps": { + "0": { "type": "scroll.home" }, + ":": { "type": "command.show" }, + "o": { "type": "command.show.open", "alter": false }, + "O": { "type": "command.show.open", "alter": true }, + "t": { "type": "command.show.tabopen", "alter": false }, + "T": { "type": "command.show.tabopen", "alter": true }, + "w": { "type": "command.show.winopen", "alter": false }, + "W": { "type": "command.show.winopen", "alter": true }, + "b": { "type": "command.show.buffer" }, + "a": { "type": "command.show.addbookmark", "alter": true }, + "k": { "type": "scroll.vertically", "count": -1 }, + "j": { "type": "scroll.vertically", "count": 1 }, + "h": { "type": "scroll.horizonally", "count": -1 }, + "l": { "type": "scroll.horizonally", "count": 1 }, + "": { "type": "scroll.pages", "count": -0.5 }, + "": { "type": "scroll.pages", "count": 0.5 }, + "": { "type": "scroll.pages", "count": -1 }, + "": { "type": "scroll.pages", "count": 1 }, + "gg": { "type": "scroll.top" }, + "G": { "type": "scroll.bottom" }, + "$": { "type": "scroll.end" }, + "d": { "type": "tabs.close" }, + "D": { "type": "tabs.close.right" }, + "!d": { "type": "tabs.close.force" }, + "u": { "type": "tabs.reopen" }, + "K": { "type": "tabs.prev", "count": 1 }, + "J": { "type": "tabs.next", "count": 1 }, + "gT": { "type": "tabs.prev", "count": 1 }, + "gt": { "type": "tabs.next", "count": 1 }, + "g0": { "type": "tabs.first" }, + "g$": { "type": "tabs.last" }, + "": { "type": "tabs.prevsel" }, + "r": { "type": "tabs.reload", "cache": false }, + "R": { "type": "tabs.reload", "cache": true }, + "zp": { "type": "tabs.pin.toggle" }, + "zd": { "type": "tabs.duplicate" }, + "zi": { "type": "zoom.in" }, + "zo": { "type": "zoom.out" }, + "zz": { "type": "zoom.neutral" }, + "f": { "type": "follow.start", "newTab": false }, + "F": { "type": "follow.start", "newTab": true, "background": false }, + "m": { "type": "mark.set.prefix" }, + "'": { "type": "mark.jump.prefix" }, + "H": { "type": "navigate.history.prev" }, + "L": { "type": "navigate.history.next" }, + "[[": { "type": "navigate.link.prev" }, + "]]": { "type": "navigate.link.next" }, + "gu": { "type": "navigate.parent" }, + "gU": { "type": "navigate.root" }, + "gi": { "type": "focus.input" }, + "gf": { "type": "page.source" }, + "gh": { "type": "page.home" }, + "gH": { "type": "page.home", "newTab": true }, + "y": { "type": "urls.yank" }, + "p": { "type": "urls.paste", "newTab": false }, + "P": { "type": "urls.paste", "newTab": true }, + "/": { "type": "find.start" }, + "n": { "type": "find.next" }, + "N": { "type": "find.prev" }, + "": { "type": "addon.toggle.enabled" } + }, + "search": { + "default": "google", + "engines": { + "google": "https://google.com/search?q={}", + "yahoo": "https://search.yahoo.com/search?p={}", + "bing": "https://www.bing.com/search?q={}", + "duckduckgo": "https://duckduckgo.com/?q={}", + "twitter": "https://twitter.com/search?q={}", + "wikipedia": "https://en.wikipedia.org/w/index.php?search={}" + } + }, + "properties": { + "hintchars": "abcdefghijklmnopqrstuvwxyz", + "smoothscroll": false, + "complete": "sbh" + }, + "blacklist": [ + ] +}`, +}; diff --git a/src/shared/settings/properties.js b/src/shared/settings/properties.js deleted file mode 100644 index f8e61a0..0000000 --- a/src/shared/settings/properties.js +++ /dev/null @@ -1,24 +0,0 @@ -// describe types of a propety as: -// mystr: 'string', -// mynum: 'number', -// mybool: 'boolean', -const types = { - hintchars: 'string', - smoothscroll: 'boolean', - complete: 'string', -}; - -// describe default values of a property -const defaults = { - hintchars: 'abcdefghijklmnopqrstuvwxyz', - smoothscroll: false, - complete: 'sbh', -}; - -const docs = { - hintchars: 'hint characters on follow mode', - smoothscroll: 'smooth scroll', - complete: 'which are completed at the open page', -}; - -export { types, defaults, docs }; diff --git a/src/shared/settings/properties.ts b/src/shared/settings/properties.ts new file mode 100644 index 0000000..f8e61a0 --- /dev/null +++ b/src/shared/settings/properties.ts @@ -0,0 +1,24 @@ +// describe types of a propety as: +// mystr: 'string', +// mynum: 'number', +// mybool: 'boolean', +const types = { + hintchars: 'string', + smoothscroll: 'boolean', + complete: 'string', +}; + +// describe default values of a property +const defaults = { + hintchars: 'abcdefghijklmnopqrstuvwxyz', + smoothscroll: false, + complete: 'sbh', +}; + +const docs = { + hintchars: 'hint characters on follow mode', + smoothscroll: 'smooth scroll', + complete: 'which are completed at the open page', +}; + +export { types, defaults, docs }; diff --git a/src/shared/settings/storage.js b/src/shared/settings/storage.js deleted file mode 100644 index 5dce3b0..0000000 --- a/src/shared/settings/storage.js +++ /dev/null @@ -1,32 +0,0 @@ -import DefaultSettings from './default'; -import * as settingsValues from './values'; - -const loadRaw = async() => { - let { settings } = await browser.storage.local.get('settings'); - if (!settings) { - return DefaultSettings; - } - return { ...DefaultSettings, ...settings }; -}; - -const loadValue = async() => { - let settings = await loadRaw(); - let value = JSON.parse(DefaultSettings.json); - if (settings.source === 'json') { - value = settingsValues.valueFromJson(settings.json); - } else if (settings.source === 'form') { - value = settingsValues.valueFromForm(settings.form); - } - if (!value.properties) { - value.properties = {}; - } - return { ...settingsValues.valueFromJson(DefaultSettings.json), ...value }; -}; - -const save = (settings) => { - return browser.storage.local.set({ - settings, - }); -}; - -export { loadRaw, loadValue, save }; diff --git a/src/shared/settings/storage.ts b/src/shared/settings/storage.ts new file mode 100644 index 0000000..5dce3b0 --- /dev/null +++ b/src/shared/settings/storage.ts @@ -0,0 +1,32 @@ +import DefaultSettings from './default'; +import * as settingsValues from './values'; + +const loadRaw = async() => { + let { settings } = await browser.storage.local.get('settings'); + if (!settings) { + return DefaultSettings; + } + return { ...DefaultSettings, ...settings }; +}; + +const loadValue = async() => { + let settings = await loadRaw(); + let value = JSON.parse(DefaultSettings.json); + if (settings.source === 'json') { + value = settingsValues.valueFromJson(settings.json); + } else if (settings.source === 'form') { + value = settingsValues.valueFromForm(settings.form); + } + if (!value.properties) { + value.properties = {}; + } + return { ...settingsValues.valueFromJson(DefaultSettings.json), ...value }; +}; + +const save = (settings) => { + return browser.storage.local.set({ + settings, + }); +}; + +export { loadRaw, loadValue, save }; diff --git a/src/shared/settings/validator.js b/src/shared/settings/validator.js deleted file mode 100644 index a800a52..0000000 --- a/src/shared/settings/validator.js +++ /dev/null @@ -1,76 +0,0 @@ -import operations from 'shared/operations'; -import * as properties from './properties'; - -const VALID_TOP_KEYS = ['keymaps', 'search', 'blacklist', 'properties']; -const VALID_OPERATION_VALUES = Object.keys(operations).map((key) => { - return operations[key]; -}); - -const validateInvalidTopKeys = (settings) => { - let invalidKey = Object.keys(settings).find((key) => { - return !VALID_TOP_KEYS.includes(key); - }); - if (invalidKey) { - throw Error(`Unknown key: "${invalidKey}"`); - } -}; - -const validateKeymaps = (keymaps) => { - for (let key of Object.keys(keymaps)) { - let value = keymaps[key]; - if (!VALID_OPERATION_VALUES.includes(value.type)) { - throw Error(`Unknown operation: "${value.type}"`); - } - } -}; - -const validateSearch = (search) => { - let engines = search.engines; - for (let key of Object.keys(engines)) { - if ((/\s/).test(key)) { - throw new Error( - `While space in search engine name is not allowed: "${key}"` - ); - } - let url = engines[key]; - if (!url.match(/{}/)) { - throw new Error(`No {}-placeholders in URL of "${key}"`); - } - if (url.match(/{}/g).length > 1) { - throw new Error(`Multiple {}-placeholders in URL of "${key}"`); - } - } - - if (!search.default) { - throw new Error(`Default engine is not set`); - } - if (!Object.keys(engines).includes(search.default)) { - throw new Error(`Default engine "${search.default}" not found`); - } -}; - -const validateProperties = (props) => { - for (let name of Object.keys(props)) { - if (!properties.types[name]) { - throw new Error(`Unknown property name: "${name}"`); - } - if (typeof props[name] !== properties.types[name]) { - throw new Error(`Invalid type for property: "${name}"`); - } - } -}; - -const validate = (settings) => { - validateInvalidTopKeys(settings); - if (settings.keymaps) { - validateKeymaps(settings.keymaps); - } - if (settings.search) { - validateSearch(settings.search); - } - if (settings.properties) { - validateProperties(settings.properties); - } -}; - -export { validate }; diff --git a/src/shared/settings/validator.ts b/src/shared/settings/validator.ts new file mode 100644 index 0000000..a800a52 --- /dev/null +++ b/src/shared/settings/validator.ts @@ -0,0 +1,76 @@ +import operations from 'shared/operations'; +import * as properties from './properties'; + +const VALID_TOP_KEYS = ['keymaps', 'search', 'blacklist', 'properties']; +const VALID_OPERATION_VALUES = Object.keys(operations).map((key) => { + return operations[key]; +}); + +const validateInvalidTopKeys = (settings) => { + let invalidKey = Object.keys(settings).find((key) => { + return !VALID_TOP_KEYS.includes(key); + }); + if (invalidKey) { + throw Error(`Unknown key: "${invalidKey}"`); + } +}; + +const validateKeymaps = (keymaps) => { + for (let key of Object.keys(keymaps)) { + let value = keymaps[key]; + if (!VALID_OPERATION_VALUES.includes(value.type)) { + throw Error(`Unknown operation: "${value.type}"`); + } + } +}; + +const validateSearch = (search) => { + let engines = search.engines; + for (let key of Object.keys(engines)) { + if ((/\s/).test(key)) { + throw new Error( + `While space in search engine name is not allowed: "${key}"` + ); + } + let url = engines[key]; + if (!url.match(/{}/)) { + throw new Error(`No {}-placeholders in URL of "${key}"`); + } + if (url.match(/{}/g).length > 1) { + throw new Error(`Multiple {}-placeholders in URL of "${key}"`); + } + } + + if (!search.default) { + throw new Error(`Default engine is not set`); + } + if (!Object.keys(engines).includes(search.default)) { + throw new Error(`Default engine "${search.default}" not found`); + } +}; + +const validateProperties = (props) => { + for (let name of Object.keys(props)) { + if (!properties.types[name]) { + throw new Error(`Unknown property name: "${name}"`); + } + if (typeof props[name] !== properties.types[name]) { + throw new Error(`Invalid type for property: "${name}"`); + } + } +}; + +const validate = (settings) => { + validateInvalidTopKeys(settings); + if (settings.keymaps) { + validateKeymaps(settings.keymaps); + } + if (settings.search) { + validateSearch(settings.search); + } + if (settings.properties) { + validateProperties(settings.properties); + } +}; + +export { validate }; diff --git a/src/shared/settings/values.js b/src/shared/settings/values.js deleted file mode 100644 index 9828af6..0000000 --- a/src/shared/settings/values.js +++ /dev/null @@ -1,108 +0,0 @@ -import * as properties from './properties'; - -const operationFromFormName = (name) => { - let [type, argStr] = name.split('?'); - let args = {}; - if (argStr) { - args = JSON.parse(argStr); - } - return { type, ...args }; -}; - -const operationToFormName = (op) => { - let type = op.type; - let args = { ...op }; - delete args.type; - - if (Object.keys(args).length === 0) { - return type; - } - return op.type + '?' + JSON.stringify(args); -}; - -const valueFromJson = (json) => { - return JSON.parse(json); -}; - -const valueFromForm = (form) => { - let keymaps = undefined; - if (form.keymaps) { - keymaps = {}; - for (let name of Object.keys(form.keymaps)) { - let keys = form.keymaps[name]; - keymaps[keys] = operationFromFormName(name); - } - } - - let search = undefined; - if (form.search) { - search = { default: form.search.default }; - - if (form.search.engines) { - search.engines = {}; - for (let [name, url] of form.search.engines) { - search.engines[name] = url; - } - } - } - - return { - keymaps, - search, - blacklist: form.blacklist, - properties: form.properties - }; -}; - -const jsonFromValue = (value) => { - return JSON.stringify(value, undefined, 2); -}; - -const formFromValue = (value, allowedOps) => { - let keymaps = undefined; - - if (value.keymaps) { - let allowedSet = new Set(allowedOps); - - keymaps = {}; - for (let keys of Object.keys(value.keymaps)) { - let op = operationToFormName(value.keymaps[keys]); - if (allowedSet.has(op)) { - keymaps[op] = keys; - } - } - } - - let search = undefined; - if (value.search) { - search = { default: value.search.default }; - if (value.search.engines) { - search.engines = Object.keys(value.search.engines).map((name) => { - return [name, value.search.engines[name]]; - }); - } - } - - let formProperties = { ...properties.defaults, ...value.properties }; - - return { - keymaps, - search, - blacklist: value.blacklist, - properties: formProperties, - }; -}; - -const jsonFromForm = (form) => { - return jsonFromValue(valueFromForm(form)); -}; - -const formFromJson = (json, allowedOps) => { - let value = valueFromJson(json); - return formFromValue(value, allowedOps); -}; - -export { - valueFromJson, valueFromForm, jsonFromValue, formFromValue, - jsonFromForm, formFromJson -}; diff --git a/src/shared/settings/values.ts b/src/shared/settings/values.ts new file mode 100644 index 0000000..9828af6 --- /dev/null +++ b/src/shared/settings/values.ts @@ -0,0 +1,108 @@ +import * as properties from './properties'; + +const operationFromFormName = (name) => { + let [type, argStr] = name.split('?'); + let args = {}; + if (argStr) { + args = JSON.parse(argStr); + } + return { type, ...args }; +}; + +const operationToFormName = (op) => { + let type = op.type; + let args = { ...op }; + delete args.type; + + if (Object.keys(args).length === 0) { + return type; + } + return op.type + '?' + JSON.stringify(args); +}; + +const valueFromJson = (json) => { + return JSON.parse(json); +}; + +const valueFromForm = (form) => { + let keymaps = undefined; + if (form.keymaps) { + keymaps = {}; + for (let name of Object.keys(form.keymaps)) { + let keys = form.keymaps[name]; + keymaps[keys] = operationFromFormName(name); + } + } + + let search = undefined; + if (form.search) { + search = { default: form.search.default }; + + if (form.search.engines) { + search.engines = {}; + for (let [name, url] of form.search.engines) { + search.engines[name] = url; + } + } + } + + return { + keymaps, + search, + blacklist: form.blacklist, + properties: form.properties + }; +}; + +const jsonFromValue = (value) => { + return JSON.stringify(value, undefined, 2); +}; + +const formFromValue = (value, allowedOps) => { + let keymaps = undefined; + + if (value.keymaps) { + let allowedSet = new Set(allowedOps); + + keymaps = {}; + for (let keys of Object.keys(value.keymaps)) { + let op = operationToFormName(value.keymaps[keys]); + if (allowedSet.has(op)) { + keymaps[op] = keys; + } + } + } + + let search = undefined; + if (value.search) { + search = { default: value.search.default }; + if (value.search.engines) { + search.engines = Object.keys(value.search.engines).map((name) => { + return [name, value.search.engines[name]]; + }); + } + } + + let formProperties = { ...properties.defaults, ...value.properties }; + + return { + keymaps, + search, + blacklist: value.blacklist, + properties: formProperties, + }; +}; + +const jsonFromForm = (form) => { + return jsonFromValue(valueFromForm(form)); +}; + +const formFromJson = (json, allowedOps) => { + let value = valueFromJson(json); + return formFromValue(value, allowedOps); +}; + +export { + valueFromJson, valueFromForm, jsonFromValue, formFromValue, + jsonFromForm, formFromJson +}; diff --git a/src/shared/urls.js b/src/shared/urls.js deleted file mode 100644 index 94b1220..0000000 --- a/src/shared/urls.js +++ /dev/null @@ -1,43 +0,0 @@ -const trimStart = (str) => { - // NOTE String.trimStart is available on Firefox 61 - return str.replace(/^\s+/, ''); -}; - -const SUPPORTED_PROTOCOLS = ['http:', 'https:', 'ftp:', 'mailto:', 'about:']; - -const searchUrl = (keywords, searchSettings) => { - try { - let u = new URL(keywords); - if (SUPPORTED_PROTOCOLS.includes(u.protocol.toLowerCase())) { - return u.href; - } - } catch (e) { - // fallthrough - } - if (keywords.includes('.') && !keywords.includes(' ')) { - return 'http://' + keywords; - } - let template = searchSettings.engines[searchSettings.default]; - let query = keywords; - - let first = trimStart(keywords).split(' ')[0]; - if (Object.keys(searchSettings.engines).includes(first)) { - template = searchSettings.engines[first]; - query = trimStart(trimStart(keywords).slice(first.length)); - } - return template.replace('{}', encodeURIComponent(query)); -}; - -const normalizeUrl = (url) => { - try { - let u = new URL(url); - if (SUPPORTED_PROTOCOLS.includes(u.protocol.toLowerCase())) { - return u.href; - } - } catch (e) { - // fallthrough - } - return 'http://' + url; -}; - -export { searchUrl, normalizeUrl }; diff --git a/src/shared/urls.ts b/src/shared/urls.ts new file mode 100644 index 0000000..94b1220 --- /dev/null +++ b/src/shared/urls.ts @@ -0,0 +1,43 @@ +const trimStart = (str) => { + // NOTE String.trimStart is available on Firefox 61 + return str.replace(/^\s+/, ''); +}; + +const SUPPORTED_PROTOCOLS = ['http:', 'https:', 'ftp:', 'mailto:', 'about:']; + +const searchUrl = (keywords, searchSettings) => { + try { + let u = new URL(keywords); + if (SUPPORTED_PROTOCOLS.includes(u.protocol.toLowerCase())) { + return u.href; + } + } catch (e) { + // fallthrough + } + if (keywords.includes('.') && !keywords.includes(' ')) { + return 'http://' + keywords; + } + let template = searchSettings.engines[searchSettings.default]; + let query = keywords; + + let first = trimStart(keywords).split(' ')[0]; + if (Object.keys(searchSettings.engines).includes(first)) { + template = searchSettings.engines[first]; + query = trimStart(trimStart(keywords).slice(first.length)); + } + return template.replace('{}', encodeURIComponent(query)); +}; + +const normalizeUrl = (url) => { + try { + let u = new URL(url); + if (SUPPORTED_PROTOCOLS.includes(u.protocol.toLowerCase())) { + return u.href; + } + } catch (e) { + // fallthrough + } + return 'http://' + url; +}; + +export { searchUrl, normalizeUrl }; diff --git a/src/shared/utils/dom.js b/src/shared/utils/dom.js deleted file mode 100644 index 974d534..0000000 --- a/src/shared/utils/dom.js +++ /dev/null @@ -1,108 +0,0 @@ -const isContentEditable = (element) => { - return element.hasAttribute('contenteditable') && ( - element.getAttribute('contenteditable').toLowerCase() === 'true' || - element.getAttribute('contenteditable').toLowerCase() === '' - ); -}; - -const rectangleCoordsRect = (coords) => { - let [left, top, right, bottom] = coords.split(',').map(n => Number(n)); - return { left, top, right, bottom }; -}; - -const circleCoordsRect = (coords) => { - let [x, y, r] = coords.split(',').map(n => Number(n)); - return { - left: x - r, - top: y - r, - right: x + r, - bottom: y + r, - }; -}; - -const polygonCoordsRect = (coords) => { - let params = coords.split(','); - let minx = Number(params[0]), - maxx = Number(params[0]), - miny = Number(params[1]), - maxy = Number(params[1]); - let len = Math.floor(params.length / 2); - for (let i = 2; i < len; i += 2) { - let x = Number(params[i]), - y = Number(params[i + 1]); - if (x < minx) { - minx = x; - } - if (x > maxx) { - maxx = x; - } - if (y < miny) { - miny = y; - } - if (y > maxy) { - maxy = y; - } - } - return { left: minx, top: miny, right: maxx, bottom: maxy }; -}; - -const viewportRect = (e) => { - if (e.tagName !== 'AREA') { - return e.getBoundingClientRect(); - } - - let mapElement = e.parentNode; - let imgElement = document.querySelector(`img[usemap="#${mapElement.name}"]`); - let { - left: mapLeft, - top: mapTop - } = imgElement.getBoundingClientRect(); - let coords = e.getAttribute('coords'); - let rect = { left: 0, top: 0, right: 0, bottom: 0 }; - switch (e.getAttribute('shape')) { - case 'rect': - case 'rectangle': - rect = rectangleCoordsRect(coords); - break; - case 'circ': - case 'circle': - rect = circleCoordsRect(coords); - break; - case 'poly': - case 'polygon': - rect = polygonCoordsRect(coords); - break; - } - return { - left: rect.left + mapLeft, - top: rect.top + mapTop, - right: rect.right + mapLeft, - bottom: rect.bottom + mapTop, - }; -}; - -const isVisible = (element) => { - let rect = element.getBoundingClientRect(); - let style = window.getComputedStyle(element); - - if (style.overflow !== 'visible' && (rect.width === 0 || rect.height === 0)) { - return false; - } - if (rect.right < 0 && rect.bottom < 0) { - return false; - } - if (window.innerWidth < rect.left && window.innerHeight < rect.top) { - return false; - } - if (element.nodeName === 'INPUT' && element.type.toLowerCase() === 'hidden') { - return false; - } - - let { display, visibility } = window.getComputedStyle(element); - if (display === 'none' || visibility === 'hidden') { - return false; - } - return true; -}; - -export { isContentEditable, viewportRect, isVisible }; diff --git a/src/shared/utils/dom.ts b/src/shared/utils/dom.ts new file mode 100644 index 0000000..974d534 --- /dev/null +++ b/src/shared/utils/dom.ts @@ -0,0 +1,108 @@ +const isContentEditable = (element) => { + return element.hasAttribute('contenteditable') && ( + element.getAttribute('contenteditable').toLowerCase() === 'true' || + element.getAttribute('contenteditable').toLowerCase() === '' + ); +}; + +const rectangleCoordsRect = (coords) => { + let [left, top, right, bottom] = coords.split(',').map(n => Number(n)); + return { left, top, right, bottom }; +}; + +const circleCoordsRect = (coords) => { + let [x, y, r] = coords.split(',').map(n => Number(n)); + return { + left: x - r, + top: y - r, + right: x + r, + bottom: y + r, + }; +}; + +const polygonCoordsRect = (coords) => { + let params = coords.split(','); + let minx = Number(params[0]), + maxx = Number(params[0]), + miny = Number(params[1]), + maxy = Number(params[1]); + let len = Math.floor(params.length / 2); + for (let i = 2; i < len; i += 2) { + let x = Number(params[i]), + y = Number(params[i + 1]); + if (x < minx) { + minx = x; + } + if (x > maxx) { + maxx = x; + } + if (y < miny) { + miny = y; + } + if (y > maxy) { + maxy = y; + } + } + return { left: minx, top: miny, right: maxx, bottom: maxy }; +}; + +const viewportRect = (e) => { + if (e.tagName !== 'AREA') { + return e.getBoundingClientRect(); + } + + let mapElement = e.parentNode; + let imgElement = document.querySelector(`img[usemap="#${mapElement.name}"]`); + let { + left: mapLeft, + top: mapTop + } = imgElement.getBoundingClientRect(); + let coords = e.getAttribute('coords'); + let rect = { left: 0, top: 0, right: 0, bottom: 0 }; + switch (e.getAttribute('shape')) { + case 'rect': + case 'rectangle': + rect = rectangleCoordsRect(coords); + break; + case 'circ': + case 'circle': + rect = circleCoordsRect(coords); + break; + case 'poly': + case 'polygon': + rect = polygonCoordsRect(coords); + break; + } + return { + left: rect.left + mapLeft, + top: rect.top + mapTop, + right: rect.right + mapLeft, + bottom: rect.bottom + mapTop, + }; +}; + +const isVisible = (element) => { + let rect = element.getBoundingClientRect(); + let style = window.getComputedStyle(element); + + if (style.overflow !== 'visible' && (rect.width === 0 || rect.height === 0)) { + return false; + } + if (rect.right < 0 && rect.bottom < 0) { + return false; + } + if (window.innerWidth < rect.left && window.innerHeight < rect.top) { + return false; + } + if (element.nodeName === 'INPUT' && element.type.toLowerCase() === 'hidden') { + return false; + } + + let { display, visibility } = window.getComputedStyle(element); + if (display === 'none' || visibility === 'hidden') { + return false; + } + return true; +}; + +export { isContentEditable, viewportRect, isVisible }; diff --git a/src/shared/utils/keys.js b/src/shared/utils/keys.js deleted file mode 100644 index f024069..0000000 --- a/src/shared/utils/keys.js +++ /dev/null @@ -1,89 +0,0 @@ -const modifiedKeyName = (name) => { - if (name === ' ') { - return 'Space'; - } - if (name.length === 1) { - return name; - } else if (name === 'Escape') { - return 'Esc'; - } - return name; -}; - -const fromKeyboardEvent = (e) => { - let key = modifiedKeyName(e.key); - let shift = e.shiftKey; - if (key.length === 1 && key.toUpperCase() === key.toLowerCase()) { - // make shift false for symbols to enable key bindings by symbold keys. - // But this limits key bindings by symbol keys with Shift (such as Shift+$>. - shift = false; - } - - return { - key: modifiedKeyName(e.key), - shiftKey: shift, - ctrlKey: e.ctrlKey, - altKey: e.altKey, - metaKey: e.metaKey, - }; -}; - -const fromMapKey = (key) => { - if (key.startsWith('<') && key.endsWith('>')) { - let inner = key.slice(1, -1); - let shift = inner.includes('S-'); - let base = inner.slice(inner.lastIndexOf('-') + 1); - if (shift && base.length === 1) { - base = base.toUpperCase(); - } else if (!shift && base.length === 1) { - base = base.toLowerCase(); - } - return { - key: base, - shiftKey: inner.includes('S-'), - ctrlKey: inner.includes('C-'), - altKey: inner.includes('A-'), - metaKey: inner.includes('M-'), - }; - } - return { - key: key, - shiftKey: key.toLowerCase() !== key, - ctrlKey: false, - altKey: false, - metaKey: false, - }; -}; - -const fromMapKeys = (keys) => { - const fromMapKeysRecursive = (remainings, mappedKeys) => { - if (remainings.length === 0) { - return mappedKeys; - } - - let nextPos = 1; - if (remainings.startsWith('<')) { - let ltPos = remainings.indexOf('>'); - if (ltPos > 0) { - nextPos = ltPos + 1; - } - } - - return fromMapKeysRecursive( - remainings.slice(nextPos), - mappedKeys.concat([fromMapKey(remainings.slice(0, nextPos))]) - ); - }; - - return fromMapKeysRecursive(keys, []); -}; - -const equals = (e1, e2) => { - return e1.key === e2.key && - e1.ctrlKey === e2.ctrlKey && - e1.metaKey === e2.metaKey && - e1.altKey === e2.altKey && - e1.shiftKey === e2.shiftKey; -}; - -export { fromKeyboardEvent, fromMapKey, fromMapKeys, equals }; diff --git a/src/shared/utils/keys.ts b/src/shared/utils/keys.ts new file mode 100644 index 0000000..f024069 --- /dev/null +++ b/src/shared/utils/keys.ts @@ -0,0 +1,89 @@ +const modifiedKeyName = (name) => { + if (name === ' ') { + return 'Space'; + } + if (name.length === 1) { + return name; + } else if (name === 'Escape') { + return 'Esc'; + } + return name; +}; + +const fromKeyboardEvent = (e) => { + let key = modifiedKeyName(e.key); + let shift = e.shiftKey; + if (key.length === 1 && key.toUpperCase() === key.toLowerCase()) { + // make shift false for symbols to enable key bindings by symbold keys. + // But this limits key bindings by symbol keys with Shift (such as Shift+$>. + shift = false; + } + + return { + key: modifiedKeyName(e.key), + shiftKey: shift, + ctrlKey: e.ctrlKey, + altKey: e.altKey, + metaKey: e.metaKey, + }; +}; + +const fromMapKey = (key) => { + if (key.startsWith('<') && key.endsWith('>')) { + let inner = key.slice(1, -1); + let shift = inner.includes('S-'); + let base = inner.slice(inner.lastIndexOf('-') + 1); + if (shift && base.length === 1) { + base = base.toUpperCase(); + } else if (!shift && base.length === 1) { + base = base.toLowerCase(); + } + return { + key: base, + shiftKey: inner.includes('S-'), + ctrlKey: inner.includes('C-'), + altKey: inner.includes('A-'), + metaKey: inner.includes('M-'), + }; + } + return { + key: key, + shiftKey: key.toLowerCase() !== key, + ctrlKey: false, + altKey: false, + metaKey: false, + }; +}; + +const fromMapKeys = (keys) => { + const fromMapKeysRecursive = (remainings, mappedKeys) => { + if (remainings.length === 0) { + return mappedKeys; + } + + let nextPos = 1; + if (remainings.startsWith('<')) { + let ltPos = remainings.indexOf('>'); + if (ltPos > 0) { + nextPos = ltPos + 1; + } + } + + return fromMapKeysRecursive( + remainings.slice(nextPos), + mappedKeys.concat([fromMapKey(remainings.slice(0, nextPos))]) + ); + }; + + return fromMapKeysRecursive(keys, []); +}; + +const equals = (e1, e2) => { + return e1.key === e2.key && + e1.ctrlKey === e2.ctrlKey && + e1.metaKey === e2.metaKey && + e1.altKey === e2.altKey && + e1.shiftKey === e2.shiftKey; +}; + +export { fromKeyboardEvent, fromMapKey, fromMapKeys, equals }; diff --git a/src/shared/utils/re.js b/src/shared/utils/re.js deleted file mode 100644 index 7db9091..0000000 --- a/src/shared/utils/re.js +++ /dev/null @@ -1,6 +0,0 @@ -const fromWildcard = (pattern) => { - let regexStr = '^' + pattern.replace(/\*/g, '.*') + '$'; - return new RegExp(regexStr); -}; - -export { fromWildcard }; diff --git a/src/shared/utils/re.ts b/src/shared/utils/re.ts new file mode 100644 index 0000000..7db9091 --- /dev/null +++ b/src/shared/utils/re.ts @@ -0,0 +1,6 @@ +const fromWildcard = (pattern) => { + let regexStr = '^' + pattern.replace(/\*/g, '.*') + '$'; + return new RegExp(regexStr); +}; + +export { fromWildcard }; -- cgit v1.2.3