diff --git a/web/docs/internal/keystroke-processing.md b/web/docs/internal/keystroke-processing.md index 60c2c44f7e0..ca44e597833 100644 --- a/web/docs/internal/keystroke-processing.md +++ b/web/docs/internal/keystroke-processing.md @@ -72,8 +72,13 @@ Note that for JS-keyboards, in 18.0 and before the true keystroke is processed a #### Keystroke-default emulation -Note that browser-default keystroke processing is defined within the `DefaultRules` class found at [web/src/engine/keyboard/src/defaultRules.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/keyboard/src/defaultRules.ts). It currently produces a (possibly `null`) string output rather than a `ProcessorAction`, but the latter can be easily constructed based on the returned string and the existing context state. -- For `epic/web-core`, it may be wise to spin the `DefaultRules` component off as its own processor, serving as a backup for _all_ keystroke processing variants. +Note that browser-default keystroke processing is defined within the `DefaultOutputRules` class +found at +[web/src/engine/keyboard/src/defaultOutputRules.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/keyboard/src/defaultOutputRules.ts). +It currently produces a (possibly `null`) string output rather than a `ProcessorAction`, but the +latter can be easily constructed based on the returned string and the existing context state. +- For `epic/web-core`, it may be wise to spin the `DefaultOutputRules` component off as its own + processor, serving as a backup for _all_ keystroke processing variants. ---- diff --git a/web/src/app/browser/src/defaultBrowserRules.ts b/web/src/app/browser/src/defaultBrowserRules.ts index a631c1a0c21..75c1850868d 100644 --- a/web/src/app/browser/src/defaultBrowserRules.ts +++ b/web/src/app/browser/src/defaultBrowserRules.ts @@ -1,14 +1,14 @@ import { ModifierKeyConstants } from '@keymanapp/common-types'; import { Codes, - DefaultRules, + DefaultOutputRules, type KeyEvent, type TextStore } from 'keyman/engine/keyboard'; import { ContextManager } from './contextManager.js'; -export class DefaultBrowserRules extends DefaultRules { +export class DefaultBrowserRules extends DefaultOutputRules { private contextManager: ContextManager; constructor(contextManager: ContextManager) { diff --git a/web/src/app/webview/src/keymanEngine.ts b/web/src/app/webview/src/keymanEngine.ts index 4e5af1d2a2c..e5d95dbcf88 100644 --- a/web/src/app/webview/src/keymanEngine.ts +++ b/web/src/app/webview/src/keymanEngine.ts @@ -1,5 +1,5 @@ import { DeviceSpec } from 'keyman/common/web-utils'; -import { DefaultRules, ProcessorAction } from 'keyman/engine/keyboard'; +import { DefaultOutputRules, ProcessorAction } from 'keyman/engine/keyboard'; import { KeymanEngineBase, KeyboardInterfaceBase } from 'keyman/engine/main'; import { AnchoredOSKView, ViewConfiguration, StaticActivator } from 'keyman/engine/osk'; import { getAbsoluteX, getAbsoluteY } from 'keyman/engine/dom-utils'; @@ -36,7 +36,7 @@ export class KeymanEngine extends KeymanEngineBase void; export interface ProcessorInitOptions { baseLayout?: string; keyboardInterface?: JSKeyboardInterface; // for tests, replace keyboardInterface with a mock, TODO-web-core: refactor into a unit test pattern - defaultOutputRules?: DefaultRules; // Takes the class def object, not an instance thereof. + defaultOutputRules?: DefaultOutputRules; // Takes the class def object, not an instance thereof. } export class JSKeyboardProcessor extends EventEmitter implements KeyboardProcessor { private static readonly DEFAULT_OPTIONS: ProcessorInitOptions = { baseLayout: 'us', - defaultOutputRules: new DefaultRules() // TODO-web-core: move this out of here and only in keymanEngine.ts, rename to DefaultOutputRules + defaultOutputRules: new DefaultOutputRules() // TODO-web-core: move this out of here and only in keymanEngine.ts, rename to DefaultOutputRules }; // Tracks the simulated value for supported state keys, allowing the OSK to mirror a physical keyboard for them. @@ -59,7 +59,7 @@ export class JSKeyboardProcessor extends EventEmitter implements Keybo public baseLayout: string; - public defaultRules: DefaultRules; + public defaultOutputRules: DefaultOutputRules; // Callbacks for various feedback types public beepHandler?: BeepHandler; @@ -77,7 +77,7 @@ export class JSKeyboardProcessor extends EventEmitter implements Keybo this.baseLayout = options.baseLayout || JSKeyboardProcessor.DEFAULT_OPTIONS.baseLayout; this.keyboardInterface = options.keyboardInterface || new JSKeyboardInterface(globalObject(), MinimalKeymanGlobal); - this.defaultRules = options.defaultOutputRules || JSKeyboardProcessor.DEFAULT_OPTIONS.defaultOutputRules; + this.defaultOutputRules = options.defaultOutputRules || JSKeyboardProcessor.DEFAULT_OPTIONS.defaultOutputRules; } public get activeKeyboard(): JSKeyboard { @@ -133,13 +133,13 @@ export class JSKeyboardProcessor extends EventEmitter implements Keybo matched = true; // All the conditions below result in matches until the final else, which restores the expected default // if no match occurs. - if(this.defaultRules.isCommand(Lkc)) { + if(this.defaultOutputRules.isCommand(Lkc)) { // Note this in the rule behavior, return successfully. We'll consider applying it later. ruleBehavior.triggersDefaultCommand = true; // We'd rather let the browser handle these keys, but we're using emulated keystrokes, forcing KMW // to emulate default behavior here. - } else if((special = this.defaultRules.forSpecialEmulation(Lkc)) != null) { + } else if((special = this.defaultOutputRules.forSpecialEmulation(Lkc)) != null) { switch(special) { case EmulationKeystrokes.Backspace: this.keyboardInterface.defaultBackspace(textStore); @@ -163,12 +163,12 @@ export class JSKeyboardProcessor extends EventEmitter implements Keybo const isMnemonic = this.activeKeyboard && this.activeKeyboard.isMnemonic; if(!matched) { - if((char = this.defaultRules.forAny(Lkc, isMnemonic, ruleBehavior)) != null) { - special = this.defaultRules.forSpecialEmulation(Lkc) + if((char = this.defaultOutputRules.forAny(Lkc, isMnemonic, ruleBehavior)) != null) { + special = this.defaultOutputRules.forSpecialEmulation(Lkc) if(special == EmulationKeystrokes.Backspace) { // A browser's default backspace may fail to delete both parts of an SMP character. this.keyboardInterface.defaultBackspace(textStore); - } else if(special || this.defaultRules.isCommand(Lkc)) { // Filters out 'commands' like TAB. + } else if(special || this.defaultOutputRules.isCommand(Lkc)) { // Filters out 'commands' like TAB. // We only do the "for special emulation" cases under the condition above... aside from backspace // Let the browser handle those. return null; @@ -638,7 +638,7 @@ export class JSKeyboardProcessor extends EventEmitter implements Keybo if (data.triggersDefaultCommand) { const keyEvent = data.transcription.keystroke; - this.defaultRules.applyCommand(keyEvent, textStore); + this.defaultOutputRules.applyCommand(keyEvent, textStore); } if (this.warningLogger && data.warningLog) { diff --git a/web/src/engine/src/keyboard/defaultRules.ts b/web/src/engine/src/keyboard/defaultOutputRules.ts similarity index 94% rename from web/src/engine/src/keyboard/defaultRules.ts rename to web/src/engine/src/keyboard/defaultOutputRules.ts index 585069f6d1f..f3fce3472dd 100644 --- a/web/src/engine/src/keyboard/defaultRules.ts +++ b/web/src/engine/src/keyboard/defaultOutputRules.ts @@ -22,9 +22,9 @@ export class LogMessages { /** * Defines a collection of static library functions that define KeymanWeb's default (implied) keyboard rule behaviors. */ -export class DefaultRules { - codeForEvent(Lkc: KeyEvent) { - return Codes.keyCodes[Lkc.kName] || Lkc.Lcode;; +export class DefaultOutputRules { + protected codeForEvent(Lkc: KeyEvent) { + return Codes.keyCodes[Lkc.kName] || Lkc.Lcode; } /** @@ -32,7 +32,7 @@ export class DefaultRules { * Also used by Processor.defaultRuleBehavior to generate output after filtering for special cases. */ public forAny(Lkc: KeyEvent, isMnemonic: boolean, logMessages?: LogMessages): string { - var char = ''; + let char = ''; // A pretty simple table of lookups, corresponding VERY closely to the original defaultKeyOutput. if((char = this.forSpecialEmulation(Lkc)) != null) { @@ -48,7 +48,7 @@ export class DefaultRules { // // Not originally defined for text output within defaultKeyOutput. // // We can't enable it yet, as it'll cause hardware keystrokes in the DOM to output '\t' rather // // than rely on the browser-default handling. - let code = this.codeForEvent(Lkc); + const code = this.codeForEvent(Lkc); switch(code) { // case Codes.keyCodes['K_TAB']: // case Codes.keyCodes['K_TABBACK']: @@ -64,7 +64,7 @@ export class DefaultRules { * isCommand - returns a boolean indicating if a non-text event should be triggered by the keystroke. */ public isCommand(Lkc: KeyEvent): boolean { - let code = this.codeForEvent(Lkc); + const code = this.codeForEvent(Lkc); switch(code) { // Should we ever implement them: @@ -115,7 +115,7 @@ export class DefaultRules { * for 'synthetic' `TextStore`s like `SyntheticTextStore`s, which have no default text handling. */ public forSpecialEmulation(Lkc: KeyEvent): EmulationKeystrokes { - let code = this.codeForEvent(Lkc); + const code = this.codeForEvent(Lkc); switch(code) { case Codes.keyCodes['K_BKSP']: @@ -141,13 +141,8 @@ export class DefaultRules { // Translate numpad keystrokes into their non-numpad equivalents if(Lkc.Lcode >= Codes.keyCodes["K_NP0"] && Lkc.Lcode <= Codes.keyCodes["K_NPSLASH"]) { // Number pad, numlock on - if(Lkc.Lcode < 106) { - var Lch = Lkc.Lcode-48; - } else { - Lch = Lkc.Lcode-64; - } - let ch = String.fromCodePoint(Lch); - return ch; + const cp = (Lkc.Lcode < 106) ? Lkc.Lcode - 48 : Lkc.Lcode - 64; + return String.fromCodePoint(cp); } else { return null; } @@ -166,7 +161,7 @@ export class DefaultRules { let result = ''; const codePoints = keyName.substr(2).split('_'); - for(let codePoint of codePoints) { + for(const codePoint of codePoints) { const codePointValue = parseInt(codePoint, 16); if (((0x0 <= codePointValue) && (codePointValue <= 0x1F)) || ((0x80 <= codePointValue) && (codePointValue <= 0x9F)) || isNaN(codePointValue)) { // Code points [U_0000 - U_001F] and [U_0080 - U_009F] refer to Unicode C0 and C1 control codes. @@ -181,13 +176,13 @@ export class DefaultRules { result += String.fromCodePoint(codePointValue); } } - return result ? result : null; + return result || null; } // Test for otherwise unimplemented keys on the the base default & shift layers. // Those keys must be blocked by keyboard rules if intentionally unimplemented; otherwise, this function will trigger. public forBaseKeys(Lkc: KeyEvent, logMessages?: LogMessages) { - let n = Lkc.Lcode; + const n = Lkc.Lcode; let keyShiftState = Lkc.Lmodifiers; // check if exact match to SHIFT's code. Only the 'default' and 'shift' layers should have default key outputs. diff --git a/web/src/engine/src/keyboard/index.ts b/web/src/engine/src/keyboard/index.ts index 965e28df2d1..c292f112660 100644 --- a/web/src/engine/src/keyboard/index.ts +++ b/web/src/engine/src/keyboard/index.ts @@ -26,7 +26,7 @@ export { type Alternate, TextTransform } from "./keyboards/textTransform.js"; export { Transcription } from "./keyboards/transcription.js"; export { Codes } from "./codes.js"; -export { EmulationKeystrokes, LogMessages, DefaultRules } from "./defaultRules.js"; +export { EmulationKeystrokes, LogMessages, DefaultOutputRules } from "./defaultOutputRules.js"; export { type KeyDistribution, KeyEventSpec, KeyEvent } from "./keyEvent.js"; export { KeyMapping } from "./keyMapping.js"; export { type SystemStoreMutationHandler, MutableSystemStore, SystemStore, SystemStoreIDs, type SystemStoreDictionary } from "./systemStore.js"; diff --git a/web/src/engine/src/keyboard/keyEvent.ts b/web/src/engine/src/keyboard/keyEvent.ts index 363212bb04f..c10605eaaf5 100644 --- a/web/src/engine/src/keyboard/keyEvent.ts +++ b/web/src/engine/src/keyboard/keyEvent.ts @@ -10,7 +10,7 @@ import { type JSKeyboard } from "./keyboards/jsKeyboard.js"; import { type DeviceSpec } from "keyman/common/web-utils"; import { Codes } from './codes.js'; -import { DefaultRules } from "./defaultRules.js"; +import { DefaultOutputRules } from "./defaultOutputRules.js"; import { ActiveKeyBase } from './keyboards/activeLayout.js'; // Represents a probability distribution over a keyboard's keys. @@ -19,9 +19,9 @@ export type KeyDistribution = { keySpec: ActiveKeyBase, p: number }[]; /** * A simple instance of the standard 'default rules' for keystroke processing from the - * DefaultRules base class. + * DefaultOutputRules base class. */ -const BASE_DEFAULT_RULES = new DefaultRules(); +const BASE_DEFAULT_RULES = new DefaultOutputRules(); export interface KeyEventSpec { diff --git a/web/src/engine/src/keyboard/keyboards/keyboardProcessor.ts b/web/src/engine/src/keyboard/keyboards/keyboardProcessor.ts index 331ea0a1bb7..7d8b06d4be2 100644 --- a/web/src/engine/src/keyboard/keyboards/keyboardProcessor.ts +++ b/web/src/engine/src/keyboard/keyboards/keyboardProcessor.ts @@ -35,7 +35,7 @@ export type BeepHandler = (textStore: TextStore) => void; export interface KeyboardProcessor extends EventEmitter { // public static readonly DEFAULT_OPTIONS: ProcessorInitOptions = { // baseLayout: 'us', - // defaultOutputRules: new DefaultRules() + // defaultOutputRules: new DefaultOutputRules() // }; /**