diff options
Diffstat (limited to 'src/shared/settings')
| -rw-r--r-- | src/shared/settings/Blacklist.ts | 49 | ||||
| -rw-r--r-- | src/shared/settings/Key.ts | 26 | ||||
| -rw-r--r-- | src/shared/settings/KeySequence.ts | 54 | ||||
| -rw-r--r-- | src/shared/settings/Keymaps.ts | 24 | ||||
| -rw-r--r-- | src/shared/settings/Properties.ts | 18 | ||||
| -rw-r--r-- | src/shared/settings/Search.ts | 52 | ||||
| -rw-r--r-- | src/shared/settings/Settings.ts | 54 | ||||
| -rw-r--r-- | src/shared/settings/schema.json | 84 | ||||
| -rw-r--r-- | src/shared/settings/validate.js | 567 | 
9 files changed, 731 insertions, 197 deletions
diff --git a/src/shared/settings/Blacklist.ts b/src/shared/settings/Blacklist.ts index 0cfbd71..6e6b51c 100644 --- a/src/shared/settings/Blacklist.ts +++ b/src/shared/settings/Blacklist.ts @@ -8,22 +8,10 @@ export type BlacklistItemJSON = string | {  export type BlacklistJSON = BlacklistItemJSON[];  const regexFromWildcard = (pattern: string): RegExp => { -  let regexStr = '^' + pattern.replace(/\*/g, '.*') + '$'; +  const regexStr = '^' + pattern.replace(/\*/g, '.*') + '$';    return new RegExp(regexStr);  }; -const isArrayOfString = (raw: any): boolean => { -  if (!Array.isArray(raw)) { -    return false; -  } -  for (let x of Array.from(raw)) { -    if (typeof x !== 'string') { -      return false; -    } -  } -  return true; -}; -  export class BlacklistItem {    public readonly pattern: string; @@ -47,30 +35,10 @@ export class BlacklistItem {      this.keyEntities = this.keys.map(Key.fromMapKey);    } -  static fromJSON(raw: any): BlacklistItem { -    if (typeof raw === 'string') { -      return new BlacklistItem(raw, false, []); -    } else if (typeof raw === 'object' && raw !== null) { -      if (!('url' in raw)) { -        throw new TypeError( -          `missing field "url" of blacklist item: ${JSON.stringify(raw)}`); -      } -      if (typeof raw.url !== 'string') { -        throw new TypeError( -          `invalid field "url" of blacklist item: ${JSON.stringify(raw)}`); -      } -      if (!('keys' in raw)) { -        throw new TypeError( -          `missing field "keys" of blacklist item: ${JSON.stringify(raw)}`); -      } -      if (!isArrayOfString(raw.keys)) { -        throw new TypeError( -          `invalid field "keys" of blacklist item: ${JSON.stringify(raw)}`); -      } -      return new BlacklistItem(raw.url as string, true, raw.keys as string[]); -    } -    throw new TypeError( -      `invalid format of blacklist item: ${JSON.stringify(raw)}`); +  static fromJSON(json: BlacklistItemJSON): BlacklistItem { +    return typeof json === 'string' +      ? new BlacklistItem(json, false, []) +      : new BlacklistItem(json.url, true, json.keys);    }    toJSON(): BlacklistItemJSON { @@ -103,11 +71,8 @@ export default class Blacklist {    ) {    } -  static fromJSON(json: any): Blacklist { -    if (!Array.isArray(json)) { -      throw new TypeError('blacklist is not an array: ' + JSON.stringify(json)); -    } -    let items = Array.from(json).map(item => BlacklistItem.fromJSON(item)); +  static fromJSON(json: BlacklistJSON): Blacklist { +    const items = json.map(o => BlacklistItem.fromJSON(o));      return new Blacklist(items);    } diff --git a/src/shared/settings/Key.ts b/src/shared/settings/Key.ts index b11eeb2..cfe1e7e 100644 --- a/src/shared/settings/Key.ts +++ b/src/shared/settings/Key.ts @@ -1,3 +1,5 @@ +const digits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; +  export default class Key {    public readonly key: string; @@ -9,12 +11,18 @@ export default class Key {    public readonly meta: boolean; -  constructor({ key, shift, ctrl, alt, meta }: { +  constructor({ +    key, +    shift = false, +    ctrl = false, +    alt = false, +    meta = false, +  }: {      key: string; -    shift: boolean; -    ctrl: boolean; -    alt: boolean; -    meta: boolean; +    shift?: boolean; +    ctrl?: boolean; +    alt?: boolean; +    meta?: boolean;    }) {      this.key = key;      this.shift = shift; @@ -25,8 +33,8 @@ export default class Key {    static fromMapKey(str: string): Key {      if (str.startsWith('<') && str.endsWith('>')) { -      let inner = str.slice(1, -1); -      let shift = inner.includes('S-'); +      const inner = str.slice(1, -1); +      const shift = inner.includes('S-');        let base = inner.slice(inner.lastIndexOf('-') + 1);        if (shift && base.length === 1) {          base = base.toUpperCase(); @@ -51,6 +59,10 @@ export default class Key {      });    } +  isDigit(): boolean { +    return digits.includes(this.key); +  } +    equals(key: Key) {      return this.key === key.key &&        this.ctrl === key.ctrl && diff --git a/src/shared/settings/KeySequence.ts b/src/shared/settings/KeySequence.ts deleted file mode 100644 index abae61a..0000000 --- a/src/shared/settings/KeySequence.ts +++ /dev/null @@ -1,54 +0,0 @@ -import Key from './Key'; - -export default class KeySequence { -  constructor( -    public readonly keys: Key[], -  ) { -  } - -  push(key: Key): number { -    return this.keys.push(key); -  } - -  length(): number { -    return this.keys.length; -  } - -  startsWith(o: KeySequence): boolean { -    if (this.keys.length < o.keys.length) { -      return false; -    } -    for (let i = 0; i < o.keys.length; ++i) { -      if (!this.keys[i].equals(o.keys[i])) { -        return false; -      } -    } -    return true; -  } - -  static fromMapKeys(keys: string): KeySequence { -    const fromMapKeysRecursive = ( -      remaining: string, mappedKeys: Key[], -    ): Key[] => { -      if (remaining.length === 0) { -        return mappedKeys; -      } - -      let nextPos = 1; -      if (remaining.startsWith('<')) { -        let ltPos = remaining.indexOf('>'); -        if (ltPos > 0) { -          nextPos = ltPos + 1; -        } -      } - -      return fromMapKeysRecursive( -        remaining.slice(nextPos), -        mappedKeys.concat([Key.fromMapKey(remaining.slice(0, nextPos))]) -      ); -    }; - -    let data = fromMapKeysRecursive(keys, []); -    return new KeySequence(data); -  } -} diff --git a/src/shared/settings/Keymaps.ts b/src/shared/settings/Keymaps.ts index a5558b0..3880654 100644 --- a/src/shared/settings/Keymaps.ts +++ b/src/shared/settings/Keymaps.ts @@ -1,23 +1,25 @@  import * as operations from '../operations'; -export type KeymapsJSON = { [key: string]: operations.Operation }; +type OperationJson = { +  type: string +} | { +  type: string; +  [prop: string]: string | number | boolean; +}; +export type KeymapsJSON = { [key: string]: OperationJson };  export default class Keymaps {    constructor( -    private readonly data: KeymapsJSON, +    private readonly data: { [key: string]: operations.Operation },    ) {    } -  static fromJSON(json: any): Keymaps { -    if (typeof json !== 'object' || json === null) { -      throw new TypeError('invalid keymaps type: ' + JSON.stringify(json)); +  static fromJSON(json: KeymapsJSON): Keymaps { +    const entries: { [key: string]: operations.Operation } = {}; +    for (const key of Object.keys(json)) { +      entries[key] = operations.valueOf(json[key]);      } - -    let data: KeymapsJSON = {}; -    for (let key of Object.keys(json)) { -      data[key] = operations.valueOf(json[key]); -    } -    return new Keymaps(data); +    return new Keymaps(entries);    }    combine(other: Keymaps): Keymaps { diff --git a/src/shared/settings/Properties.ts b/src/shared/settings/Properties.ts index 63ff991..27fb62e 100644 --- a/src/shared/settings/Properties.ts +++ b/src/shared/settings/Properties.ts @@ -1,3 +1,4 @@ +  export type PropertiesJSON = {    hintchars?: string;    smoothscroll?: boolean; @@ -65,22 +66,7 @@ export default class Properties {      this.complete = complete || defaultValues.complete;    } -  static fromJSON(json: any): Properties { -    let defNames: Set<string> = new Set(defs.map(def => def.name)); -    let unknownName = Object.keys(json).find(name => !defNames.has(name)); -    if (unknownName) { -      throw new TypeError(`Unknown property name: "${unknownName}"`); -    } - -    for (let def of defs) { -      if (!Object.prototype.hasOwnProperty.call(json, def.name)) { -        continue; -      } -      if (typeof json[def.name] !== def.type) { -        throw new TypeError( -          `property "${def.name}" is not ${def.type}`); -      } -    } +  static fromJSON(json: PropertiesJSON): Properties {      return new Properties(json);    } diff --git a/src/shared/settings/Search.ts b/src/shared/settings/Search.ts index 4580236..7de03de 100644 --- a/src/shared/settings/Search.ts +++ b/src/shared/settings/Search.ts @@ -12,35 +12,23 @@ export default class Search {    ) {    } -  static fromJSON(json: any): Search { -    let defaultEngine = Search.getStringField(json, 'default'); -    let engines = Search.getObjectField(json, 'engines'); - -    for (let [name, url] of Object.entries(engines)) { -      if ((/\s/).test(name)) { -        throw new TypeError( -          `While space in the search engine not allowed: "${name}"`); -      } -      if (typeof url !== 'string') { -        throw new TypeError( -          `Invalid type of value in filed "engines": ${JSON.stringify(json)}`); +  static fromJSON(json: SearchJSON): Search { +    for (const [name, url] of Object.entries(json.engines)) { +      if (!(/^[a-zA-Z0-9]+$/).test(name)) { +        throw new TypeError('Search engine\'s name must be [a-zA-Z0-9]+');        } -      let matches = url.match(/{}/g); +      const matches = url.match(/{}/g);        if (matches === null) {          throw new TypeError(`No {}-placeholders in URL of "${name}"`);        } else if (matches.length > 1) {          throw new TypeError(`Multiple {}-placeholders in URL of "${name}"`);        }      } - -    if (!Object.keys(engines).includes(defaultEngine)) { -      throw new TypeError(`Default engine "${defaultEngine}" not found`); +    if (!Object.keys(json.engines).includes(json.default)) { +      throw new TypeError(`Default engine "${json.default}" not found`);      } -    return new Search( -      json.default as string, -      json.engines, -    ); +    return new Search(json.default, json.engines);    }    toJSON(): SearchJSON { @@ -49,28 +37,4 @@ export default class Search {        engines: this.engines,      };    } - -  private static getStringField(json: any, name: string): string { -    if (!Object.prototype.hasOwnProperty.call(json, name)) { -      throw new TypeError( -        `missing field "${name}" on search: ${JSON.stringify(json)}`); -    } -    if (typeof json[name] !== 'string') { -      throw new TypeError( -        `invalid type of filed "${name}" on search: ${JSON.stringify(json)}`); -    } -    return json[name]; -  } - -  private static getObjectField(json: any, name: string): Object { -    if (!Object.prototype.hasOwnProperty.call(json, name)) { -      throw new TypeError( -        `missing field "${name}" on search: ${JSON.stringify(json)}`); -    } -    if (typeof json[name] !== 'object' || json[name] === null) { -      throw new TypeError( -        `invalid type of filed "${name}" on search: ${JSON.stringify(json)}`); -    } -    return json[name]; -  }  } diff --git a/src/shared/settings/Settings.ts b/src/shared/settings/Settings.ts index 2c9e37f..add5389 100644 --- a/src/shared/settings/Settings.ts +++ b/src/shared/settings/Settings.ts @@ -1,13 +1,16 @@ +import 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, +  keymaps?: KeymapsJSON, +  search?: SearchJSON, +  properties?: PropertiesJSON, +  blacklist?: BlacklistJSON,  };  export default class Settings { @@ -36,25 +39,30 @@ export default class Settings {      this.blacklist = blacklist;    } -  static fromJSON(json: any): Settings { -    let settings = { ...DefaultSetting }; -    for (let key of Object.keys(json)) { -      switch (key) { -      case 'keymaps': -        settings.keymaps = Keymaps.fromJSON(json.keymaps); -        break; -      case 'search': -        settings.search = Search.fromJSON(json.search); -        break; -      case 'properties': -        settings.properties = Properties.fromJSON(json.properties); -        break; -      case 'blacklist': -        settings.blacklist = Blacklist.fromJSON(json.blacklist); -        break; -      default: -        throw new TypeError('unknown setting: ' + key); -      } +  static fromJSON(json: unknown): Settings { +    const valid = validate(json); +    if (!valid) { +      const message = (validate as any).errors!! +        .map((err: Ajv.ErrorObject) => { +          return `'${err.dataPath}' ${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);    } diff --git a/src/shared/settings/schema.json b/src/shared/settings/schema.json new file mode 100644 index 0000000..31d47f1 --- /dev/null +++ b/src/shared/settings/schema.json @@ -0,0 +1,84 @@ +{ +  "type": "object", +  "properties": { +    "keymaps": { +      "type": "object", +      "patternProperties": { +        ".*": { +          "type": "object", +          "properties": { +            "type": { +              "type": "string" +            } +          }, +          "required": [ +            "type" +          ] +        } +      } +    }, +    "search": { +      "type": "object", +      "properties": { +        "default": { +          "type": "string" +        }, +        "engines": { +          "type": "object", +          "patternProperties": { +            ".*": { +              "type": "string" +            } +          } +        } +      }, +      "required": [ +        "default", +        "engines" +      ] +    }, +    "properties": { +      "type": "object", +      "properties": { +        "hintchars": { +          "type": "string" +        }, +        "smoothscroll": { +          "type": "boolean" +        }, +        "complete": { +          "type": "string" +        } +      } +    }, +    "blacklist": { +      "type": "array", +      "items": { +        "anyOf": [ +          { +            "type": "string" +          }, +          { +            "type": "object", +            "properties": { +              "url": { +                "type": "string" +              }, +              "keys": { +                "type": "array", +                "items": { +                  "type": "string" +                } +              } +            }, +            "required": [ +              "url", +              "keys" +            ] +          } +        ] +      } +    } +  }, +  "additionalProperties": false +} diff --git a/src/shared/settings/validate.js b/src/shared/settings/validate.js new file mode 100644 index 0000000..236488d --- /dev/null +++ b/src/shared/settings/validate.js @@ -0,0 +1,567 @@ +'use strict'; +var validate = (function() { +  var pattern0 = new RegExp('.*'); +  var refVal = []; +  return function validate(data, dataPath, parentData, parentDataProperty, rootData) { +    'use strict'; +    var vErrors = null; +    var errors = 0; +    if ((data && typeof data === "object" && !Array.isArray(data))) { +      var errs__0 = errors; +      var valid1 = true; +      for (var key0 in data) { +        var isAdditional0 = !(false || key0 == 'keymaps' || key0 == 'search' || key0 == 'properties' || key0 == 'blacklist'); +        if (isAdditional0) { +          valid1 = false; +          validate.errors = [{ +            keyword: 'additionalProperties', +            dataPath: (dataPath || '') + "", +            schemaPath: '#/additionalProperties', +            params: { +              additionalProperty: '' + key0 + '' +            }, +            message: 'should NOT have additional properties' +          }]; +          return false; +          break; +        } +      } +      if (valid1) { +        var data1 = data.keymaps; +        if (data1 === undefined) { +          valid1 = true; +        } else { +          var errs_1 = errors; +          if ((data1 && typeof data1 === "object" && !Array.isArray(data1))) { +            var errs__1 = errors; +            var valid2 = true; +            for (var key1 in data1) { +              if (pattern0.test(key1)) { +                var data2 = data1[key1]; +                var errs_2 = errors; +                if ((data2 && typeof data2 === "object" && !Array.isArray(data2))) { +                  if (true) { +                    var errs__2 = errors; +                    var valid3 = true; +                    if (data2.type === undefined) { +                      valid3 = false; +                      validate.errors = [{ +                        keyword: 'required', +                        dataPath: (dataPath || '') + '.keymaps[\'' + key1 + '\']', +                        schemaPath: '#/properties/keymaps/patternProperties/.*/required', +                        params: { +                          missingProperty: 'type' +                        }, +                        message: 'should have required property \'type\'' +                      }]; +                      return false; +                    } else { +                      var errs_3 = errors; +                      if (typeof data2.type !== "string") { +                        validate.errors = [{ +                          keyword: 'type', +                          dataPath: (dataPath || '') + '.keymaps[\'' + key1 + '\'].type', +                          schemaPath: '#/properties/keymaps/patternProperties/.*/properties/type/type', +                          params: { +                            type: 'string' +                          }, +                          message: 'should be string' +                        }]; +                        return false; +                      } +                      var valid3 = errors === errs_3; +                    } +                  } +                } else { +                  validate.errors = [{ +                    keyword: 'type', +                    dataPath: (dataPath || '') + '.keymaps[\'' + key1 + '\']', +                    schemaPath: '#/properties/keymaps/patternProperties/.*/type', +                    params: { +                      type: 'object' +                    }, +                    message: 'should be object' +                  }]; +                  return false; +                } +                var valid2 = errors === errs_2; +                if (!valid2) break; +              } else valid2 = true; +            } +          } else { +            validate.errors = [{ +              keyword: 'type', +              dataPath: (dataPath || '') + '.keymaps', +              schemaPath: '#/properties/keymaps/type', +              params: { +                type: 'object' +              }, +              message: 'should be object' +            }]; +            return false; +          } +          var valid1 = errors === errs_1; +        } +        if (valid1) { +          var data1 = data.search; +          if (data1 === undefined) { +            valid1 = true; +          } else { +            var errs_1 = errors; +            if ((data1 && typeof data1 === "object" && !Array.isArray(data1))) { +              if (true) { +                var errs__1 = errors; +                var valid2 = true; +                if (data1.default === undefined) { +                  valid2 = false; +                  validate.errors = [{ +                    keyword: 'required', +                    dataPath: (dataPath || '') + '.search', +                    schemaPath: '#/properties/search/required', +                    params: { +                      missingProperty: 'default' +                    }, +                    message: 'should have required property \'default\'' +                  }]; +                  return false; +                } else { +                  var errs_2 = errors; +                  if (typeof data1.default !== "string") { +                    validate.errors = [{ +                      keyword: 'type', +                      dataPath: (dataPath || '') + '.search.default', +                      schemaPath: '#/properties/search/properties/default/type', +                      params: { +                        type: 'string' +                      }, +                      message: 'should be string' +                    }]; +                    return false; +                  } +                  var valid2 = errors === errs_2; +                } +                if (valid2) { +                  var data2 = data1.engines; +                  if (data2 === undefined) { +                    valid2 = false; +                    validate.errors = [{ +                      keyword: 'required', +                      dataPath: (dataPath || '') + '.search', +                      schemaPath: '#/properties/search/required', +                      params: { +                        missingProperty: 'engines' +                      }, +                      message: 'should have required property \'engines\'' +                    }]; +                    return false; +                  } else { +                    var errs_2 = errors; +                    if ((data2 && typeof data2 === "object" && !Array.isArray(data2))) { +                      var errs__2 = errors; +                      var valid3 = true; +                      for (var key2 in data2) { +                        if (pattern0.test(key2)) { +                          var errs_3 = errors; +                          if (typeof data2[key2] !== "string") { +                            validate.errors = [{ +                              keyword: 'type', +                              dataPath: (dataPath || '') + '.search.engines[\'' + key2 + '\']', +                              schemaPath: '#/properties/search/properties/engines/patternProperties/.*/type', +                              params: { +                                type: 'string' +                              }, +                              message: 'should be string' +                            }]; +                            return false; +                          } +                          var valid3 = errors === errs_3; +                          if (!valid3) break; +                        } else valid3 = true; +                      } +                    } else { +                      validate.errors = [{ +                        keyword: 'type', +                        dataPath: (dataPath || '') + '.search.engines', +                        schemaPath: '#/properties/search/properties/engines/type', +                        params: { +                          type: 'object' +                        }, +                        message: 'should be object' +                      }]; +                      return false; +                    } +                    var valid2 = errors === errs_2; +                  } +                } +              } +            } else { +              validate.errors = [{ +                keyword: 'type', +                dataPath: (dataPath || '') + '.search', +                schemaPath: '#/properties/search/type', +                params: { +                  type: 'object' +                }, +                message: 'should be object' +              }]; +              return false; +            } +            var valid1 = errors === errs_1; +          } +          if (valid1) { +            var data1 = data.properties; +            if (data1 === undefined) { +              valid1 = true; +            } else { +              var errs_1 = errors; +              if ((data1 && typeof data1 === "object" && !Array.isArray(data1))) { +                var errs__1 = errors; +                var valid2 = true; +                if (data1.hintchars === undefined) { +                  valid2 = true; +                } else { +                  var errs_2 = errors; +                  if (typeof data1.hintchars !== "string") { +                    validate.errors = [{ +                      keyword: 'type', +                      dataPath: (dataPath || '') + '.properties.hintchars', +                      schemaPath: '#/properties/properties/properties/hintchars/type', +                      params: { +                        type: 'string' +                      }, +                      message: 'should be string' +                    }]; +                    return false; +                  } +                  var valid2 = errors === errs_2; +                } +                if (valid2) { +                  if (data1.smoothscroll === undefined) { +                    valid2 = true; +                  } else { +                    var errs_2 = errors; +                    if (typeof data1.smoothscroll !== "boolean") { +                      validate.errors = [{ +                        keyword: 'type', +                        dataPath: (dataPath || '') + '.properties.smoothscroll', +                        schemaPath: '#/properties/properties/properties/smoothscroll/type', +                        params: { +                          type: 'boolean' +                        }, +                        message: 'should be boolean' +                      }]; +                      return false; +                    } +                    var valid2 = errors === errs_2; +                  } +                  if (valid2) { +                    if (data1.complete === undefined) { +                      valid2 = true; +                    } else { +                      var errs_2 = errors; +                      if (typeof data1.complete !== "string") { +                        validate.errors = [{ +                          keyword: 'type', +                          dataPath: (dataPath || '') + '.properties.complete', +                          schemaPath: '#/properties/properties/properties/complete/type', +                          params: { +                            type: 'string' +                          }, +                          message: 'should be string' +                        }]; +                        return false; +                      } +                      var valid2 = errors === errs_2; +                    } +                  } +                } +              } else { +                validate.errors = [{ +                  keyword: 'type', +                  dataPath: (dataPath || '') + '.properties', +                  schemaPath: '#/properties/properties/type', +                  params: { +                    type: 'object' +                  }, +                  message: 'should be object' +                }]; +                return false; +              } +              var valid1 = errors === errs_1; +            } +            if (valid1) { +              var data1 = data.blacklist; +              if (data1 === undefined) { +                valid1 = true; +              } else { +                var errs_1 = errors; +                if (Array.isArray(data1)) { +                  var errs__1 = errors; +                  var valid1; +                  for (var i1 = 0; i1 < data1.length; i1++) { +                    var data2 = data1[i1]; +                    var errs_2 = errors; +                    var errs__2 = errors; +                    var valid2 = false; +                    var errs_3 = errors; +                    if (typeof data2 !== "string") { +                      var err = { +                        keyword: 'type', +                        dataPath: (dataPath || '') + '.blacklist[' + i1 + ']', +                        schemaPath: '#/properties/blacklist/items/anyOf/0/type', +                        params: { +                          type: 'string' +                        }, +                        message: 'should be string' +                      }; +                      if (vErrors === null) vErrors = [err]; +                      else vErrors.push(err); +                      errors++; +                    } +                    var valid3 = errors === errs_3; +                    valid2 = valid2 || valid3; +                    if (!valid2) { +                      var errs_3 = errors; +                      if ((data2 && typeof data2 === "object" && !Array.isArray(data2))) { +                        if (true) { +                          var errs__3 = errors; +                          var valid4 = true; +                          if (data2.url === undefined) { +                            valid4 = false; +                            var err = { +                              keyword: 'required', +                              dataPath: (dataPath || '') + '.blacklist[' + i1 + ']', +                              schemaPath: '#/properties/blacklist/items/anyOf/1/required', +                              params: { +                                missingProperty: 'url' +                              }, +                              message: 'should have required property \'url\'' +                            }; +                            if (vErrors === null) vErrors = [err]; +                            else vErrors.push(err); +                            errors++; +                          } else { +                            var errs_4 = errors; +                            if (typeof data2.url !== "string") { +                              var err = { +                                keyword: 'type', +                                dataPath: (dataPath || '') + '.blacklist[' + i1 + '].url', +                                schemaPath: '#/properties/blacklist/items/anyOf/1/properties/url/type', +                                params: { +                                  type: 'string' +                                }, +                                message: 'should be string' +                              }; +                              if (vErrors === null) vErrors = [err]; +                              else vErrors.push(err); +                              errors++; +                            } +                            var valid4 = errors === errs_4; +                          } +                          if (valid4) { +                            var data3 = data2.keys; +                            if (data3 === undefined) { +                              valid4 = false; +                              var err = { +                                keyword: 'required', +                                dataPath: (dataPath || '') + '.blacklist[' + i1 + ']', +                                schemaPath: '#/properties/blacklist/items/anyOf/1/required', +                                params: { +                                  missingProperty: 'keys' +                                }, +                                message: 'should have required property \'keys\'' +                              }; +                              if (vErrors === null) vErrors = [err]; +                              else vErrors.push(err); +                              errors++; +                            } else { +                              var errs_4 = errors; +                              if (Array.isArray(data3)) { +                                var errs__4 = errors; +                                var valid4; +                                for (var i4 = 0; i4 < data3.length; i4++) { +                                  var errs_5 = errors; +                                  if (typeof data3[i4] !== "string") { +                                    var err = { +                                      keyword: 'type', +                                      dataPath: (dataPath || '') + '.blacklist[' + i1 + '].keys[' + i4 + ']', +                                      schemaPath: '#/properties/blacklist/items/anyOf/1/properties/keys/items/type', +                                      params: { +                                        type: 'string' +                                      }, +                                      message: 'should be string' +                                    }; +                                    if (vErrors === null) vErrors = [err]; +                                    else vErrors.push(err); +                                    errors++; +                                  } +                                  var valid5 = errors === errs_5; +                                  if (!valid5) break; +                                } +                              } else { +                                var err = { +                                  keyword: 'type', +                                  dataPath: (dataPath || '') + '.blacklist[' + i1 + '].keys', +                                  schemaPath: '#/properties/blacklist/items/anyOf/1/properties/keys/type', +                                  params: { +                                    type: 'array' +                                  }, +                                  message: 'should be array' +                                }; +                                if (vErrors === null) vErrors = [err]; +                                else vErrors.push(err); +                                errors++; +                              } +                              var valid4 = errors === errs_4; +                            } +                          } +                        } +                      } else { +                        var err = { +                          keyword: 'type', +                          dataPath: (dataPath || '') + '.blacklist[' + i1 + ']', +                          schemaPath: '#/properties/blacklist/items/anyOf/1/type', +                          params: { +                            type: 'object' +                          }, +                          message: 'should be object' +                        }; +                        if (vErrors === null) vErrors = [err]; +                        else vErrors.push(err); +                        errors++; +                      } +                      var valid3 = errors === errs_3; +                      valid2 = valid2 || valid3; +                    } +                    if (!valid2) { +                      var err = { +                        keyword: 'anyOf', +                        dataPath: (dataPath || '') + '.blacklist[' + i1 + ']', +                        schemaPath: '#/properties/blacklist/items/anyOf', +                        params: {}, +                        message: 'should match some schema in anyOf' +                      }; +                      if (vErrors === null) vErrors = [err]; +                      else vErrors.push(err); +                      errors++; +                      validate.errors = vErrors; +                      return false; +                    } else { +                      errors = errs__2; +                      if (vErrors !== null) { +                        if (errs__2) vErrors.length = errs__2; +                        else vErrors = null; +                      } +                    } +                    var valid2 = errors === errs_2; +                    if (!valid2) break; +                  } +                } else { +                  validate.errors = [{ +                    keyword: 'type', +                    dataPath: (dataPath || '') + '.blacklist', +                    schemaPath: '#/properties/blacklist/type', +                    params: { +                      type: 'array' +                    }, +                    message: 'should be array' +                  }]; +                  return false; +                } +                var valid1 = errors === errs_1; +              } +            } +          } +        } +      } +    } else { +      validate.errors = [{ +        keyword: 'type', +        dataPath: (dataPath || '') + "", +        schemaPath: '#/type', +        params: { +          type: 'object' +        }, +        message: 'should be object' +      }]; +      return false; +    } +    validate.errors = vErrors; +    return errors === 0; +  }; +})(); +validate.schema = { +  "type": "object", +  "properties": { +    "keymaps": { +      "type": "object", +      "patternProperties": { +        ".*": { +          "type": "object", +          "properties": { +            "type": { +              "type": "string" +            } +          }, +          "required": ["type"] +        } +      } +    }, +    "search": { +      "type": "object", +      "properties": { +        "default": { +          "type": "string" +        }, +        "engines": { +          "type": "object", +          "patternProperties": { +            ".*": { +              "type": "string" +            } +          } +        } +      }, +      "required": ["default", "engines"] +    }, +    "properties": { +      "type": "object", +      "properties": { +        "hintchars": { +          "type": "string" +        }, +        "smoothscroll": { +          "type": "boolean" +        }, +        "complete": { +          "type": "string" +        } +      } +    }, +    "blacklist": { +      "type": "array", +      "items": { +        "anyOf": [{ +          "type": "string" +        }, { +          "type": "object", +          "properties": { +            "url": { +              "type": "string" +            }, +            "keys": { +              "type": "array", +              "items": { +                "type": "string" +              } +            } +          }, +          "required": ["url", "keys"] +        }] +      } +    } +  }, +  "additionalProperties": false +}; +validate.errors = null; +module.exports = validate;
\ No newline at end of file  | 
