From b56628ea24b30d0f10dfc5dc053e94913c8b79e4 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Mon, 13 May 2024 12:24:57 +0700 Subject: [PATCH 01/13] chore(web): removes all Web-related implicit-any usage outside of web/ and common/web/gesture-recognizer --- .../src/text/prediction/predictionContext.ts | 2 +- .../src/keyboards/activeLayout.ts | 14 +++--- .../src/keyboards/defaultLayouts.ts | 35 ++++++++----- .../src/keyboards/keyboard.ts | 49 ++++++++++++++----- .../src/keyboards/keyboardLoaderBase.ts | 4 +- .../src/keyboards/keyboardProperties.ts | 1 + .../keyboards/loaders/domKeyboardLoader.ts | 2 +- .../web/keyboard-processor/src/text/codes.ts | 8 +-- .../src/text/kbdInterface.ts | 33 +++++++------ .../keyboard-processor/src/text/keyEvent.ts | 5 +- .../src/text/keyboardProcessor.ts | 10 ++-- common/web/lm-worker/build-wrapper.js | 11 ++++- common/web/lm-worker/package.json | 2 + .../src/main/correction/distance-modeler.ts | 6 +-- common/web/lm-worker/src/main/index.ts | 9 +++- .../lm-worker/src/main/model-compositor.ts | 16 ++++-- common/web/recorder/src/proctor.ts | 4 +- common/web/sentry-manager/src/index.ts | 9 ++-- common/web/utils/src/deepCopy.ts | 30 +++++++----- common/web/utils/src/kmwstring.ts | 2 +- common/web/utils/src/timeoutPromise.ts | 2 +- web/src/tsconfig.dom.json | 3 +- web/tsconfig.base.json | 1 - 23 files changed, 166 insertions(+), 92 deletions(-) diff --git a/common/web/input-processor/src/text/prediction/predictionContext.ts b/common/web/input-processor/src/text/prediction/predictionContext.ts index 0b87d5fa60..2e2dbdd5c5 100644 --- a/common/web/input-processor/src/text/prediction/predictionContext.ts +++ b/common/web/input-processor/src/text/prediction/predictionContext.ts @@ -131,7 +131,7 @@ export default class PredictionContext extends EventEmitter 0 && shiftKey != null) { shiftKey['sp']=ButtonClasses.specialActive; shiftKey['sk']=null; - shiftKey['text'] = Layouts.modifierSpecials[layers[n].id] ? Layouts.modifierSpecials[layers[n].id] : "*Shift*"; + shiftKey['text'] = Layouts.modifierSpecials[layerId] ?? "*Shift*"; } } } @@ -482,11 +491,11 @@ export class Layouts { * @param {Array} BK keyboard object (as loaded) * @return {Object} */ - static processLegacyDefinitions(BK: string[]): KLS { + static processLegacyDefinitions(BK: string[]): EncodedVisualKeyboard['KLS'] { //['default','shift','ctrl','shiftctrl','alt','shiftalt','ctrlalt','shiftctrlalt']; var idList=Layouts.generateLayerIds(false); // Non-chiral. - var KLS: KLS = {}; + var KLS: EncodedVisualKeyboard['KLS'] = {}; // The old default: eight auto-managed layers... for(var n=0; n, + KHF?: (e: any) => string; + KNS?: (_PCommand: number, _PTarget: OutputTarget, _PData: number) => void; +} & Record<`s${number}`, string> + /** * Acts as a wrapper class for Keyman keyboards compiled to JS, providing type information @@ -37,8 +64,8 @@ export interface VariableStoreDictionary { * wrapped keyboard itself. */ export default class Keyboard { - public static DEFAULT_SCRIPT_OBJECT = { - 'gs': function(outputTarget, keystroke) { return false; }, // no matching rules; rely on defaultRuleOutput entirely + public static DEFAULT_SCRIPT_OBJECT: KeyboardObject = { + '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': '', 'KV': Layouts.DEFAULT_RAW_SPEC, @@ -51,7 +78,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: any; + public readonly scriptObject: KeyboardObject; private layoutStates: {[layout: string]: LayoutState}; constructor(keyboardScript: any) { @@ -109,7 +136,7 @@ export default class Keyboard { */ get variableStores(): VariableStoreDictionary { const storeNames = this.scriptObject['KVS']; - let values = {}; + let values: VariableStoreDictionary = {}; if(Array.isArray(storeNames)) { for(let store of storeNames) { values[store] = this.scriptObject[store]; @@ -147,11 +174,11 @@ export default class Keyboard { } // May return null if no layouts exist or have been initialized. - private get _layouts(): {[formFactor: string]: LayoutFormFactor} { + private get _layouts(): LayoutSpec { return this.scriptObject['KVKL']; // This one is compiled by Developer's visual keyboard layout editor. } - private set _layouts(value) { + private set _layouts(value: LayoutSpec) { this.scriptObject['KVKL'] = value; } @@ -488,7 +515,7 @@ export default class Keyboard { 'K_NUMLOCK': Codes.stateBitmasks.NUM_LOCK, 'K_SCROLL': Codes.stateBitmasks.SCROLL_LOCK }; - const bitmask = bitmap[Lkc.kName]; + const bitmask = bitmap[Lkc.kName as keyof typeof bitmap]; if(bitmask) { Lkc.Lstates ^= bitmask; @@ -558,8 +585,8 @@ 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']; if(!this.scriptObject['VKDictionary']) { - const a=[]; if(typeof this.scriptObject['KVKD'] == 'string') { // Build the VK dictionary // TODO: Move the dictionary build into the compiler -- so compiler generates code such as following. @@ -567,10 +594,10 @@ export default class Keyboard { // this.KVKD={"K_ABC":256,"K_DEF":257,...}; const s=this.scriptObject['KVKD'].split(' '); for(var i=0; i { + script.onerror = (err: any) => { promise.reject(errorBuilder.missingError(err)); } script.onload = () => { diff --git a/common/web/keyboard-processor/src/text/codes.ts b/common/web/keyboard-processor/src/text/codes.ts index 654acad68b..b96ae320c4 100644 --- a/common/web/keyboard-processor/src/text/codes.ts +++ b/common/web/keyboard-processor/src/text/codes.ts @@ -29,7 +29,7 @@ const Codes = { // Note: keys_mod_other = 0x10000, used by KMX+ for the // other modifier flag in layers, > 16 bit so not available here. // See keys_mod_other in keyman_core_ldml.ts - }, + } as {[name: string]: number}, modifierBitmasks: { "ALL":0x007F, @@ -39,14 +39,14 @@ const Codes = { "NON_CHIRAL":0x0070, // The default bitmask, for non-chiral keyboards, // Represents all modifier codes not supported by KMW 1.0 legacy keyboards. "NON_LEGACY": 0x006F // ALL, but without the SHIFT bit - }, + } as {[name: string]: number}, stateBitmasks: { "ALL":0x3F00, "CAPS":0x0300, "NUM_LOCK":0x0C00, "SCROLL_LOCK":0x3000 - }, + } as {[name: string]: number}, // Define standard keycode numbers (exposed for use by other modules) keyCodes: { @@ -79,7 +79,7 @@ const Codes = { "K_UPPER":50006,"K_LOWER":50007,"K_ALPHA":50008, "K_SHIFTED":50009,"K_ALTGR":50010, "K_TABBACK":50011,"K_TABFWD":50012 - }, + } as {[name: string]: number}, codesUS: [ ['0123456789',';=,-./`', '[\\]\''], diff --git a/common/web/keyboard-processor/src/text/kbdInterface.ts b/common/web/keyboard-processor/src/text/kbdInterface.ts index 8491f857a1..c23fe68756 100644 --- a/common/web/keyboard-processor/src/text/kbdInterface.ts +++ b/common/web/keyboard-processor/src/text/kbdInterface.ts @@ -48,12 +48,12 @@ type RuleChar = string; class RuleDeadkey { /** Discriminant field - 'd' for Deadkey. */ - ['t']: 'd'; + t: 'd'; /** * Value: the deadkey's ID. */ - ['d']: number; // For 'd'eadkey; also reflects the Deadkey class's 'd' property. + d: number; // For 'd'eadkey; also reflects the Deadkey class's 'd' property. } class ContextAny { @@ -254,7 +254,7 @@ export default class KeyboardInterface extends KeyboardHarness { * In web-core, this also activates the keyboard; in other modules, this method * may be replaced with other implementations. */ - registerKeyboard(Pk): void { + registerKeyboard(Pk: any): void { // NOTE: This implementation is web-core specific and is intentionally replaced, whole-sale, // by DOM-aware code. let keyboard = new Keyboard(Pk); @@ -400,7 +400,7 @@ export default class KeyboardInterface extends KeyboardHarness { var subCache = cache; subCache.valContext = subCache.valContext.slice(0, ln); for(var i=0; i < subCache.valContext.length; i++) { - if(subCache[i] == '\ufffe') { + if(subCache.valContext[i] == '\ufffe') { subCache.valContext.splice(0, 1); subCache.deadContext.splice(0, 1); } @@ -709,12 +709,14 @@ export default class KeyboardInterface extends KeyboardHarness { s = this._ExplodeStore(s); var Lix = -1; for(var i=0; i < s.length; i++) { - if(typeof(s[i]) == 'string') { + const entry = s[i]; + if(typeof(entry) == 'string') { if(s[i] == ch) { Lix = i; break; } - } else if(s[i]['d'] === ch['d']) { + // @ts-ignore // Needs to test against .t for automatic inference, but it's not actually there. + } else if(entry.d === (ch as RuleDeadkey).d) { Lix = i; break; } @@ -765,21 +767,19 @@ export default class KeyboardInterface extends KeyboardHarness { if(indexChar !== "") { if(typeof indexChar == 'string' ) { this.output(Pdn, outputTarget, indexChar); //I3319 - } else if(indexChar['t']) { - var storeEntry = indexChar as StoreNonCharEntry; - - switch(storeEntry.t) { + } else if(indexChar.t) { + switch(indexChar.t) { case 'b': // Beep commands may appear within stores. this.beep(outputTarget); break; case 'd': - this.deadkeyOutput(Pdn, outputTarget, indexChar['d']); + this.deadkeyOutput(Pdn, outputTarget, indexChar.d); break; default: - assertNever(storeEntry); + assertNever(indexChar); } } else { // For keyboards developed during 10.0's alpha phase - t:'d' was assumed. - this.deadkeyOutput(Pdn, outputTarget, indexChar['d']); + this.deadkeyOutput(Pdn, outputTarget, (indexChar as any).d); } } } @@ -1058,7 +1058,7 @@ export default class KeyboardInterface extends KeyboardHarness { return this.process(this.activeKeyboard.process.bind(this.activeKeyboard), outputTarget, keystroke, false); } - private process(callee, outputTarget: OutputTarget, keystroke: KeyEvent, readonly: boolean): RuleBehavior { + private process(callee: (outputTarget: OutputTarget, keystroke: KeyEvent) => boolean, outputTarget: OutputTarget, keystroke: KeyEvent, readonly: boolean): RuleBehavior { // Clear internal state tracking data from prior keystrokes. if(!outputTarget) { throw "No target specified for keyboard output!"; @@ -1139,16 +1139,19 @@ export default class KeyboardInterface extends KeyboardHarness { // Keyboard callbacks let prototype = this.prototype; - var exportKBCallback = function(miniName: string, longName: string) { + var exportKBCallback = function(miniName: string, longName: keyof KeyboardInterface) { if(prototype[longName]) { + // @ts-ignore prototype[miniName] = prototype[longName]; } } exportKBCallback('KSF', 'saveFocus'); + // @ts-ignore // is defined at a higher level exportKBCallback('KBR', 'beepReset'); exportKBCallback('KT', 'insertText'); exportKBCallback('KR', 'registerKeyboard'); + // @ts-ignore // is defined at a higher level exportKBCallback('KRS', 'registerStub'); exportKBCallback('KC', 'context'); exportKBCallback('KN', 'nul'); diff --git a/common/web/keyboard-processor/src/text/keyEvent.ts b/common/web/keyboard-processor/src/text/keyEvent.ts index 4e7e25b1cc..a38992a3a1 100644 --- a/common/web/keyboard-processor/src/text/keyEvent.ts +++ b/common/web/keyboard-processor/src/text/keyEvent.ts @@ -104,7 +104,9 @@ export default class KeyEvent implements KeyEventSpec { public constructor(keyEventSpec: KeyEventSpec) { for(let key in keyEventSpec) { + // @ts-ignore if(keyEventSpec[key] !== undefined) { + // @ts-ignore this[key] = keyEventSpec[key]; } } @@ -146,7 +148,8 @@ export default class KeyEvent implements KeyEventSpec { // We need to determine the mnemonic base character - for example, SHIFT + K_PERIOD needs to map to '>'. let mappingEvent: KeyEvent = new KeyEvent(this); for(let key in (this as KeyEvent)) { - mappingEvent[key] = this[key]; + // @ts-ignore + mappingEvent[key as keyof KeyEvent] = this[key]; } // To facilitate storing relevant commands, we should probably reverse-lookup diff --git a/common/web/keyboard-processor/src/text/keyboardProcessor.ts b/common/web/keyboard-processor/src/text/keyboardProcessor.ts index c890c9653b..bdcf4e33a6 100644 --- a/common/web/keyboard-processor/src/text/keyboardProcessor.ts +++ b/common/web/keyboard-processor/src/text/keyboardProcessor.ts @@ -27,7 +27,7 @@ export type LogMessageHandler = (str: string) => void; export interface VariableStoreSerializer { loadStore(keyboardID: string, storeName: string): VariableStore; - saveStore(keyboardID: string, storeName: string, storeMap: VariableStore); + saveStore(keyboardID: string, storeName: string, storeMap: VariableStore): void; } export interface ProcessorInitOptions { @@ -273,8 +273,8 @@ export default class KeyboardProcessor extends EventEmitter { _UpdateVKShift(e: KeyEvent): boolean { let keyShiftState=0; - const lockNames = ['CAPS', 'NUM_LOCK', 'SCROLL_LOCK']; - const lockKeys = ['K_CAPS', 'K_NUMLOCK', 'K_SCROLL']; + const lockNames = ['CAPS', 'NUM_LOCK', 'SCROLL_LOCK'] as const; + const lockKeys = ['K_CAPS', 'K_NUMLOCK', 'K_SCROLL'] as const; if(!this.activeKeyboard) { return true; @@ -322,8 +322,8 @@ export default class KeyboardProcessor extends EventEmitter { } private updateStates(): void { - var lockNames = ['CAPS', 'NUM_LOCK', 'SCROLL_LOCK']; - var lockKeys = ['K_CAPS', 'K_NUMLOCK', 'K_SCROLL']; + var lockNames = ['CAPS', 'NUM_LOCK', 'SCROLL_LOCK'] as const; + var lockKeys = ['K_CAPS', 'K_NUMLOCK', 'K_SCROLL'] as const; for(let i=0; i < lockKeys.length; i++) { const key = lockKeys[i]; diff --git a/common/web/lm-worker/build-wrapper.js b/common/web/lm-worker/build-wrapper.js index 368d5c2815..66fff07b6f 100644 --- a/common/web/lm-worker/build-wrapper.js +++ b/common/web/lm-worker/build-wrapper.js @@ -109,4 +109,13 @@ export var LMLayerWorkerSourcemapComment = "${srcMapString}"; // --END:LMLayerWorkerCode `; -fs.writeFileSync(destFile, wrapper); \ No newline at end of file +fs.writeFileSync(destFile, wrapper); + +// Don't let there be multiples; TS may signal typing conflict if it thinks +// these are defined multiple times. +let wrapperDeclarations = ` +export const LMLayerWorkerCode: string; +export const LMLayerWorkerSourcemapComment: string; +`; + +fs.writeFileSync('build/lib/worker-main.wrapped.d.ts', wrapperDeclarations); \ No newline at end of file diff --git a/common/web/lm-worker/package.json b/common/web/lm-worker/package.json index 3c39546497..77bbc1d49f 100644 --- a/common/web/lm-worker/package.json +++ b/common/web/lm-worker/package.json @@ -5,10 +5,12 @@ "exports": { "./worker-main.wrapped.js": { "es6-bundling": "./build/lib/worker-main.wrapped.js", + "types": "./build/lib/worker-main.wrapped.d.ts", "default": "./build/lib/worker-main.wrapped.es5.js" }, "./worker-main.wrapped.min.js": { "es6-bundling": "./build/lib/worker-main.wrapped.min.js", + "types": "./build/lib/worker-main.wrapped.d.ts", "default": "./build/lib/worker-main.wrapped.es5.min.js" } }, diff --git a/common/web/lm-worker/src/main/correction/distance-modeler.ts b/common/web/lm-worker/src/main/correction/distance-modeler.ts index 47f7dcbb3d..ad722484cc 100644 --- a/common/web/lm-worker/src/main/correction/distance-modeler.ts +++ b/common/web/lm-worker/src/main/correction/distance-modeler.ts @@ -39,9 +39,9 @@ export class SearchNode { // Internal lazy-cache for .inputSamplingCost, as it's a bit expensive to re-compute. private _inputCost?: number; - constructor(rootTraversal: LexiconTraversal, toKey?: (USVString) => USVString); + constructor(rootTraversal: LexiconTraversal, toKey?: (arg0: USVString) => USVString); constructor(node: SearchNode); - constructor(rootTraversal: LexiconTraversal | SearchNode, toKey?: (USVString) => USVString) { + constructor(rootTraversal: LexiconTraversal | SearchNode, toKey?: (arg0: USVString) => USVString) { toKey = toKey || (x => x); if(rootTraversal instanceof SearchNode) { @@ -549,7 +549,7 @@ export class SearchSpace { let inputIndex = nextTier.index; - let deletionEdges = []; + let deletionEdges: SearchNode[] = []; if(!substitutionsOnly) { deletionEdges = currentNode.buildDeletionEdges(this.inputSequence[inputIndex-1]); } diff --git a/common/web/lm-worker/src/main/index.ts b/common/web/lm-worker/src/main/index.ts index 3db9ca9a1d..e775ed5d35 100644 --- a/common/web/lm-worker/src/main/index.ts +++ b/common/web/lm-worker/src/main/index.ts @@ -97,7 +97,10 @@ export default class LMLayerWorker { private _currentModelSource: ModelSourceSpec; - constructor(options = { + constructor(options: { + importScripts: typeof importScripts, + postMessage: typeof postMessage + } = { importScripts: null, postMessage: null }) { @@ -401,9 +404,13 @@ export default class LMLayerWorker { // Ensures that the worker instance is accessible for loaded model scripts. // Assists unit-testing. + // @ts-ignore scope['LMLayerWorker'] = worker; + // @ts-ignore scope['models'] = models; + // @ts-ignore scope['correction'] = correction; + // @ts-ignore scope['wordBreakers'] = wordBreakers; return worker; diff --git a/common/web/lm-worker/src/main/model-compositor.ts b/common/web/lm-worker/src/main/model-compositor.ts index 8f52e51087..492bb1c730 100644 --- a/common/web/lm-worker/src/main/model-compositor.ts +++ b/common/web/lm-worker/src/main/model-compositor.ts @@ -434,18 +434,24 @@ export default class ModelCompositor { }); let suggestions = suggestionDistribution.splice(0, ModelCompositor.MAX_SUGGESTIONS).map(function(value) { - if(value.sample['p']) { + let sample: Suggestion & { + p?: number, + "lexical-p"?: number, + "correction-p"?: number + } = value.sample; + + if(sample['p']) { // For analysis / debugging - value.sample['lexical-p'] = value.sample['p']; - value.sample['correction-p'] = value.p / value.sample['p']; + sample['lexical-p'] = sample['p']; + sample['correction-p'] = value.p / sample['p']; // Use of the Trie model always exposed the lexical model's probability for a word to KMW. // It's useful for debugging right now, so may as well repurpose it as the posterior. // // We still condition on 'p' existing so that test cases aren't broken. - value.sample['p'] = value.p; + sample['p'] = value.p; } // - return value.sample; + return sample; }); if(keepOption) { diff --git a/common/web/recorder/src/proctor.ts b/common/web/recorder/src/proctor.ts index 47d5b5d81e..940fa4a76b 100644 --- a/common/web/recorder/src/proctor.ts +++ b/common/web/recorder/src/proctor.ts @@ -32,7 +32,7 @@ export default abstract class Proctor { abstract beforeAll(): Promise; // Performs per-test setup - abstract before(); + abstract before(): void; /** * Allows the proctor to indicate if is capable of executing a suite of tests or not. @@ -43,7 +43,7 @@ export default abstract class Proctor { /** * Indicates whether or not this Proctor is capable of running the specified set of tests. */ - abstract matchesTestSet(testSet: TestSet); + abstract matchesTestSet(testSet: TestSet): boolean; /** * Simulates the specified test sequence for use in testing. diff --git a/common/web/sentry-manager/src/index.ts b/common/web/sentry-manager/src/index.ts index aab835cda0..ad783effba 100644 --- a/common/web/sentry-manager/src/index.ts +++ b/common/web/sentry-manager/src/index.ts @@ -8,6 +8,7 @@ import { default as SentryType } from '@sentry/browser'; // a pre-bundled Sentry build artifact. let Sentry: { init: typeof SentryType.init; + // @ts-ignore } = window['Sentry']; /** @@ -34,7 +35,7 @@ export class KeymanSentryManager { 'kmwuitoggle.js': 'kmwuitoggle.js', 'kmwuitoolbar.js': 'kmwuitoolbar.js' // Also add entries for the naming system used by Android and iOS - and map them to the EMBEDDED upload, not the std 'native' one. - } + } as Record; static DEFAULT_OPTIONS: Options = { hostPlatform: "native-web" @@ -104,6 +105,7 @@ export class KeymanSentryManager { attachEventMetadata(event: any) { // Ensure that the 'extra' object exists. (May not exist for synthetic/custom Errors.) event.extra = event.extra || {}; + //@ts-ignore event.extra.keymanState = window['keyman']['getDebugInfo'](); event.extra.keymanHostPlatform = this.keymanPlatform; } @@ -215,7 +217,7 @@ export class KeymanSentryManager { return oldConsoleWarn.apply(console, args); } - function reduceConsoleArgs(args) { + function reduceConsoleArgs(args: any) { let errorMsg = args[0]; // Make sure errorMsg is either an error or string. // It's therefore best to pass in new Error('msg') instead of just 'msg' since @@ -225,7 +227,7 @@ export class KeymanSentryManager { if (!(errorMsg instanceof Error)) { // stringify all args as a new Error (which creates a stack trace) errorMsg = new Error( - args.reduce(function(accumulator, currentValue) { + args.reduce(function(accumulator: any, currentValue: any) { return accumulator.toString() + ' ' + currentValue.toString(); }, '') ); @@ -259,4 +261,5 @@ export class KeymanSentryManager { } // Publish to the window. +// @ts-ignore window['KeymanSentryManager'] = KeymanSentryManager; \ No newline at end of file diff --git a/common/web/utils/src/deepCopy.ts b/common/web/utils/src/deepCopy.ts index ce05270365..083b598cc4 100644 --- a/common/web/utils/src/deepCopy.ts +++ b/common/web/utils/src/deepCopy.ts @@ -2,22 +2,26 @@ * Function deepCopy * Scope Private * @param {Object} p object to copy - * @param {Array=} c0 array member being copied * @return {Object} clone ('deep copy') of object * Description Makes an actual copy (not a reference) of an object, copying simple members, * arrays and member objects but not functions, so use with care! */ -export default function deepCopy(p:T, c0?): T { - var c = c0 || {}; - for (var i in p) { - if(typeof p[i] === 'object' && p[i] != null) { - c[i] = (p[i].constructor === Array ) ? [] : {}; - deepCopy(p[i],c[i]); - } - else { - c[i] = p[i]; - } - } +export default function deepCopy)>(p:T): T { + // typeof undefined == 'undefined', ![] == false, !{} == false + if(typeof p != 'object' || !p) { + return p; + } else { + const clone = Array.isArray(p) ? [] : {}; + // For arrays, skips over sparse entries. Not that we use sparse arrays, but still. + const keys = Object.keys(p); - return c; + for(let key of keys) { + // @ts-ignore + if(p[key] !== undefined) { + // @ts-ignore + clone[key] = deepCopy(p[key]); + } + } + return clone as T; + } } \ No newline at end of file diff --git a/common/web/utils/src/kmwstring.ts b/common/web/utils/src/kmwstring.ts index 21d165e8ff..4766bbc1d9 100644 --- a/common/web/utils/src/kmwstring.ts +++ b/common/web/utils/src/kmwstring.ts @@ -12,7 +12,7 @@ declare global { interface StringConstructor { kmwFromCharCode(cp0: number): string, _kmwFromCharCode(cp0: number): string, - kmwEnableSupplementaryPlane(bEnable: boolean) + kmwEnableSupplementaryPlane(bEnable: boolean): void } interface String { diff --git a/common/web/utils/src/timeoutPromise.ts b/common/web/utils/src/timeoutPromise.ts index 1961c2db1f..4b6fb3a7d6 100644 --- a/common/web/utils/src/timeoutPromise.ts +++ b/common/web/utils/src/timeoutPromise.ts @@ -51,7 +51,7 @@ export default class TimeoutPromise extends ManagedPromise { * A simplified, but non-cancelable, version of `TimeoutPromise`. Returns a simple, * Promise that resolves after the specified timeout duration. */ -export const timedPromise = (time) => { +export const timedPromise = (time: number) => { const promise = new TimeoutPromise(time); return promise.corePromise; } \ No newline at end of file diff --git a/web/src/tsconfig.dom.json b/web/src/tsconfig.dom.json index 2e71d4ed38..3227a5cac3 100644 --- a/web/src/tsconfig.dom.json +++ b/web/src/tsconfig.dom.json @@ -2,6 +2,7 @@ { "extends": "../tsconfig.base.json", "compilerOptions": { - "lib": [ "DOM", "ES6"] + "lib": [ "DOM", "ES6"], + "noImplicitAny": false, } } \ No newline at end of file diff --git a/web/tsconfig.base.json b/web/tsconfig.base.json index 24ca6ac570..a7c122a93d 100644 --- a/web/tsconfig.base.json +++ b/web/tsconfig.base.json @@ -13,7 +13,6 @@ // TODO: These override ../tsconfig.base.json settings, and so should be removed if possible, // but existing code in web/ breaks some of these settinsg "noImplicitReturns": false, - "noImplicitAny": false, "strictFunctionTypes": false, "strictNullChecks": false, From 09416e50b61bd2cd2c20b906a103cf692d2334cf Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Mon, 13 May 2024 12:25:24 +0700 Subject: [PATCH 02/13] chore(web): preps gesture-recognizer, but doesn't remove setting --- .../src/engine/headless/gestures/matchers/matcherSelector.ts | 2 +- .../src/engine/headless/gestures/specs/modelDefValidator.ts | 2 ++ .../src/engine/headless/inputEngineBase.ts | 5 +++-- .../src/engine/headless/touchpointCoordinator.ts | 2 +- common/web/gesture-recognizer/src/engine/touchEventEngine.ts | 5 +++-- common/web/gesture-recognizer/src/test/auto/tsconfig.json | 2 ++ common/web/gesture-recognizer/tsconfig.json | 5 ++++- 7 files changed, 16 insertions(+), 7 deletions(-) diff --git a/common/web/gesture-recognizer/src/engine/headless/gestures/matchers/matcherSelector.ts b/common/web/gesture-recognizer/src/engine/headless/gestures/matchers/matcherSelector.ts index cdbe9c1746..833419defd 100644 --- a/common/web/gesture-recognizer/src/engine/headless/gestures/matchers/matcherSelector.ts +++ b/common/web/gesture-recognizer/src/engine/headless/gestures/matchers/matcherSelector.ts @@ -211,7 +211,7 @@ export class MatcherSelector extends EventEmitter) => { + const determinePredecessorSources = (source: PredecessorMatch): GestureSource[] => { const directSources = (source.sources as GestureSourceSubview[]).map((source => source.baseSource)); if(directSources && directSources.length > 0) { diff --git a/common/web/gesture-recognizer/src/engine/headless/gestures/specs/modelDefValidator.ts b/common/web/gesture-recognizer/src/engine/headless/gestures/specs/modelDefValidator.ts index 29b51a4d3e..cbdbb06608 100644 --- a/common/web/gesture-recognizer/src/engine/headless/gestures/specs/modelDefValidator.ts +++ b/common/web/gesture-recognizer/src/engine/headless/gestures/specs/modelDefValidator.ts @@ -1,3 +1,4 @@ +import { FulfillmentCause } from "../matchers/pathMatcher.js"; import { GestureResolutionSpec, RejectionReplace } from "./gestureModel.js"; import { GestureModelDefs } from "./gestureModelDefs.js"; @@ -99,6 +100,7 @@ export function validateModelDefs(definitions: GestureModelDefs): Mode processAction(entry.resolutionAction, `model: ${entry.id}`); Object.keys(entry.rejectionActions ?? {}).forEach((key) => { + // @ts-ignore processAction(entry.rejectionActions[key], `model: ${entry.id}`); }); }); diff --git a/common/web/gesture-recognizer/src/engine/headless/inputEngineBase.ts b/common/web/gesture-recognizer/src/engine/headless/inputEngineBase.ts index 1747010f1e..6b33e0c88c 100644 --- a/common/web/gesture-recognizer/src/engine/headless/inputEngineBase.ts +++ b/common/web/gesture-recognizer/src/engine/headless/inputEngineBase.ts @@ -115,8 +115,9 @@ export abstract class InputEngineBase extends this._activeTouchpoints = this._activeTouchpoints.filter((pt) => point != pt); for(const key of Object.keys(this.identifierMap)) { - if(this.identifierMap[key] == id) { - delete this.identifierMap[key]; + const keyVal = Number.parseInt(key, 10); + if(this.identifierMap[keyVal] == id) { + delete this.identifierMap[keyVal]; } } } diff --git a/common/web/gesture-recognizer/src/engine/headless/touchpointCoordinator.ts b/common/web/gesture-recognizer/src/engine/headless/touchpointCoordinator.ts index bf54254124..f69bc7196b 100644 --- a/common/web/gesture-recognizer/src/engine/headless/touchpointCoordinator.ts +++ b/common/web/gesture-recognizer/src/engine/headless/touchpointCoordinator.ts @@ -323,7 +323,7 @@ export class TouchpointCoordinator extends Even } public get historyJSON() { - const sanitizingReplacer = function (key: string, value) { + const sanitizingReplacer = function (key: string, value: any) { if(key == 'item') { // KMW 'key' elements involve circular refs. // Just return the key ID. (Assumes use in KMW) diff --git a/common/web/gesture-recognizer/src/engine/touchEventEngine.ts b/common/web/gesture-recognizer/src/engine/touchEventEngine.ts index 611e205b5e..0fe66c3ae5 100644 --- a/common/web/gesture-recognizer/src/engine/touchEventEngine.ts +++ b/common/web/gesture-recognizer/src/engine/touchEventEngine.ts @@ -76,8 +76,9 @@ export class TouchEventEngine extends InputEventEngi super.dropTouchpoint(source); for(const key of Object.keys(this.safeBoundMaskMap)) { - if(this.getTouchpointWithId(Number.parseInt(key, 10)) == source) { - delete this.safeBoundMaskMap[key]; + const keyVal = Number.parseInt(key, 10) + if(this.getTouchpointWithId(keyVal) == source) { + delete this.safeBoundMaskMap[keyVal]; } } } diff --git a/common/web/gesture-recognizer/src/test/auto/tsconfig.json b/common/web/gesture-recognizer/src/test/auto/tsconfig.json index 336b2d5f57..e091004e2b 100644 --- a/common/web/gesture-recognizer/src/test/auto/tsconfig.json +++ b/common/web/gesture-recognizer/src/test/auto/tsconfig.json @@ -9,5 +9,7 @@ // Not needed when testing via Node, and when `true` it seems to desync preset breakpoints // worse than when `false`. "importHelpers": false, + // Makes the tests... somewhat tricky to handle properly. + "noImplicitAny": false } } diff --git a/common/web/gesture-recognizer/tsconfig.json b/common/web/gesture-recognizer/tsconfig.json index 9cf67a6220..261906e1f4 100644 --- a/common/web/gesture-recognizer/tsconfig.json +++ b/common/web/gesture-recognizer/tsconfig.json @@ -5,7 +5,10 @@ "lib": [ "dom", "es6" ], "outDir": "./build/obj/", "rootDir": "./src/engine", - "tsBuildInfoFile": "./build/obj/tsconfig.tsbuildinfo" + "tsBuildInfoFile": "./build/obj/tsconfig.tsbuildinfo", + // The TS tests appear to reference this value, despite not being the tsconfig the tests are + // supposed to reference. So, can't drop it -quite- yet. + "noImplicitAny": false }, "include": ["./src/engine/**/*.ts"], "exclude": ["./src/test/**/*.ts", "./src/tools/**/*.ts"], From 32d72bf2dcea0a4a092949db7eec7cdc2637a3a1 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Mon, 13 May 2024 12:40:19 +0700 Subject: [PATCH 03/13] chore(web): also, strictFunctionTypes - an easy one at lower-levels --- .../tools/unit-test-resources/src/inputSequenceSimulator.ts | 1 + .../src/tools/unit-test-resources/src/sequenceRecorder.ts | 6 +++--- web/src/tsconfig.dom.json | 3 +++ web/tsconfig.base.json | 3 +-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/common/web/gesture-recognizer/src/tools/unit-test-resources/src/inputSequenceSimulator.ts b/common/web/gesture-recognizer/src/tools/unit-test-resources/src/inputSequenceSimulator.ts index 1f997a0041..9f2e834066 100644 --- a/common/web/gesture-recognizer/src/tools/unit-test-resources/src/inputSequenceSimulator.ts +++ b/common/web/gesture-recognizer/src/tools/unit-test-resources/src/inputSequenceSimulator.ts @@ -57,6 +57,7 @@ export class InputSequenceSimulator { return { _arr: arr, // Obviously, this isn't a standard member of TouchList. length: arr.length, + //@ts-ignore item: function(i: number) { return this._arr[i]; } } } diff --git a/common/web/gesture-recognizer/src/tools/unit-test-resources/src/sequenceRecorder.ts b/common/web/gesture-recognizer/src/tools/unit-test-resources/src/sequenceRecorder.ts index bb584bd792..a8070ac4fa 100644 --- a/common/web/gesture-recognizer/src/tools/unit-test-resources/src/sequenceRecorder.ts +++ b/common/web/gesture-recognizer/src/tools/unit-test-resources/src/sequenceRecorder.ts @@ -1,4 +1,4 @@ -import { GestureDebugSource } from "@keymanapp/gesture-recognizer"; +import { GestureDebugSource, GestureSource } from "@keymanapp/gesture-recognizer"; import { HostFixtureLayoutController } from "./hostFixtureLayoutController.js"; import { RecordedCoordSequenceSet } from "./inputRecording.js"; @@ -32,9 +32,9 @@ export class SequenceRecorder { } private _attachRecognizerHooks() { - this.controller.recognizer.on('inputstart', (wrappedSequence: WrappedInputSequence) => { + this.controller.recognizer.on('inputstart', (wrappedSequence: GestureSource) => { const id = wrappedSequence.identifier; - this.records[id] = wrappedSequence; + this.records[id] = wrappedSequence as WrappedInputSequence; this.startOrder.push(id); }); diff --git a/web/src/tsconfig.dom.json b/web/src/tsconfig.dom.json index 3227a5cac3..47f2d25016 100644 --- a/web/src/tsconfig.dom.json +++ b/web/src/tsconfig.dom.json @@ -3,6 +3,9 @@ "extends": "../tsconfig.base.json", "compilerOptions": { "lib": [ "DOM", "ES6"], + // TODO: These override ../tsconfig.base.json settings, and so should be removed if possible, + // but existing code in web/ breaks some of these settings "noImplicitAny": false, + "strictFunctionTypes": false } } \ No newline at end of file diff --git a/web/tsconfig.base.json b/web/tsconfig.base.json index a7c122a93d..aac6de4f32 100644 --- a/web/tsconfig.base.json +++ b/web/tsconfig.base.json @@ -11,9 +11,8 @@ "target": "es5", // TODO: These override ../tsconfig.base.json settings, and so should be removed if possible, - // but existing code in web/ breaks some of these settinsg + // but existing code in web/ breaks some of these settings "noImplicitReturns": false, - "strictFunctionTypes": false, "strictNullChecks": false, // Other settings - declaration files, sourcemapping, and other miscellaneous bits. From 35b7ed647f6ff2ce9682d9ade70323529ac75fe4 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Mon, 13 May 2024 12:58:44 +0700 Subject: [PATCH 04/13] fix(web): gesture-recognizer tests aren't ready yet --- common/web/gesture-recognizer/tsconfig.json | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/common/web/gesture-recognizer/tsconfig.json b/common/web/gesture-recognizer/tsconfig.json index 261906e1f4..b69d85cf07 100644 --- a/common/web/gesture-recognizer/tsconfig.json +++ b/common/web/gesture-recognizer/tsconfig.json @@ -6,9 +6,15 @@ "outDir": "./build/obj/", "rootDir": "./src/engine", "tsBuildInfoFile": "./build/obj/tsconfig.tsbuildinfo", - // The TS tests appear to reference this value, despite not being the tsconfig the tests are - // supposed to reference. So, can't drop it -quite- yet. - "noImplicitAny": false + + // TODO: These override ../tsconfig.base.json settings, and so should be removed if possible, + // but existing code in web/ breaks some of these settings + // + // At present, the code actually compiles without them... but the TS tests are a different matter. + "noImplicitAny": false, + "noUnusedLocals": false, + "strictFunctionTypes": false, + "noImplicitReturns": false }, "include": ["./src/engine/**/*.ts"], "exclude": ["./src/test/**/*.ts", "./src/tools/**/*.ts"], From 3530314cbd69e64fb9433d20d1c241d400a50ee4 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Mon, 13 May 2024 13:04:41 +0700 Subject: [PATCH 05/13] chore(web): noImplicitReturns, strictNullChecks --- .../engine/headless/gestures/matchers/gestureMatcher.ts | 9 ++++++++- .../gesture-recognizer/src/engine/touchEventEngine.ts | 2 ++ .../src/text/prediction/languageProcessor.ts | 3 ++- .../src/text/prediction/predictionContext.ts | 4 +++- .../web/keyboard-processor/src/text/keyboardProcessor.ts | 2 +- .../web/lm-worker/src/main/correction/context-tracker.ts | 2 +- common/web/recorder/src/index.ts | 2 ++ web/src/tsconfig.dom.json | 4 +++- web/tsconfig.base.json | 5 ----- 9 files changed, 22 insertions(+), 11 deletions(-) diff --git a/common/web/gesture-recognizer/src/engine/headless/gestures/matchers/gestureMatcher.ts b/common/web/gesture-recognizer/src/engine/headless/gestures/matchers/gestureMatcher.ts index 094a5d632d..2a040a1416 100644 --- a/common/web/gesture-recognizer/src/engine/headless/gestures/matchers/gestureMatcher.ts +++ b/common/web/gesture-recognizer/src/engine/headless/gestures/matchers/gestureMatcher.ts @@ -178,7 +178,7 @@ export class GestureMatcher implements PredecessorMatch< return this._isCancelled; } - private finalize(matched: boolean, cause: FulfillmentCause) { + private finalize(matched: boolean, cause: FulfillmentCause): MatchResult { if(this.publishedPromise.isFulfilled) { return this._result; } @@ -242,6 +242,13 @@ export class GestureMatcher implements PredecessorMatch< /* c8 ignore next 3 */ } catch(err) { this.publishedPromise.reject(err); + return { + matched: false, + action: { + type: 'none', + item: null + } + } } } diff --git a/common/web/gesture-recognizer/src/engine/touchEventEngine.ts b/common/web/gesture-recognizer/src/engine/touchEventEngine.ts index 0fe66c3ae5..2dcddffb09 100644 --- a/common/web/gesture-recognizer/src/engine/touchEventEngine.ts +++ b/common/web/gesture-recognizer/src/engine/touchEventEngine.ts @@ -227,6 +227,8 @@ export class TouchEventEngine extends InputEventEngi this.inputStartSignalMap.set(touchpoint, eventSignalPromise); return eventSignalPromise.corePromise; + } else { + return Promise.resolve(); } }); } diff --git a/common/web/input-processor/src/text/prediction/languageProcessor.ts b/common/web/input-processor/src/text/prediction/languageProcessor.ts index 85485f2273..19f5010806 100644 --- a/common/web/input-processor/src/text/prediction/languageProcessor.ts +++ b/common/web/input-processor/src/text/prediction/languageProcessor.ts @@ -167,6 +167,8 @@ export default class LanguageProcessor extends EventEmitter { if(validSuggestionState()) { return langProcessor.applySuggestion(suggestion, this.currentTarget, () => kbdProcessor.layerId); + } else { + return Promise.resolve(null); } } @@ -243,7 +245,7 @@ export default class PredictionContext extends EventEmitter { + private doTryRevert = (/*returnObj: {shouldSwallow: boolean}*/): void => { // Has the revert keystroke (BKSP) already been sent once since the last accept? if(this.doRevert) { // If so, clear the 'revert' option and start doing normal predictions again. diff --git a/common/web/keyboard-processor/src/text/keyboardProcessor.ts b/common/web/keyboard-processor/src/text/keyboardProcessor.ts index bdcf4e33a6..ac8bf53b00 100644 --- a/common/web/keyboard-processor/src/text/keyboardProcessor.ts +++ b/common/web/keyboard-processor/src/text/keyboardProcessor.ts @@ -443,7 +443,7 @@ export default class KeyboardProcessor extends EventEmitter { // Do not change layer unless needed (27/08/2015) if(id == activeLayer && keyEvent.device.formFactor != DeviceSpec.FormFactor.Desktop) { - return false; + return; } var idx=id; diff --git a/common/web/lm-worker/src/main/correction/context-tracker.ts b/common/web/lm-worker/src/main/correction/context-tracker.ts index b25f727440..2f15165e5e 100644 --- a/common/web/lm-worker/src/main/correction/context-tracker.ts +++ b/common/web/lm-worker/src/main/correction/context-tracker.ts @@ -413,7 +413,7 @@ export class ContextTracker extends CircularArray { There's already an implied whitespace to the left, so we conceptually merge the new whitespace with that one. */ - return state; + return; } else if(isBackspace) { // Consider backspace entry for this case? state.replaceTailForBackspace(finalToken, primaryInput.id); diff --git a/common/web/recorder/src/index.ts b/common/web/recorder/src/index.ts index c83112e9cb..f776dc1370 100644 --- a/common/web/recorder/src/index.ts +++ b/common/web/recorder/src/index.ts @@ -104,6 +104,8 @@ export abstract class RecordedKeystroke { return new RecordedPhysicalKeystroke(obj as RecordedPhysicalKeystroke); } else if(obj.type == "osk") { return new RecordedSyntheticKeystroke(obj as RecordedSyntheticKeystroke); + } else { + return null; } } diff --git a/web/src/tsconfig.dom.json b/web/src/tsconfig.dom.json index 47f2d25016..3c06cfbfbc 100644 --- a/web/src/tsconfig.dom.json +++ b/web/src/tsconfig.dom.json @@ -6,6 +6,8 @@ // TODO: These override ../tsconfig.base.json settings, and so should be removed if possible, // but existing code in web/ breaks some of these settings "noImplicitAny": false, - "strictFunctionTypes": false + "strictFunctionTypes": false, + "noImplicitReturns": false, + "strictNullChecks": false, } } \ No newline at end of file diff --git a/web/tsconfig.base.json b/web/tsconfig.base.json index aac6de4f32..e0ed00a89a 100644 --- a/web/tsconfig.base.json +++ b/web/tsconfig.base.json @@ -10,11 +10,6 @@ "lib": ["es6"], "target": "es5", - // TODO: These override ../tsconfig.base.json settings, and so should be removed if possible, - // but existing code in web/ breaks some of these settings - "noImplicitReturns": false, - "strictNullChecks": false, - // Other settings - declaration files, sourcemapping, and other miscellaneous bits. "allowJs": false, "declaration": true, From 04244415a4288cdde29b76fae55525f08c4d3d0c Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Thu, 23 May 2024 14:10:31 +0700 Subject: [PATCH 06/13] chore(web): resolves some nits observed in review --- .../src/engine/headless/gestures/specs/modelDefValidator.ts | 3 +-- common/web/gesture-recognizer/src/engine/touchEventEngine.ts | 2 +- .../tools/unit-test-resources/src/inputSequenceSimulator.ts | 1 - .../input-processor/src/text/prediction/languageProcessor.ts | 1 + 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/common/web/gesture-recognizer/src/engine/headless/gestures/specs/modelDefValidator.ts b/common/web/gesture-recognizer/src/engine/headless/gestures/specs/modelDefValidator.ts index cbdbb06608..ff22ddd45a 100644 --- a/common/web/gesture-recognizer/src/engine/headless/gestures/specs/modelDefValidator.ts +++ b/common/web/gesture-recognizer/src/engine/headless/gestures/specs/modelDefValidator.ts @@ -100,8 +100,7 @@ export function validateModelDefs(definitions: GestureModelDefs): Mode processAction(entry.resolutionAction, `model: ${entry.id}`); Object.keys(entry.rejectionActions ?? {}).forEach((key) => { - // @ts-ignore - processAction(entry.rejectionActions[key], `model: ${entry.id}`); + processAction(entry.rejectionActions[key as Exclude], `model: ${entry.id}`); }); }); diff --git a/common/web/gesture-recognizer/src/engine/touchEventEngine.ts b/common/web/gesture-recognizer/src/engine/touchEventEngine.ts index 2dcddffb09..dea11fe6ab 100644 --- a/common/web/gesture-recognizer/src/engine/touchEventEngine.ts +++ b/common/web/gesture-recognizer/src/engine/touchEventEngine.ts @@ -76,7 +76,7 @@ export class TouchEventEngine extends InputEventEngi super.dropTouchpoint(source); for(const key of Object.keys(this.safeBoundMaskMap)) { - const keyVal = Number.parseInt(key, 10) + const keyVal = Number.parseInt(key, 10); if(this.getTouchpointWithId(keyVal) == source) { delete this.safeBoundMaskMap[keyVal]; } diff --git a/common/web/gesture-recognizer/src/tools/unit-test-resources/src/inputSequenceSimulator.ts b/common/web/gesture-recognizer/src/tools/unit-test-resources/src/inputSequenceSimulator.ts index 9f2e834066..1f997a0041 100644 --- a/common/web/gesture-recognizer/src/tools/unit-test-resources/src/inputSequenceSimulator.ts +++ b/common/web/gesture-recognizer/src/tools/unit-test-resources/src/inputSequenceSimulator.ts @@ -57,7 +57,6 @@ export class InputSequenceSimulator { return { _arr: arr, // Obviously, this isn't a standard member of TouchList. length: arr.length, - //@ts-ignore item: function(i: number) { return this._arr[i]; } } } diff --git a/common/web/input-processor/src/text/prediction/languageProcessor.ts b/common/web/input-processor/src/text/prediction/languageProcessor.ts index 19f5010806..ae0515b961 100644 --- a/common/web/input-processor/src/text/prediction/languageProcessor.ts +++ b/common/web/input-processor/src/text/prediction/languageProcessor.ts @@ -286,6 +286,7 @@ export default class LanguageProcessor extends EventEmitter Date: Thu, 23 May 2024 14:11:32 +0700 Subject: [PATCH 07/13] chore(web): better use of scope within getVKDictionaryCode --- common/web/keyboard-processor/src/keyboards/keyboard.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/web/keyboard-processor/src/keyboards/keyboard.ts b/common/web/keyboard-processor/src/keyboards/keyboard.ts index 31978ddfdf..0cd0a99bee 100644 --- a/common/web/keyboard-processor/src/keyboards/keyboard.ts +++ b/common/web/keyboard-processor/src/keyboards/keyboard.ts @@ -600,7 +600,7 @@ export default class Keyboard { this.scriptObject['VKDictionary']=dict; } - const res=this.scriptObject['VKDictionary'][keyName.toUpperCase()]; + const res=dict[keyName.toUpperCase()]; return res ? res : 0; } } \ No newline at end of file From 12c91d90c36b39258ba0fc67257475e5c6fe303e Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Thu, 23 May 2024 14:36:00 +0700 Subject: [PATCH 08/13] fix(web): better suggestionApplier fix for the 'reversion' path --- .../input-processor/src/text/prediction/predictionContext.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/web/input-processor/src/text/prediction/predictionContext.ts b/common/web/input-processor/src/text/prediction/predictionContext.ts index 2b3776792d..82a167d96f 100644 --- a/common/web/input-processor/src/text/prediction/predictionContext.ts +++ b/common/web/input-processor/src/text/prediction/predictionContext.ts @@ -81,7 +81,7 @@ export default class PredictionContext extends EventEmitter kbdProcessor.layerId); } else { - return Promise.resolve(null); + return null; } } From 61dfcc98f670787721deb6b9046f043aca2f7989 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Thu, 30 May 2024 16:37:00 +0700 Subject: [PATCH 09/13] docs(web): documents KeyboardObject properties --- .../src/keyboards/keyboard.ts | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/common/web/keyboard-processor/src/keyboards/keyboard.ts b/common/web/keyboard-processor/src/keyboards/keyboard.ts index 0cd0a99bee..b11da683fd 100644 --- a/common/web/keyboard-processor/src/keyboards/keyboard.ts +++ b/common/web/keyboard-processor/src/keyboards/keyboard.ts @@ -31,29 +31,152 @@ export interface VariableStoreDictionary { }; 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 + * Keyman keyboard language. + * @param outputTarget The context to which the keystroke applies + * @param keystroke The full, pre-processed keystroke triggering + * keyboard-rule application. + */ gs(outputTarget: OutputTarget, keystroke: KeyEvent): boolean; + + /** + * group-newcontext: the function triggering processing for the keyboard's + * "NewContext" start group, corresponding to `begin NewContext > use(_____)` + * in Keyman keyboard language. + * @param outputTarget The new context to be used with future keystrokes + * @param keystroke Unused, as this group type is inherently `readonly`. + */ gn?(outputTarget: OutputTarget, keystroke: KeyEvent): boolean; + + /** + * group-postkeystroke: the function triggering processing for the keyboard's + * "PostKeystroke" start group, corresponding to `begin PostKeystroke > + * use(_____)` in Keyman keyboard language. + * @param outputTarget The context altered by a recent keystroke. As a + * precondition, all changes due to `gs` / `begin Unicode` should already be + * applied. + * @param keystroke Unused, as this group type is inherently `readonly`. + */ gpk?(outputTarget: OutputTarget, keystroke: KeyEvent): boolean; + + /** + * Keyboard ID: the uniquely-identifying name for this keyboard. Includes the standard + * `Keyboard_` prefix. May be 'namespaced' with a prefix corresponding to a package name + * within app/webview. + */ KI: string; + /** + * Keyboard Name: the human-readable name of the keyboard. + */ KN: string; + /** + * Encoded data usable to construct a desktop/hardware-oriented on-screen keyboard. + */ KV: EncodedVisualKeyboard; + /** + * Keyboard Language Code: set within select keyboards. + * + * Currently, it's only used to determine the need for CJK-picker support. Is missing + * in most compiled keyboards. + */ KLC?: string; + /** + * @deprecated + * Keyboard Language Code: set within select keyboards. + * + * Currently, it's only used to determine the need for CJK-picker support. + * Is (probably) an older name of KLC with the identical purpose. Is missing + * in most compiled keyboards. + */ LanguageCode?: string; + /** + * Keyboard CSS: provides the definition for custom keyboard style sheets + */ KCSS?: string; + /** + * Keyboard is RTL: a simple flag noting if the keyboard's script is RTL. + */ KRTL?: boolean; + /** + * Keyboard Modifier BitMask: a set of bitflags indicating which modifiers + * the keyboard's rules utilize. See also: `Codes.modifierCodes`. + */ KMBM?: number; + /** + * Keyboard Supplementary plane: set to 1 if the keyboard uses non-BMP Unicode + * characters. + */ KS?: number; + /** + * Keyman Visual Keyboard Layout: defines the touch-layout definitions used for + * 'phone' and 'tablet' form-factors. + */ KVKL?: LayoutSpec; + /** + * Keyboard is Mnemonic: set to 1 if the keyboard uses a mnemonic layout. + */ KM?: number; + /** + * KeyBoard VERsion: the version of this keyboard. + */ KBVER?: string; + /** + * Keyman VERsion: the version of Keyman Developer used to compile this keyboard. + */ KVER?: string; + /** + * Keyman Variable Stores: an array of the names of all variable stores used by the + * keyboard. + */ KVS?: (`s${number}`)[]; + /** + * Keyboard Help: HTML help text, as specified by either the &kmw_helptext or &kmw_helpfile system stores. + * + * Reference: https://help.keyman.com/developer/language/reference/kmw_helptext, + * https://help.keyman.com/developer/language/reference/kmw_helpfile + */ KH?: string; + /** + * Keyboard Virtual Key Dictionary: the Developer-compiled, minified dictionary of virtual-key codes + */ KVKD?: string; + /** + * Keyboard Display Underlying: set to 1 if the desktop form of the keyboard + * should show the US QWERTY underlying keycaps. These may also appear on + * 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 + * in a keyboard's source, though that file may also contain _other_ script + * definitions as well. (`KHF` must be explicitly defined within that file.) + * @param e Will be provided with the root element (a
) of the On-Screen Keyboard. + * @returns + */ KHF?: (e: any) => string; + + /** + * Keyboard Notify Shift: Provided by CJK-picker keyboards to properly + * interface them with Keyman Engine for Web. + * @param {number} _PCommand event code (16,17,18) or 0; 16-18 + * correspond to modifier codes when pressed, while 0 corresponds to loss of focus + * @param {Object} _PTarget target element + * @param {number} _PData 1 or 0 + * @returns + */ KNS?: (_PCommand: number, _PTarget: OutputTarget, _PData: number) => void; } & Record<`s${number}`, string> From 10033f4dead6389cdc41be56627628dbc48d26ea Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Thu, 30 May 2024 16:40:59 +0700 Subject: [PATCH 10/13] docs(web): fixes detail about readonly keystroke params --- common/web/keyboard-processor/src/keyboards/keyboard.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/web/keyboard-processor/src/keyboards/keyboard.ts b/common/web/keyboard-processor/src/keyboards/keyboard.ts index b11da683fd..6fad53c0d7 100644 --- a/common/web/keyboard-processor/src/keyboards/keyboard.ts +++ b/common/web/keyboard-processor/src/keyboards/keyboard.ts @@ -51,7 +51,7 @@ export type KeyboardObject = { * "NewContext" start group, corresponding to `begin NewContext > use(_____)` * in Keyman keyboard language. * @param outputTarget The new context to be used with future keystrokes - * @param keystroke Unused, as this group type is inherently `readonly`. + * @param keystroke A 'null' `KeyEvent` providing current modifier + state information. */ gn?(outputTarget: OutputTarget, keystroke: KeyEvent): boolean; @@ -62,7 +62,7 @@ export type KeyboardObject = { * @param outputTarget The context altered by a recent keystroke. As a * precondition, all changes due to `gs` / `begin Unicode` should already be * applied. - * @param keystroke Unused, as this group type is inherently `readonly`. + * @param keystroke A 'null' `KeyEvent` providing current modifier + state information. */ gpk?(outputTarget: OutputTarget, keystroke: KeyEvent): boolean; From 487a28da8e64e56b3c328d3fb6d15fb5d13afb06 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Thu, 30 May 2024 16:44:27 +0700 Subject: [PATCH 11/13] docs(web): for EncodedVisualKeyboard --- .../src/keyboards/defaultLayouts.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/common/web/keyboard-processor/src/keyboards/defaultLayouts.ts b/common/web/keyboard-processor/src/keyboards/defaultLayouts.ts index 4ef864dce6..47fefb8c57 100644 --- a/common/web/keyboard-processor/src/keyboards/defaultLayouts.ts +++ b/common/web/keyboard-processor/src/keyboards/defaultLayouts.ts @@ -24,7 +24,19 @@ export interface EncodedVisualKeyboard { F: string; /** Should there be a 102nd key? */ K102?: boolean, + /** + * Keyboard Layer Specification: an object-based map of layer name to the keycaps for its + * 65 keys. The 65 keys are ordered from left to right, then top to bottom. + * + * There are a few reserved entries. + * TODO: better document the exact ranges involved. + */ KLS?: {[layerName: string]: string[]}, + /** + * @deprecated + * The older form for data in KLS - defines keycaps for 'default' keys, then 'shift' keys, + * in a single concatenated array. + */ BK?: string[]; } From c4932b7fd1f3498ec5a6b027b3e8aef047c339c2 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Fri, 31 May 2024 10:06:05 +0700 Subject: [PATCH 12/13] docs(web): adds suggested documentation from code review Co-authored-by: Marc Durdin --- .../input-processor/src/text/prediction/languageProcessor.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/common/web/input-processor/src/text/prediction/languageProcessor.ts b/common/web/input-processor/src/text/prediction/languageProcessor.ts index ae0515b961..5f7aeda886 100644 --- a/common/web/input-processor/src/text/prediction/languageProcessor.ts +++ b/common/web/input-processor/src/text/prediction/languageProcessor.ts @@ -168,6 +168,10 @@ export default class LanguageProcessor extends EventEmitter Date: Mon, 3 Jun 2024 08:37:42 +0700 Subject: [PATCH 13/13] docs(web): on KLS format and its arrays of 65 entries --- common/web/keyboard-processor/src/keyboards/defaultLayouts.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/web/keyboard-processor/src/keyboards/defaultLayouts.ts b/common/web/keyboard-processor/src/keyboards/defaultLayouts.ts index 47fefb8c57..bda44ce97f 100644 --- a/common/web/keyboard-processor/src/keyboards/defaultLayouts.ts +++ b/common/web/keyboard-processor/src/keyboards/defaultLayouts.ts @@ -28,8 +28,8 @@ export interface EncodedVisualKeyboard { * Keyboard Layer Specification: an object-based map of layer name to the keycaps for its * 65 keys. The 65 keys are ordered from left to right, then top to bottom. * - * There are a few reserved entries. - * TODO: better document the exact ranges involved. + * The key ID corresponding to each index of the array is specified within `Codes.dfltCodes`. + * Entries corresponding to `K_*` in `Codes.dfltCodes` are reserved for future use. */ KLS?: {[layerName: string]: string[]}, /**