diff options
Diffstat (limited to 'src/shared/settings')
-rw-r--r-- | src/shared/settings/default.js | 71 | ||||
-rw-r--r-- | src/shared/settings/properties.js | 16 | ||||
-rw-r--r-- | src/shared/settings/storage.js | 33 | ||||
-rw-r--r-- | src/shared/settings/validator.js | 76 | ||||
-rw-r--r-- | src/shared/settings/values.js | 32 |
5 files changed, 149 insertions, 79 deletions
diff --git a/src/shared/settings/default.js b/src/shared/settings/default.js index a9c363b..e81df2b 100644 --- a/src/shared/settings/default.js +++ b/src/shared/settings/default.js @@ -15,8 +15,6 @@ export default { "j": { "type": "scroll.vertically", "count": 1 }, "h": { "type": "scroll.horizonally", "count": -1 }, "l": { "type": "scroll.horizonally", "count": 1 }, - "<C-Y>": { "type": "scroll.vertically", "count": -1 }, - "<C-E>": { "type": "scroll.vertically", "count": 1 }, "<C-U>": { "type": "scroll.pages", "count": -0.5 }, "<C-D>": { "type": "scroll.pages", "count": 0.5 }, "<C-B>": { "type": "scroll.pages", "count": -1 }, @@ -47,6 +45,8 @@ export default { "gu": { "type": "navigate.parent" }, "gU": { "type": "navigate.root" }, "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" }, @@ -62,71 +62,8 @@ export default { "twitter": "https://twitter.com/search?q={}", "wikipedia": "https://en.wikipedia.org/w/index.php?search={}" } + }, + "properties": { } }`, - - 'form': { - 'keymaps': { - 'scroll.vertically?{"count":1}': 'j', - 'scroll.vertically?{"count":-1}': 'k', - 'scroll.horizonally?{"count":-1}': 'h', - 'scroll.horizonally?{"count":1}': 'l', - 'scroll.home': '0', - 'scroll.end': '$', - 'scroll.pages?{"count":-0.5}': '<C-U>', - 'scroll.pages?{"count":0.5}': '<C-D>', - 'scroll.pages?{"count":-1}': '<C-B>', - 'scroll.pages?{"count":1}': '<C-F>', - - 'tabs.close': 'd', - 'tabs.reopen': 'u', - 'tabs.next?{"count":1}': 'J', - 'tabs.prev?{"count":1}': 'K', - 'tabs.first': 'g0', - 'tabs.last': 'g$', - 'tabs.reload?{"cache":true}': 'r', - 'tabs.pin.toggle': 'zp', - 'tabs.duplicate': 'zd', - - 'follow.start?{"newTab":false}': 'f', - 'follow.start?{"newTab":true}': 'F', - 'navigate.history.prev': 'H', - 'navigate.history.next': 'L', - 'navigate.link.next': ']]', - 'navigate.link.prev': '[[', - 'navigate.parent': 'gu', - 'navigate.root': 'gU', - - 'find.start': '/', - 'find.next': 'n', - 'find.prev': 'N', - - 'command.show': ':', - 'command.show.open?{"alter":false}': 'o', - 'command.show.open?{"alter":true}': 'O', - 'command.show.tabopen?{"alter":false}': 't', - 'command.show.tabopen?{"alter":true}': 'T', - 'command.show.winopen?{"alter":false}': 'w', - 'command.show.winopen?{"alter":true}': 'W', - 'command.show.buffer': 'b', - - 'addon.toggle.enabled': '<S-Esc>', - 'urls.yank': 'y', - 'zoom.in': 'zi', - 'zoom.out': 'zo', - 'zoom.neutral': 'zz', - }, - '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={}'], - ] - }, - 'blacklist': [], - } }; diff --git a/src/shared/settings/properties.js b/src/shared/settings/properties.js new file mode 100644 index 0000000..37dc881 --- /dev/null +++ b/src/shared/settings/properties.js @@ -0,0 +1,16 @@ +// describe types of a propety as: +// mystr: 'string', +// mynum: 'number', +// mybool: 'boolean', +const types = { + hintchars: 'string', + smoothscroll: 'boolean', +}; + +// describe default values of a property +const defaults = { + hintchars: 'abcdefghijklmnopqrstuvwxyz', + smoothscroll: false, +}; + +export { types, defaults }; diff --git a/src/shared/settings/storage.js b/src/shared/settings/storage.js new file mode 100644 index 0000000..25ebfcd --- /dev/null +++ b/src/shared/settings/storage.js @@ -0,0 +1,33 @@ +import DefaultSettings from './default'; +import * as settingsValues from './values'; + +const loadRaw = () => { + return browser.storage.local.get('settings').then(({ settings }) => { + if (!settings) { + return DefaultSettings; + } + return Object.assign({}, DefaultSettings, settings); + }); +}; + +const loadValue = () => { + return loadRaw().then((settings) => { + 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); + } + return Object.assign({}, + 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 new file mode 100644 index 0000000..1589420 --- /dev/null +++ b/src/shared/settings/validator.js @@ -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 index 4482fbb..bd03be2 100644 --- a/src/shared/settings/values.js +++ b/src/shared/settings/values.js @@ -1,4 +1,4 @@ -import DefaultSettings from './default'; +import * as properties from './properties'; const operationFromFormName = (name) => { let [type, argStr] = name.split('?'); @@ -46,25 +46,28 @@ const valueFromForm = (form) => { } } - let blacklist = form.blacklist; - - return { keymaps, search, blacklist }; + return { + keymaps, + search, + blacklist: form.blacklist, + properties: form.properties + }; }; const jsonFromValue = (value) => { return JSON.stringify(value, undefined, 2); }; -const formFromValue = (value) => { - +const formFromValue = (value, allowedOps) => { let keymaps = undefined; + if (value.keymaps) { - let allowedOps = new Set(Object.keys(DefaultSettings.form.keymaps)); + let allowedSet = new Set(allowedOps); keymaps = {}; for (let keys of Object.keys(value.keymaps)) { let op = operationToFormName(value.keymaps[keys]); - if (allowedOps.has(op)) { + if (allowedSet.has(op)) { keymaps[op] = keys; } } @@ -80,18 +83,23 @@ const formFromValue = (value) => { } } - let blacklist = value.blacklist; + let formProperties = Object.assign({}, properties.defaults, value.properties); - return { keymaps, search, blacklist }; + return { + keymaps, + search, + blacklist: value.blacklist, + properties: formProperties, + }; }; const jsonFromForm = (form) => { return jsonFromValue(valueFromForm(form)); }; -const formFromJson = (json) => { +const formFromJson = (json, allowedOps) => { let value = valueFromJson(json); - return formFromValue(value); + return formFromValue(value, allowedOps); }; export { |