import * as Ajv from "ajv"; import Keymaps, { KeymapsJSON } from "./Keymaps"; import Search, { SearchJSON } from "./Search"; import Properties, { PropertiesJSON } from "./Properties"; import Blacklist, { BlacklistJSON } from "./Blacklist"; import validate from "./validate"; export type SettingsJSON = { keymaps?: KeymapsJSON; search?: SearchJSON; properties?: PropertiesJSON; blacklist?: BlacklistJSON; }; export default class Settings { public keymaps: Keymaps; public search: Search; public properties: Properties; public blacklist: Blacklist; constructor({ keymaps, search, properties, blacklist, }: { keymaps: Keymaps; search: Search; properties: Properties; blacklist: Blacklist; }) { this.keymaps = keymaps; this.search = search; this.properties = properties; this.blacklist = blacklist; } static fromJSON(json: unknown): Settings { const valid = validate(json); if (!valid) { const message = (validate as any) .errors!.map((err: Ajv.ErrorObject) => { return `'${err.instancePath}' ${err.message}`; }) .join("; "); throw new TypeError(message); } const obj = json as SettingsJSON; const settings = { ...DefaultSetting }; if (obj.keymaps) { settings.keymaps = Keymaps.fromJSON(obj.keymaps); } if (obj.search) { settings.search = Search.fromJSON(obj.search); } if (obj.properties) { settings.properties = Properties.fromJSON(obj.properties); } if (obj.blacklist) { settings.blacklist = Blacklist.fromJSON(obj.blacklist); } return new Settings(settings); } toJSON(): SettingsJSON { return { keymaps: this.keymaps.toJSON(), search: this.search.toJSON(), properties: this.properties.toJSON(), blacklist: this.blacklist.toJSON(), }; } } export const DefaultSettingJSONText = `{ "keymaps": { "a": { "type": "scroll.home" }, "x": { "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 }, "Z": { "type": "command.show.buffer" }, "p": { "type": "scroll.vertically", "count": -1 }, "n": { "type": "scroll.vertically", "count": 1 }, "b": { "type": "scroll.horizonally", "count": -1 }, "f": { "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 }, "<": { "type": "scroll.top" }, ">": { "type": "scroll.bottom" }, "e": { "type": "scroll.end" }, "k": { "type": "tabs.close" }, "K": { "type": "tabs.close", "select": "left" }, "/": { "type": "tabs.reopen" }, "B": { "type": "tabs.prev" }, "F": { "type": "tabs.next" }, "A": { "type": "tabs.first" }, "E": { "type": "tabs.last" }, "": { "type": "tabs.prevsel" }, "g": { "type": "tabs.reload", "cache": false }, "G": { "type": "tabs.reload", "cache": true }, "j": { "type": "follow.start", "newTab": false }, "J": { "type": "follow.start", "newTab": true, "background": false }, "m": { "type": "mark.set.prefix" }, "'": { "type": "mark.jump.prefix" }, "l": { "type": "navigate.history.prev" }, "r": { "type": "navigate.history.next" }, "[[": { "type": "navigate.link.prev" }, "]]": { "type": "navigate.link.next" }, "u": { "type": "navigate.parent" }, "U": { "type": "navigate.root" }, ".": { "type": "page.source" }, "R": { "type": "tabs.reader.toggle" }, "w": { "type": "urls.yank" }, "y": { "type": "urls.paste", "newTab": false }, "Y": { "type": "urls.paste", "newTab": true }, "": { "type": "find.start" }, "s": { "type": "find.next" }, "S": { "type": "find.prev" }, "z": { "type": "repeat.last" }, "": { "type": "addon.toggle.enabled" } }, "search": { "default": "d", "engines": { "a": "https://wiki.archlinux.org/index.php?search={}", "aa": "https://aur.archlinux.org/packages?K={}", "ap": "https://archlinux.org/packages/?q={}", "d": "https://html.duckduckgo.com/html?q={}", "db": "https://packages.debian.org/search?keywords={}", "f": "https://search.f-droid.org/?q={}", "fs": "https://directory.fsf.org/w/index.php?search={}", "g": "https://github.com/search?q={}", "hoog": "https://hoogle.haskell.org/?hoogle={}", "i": "https://imdb.com/find?q={}", "o": "https://openlibrary.org/search?q={}", "p": "https://ptv.libreau.org/?q={}", "r": "https://reddit.com/r/all/search?q={}", "t": "https://twitter.com/search?q={}", "w": "https://en.wikipedia.org/w/index.php?search={}", "wt": "https://wiktionary.org/w/index.php?search={}", "wy": "https://wikivoyage.org/w/index.php?search={}", "wz": "https://zh.wikipedia.org/w/index.php?search={}", "y": "https://youtube.com/search?q={}" } }, "properties": { "hintchars": "abcdefghijklmnopqrstuvwxyz", "smoothscroll": false, "complete": "sbh", "colorscheme": "system" }, "blacklist": [ ] }`; export const DefaultSetting: Settings = Settings.fromJSON( JSON.parse(DefaultSettingJSONText) );