diff --git a/common/web/types/.c8rc.json b/common/web/types/.c8rc.json new file mode 100644 index 0000000000..f7137ed999 --- /dev/null +++ b/common/web/types/.c8rc.json @@ -0,0 +1,12 @@ +{ + "exclude": [ + "src/keyboard-object.ts", + "src/lexical-model-types.ts", + "src/outputTarget.interface.ts", + "src/*.d.ts", + "src/main.ts", + "src/schemas/*", + "src/schema-validators.ts", + "src/schemas.ts" + ] +} diff --git a/common/web/types/build.sh b/common/web/types/build.sh index 0d7abba7e9..3f7b48f8fc 100755 --- a/common/web/types/build.sh +++ b/common/web/types/build.sh @@ -84,21 +84,11 @@ function do_test() { tsc --build test readonly C8_THRESHOLD=60 - # Exclude files from coverage analysis that only define types: - exclude=(\ - src/keyboard-object.ts \ - src/lexical-model-types.ts \ - src/outputTarget.interface.ts \ - src/*.d.ts \ - src/main.ts \ - src/schemas/* \ - src/schema-validators.ts \ - src/schemas.ts \ - ) - # shellcheck disable=SC2068 + + # Excludes are defined in .c8rc.json c8 --skip-full --reporter=lcov --reporter=text --lines "${C8_THRESHOLD}" \ --statements "${C8_THRESHOLD}" --branches "${C8_THRESHOLD}" \ - --functions "${C8_THRESHOLD}" ${exclude[@]/#/--exclude } \ + --functions "${C8_THRESHOLD}" \ mocha "${builder_extra_params[@]}" builder_echo warning "Coverage thresholds are currently ${C8_THRESHOLD}%, which is lower than ideal." diff --git a/common/web/types/src/keyboard-object.ts b/common/web/types/src/keyboard-object.ts index dd6f244672..afd0029af0 100644 --- a/common/web/types/src/keyboard-object.ts +++ b/common/web/types/src/keyboard-object.ts @@ -1,23 +1,15 @@ /* * Keyman is copyright (C) SIL Global. MIT License. */ -import { OutputTarget } from './outputTarget.interface.js'; import { TouchLayoutPlatform as LayoutFormFactorSpec } from './keyman-touch-layout/keyman-touch-layout-file.js'; export type ComplexKeyboardStore = (string | { t: 'd', d: number } | { ['t']: 'b' })[]; -type KeyEvent = {}; +// A stub for KeyEvent which is properly defined in KeymanWeb +type KeyEventStub = {}; -/** - * Stores preprocessed properties of a keyboard for quick retrieval later. - */ -export class CacheTag { - stores: { [storeName: string]: ComplexKeyboardStore }; - - constructor() { - this.stores = {}; - } -} +// A stub for OutputTarget which is properly defined in KeymanWeb +type OutputTargetStub = {}; export interface EncodedVisualKeyboard { /** Represents CSS font styling to use for VisualKeyboard text */ @@ -47,11 +39,6 @@ export type LayoutSpec = { } export type KeyboardObject = { - /** - * Used internally by Keyman Engine for Web to hold preprocessed stores. - */ - _kmw?: CacheTag; - /** * group-start: the function triggering processing for the keyboard's * "Unicode" start group, corresponding to `begin Unicode > use(_____)` in @@ -60,7 +47,7 @@ export type KeyboardObject = { * @param keystroke The full, pre-processed keystroke triggering * keyboard-rule application. */ - gs(outputTarget: OutputTarget, keystroke: KeyEvent): boolean; + gs(outputTarget: OutputTargetStub, keystroke: KeyEventStub): boolean; /** * group-newcontext: the function triggering processing for the keyboard's @@ -69,7 +56,7 @@ export type KeyboardObject = { * @param outputTarget The new context to be used with future keystrokes * @param keystroke A 'null' `KeyEvent` providing current modifier + state information. */ - gn?(outputTarget: OutputTarget, keystroke: KeyEvent): boolean; + gn?(outputTarget: OutputTargetStub, keystroke: KeyEventStub): boolean; /** * group-postkeystroke: the function triggering processing for the keyboard's @@ -80,7 +67,7 @@ export type KeyboardObject = { * applied. * @param keystroke A 'null' `KeyEvent` providing current modifier + state information. */ - gpk?(outputTarget: OutputTarget, keystroke: KeyEvent): boolean; + gpk?(outputTarget: OutputTargetStub, keystroke: KeyEventStub): boolean; /** * Keyboard ID: the uniquely-identifying name for this keyboard. Includes the standard @@ -169,11 +156,6 @@ export type KeyboardObject = { * touch layouts if set and no touch-layout information is available. */ KDU?: number; - /** - * Virtual Key Dictionary: the engine pre-processed, unminified dictionary. This is built within - * Keyman Engine for Web at runtime as needed based on the definitions in `KVKD`. - */ - VKDictionary?: Record, /** * Keyboard Help File: Embedded JS script designed for use with a keyboard's * HTML help text. Always defined within the file referenced by &kmw_embedjs @@ -193,6 +175,6 @@ export type KeyboardObject = { * @param {number} _PData 1 or 0 * @returns */ - KNS?: (_PCommand: number, _PTarget: OutputTarget, _PData: number) => void; + KNS?: (_PCommand: number, _PTarget: OutputTargetStub, _PData: number) => void; } & Record<`s${number}`, string> diff --git a/common/web/types/src/main.ts b/common/web/types/src/main.ts index eb0b8a7596..bd1cafbf57 100644 --- a/common/web/types/src/main.ts +++ b/common/web/types/src/main.ts @@ -32,5 +32,4 @@ export { ElementString } from './kmx/kmx-plus/element-string.js'; export { USVString, CasingForm, CasingFunction, TextWithProbability, LexiconTraversal, LexicalModel, LexicalModelPunctuation, Transform, Suggestion, Reversion, Keep, SuggestionTag, Context, Distribution, Outcome, WithOutcome, ProbabilityMass, Configuration, Capabilities, WordBreakingFunction, Span } from './lexical-model-types.js'; -export { CacheTag, ComplexKeyboardStore, EncodedVisualKeyboard, LayoutSpec, KeyboardObject } from './keyboard-object.js'; -export { OutputTarget } from './outputTarget.interface.js'; +export { ComplexKeyboardStore, EncodedVisualKeyboard, LayoutSpec, KeyboardObject } from './keyboard-object.js'; diff --git a/web/src/engine/interfaces/src/prediction/languageProcessor.interface.ts b/web/src/engine/interfaces/src/prediction/languageProcessor.interface.ts index 52ed1ca510..971566058e 100644 --- a/web/src/engine/interfaces/src/prediction/languageProcessor.interface.ts +++ b/web/src/engine/interfaces/src/prediction/languageProcessor.interface.ts @@ -1,5 +1,6 @@ -import { OutputTarget, Suggestion, Reversion } from '@keymanapp/common-types'; +import { Suggestion, Reversion } from '@keymanapp/common-types'; import { EventEmitter } from "eventemitter3"; +import { OutputTarget } from 'keyman/engine/keyboard'; export class ReadySuggestions { suggestions: Suggestion[]; diff --git a/web/src/engine/interfaces/src/prediction/predictionContext.ts b/web/src/engine/interfaces/src/prediction/predictionContext.ts index 67c433d3f2..943160eb9d 100644 --- a/web/src/engine/interfaces/src/prediction/predictionContext.ts +++ b/web/src/engine/interfaces/src/prediction/predictionContext.ts @@ -1,6 +1,7 @@ import { EventEmitter } from "eventemitter3"; -import { Keep, type OutputTarget, Reversion, Suggestion } from '@keymanapp/common-types'; -import { type LanguageProcessorSpec , ReadySuggestions, type InvalidateSourceEnum, StateChangeHandler } from './languageProcessor.interface.js'; +import { Keep, Reversion, Suggestion } from '@keymanapp/common-types'; +import { type LanguageProcessorSpec, ReadySuggestions, type InvalidateSourceEnum, StateChangeHandler } from './languageProcessor.interface.js'; +import { type OutputTarget } from 'keyman/engine/keyboard'; interface PredictionContextEventMap { update: (suggestions: Suggestion[]) => void; diff --git a/web/src/engine/js-processor/src/outputTarget.ts b/web/src/engine/js-processor/src/outputTarget.ts index 2962046692..c055e47602 100644 --- a/web/src/engine/js-processor/src/outputTarget.ts +++ b/web/src/engine/js-processor/src/outputTarget.ts @@ -1,13 +1,14 @@ import { extendString } from "@keymanapp/web-utils"; import { findCommonSubstringEndIndex } from "./stringDivergence.js"; import { Mock } from "./mock.js"; +import { OutputTarget as OutputTargetInterface } from 'keyman/engine/keyboard'; extendString(); // Defines deadkey management in a manner attachable to each element interface. import { type KeyEvent } from 'keyman/engine/keyboard'; import { Deadkey, DeadkeyTracker } from "./deadkeys.js"; -import { OutputTarget as OutputTargetInterface, ProbabilityMass, Transform } from '@keymanapp/common-types'; +import { ProbabilityMass, Transform } from '@keymanapp/common-types'; // Also relies on string-extensions provided by the web-utils package. diff --git a/web/src/engine/keyboard/src/defaultRules.ts b/web/src/engine/keyboard/src/defaultRules.ts index c1e8c97968..b6ad708fd9 100644 --- a/web/src/engine/keyboard/src/defaultRules.ts +++ b/web/src/engine/keyboard/src/defaultRules.ts @@ -4,9 +4,10 @@ * Implementation of default rules */ -import { ModifierKeyConstants, type OutputTarget } from '@keymanapp/common-types'; +import { ModifierKeyConstants } from '@keymanapp/common-types'; import Codes from './codes.js'; import type KeyEvent from './keyEvent.js'; +import { type OutputTarget } from './outputTarget.interface.js'; export enum EmulationKeystrokes { Enter = '\n', diff --git a/web/src/engine/keyboard/src/index.ts b/web/src/engine/keyboard/src/index.ts index 830e37fa90..28b6331c21 100644 --- a/web/src/engine/keyboard/src/index.ts +++ b/web/src/engine/keyboard/src/index.ts @@ -31,11 +31,12 @@ export * from "./defaultRules.js"; export { default as KeyEvent } from "./keyEvent.js"; export * from "./keyEvent.js"; export { default as KeyMapping } from "./keyMapping.js"; +export { OutputTarget } from "./outputTarget.interface.js"; export * from "@keymanapp/web-utils"; // At the top level, there should be no default export. -// Without the line below... KeyMapping would likely be aliased there, as it's +// Without the line below... OutputTarget would likely be aliased there, as it's // the last `export { default as _ }` => `export * from` pairing seen above. export default undefined; diff --git a/web/src/engine/keyboard/src/keyboards/keyboard.ts b/web/src/engine/keyboard/src/keyboards/keyboard.ts index 01e584a36d..0d58f46706 100644 --- a/web/src/engine/keyboard/src/keyboards/keyboard.ts +++ b/web/src/engine/keyboard/src/keyboards/keyboard.ts @@ -2,12 +2,24 @@ import Codes from "../codes.js"; import { Layouts } from "./defaultLayouts.js"; import { ActiveKey, ActiveLayout, ActiveSubKey } from "./activeLayout.js"; import KeyEvent from "../keyEvent.js"; -import { CacheTag, ComplexKeyboardStore, KeyboardObject, LayoutSpec, ModifierKeyConstants, type OutputTarget, TouchLayout } from "@keymanapp/common-types"; +import { type OutputTarget } from '../outputTarget.interface.js'; +import { ComplexKeyboardStore, KeyboardObject, LayoutSpec, ModifierKeyConstants, TouchLayout } from "@keymanapp/common-types"; type TouchLayoutSpec = TouchLayout.TouchLayoutPlatform & { isDefault?: boolean}; import { Version, DeviceSpec } from "@keymanapp/web-utils"; import StateKeyMap from "./stateKeyMap.js"; +/** + * Stores preprocessed properties of a keyboard for quick retrieval later. + */ +class CacheTag { + stores: { [storeName: string]: ComplexKeyboardStore }; + + constructor() { + this.stores = {}; + } +} + export enum LayoutState { NOT_LOADED = undefined, POLYFILLED = 1, @@ -18,13 +30,25 @@ export interface VariableStoreDictionary { [name: string]: string; }; +type KmwKeyboardObject = KeyboardObject & { + /** + * Used internally by Keyman Engine for Web to hold preprocessed stores. + */ + _kmw?: CacheTag; + /** + * Virtual Key Dictionary: the engine pre-processed, unminified dictionary. This is built within + * Keyman Engine for Web at runtime as needed based on the definitions in `KVKD`. + */ + VKDictionary?: Record, +}; + /** * Acts as a wrapper class for Keyman keyboards compiled to JS, providing type information * and keyboard-centered functionality in an object-oriented way without modifying the * wrapped keyboard itself. */ export default class Keyboard { - public static DEFAULT_SCRIPT_OBJECT: KeyboardObject = { + public static DEFAULT_SCRIPT_OBJECT: KmwKeyboardObject = { 'gs': function(outputTarget: OutputTarget, keystroke: KeyEvent) { return false; }, // no matching rules; rely on defaultRuleOutput entirely 'KI': '', // The currently-existing default keyboard ID; we already have checks that focus against this. 'KN': '', @@ -38,7 +62,7 @@ export default class Keyboard { * * TODO: Make this private instead. But there are a LOT of references that must be rooted out first. */ - public readonly scriptObject: KeyboardObject; + public readonly scriptObject: KmwKeyboardObject; private layoutStates: {[layout: string]: LayoutState}; constructor(keyboardScript: any) { @@ -544,7 +568,7 @@ export default class Keyboard { * @return {number} key code > 255 on success, or 0 if not found */ getVKDictionaryCode(keyName: string) { - const dict = this.scriptObject['VKDictionary'] || {} as KeyboardObject['VKDictionary']; + const dict = this.scriptObject['VKDictionary'] || {} as KmwKeyboardObject['VKDictionary']; if(!this.scriptObject['VKDictionary']) { if(typeof this.scriptObject['KVKD'] == 'string') { // Build the VK dictionary diff --git a/common/web/types/src/outputTarget.interface.ts b/web/src/engine/keyboard/src/outputTarget.interface.ts similarity index 100% rename from common/web/types/src/outputTarget.interface.ts rename to web/src/engine/keyboard/src/outputTarget.interface.ts