diff options
Diffstat (limited to 'ext/js/background')
| -rw-r--r-- | ext/js/background/backend.js | 38 | ||||
| -rw-r--r-- | ext/js/background/offscreen-proxy.js | 4 | ||||
| -rw-r--r-- | ext/js/background/offscreen.js | 4 | ||||
| -rw-r--r-- | ext/js/background/profile-conditions-util.js | 662 | 
4 files changed, 347 insertions, 361 deletions
| diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js index 0773dc4b..b95626f5 100644 --- a/ext/js/background/backend.js +++ b/ext/js/background/backend.js @@ -26,19 +26,19 @@ import {ExtensionError} from '../core/extension-error.js';  import {readResponseJson} from '../core/json.js';  import {log} from '../core/logger.js';  import {clone, deferPromise, isObject, promiseTimeout} from '../core/utilities.js'; -import {AnkiUtil} from '../data/anki-util.js'; +import {isNoteDataValid} from '../data/anki-util.js';  import {OptionsUtil} from '../data/options-util.js'; -import {PermissionsUtil} from '../data/permissions-util.js'; -import {ArrayBufferUtil} from '../data/sandbox/array-buffer-util.js'; +import {getAllPermissions, hasPermissions, hasRequiredPermissionsForOptions} from '../data/permissions-util.js'; +import {arrayBufferToBase64} from '../data/sandbox/array-buffer-util.js';  import {DictionaryDatabase} from '../dictionary/dictionary-database.js';  import {Environment} from '../extension/environment.js';  import {ObjectPropertyAccessor} from '../general/object-property-accessor.js';  import {distributeFuriganaInflected, isCodePointJapanese, isStringPartiallyJapanese, convertKatakanaToHiragana as jpConvertKatakanaToHiragana} from '../language/japanese.js';  import {Translator} from '../language/translator.js';  import {AudioDownloader} from '../media/audio-downloader.js'; -import {MediaUtil} from '../media/media-util.js'; +import {getFileExtensionFromAudioMediaType, getFileExtensionFromImageMediaType} from '../media/media-util.js';  import {ClipboardReaderProxy, DictionaryDatabaseProxy, OffscreenProxy, TranslatorProxy} from './offscreen-proxy.js'; -import {ProfileConditionsUtil} from './profile-conditions-util.js'; +import {createSchema, normalizeContext} from './profile-conditions-util.js';  import {RequestBuilder} from './request-builder.js';  import {injectStylesheet} from './script-manager.js'; @@ -95,8 +95,6 @@ export class Backend {          this._options = null;          /** @type {import('../data/json-schema.js').JsonSchema[]} */          this._profileConditionsSchemaCache = []; -        /** @type {ProfileConditionsUtil} */ -        this._profileConditionsUtil = new ProfileConditionsUtil();          /** @type {?string} */          this._defaultAnkiFieldTemplates = null;          /** @type {RequestBuilder} */ @@ -138,8 +136,6 @@ export class Backend {          this._logErrorLevel = null;          /** @type {?chrome.permissions.Permissions} */          this._permissions = null; -        /** @type {PermissionsUtil} */ -        this._permissionsUtil = new PermissionsUtil();          /** @type {Map<string, (() => void)[]>} */          this._applicationReadyHandlers = new Map(); @@ -259,7 +255,7 @@ export class Backend {          try {              this._prepareInternalSync(); -            this._permissions = await this._permissionsUtil.getAllPermissions(); +            this._permissions = await getAllPermissions();              this._defaultBrowserActionTitle = await this._getBrowserIconTitle();              this._badgePrepareDelayTimer = setTimeout(() => {                  this._badgePrepareDelayTimer = null; @@ -545,7 +541,7 @@ export class Backend {          for (let i = 0; i < notes.length; ++i) {              const note = notes[i];              let canAdd = canAddArray[i]; -            const valid = AnkiUtil.isNoteDataValid(note); +            const valid = isNoteDataValid(note);              if (!valid) { canAdd = false; }              const info = {canAdd, valid, noteIds: null};              results.push(info); @@ -815,7 +811,7 @@ export class Backend {          let permissionsOkay = false;          try { -            permissionsOkay = await this._permissionsUtil.hasPermissions({permissions: ['nativeMessaging']}); +            permissionsOkay = await hasPermissions({permissions: ['nativeMessaging']});          } catch (e) {              // NOP          } @@ -1302,7 +1298,7 @@ export class Backend {       * @returns {?import('settings').Profile}       */      _getProfileFromContext(options, optionsContext) { -        const normalizedOptionsContext = this._profileConditionsUtil.normalizeContext(optionsContext); +        const normalizedOptionsContext = normalizeContext(optionsContext);          let index = 0;          for (const profile of options.profiles) { @@ -1312,7 +1308,7 @@ export class Backend {              if (index < this._profileConditionsSchemaCache.length) {                  schema = this._profileConditionsSchemaCache[index];              } else { -                schema = this._profileConditionsUtil.createSchema(conditionGroups); +                schema = createSchema(conditionGroups);                  this._profileConditionsSchemaCache.push(schema);              } @@ -2128,7 +2124,7 @@ export class Backend {              return null;          } -        let extension = contentType !== null ? MediaUtil.getFileExtensionFromAudioMediaType(contentType) : null; +        let extension = contentType !== null ? getFileExtensionFromAudioMediaType(contentType) : null;          if (extension === null) { extension = '.mp3'; }          let fileName = this._generateAnkiNoteMediaFileName('yomitan_audio', extension, timestamp, definitionDetails);          fileName = fileName.replace(/\]/g, ''); @@ -2147,7 +2143,7 @@ export class Backend {          const dataUrl = await this._getScreenshot(tabId, frameId, format, quality);          const {mediaType, data} = this._getDataUrlInfo(dataUrl); -        const extension = MediaUtil.getFileExtensionFromImageMediaType(mediaType); +        const extension = getFileExtensionFromImageMediaType(mediaType);          if (extension === null) {              throw new Error('Unknown media type for screenshot image');          } @@ -2169,7 +2165,7 @@ export class Backend {          }          const {mediaType, data} = this._getDataUrlInfo(dataUrl); -        const extension = MediaUtil.getFileExtensionFromImageMediaType(mediaType); +        const extension = getFileExtensionFromImageMediaType(mediaType);          if (extension === null) {              throw new Error('Unknown media type for clipboard image');          } @@ -2215,7 +2211,7 @@ export class Backend {              let fileName = null;              if (media !== null) {                  const {content, mediaType} = media; -                const extension = MediaUtil.getFileExtensionFromImageMediaType(mediaType); +                const extension = getFileExtensionFromImageMediaType(mediaType);                  fileName = this._generateAnkiNoteMediaFileName(                      `yomitan_dictionary_media_${i + 1}`,                      extension !== null ? extension : '', @@ -2611,7 +2607,7 @@ export class Backend {       * @returns {Promise<void>}       */      async _checkPermissions() { -        this._permissions = await this._permissionsUtil.getAllPermissions(); +        this._permissions = await getAllPermissions();          this._updateBadge();      } @@ -2628,7 +2624,7 @@ export class Backend {       */      _hasRequiredPermissionsForSettings(options) {          if (!this._canObservePermissionsChanges()) { return true; } -        return this._permissions === null || this._permissionsUtil.hasRequiredPermissionsForOptions(this._permissions, options); +        return this._permissions === null || hasRequiredPermissionsForOptions(this._permissions, options);      }      /** @@ -2663,7 +2659,7 @@ export class Backend {          const results = [];          for (const item of await this._dictionaryDatabase.getMedia(targets)) {              const {content, dictionary, height, mediaType, path, width} = item; -            const content2 = ArrayBufferUtil.arrayBufferToBase64(content); +            const content2 = arrayBufferToBase64(content);              results.push({content: content2, dictionary, height, mediaType, path, width});          }          return results; diff --git a/ext/js/background/offscreen-proxy.js b/ext/js/background/offscreen-proxy.js index 80ff31c0..716deddd 100644 --- a/ext/js/background/offscreen-proxy.js +++ b/ext/js/background/offscreen-proxy.js @@ -18,7 +18,7 @@  import {ExtensionError} from '../core/extension-error.js';  import {isObject} from '../core/utilities.js'; -import {ArrayBufferUtil} from '../data/sandbox/array-buffer-util.js'; +import {base64ToArrayBuffer} from '../data/sandbox/array-buffer-util.js';  export class OffscreenProxy {      /** @@ -144,7 +144,7 @@ export class DictionaryDatabaseProxy {       */      async getMedia(targets) {          const serializedMedia = /** @type {import('dictionary-database').Media<string>[]} */ (await this._offscreen.sendMessagePromise({action: 'databaseGetMediaOffscreen', params: {targets}})); -        const media = serializedMedia.map((m) => ({...m, content: ArrayBufferUtil.base64ToArrayBuffer(m.content)})); +        const media = serializedMedia.map((m) => ({...m, content: base64ToArrayBuffer(m.content)}));          return media;      }  } diff --git a/ext/js/background/offscreen.js b/ext/js/background/offscreen.js index ef05508a..b203e326 100644 --- a/ext/js/background/offscreen.js +++ b/ext/js/background/offscreen.js @@ -18,7 +18,7 @@  import {ClipboardReader} from '../comm/clipboard-reader.js';  import {createApiMap, invokeApiMapHandler} from '../core/api-map.js'; -import {ArrayBufferUtil} from '../data/sandbox/array-buffer-util.js'; +import {arrayBufferToBase64} from '../data/sandbox/array-buffer-util.js';  import {DictionaryDatabase} from '../dictionary/dictionary-database.js';  import {Translator} from '../language/translator.js'; @@ -110,7 +110,7 @@ export class Offscreen {      /** @type {import('offscreen').ApiHandler<'databaseGetMediaOffscreen'>} */      async _getMediaHandler({targets}) {          const media = await this._dictionaryDatabase.getMedia(targets); -        const serializedMedia = media.map((m) => ({...m, content: ArrayBufferUtil.arrayBufferToBase64(m.content)})); +        const serializedMedia = media.map((m) => ({...m, content: arrayBufferToBase64(m.content)}));          return serializedMedia;      } diff --git a/ext/js/background/profile-conditions-util.js b/ext/js/background/profile-conditions-util.js index f3be226d..e2d58725 100644 --- a/ext/js/background/profile-conditions-util.js +++ b/ext/js/background/profile-conditions-util.js @@ -18,379 +18,369 @@  import {JsonSchema} from '../data/json-schema.js'; +/** @type {RegExp} */ +const splitPattern = /[,;\s]+/; +/** @type {Map<string, {operators: Map<string, import('profile-conditions-util').CreateSchemaFunction>}>} */ +const descriptors = new Map([ +    [ +        'popupLevel', +        { +            operators: new Map(/** @type {import('profile-conditions-util').OperatorMapArray} */ ([ +                ['equal', createSchemaPopupLevelEqual.bind(this)], +                ['notEqual', createSchemaPopupLevelNotEqual.bind(this)], +                ['lessThan', createSchemaPopupLevelLessThan.bind(this)], +                ['greaterThan', createSchemaPopupLevelGreaterThan.bind(this)], +                ['lessThanOrEqual', createSchemaPopupLevelLessThanOrEqual.bind(this)], +                ['greaterThanOrEqual', createSchemaPopupLevelGreaterThanOrEqual.bind(this)] +            ])) +        } +    ], +    [ +        'url', +        { +            operators: new Map(/** @type {import('profile-conditions-util').OperatorMapArray} */ ([ +                ['matchDomain', createSchemaUrlMatchDomain.bind(this)], +                ['matchRegExp', createSchemaUrlMatchRegExp.bind(this)] +            ])) +        } +    ], +    [ +        'modifierKeys', +        { +            operators: new Map(/** @type {import('profile-conditions-util').OperatorMapArray} */ ([ +                ['are', createSchemaModifierKeysAre.bind(this)], +                ['areNot', createSchemaModifierKeysAreNot.bind(this)], +                ['include', createSchemaModifierKeysInclude.bind(this)], +                ['notInclude', createSchemaModifierKeysNotInclude.bind(this)] +            ])) +        } +    ], +    [ +        'flags', +        { +            operators: new Map(/** @type {import('profile-conditions-util').OperatorMapArray} */ ([ +                ['are', createSchemaFlagsAre.bind(this)], +                ['areNot', createSchemaFlagsAreNot.bind(this)], +                ['include', createSchemaFlagsInclude.bind(this)], +                ['notInclude', createSchemaFlagsNotInclude.bind(this)] +            ])) +        } +    ] +]); +  /** - * Utility class to help processing profile conditions. + * Creates a new JSON schema descriptor for the given set of condition groups. + * @param {import('settings').ProfileConditionGroup[]} conditionGroups An array of condition groups. + *   For a profile match, all of the items must return successfully in at least one of the groups. + * @returns {JsonSchema} A new `JsonSchema` object.   */ -export class ProfileConditionsUtil { -    /** -     * Creates a new instance. -     */ -    constructor() { -        /** @type {RegExp} */ -        this._splitPattern = /[,;\s]+/; -        /** @type {Map<string, {operators: Map<string, import('profile-conditions-util').CreateSchemaFunction>}>} */ -        this._descriptors = new Map([ -            [ -                'popupLevel', -                { -                    operators: new Map(/** @type {import('profile-conditions-util').OperatorMapArray} */ ([ -                        ['equal', this._createSchemaPopupLevelEqual.bind(this)], -                        ['notEqual', this._createSchemaPopupLevelNotEqual.bind(this)], -                        ['lessThan', this._createSchemaPopupLevelLessThan.bind(this)], -                        ['greaterThan', this._createSchemaPopupLevelGreaterThan.bind(this)], -                        ['lessThanOrEqual', this._createSchemaPopupLevelLessThanOrEqual.bind(this)], -                        ['greaterThanOrEqual', this._createSchemaPopupLevelGreaterThanOrEqual.bind(this)] -                    ])) -                } -            ], -            [ -                'url', -                { -                    operators: new Map(/** @type {import('profile-conditions-util').OperatorMapArray} */ ([ -                        ['matchDomain', this._createSchemaUrlMatchDomain.bind(this)], -                        ['matchRegExp', this._createSchemaUrlMatchRegExp.bind(this)] -                    ])) -                } -            ], -            [ -                'modifierKeys', -                { -                    operators: new Map(/** @type {import('profile-conditions-util').OperatorMapArray} */ ([ -                        ['are', this._createSchemaModifierKeysAre.bind(this)], -                        ['areNot', this._createSchemaModifierKeysAreNot.bind(this)], -                        ['include', this._createSchemaModifierKeysInclude.bind(this)], -                        ['notInclude', this._createSchemaModifierKeysNotInclude.bind(this)] -                    ])) -                } -            ], -            [ -                'flags', -                { -                    operators: new Map(/** @type {import('profile-conditions-util').OperatorMapArray} */ ([ -                        ['are', this._createSchemaFlagsAre.bind(this)], -                        ['areNot', this._createSchemaFlagsAreNot.bind(this)], -                        ['include', this._createSchemaFlagsInclude.bind(this)], -                        ['notInclude', this._createSchemaFlagsNotInclude.bind(this)] -                    ])) -                } -            ] -        ]); -    } +export function createSchema(conditionGroups) { +    const anyOf = []; +    for (const {conditions} of conditionGroups) { +        const allOf = []; +        for (const {type, operator, value} of conditions) { +            const conditionDescriptor = descriptors.get(type); +            if (typeof conditionDescriptor === 'undefined') { continue; } -    /** -     * Creates a new JSON schema descriptor for the given set of condition groups. -     * @param {import('settings').ProfileConditionGroup[]} conditionGroups An array of condition groups. -     *   For a profile match, all of the items must return successfully in at least one of the groups. -     * @returns {JsonSchema} A new `JsonSchema` object. -     */ -    createSchema(conditionGroups) { -        const anyOf = []; -        for (const {conditions} of conditionGroups) { -            const allOf = []; -            for (const {type, operator, value} of conditions) { -                const conditionDescriptor = this._descriptors.get(type); -                if (typeof conditionDescriptor === 'undefined') { continue; } +            const createSchema2 = conditionDescriptor.operators.get(operator); +            if (typeof createSchema2 === 'undefined') { continue; } -                const createSchema = conditionDescriptor.operators.get(operator); -                if (typeof createSchema === 'undefined') { continue; } - -                const schema = createSchema(value); -                allOf.push(schema); -            } -            switch (allOf.length) { -                case 0: break; -                case 1: anyOf.push(allOf[0]); break; -                default: anyOf.push({allOf}); break; -            } +            const schema = createSchema2(value); +            allOf.push(schema);          } -        let schema; -        switch (anyOf.length) { -            case 0: schema = {}; break; -            case 1: schema = anyOf[0]; break; -            default: schema = {anyOf}; break; +        switch (allOf.length) { +            case 0: break; +            case 1: anyOf.push(allOf[0]); break; +            default: anyOf.push({allOf}); break;          } -        return new JsonSchema(schema);      } +    let schema; +    switch (anyOf.length) { +        case 0: schema = {}; break; +        case 1: schema = anyOf[0]; break; +        default: schema = {anyOf}; break; +    } +    return new JsonSchema(schema); +} -    /** -     * Creates a normalized version of the context object to test, -     * assigning dependent fields as needed. -     * @param {import('settings').OptionsContext} context A context object which is used during schema validation. -     * @returns {import('profile-conditions-util').NormalizedOptionsContext} A normalized context object. -     */ -    normalizeContext(context) { -        const normalizedContext = /** @type {import('profile-conditions-util').NormalizedOptionsContext} */ (Object.assign({}, context)); -        const {url} = normalizedContext; -        if (typeof url === 'string') { -            try { -                normalizedContext.domain = new URL(url).hostname; -            } catch (e) { -                // NOP -            } -        } -        const {flags} = normalizedContext; -        if (!Array.isArray(flags)) { -            normalizedContext.flags = []; +/** + * Creates a normalized version of the context object to test, + * assigning dependent fields as needed. + * @param {import('settings').OptionsContext} context A context object which is used during schema validation. + * @returns {import('profile-conditions-util').NormalizedOptionsContext} A normalized context object. + */ +export function normalizeContext(context) { +    const normalizedContext = /** @type {import('profile-conditions-util').NormalizedOptionsContext} */ (Object.assign({}, context)); +    const {url} = normalizedContext; +    if (typeof url === 'string') { +        try { +            normalizedContext.domain = new URL(url).hostname; +        } catch (e) { +            // NOP          } -        return normalizedContext;      } - -    // Private - -    /** -     * @param {string} value -     * @returns {string[]} -     */ -    _split(value) { -        return value.split(this._splitPattern); +    const {flags} = normalizedContext; +    if (!Array.isArray(flags)) { +        normalizedContext.flags = [];      } +    return normalizedContext; +} -    /** -     * @param {string} value -     * @returns {number} -     */ -    _stringToNumber(value) { -        const number = Number.parseFloat(value); -        return Number.isFinite(number) ? number : 0; -    } +// Private -    // popupLevel schema creation functions +/** + * @param {string} value + * @returns {string[]} + */ +function split(value) { +    return value.split(splitPattern); +} -    /** -     * @param {string} value -     * @returns {import('ext/json-schema').Schema} -     */ -    _createSchemaPopupLevelEqual(value) { -        const number = this._stringToNumber(value); -        return { -            required: ['depth'], -            properties: { -                depth: {const: number} -            } -        }; -    } +/** + * @param {string} value + * @returns {number} + */ +function stringToNumber(value) { +    const number = Number.parseFloat(value); +    return Number.isFinite(number) ? number : 0; +} -    /** -     * @param {string} value -     * @returns {import('ext/json-schema').Schema} -     */ -    _createSchemaPopupLevelNotEqual(value) { -        return { -            not: { -                anyOf: [this._createSchemaPopupLevelEqual(value)] -            } -        }; -    } +// popupLevel schema creation functions -    /** -     * @param {string} value -     * @returns {import('ext/json-schema').Schema} -     */ -    _createSchemaPopupLevelLessThan(value) { -        const number = this._stringToNumber(value); -        return { -            required: ['depth'], -            properties: { -                depth: {type: 'number', exclusiveMaximum: number} -            } -        }; -    } +/** + * @param {string} value + * @returns {import('ext/json-schema').Schema} + */ +function createSchemaPopupLevelEqual(value) { +    const number = stringToNumber(value); +    return { +        required: ['depth'], +        properties: { +            depth: {const: number} +        } +    }; +} -    /** -     * @param {string} value -     * @returns {import('ext/json-schema').Schema} -     */ -    _createSchemaPopupLevelGreaterThan(value) { -        const number = this._stringToNumber(value); -        return { -            required: ['depth'], -            properties: { -                depth: {type: 'number', exclusiveMinimum: number} -            } -        }; -    } +/** + * @param {string} value + * @returns {import('ext/json-schema').Schema} + */ +function createSchemaPopupLevelNotEqual(value) { +    return { +        not: { +            anyOf: [createSchemaPopupLevelEqual(value)] +        } +    }; +} -    /** -     * @param {string} value -     * @returns {import('ext/json-schema').Schema} -     */ -    _createSchemaPopupLevelLessThanOrEqual(value) { -        const number = this._stringToNumber(value); -        return { -            required: ['depth'], -            properties: { -                depth: {type: 'number', maximum: number} -            } -        }; -    } +/** + * @param {string} value + * @returns {import('ext/json-schema').Schema} + */ +function createSchemaPopupLevelLessThan(value) { +    const number = stringToNumber(value); +    return { +        required: ['depth'], +        properties: { +            depth: {type: 'number', exclusiveMaximum: number} +        } +    }; +} -    /** -     * @param {string} value -     * @returns {import('ext/json-schema').Schema} -     */ -    _createSchemaPopupLevelGreaterThanOrEqual(value) { -        const number = this._stringToNumber(value); -        return { -            required: ['depth'], -            properties: { -                depth: {type: 'number', minimum: number} -            } -        }; -    } +/** + * @param {string} value + * @returns {import('ext/json-schema').Schema} + */ +function createSchemaPopupLevelGreaterThan(value) { +    const number = stringToNumber(value); +    return { +        required: ['depth'], +        properties: { +            depth: {type: 'number', exclusiveMinimum: number} +        } +    }; +} -    // url schema creation functions +/** + * @param {string} value + * @returns {import('ext/json-schema').Schema} + */ +function createSchemaPopupLevelLessThanOrEqual(value) { +    const number = stringToNumber(value); +    return { +        required: ['depth'], +        properties: { +            depth: {type: 'number', maximum: number} +        } +    }; +} -    /** -     * @param {string} value -     * @returns {import('ext/json-schema').Schema} -     */ -    _createSchemaUrlMatchDomain(value) { -        const oneOf = []; -        for (let domain of this._split(value)) { -            if (domain.length === 0) { continue; } -            domain = domain.toLowerCase(); -            oneOf.push({const: domain}); +/** + * @param {string} value + * @returns {import('ext/json-schema').Schema} + */ +function createSchemaPopupLevelGreaterThanOrEqual(value) { +    const number = stringToNumber(value); +    return { +        required: ['depth'], +        properties: { +            depth: {type: 'number', minimum: number}          } -        return { -            required: ['domain'], -            properties: { -                domain: {oneOf} -            } -        }; -    } +    }; +} -    /** -     * @param {string} value -     * @returns {import('ext/json-schema').Schema} -     */ -    _createSchemaUrlMatchRegExp(value) { -        return { -            required: ['url'], -            properties: { -                url: {type: 'string', pattern: value, patternFlags: 'i'} -            } -        }; +// url schema creation functions + +/** + * @param {string} value + * @returns {import('ext/json-schema').Schema} + */ +function createSchemaUrlMatchDomain(value) { +    const oneOf = []; +    for (let domain of split(value)) { +        if (domain.length === 0) { continue; } +        domain = domain.toLowerCase(); +        oneOf.push({const: domain});      } +    return { +        required: ['domain'], +        properties: { +            domain: {oneOf} +        } +    }; +} -    // modifierKeys schema creation functions +/** + * @param {string} value + * @returns {import('ext/json-schema').Schema} + */ +function createSchemaUrlMatchRegExp(value) { +    return { +        required: ['url'], +        properties: { +            url: {type: 'string', pattern: value, patternFlags: 'i'} +        } +    }; +} -    /** -     * @param {string} value -     * @returns {import('ext/json-schema').Schema} -     */ -    _createSchemaModifierKeysAre(value) { -        return this._createSchemaArrayCheck('modifierKeys', value, true, false); -    } +// modifierKeys schema creation functions -    /** -     * @param {string} value -     * @returns {import('ext/json-schema').Schema} -     */ -    _createSchemaModifierKeysAreNot(value) { -        return { -            not: { -                anyOf: [this._createSchemaArrayCheck('modifierKeys', value, true, false)] -            } -        }; -    } +/** + * @param {string} value + * @returns {import('ext/json-schema').Schema} + */ +function createSchemaModifierKeysAre(value) { +    return createSchemaArrayCheck('modifierKeys', value, true, false); +} -    /** -     * @param {string} value -     * @returns {import('ext/json-schema').Schema} -     */ -    _createSchemaModifierKeysInclude(value) { -        return this._createSchemaArrayCheck('modifierKeys', value, false, false); -    } +/** + * @param {string} value + * @returns {import('ext/json-schema').Schema} + */ +function createSchemaModifierKeysAreNot(value) { +    return { +        not: { +            anyOf: [createSchemaArrayCheck('modifierKeys', value, true, false)] +        } +    }; +} -    /** -     * @param {string} value -     * @returns {import('ext/json-schema').Schema} -     */ -    _createSchemaModifierKeysNotInclude(value) { -        return this._createSchemaArrayCheck('modifierKeys', value, false, true); -    } +/** + * @param {string} value + * @returns {import('ext/json-schema').Schema} + */ +function createSchemaModifierKeysInclude(value) { +    return createSchemaArrayCheck('modifierKeys', value, false, false); +} -    // modifierKeys schema creation functions +/** + * @param {string} value + * @returns {import('ext/json-schema').Schema} + */ +function createSchemaModifierKeysNotInclude(value) { +    return createSchemaArrayCheck('modifierKeys', value, false, true); +} -    /** -     * @param {string} value -     * @returns {import('ext/json-schema').Schema} -     */ -    _createSchemaFlagsAre(value) { -        return this._createSchemaArrayCheck('flags', value, true, false); -    } +// modifierKeys schema creation functions -    /** -     * @param {string} value -     * @returns {import('ext/json-schema').Schema} -     */ -    _createSchemaFlagsAreNot(value) { -        return { -            not: { -                anyOf: [this._createSchemaArrayCheck('flags', value, true, false)] -            } -        }; -    } +/** + * @param {string} value + * @returns {import('ext/json-schema').Schema} + */ +function createSchemaFlagsAre(value) { +    return createSchemaArrayCheck('flags', value, true, false); +} -    /** -     * @param {string} value -     * @returns {import('ext/json-schema').Schema} -     */ -    _createSchemaFlagsInclude(value) { -        return this._createSchemaArrayCheck('flags', value, false, false); -    } +/** + * @param {string} value + * @returns {import('ext/json-schema').Schema} + */ +function createSchemaFlagsAreNot(value) { +    return { +        not: { +            anyOf: [createSchemaArrayCheck('flags', value, true, false)] +        } +    }; +} -    /** -     * @param {string} value -     * @returns {import('ext/json-schema').Schema} -     */ -    _createSchemaFlagsNotInclude(value) { -        return this._createSchemaArrayCheck('flags', value, false, true); -    } +/** + * @param {string} value + * @returns {import('ext/json-schema').Schema} + */ +function createSchemaFlagsInclude(value) { +    return createSchemaArrayCheck('flags', value, false, false); +} -    // Generic +/** + * @param {string} value + * @returns {import('ext/json-schema').Schema} + */ +function createSchemaFlagsNotInclude(value) { +    return createSchemaArrayCheck('flags', value, false, true); +} -    /** -     * @param {string} key -     * @param {string} value -     * @param {boolean} exact -     * @param {boolean} none -     * @returns {import('ext/json-schema').Schema} -     */ -    _createSchemaArrayCheck(key, value, exact, none) { -        /** @type {import('ext/json-schema').Schema[]} */ -        const containsList = []; -        for (const item of this._split(value)) { -            if (item.length === 0) { continue; } -            containsList.push({ -                contains: { -                    const: item -                } -            }); -        } -        const containsListCount = containsList.length; -        /** @type {import('ext/json-schema').Schema} */ -        const schema = { -            type: 'array' -        }; -        if (exact) { -            schema.maxItems = containsListCount; -        } -        if (none) { -            if (containsListCount > 0) { -                schema.not = {anyOf: containsList}; -            } -        } else { -            schema.minItems = containsListCount; -            if (containsListCount > 0) { -                schema.allOf = containsList; +// Generic + +/** + * @param {string} key + * @param {string} value + * @param {boolean} exact + * @param {boolean} none + * @returns {import('ext/json-schema').Schema} + */ +function createSchemaArrayCheck(key, value, exact, none) { +    /** @type {import('ext/json-schema').Schema[]} */ +    const containsList = []; +    for (const item of split(value)) { +        if (item.length === 0) { continue; } +        containsList.push({ +            contains: { +                const: item              } +        }); +    } +    const containsListCount = containsList.length; +    /** @type {import('ext/json-schema').Schema} */ +    const schema = { +        type: 'array' +    }; +    if (exact) { +        schema.maxItems = containsListCount; +    } +    if (none) { +        if (containsListCount > 0) { +            schema.not = {anyOf: containsList}; +        } +    } else { +        schema.minItems = containsListCount; +        if (containsListCount > 0) { +            schema.allOf = containsList;          } -        return { -            required: [key], -            properties: { -                [key]: schema -            } -        };      } +    return { +        required: [key], +        properties: { +            [key]: schema +        } +    };  } |