From 3ee71158fea207d9936ffd72360fdc67d660b8f8 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Tue, 6 Aug 2024 16:03:19 +0700 Subject: [PATCH 01/65] fix(windows): Don't translate "Keyman" in some Windows strings --- windows/src/desktop/kmshell/xml/strings.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/windows/src/desktop/kmshell/xml/strings.xml b/windows/src/desktop/kmshell/xml/strings.xml index 1e1df09ce00..4cef9daa9ba 100644 --- a/windows/src/desktop/kmshell/xml/strings.xml +++ b/windows/src/desktop/kmshell/xml/strings.xml @@ -792,13 +792,18 @@ keyboard that you use in Windows. Keyman keyboards will adapt automatically to - Keyman + Keyman Start Keyman + + + + Start %1$s + From 4335f19a6ac7b6ba69d35f95e7e4adf85b2e4fb8 Mon Sep 17 00:00:00 2001 From: "Steven R. Loomis" Date: Mon, 24 Jun 2024 09:48:26 -0500 Subject: [PATCH 02/65] fix(developer): remove redundant check in linter - simplify LdmlKeyboardCompiler.validate() by removing a redundant check --- developer/src/kmc-ldml/src/compiler/compiler.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/developer/src/kmc-ldml/src/compiler/compiler.ts b/developer/src/kmc-ldml/src/compiler/compiler.ts index 59ed5f9a072..bdb11ac176d 100644 --- a/developer/src/kmc-ldml/src/compiler/compiler.ts +++ b/developer/src/kmc-ldml/src/compiler/compiler.ts @@ -291,10 +291,14 @@ export class LdmlKeyboardCompiler implements KeymanCompiler { } /** - * Runs any linter steps + * Runs any linter steps, adding hints to the callbacks as needed * @internal + * @returns true unless there was a linter failure. */ private async lint(source: LDMLKeyboardXMLSourceFile, kmx: KMXPlus.KMXPlusFile) : Promise { + if (!kmx || !source) { + return false; + } // run each of the linters for (const linter of this.buildLinters(source, kmx)) { if (!await linter.lint()) { @@ -319,12 +323,7 @@ export class LdmlKeyboardCompiler implements KeymanCompiler { } // Run the linters - if (!await this.lint(source, kmx)) { - return false; - } - - // We are valid if we have a keyboard file at this point. - return !!kmx; + return (await this.lint(source, kmx)); } /** From 88c538160a4de30825943a959fdf2ac9d0a6b5bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 05:13:47 +0000 Subject: [PATCH 03/65] chore(deps-dev): bump @75lb/deep-merge from 1.1.1 to 1.1.2 Bumps [@75lb/deep-merge](https://github.com/75lb/deep-merge) from 1.1.1 to 1.1.2. - [Commits](https://github.com/75lb/deep-merge/compare/v1.1.1...v1.1.2) --- updated-dependencies: - dependency-name: "@75lb/deep-merge" dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 26e925843d9..8f739de9e19 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2071,12 +2071,12 @@ } }, "node_modules/@75lb/deep-merge": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@75lb/deep-merge/-/deep-merge-1.1.1.tgz", - "integrity": "sha512-xvgv6pkMGBA6GwdyJbNAnDmfAIR/DfWhrj9jgWh3TY7gRm3KO46x/GPjRg6wJ0nOepwqrNxFfojebh0Df4h4Tw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@75lb/deep-merge/-/deep-merge-1.1.2.tgz", + "integrity": "sha512-08K9ou5VNbheZFxM5tDWoqjA3ImC50DiuuJ2tj1yEPRfkp8lLLg6XAaJ4On+a0yAXor/8ay5gHnAIshRM44Kpw==", "dev": true, "dependencies": { - "lodash.assignwith": "^4.2.0", + "lodash": "^4.17.21", "typical": "^7.1.1" }, "engines": { @@ -10617,12 +10617,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.assignwith": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignwith/-/lodash.assignwith-4.2.0.tgz", - "integrity": "sha512-ZznplvbvtjK2gMvnQ1BR/zqPFZmS6jbK4p+6Up4xcRYA7yMIwxHCfbTcrYxXKzzqLsQ05eJPVznEW3tuwV7k1g==", - "dev": true - }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", From 4c87a16b276fb2ba6b17895c8243766dba459ecf Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Mon, 5 Aug 2024 13:05:40 +0700 Subject: [PATCH 04/65] feat(android/engine): Add special handling for ENTER key --- .../com/keyman/android/SystemKeyboard.java | 3 ++ .../keyman/engine/KMKeyboardJSHandler.java | 29 ++++++++++- .../java/com/keyman/engine/KMManager.java | 49 ++++++++++++++++++- 3 files changed, 79 insertions(+), 2 deletions(-) diff --git a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java index c6885b2b564..9bc5a4a8558 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java +++ b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java @@ -147,6 +147,9 @@ public void onStartInput(EditorInfo attribute, boolean restarting) { KMManager.onStartInput(attribute, restarting); KMManager.resetContext(KeyboardType.KEYBOARD_TYPE_SYSTEM); + // Determine special handling for ENTER key + KMManager.setEnterMode(attribute.imeOptions); + // This method (likely) includes the IME equivalent to `onResume` for `Activity`-based classes, // making it an important time to detect orientation changes. Context appContext = getApplicationContext(); diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java index 926ef094f74..426cfb3e52e 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java @@ -20,6 +20,7 @@ import static android.content.Context.VIBRATOR_SERVICE; +import com.keyman.engine.KMManager.EnterModeType; import com.keyman.engine.KMManager.KeyboardType; import com.keyman.engine.data.Keyboard; import com.keyman.engine.util.CharSequenceUtil; @@ -153,7 +154,33 @@ public void run() { } if (s.length() > 0 && s.charAt(0) == '\n') { - keyDownUp(KeyEvent.KEYCODE_ENTER, 0); + if (k.keyboardType == KeyboardType.KEYBOARD_TYPE_SYSTEM) { + // Special handling of ENTER key + switch (KMManager.enterMode) { + // Go action + case GO : + ic.performEditorAction(EditorInfo.IME_ACTION_GO); + break; + + // Search action + case SEARCH : + ic.performEditorAction(EditorInfo.IME_ACTION_SEARCH); + break; + + // Messaging apps + case NEWLINE : + // Send newline without advancing cursor + ic.commitText("\n", 0); + break; + + // Default ENTER action + default: + keyDownUp(KeyEvent.KEYCODE_ENTER, 0); + } + } else { + // In-app keyboard uses default ENTER action + keyDownUp(KeyEvent.KEYCODE_ENTER, 0); + } ic.endBatchEdit(); return; } diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java index aa1c43626a7..adef3d3fe51 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java @@ -25,7 +25,6 @@ import android.content.pm.PackageManager; import android.content.res.AssetManager; import android.content.res.Configuration; -import android.content.res.Resources; import android.graphics.Point; import android.graphics.Typeface; import android.inputmethodservice.InputMethodService; @@ -180,6 +179,15 @@ public String toString() { } } + // Enum for how the System Keyboard ENTER key is handled for the EditorInfo action + // Reference: https://developer.android.com/reference/android/view/inputmethod/EditorInfo#summary + public enum EnterModeType { + GO, // Go action + SEARCH, // Search action + NEWLINE, // Send newline character + DEFAULT, // Default ENTER action + } + protected static InputMethodService IMService; private static boolean debugMode = false; @@ -218,6 +226,9 @@ public String toString() { // regardless what the Settings preference is. private static boolean mayPredictOverride = false; + // Determine how system keyboard handles ENTER key + public static EnterModeType enterMode = EnterModeType.DEFAULT; + // Boolean for whether a keyboard can send embedded KMW crash reports to Sentry // When maySendCrashReport is false, KMW will still attempt to send crash reports, but it // will be blocked. @@ -1251,6 +1262,42 @@ public boolean accept(File pathname) { } } + /** + * Sets enterMode which specifies how the System keyboard ENTER key is handled + * + * @param imeOptions EditorInfo.imeOptions + */ + public static void setEnterMode(int imeOptions) { + int imeActions = imeOptions&EditorInfo.IME_MASK_ACTION; + EnterModeType value = EnterModeType.DEFAULT; + + switch (imeActions) { + case EditorInfo.IME_ACTION_GO: + value = EnterModeType.GO; + break; + + case EditorInfo.IME_ACTION_SEARCH: + value = EnterModeType.SEARCH; + break; + + case EditorInfo.IME_ACTION_DONE: + value = EnterModeType.NEWLINE; + break; + + default: + value = EnterModeType.DEFAULT; + } + enterMode = value; + } + + /** + * Get the value of enterMode + * @return EnterModeType + */ + public static EnterModeType getEnterMode() { + return enterMode; + } + /** * Sets mayPredictOverride true if the InputType field is a hidden password text field * (either TYPE_TEXT_VARIATION_PASSWORD or TYPE_TEXT_VARIATION_WEB_PASSWORD From ea2b062c5273684a78f46dce5da3c34ecbed1648 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 7 Aug 2024 15:21:40 +0700 Subject: [PATCH 05/65] fix(android/engine): Separate DONE from NEWLINE action --- .../java/com/keyman/android/SystemKeyboard.java | 6 +++--- .../com/keyman/engine/KMKeyboardJSHandler.java | 5 +++++ .../src/main/java/com/keyman/engine/KMManager.java | 14 +++++++++++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java index 9bc5a4a8558..ab9b4fcb449 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java +++ b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java @@ -147,9 +147,6 @@ public void onStartInput(EditorInfo attribute, boolean restarting) { KMManager.onStartInput(attribute, restarting); KMManager.resetContext(KeyboardType.KEYBOARD_TYPE_SYSTEM); - // Determine special handling for ENTER key - KMManager.setEnterMode(attribute.imeOptions); - // This method (likely) includes the IME equivalent to `onResume` for `Activity`-based classes, // making it an important time to detect orientation changes. Context appContext = getApplicationContext(); @@ -178,6 +175,9 @@ public void onStartInput(EditorInfo attribute, boolean restarting) { } } + // Determine special handling for ENTER key + KMManager.setEnterMode(attribute.imeOptions, inputType); + InputConnection ic = getCurrentInputConnection(); if (ic != null) { ExtractedText icText = ic.getExtractedText(new ExtractedTextRequest(), 0); diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java index 426cfb3e52e..66af2ebe07d 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java @@ -167,6 +167,11 @@ public void run() { ic.performEditorAction(EditorInfo.IME_ACTION_SEARCH); break; + // Done action + case DONE : + ic.performEditorAction(EditorInfo.IME_ACTION_DONE); + break; + // Messaging apps case NEWLINE : // Send newline without advancing cursor diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java index adef3d3fe51..adf9d30737d 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java @@ -185,6 +185,7 @@ public enum EnterModeType { GO, // Go action SEARCH, // Search action NEWLINE, // Send newline character + DONE, // Done action DEFAULT, // Default ENTER action } @@ -1266,9 +1267,15 @@ public boolean accept(File pathname) { * Sets enterMode which specifies how the System keyboard ENTER key is handled * * @param imeOptions EditorInfo.imeOptions + * @param inputType InputType */ - public static void setEnterMode(int imeOptions) { - int imeActions = imeOptions&EditorInfo.IME_MASK_ACTION; + public static void setEnterMode(int imeOptions, int inputType) { + if ((inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) != 0) { + enterMode = EnterModeType.NEWLINE; + return; + } + + int imeActions = imeOptions & EditorInfo.IME_MASK_ACTION; EnterModeType value = EnterModeType.DEFAULT; switch (imeActions) { @@ -1281,12 +1288,13 @@ public static void setEnterMode(int imeOptions) { break; case EditorInfo.IME_ACTION_DONE: - value = EnterModeType.NEWLINE; + value = EnterModeType.DONE; break; default: value = EnterModeType.DEFAULT; } + enterMode = value; } From c09c895333ef5acb5872d92b8413feadf0282e12 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 30 Jul 2024 18:08:41 +0200 Subject: [PATCH 06/65] =?UTF-8?q?refactor(web):=20move=20parts=20of=20`key?= =?UTF-8?q?board-processor`=20=E2=86=92=20`js-processor`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move parts of `common/web/keyboard-processor/` → `web/src/engine/js-processor/`. Note this temporarily disable tests for keyboard-processor which depend on js-processor, until #12110 is fixed. Fixes: #12067 --- common/web/keyboard-processor/build.sh | 11 +- common/web/keyboard-processor/src/index.ts | 10 +- .../src/keyboards/keyboard.ts | 74 ++++++++++++- .../src/keyboards/keyboardHarness.ts | 3 + .../keyboard-processor/src/text/keyEvent.ts | 30 +++-- .../src/text/ruleBehavior.interface.ts | 12 ++ .../src/text/systemStores.ts | 36 +++++- .../keyboard-processor/tests/dom/readme.md | 5 - .../tests/dom/web-test-runner.CI.config.mjs | 13 --- .../tests/dom/web-test-runner.config.mjs | 62 ----------- .../keyboard-processor/tests/tsconfig.json | 11 -- .../web/keyboard-processor/tsconfig.all.json | 1 - web/README.md | 4 +- web/build.sh | 2 + web/package.json | 5 + web/src/app/browser/src/beepHandler.ts | 2 +- web/src/app/browser/src/configuration.ts | 3 +- .../app/browser/src/defaultBrowserRules.ts | 2 +- .../app/browser/src/hardwareEventKeyboard.ts | 3 +- web/src/app/webview/src/keymanEngine.ts | 3 +- .../events/src/keyEventSource.interface.ts | 4 +- web/src/engine/interfaces/build.sh | 1 + .../src/prediction/predictionContext.ts | 3 +- web/src/engine/interfaces/tsconfig.json | 1 + web/src/engine/js-processor/build.sh | 41 +++++++ .../engine/js-processor/src}/defaultRules.ts | 31 +++--- web/src/engine/js-processor/src/index.ts | 7 ++ .../engine/js-processor/src}/kbdInterface.ts | 103 +----------------- .../js-processor/src}/keyboardProcessor.ts | 36 +++--- .../engine/js-processor/src}/ruleBehavior.ts | 4 +- web/src/engine/js-processor/tsconfig.json | 13 +++ web/src/engine/main/build.sh | 1 + web/src/engine/main/src/contextManagerBase.ts | 3 +- .../engine/main/src/engineConfiguration.ts | 3 +- web/src/engine/main/src/hardKeyboard.ts | 3 +- .../main/src/headless/inputProcessor.ts | 6 +- web/src/engine/main/src/keyboardInterface.ts | 5 +- web/src/engine/main/src/keymanEngine.ts | 10 +- web/src/engine/main/tsconfig.json | 1 + .../domKeyboardLoader.spec.ts | 3 +- web/src/test/auto/dom/kbdLoader.ts | 2 +- .../prediction/predictionContext.spec.js | 3 +- .../testing/recorder-core/src/nodeProctor.ts | 3 +- .../tools/testing/recorder-core/tsconfig.json | 3 +- 44 files changed, 294 insertions(+), 288 deletions(-) create mode 100644 common/web/keyboard-processor/src/text/ruleBehavior.interface.ts delete mode 100644 common/web/keyboard-processor/tests/dom/readme.md delete mode 100644 common/web/keyboard-processor/tests/dom/web-test-runner.CI.config.mjs delete mode 100644 common/web/keyboard-processor/tests/dom/web-test-runner.config.mjs delete mode 100644 common/web/keyboard-processor/tests/tsconfig.json create mode 100755 web/src/engine/js-processor/build.sh rename {common/web/keyboard-processor/src/text => web/src/engine/js-processor/src}/defaultRules.ts (91%) create mode 100644 web/src/engine/js-processor/src/index.ts rename {common/web/keyboard-processor/src/text => web/src/engine/js-processor/src}/kbdInterface.ts (94%) rename {common/web/keyboard-processor/src/text => web/src/engine/js-processor/src}/keyboardProcessor.ts (96%) rename {common/web/keyboard-processor/src/text => web/src/engine/js-processor/src}/ruleBehavior.ts (96%) create mode 100644 web/src/engine/js-processor/tsconfig.json rename {common/web/keyboard-processor/tests/dom/cases => web/src/test/auto/dom/cases/keyboard-processor}/domKeyboardLoader.spec.ts (95%) diff --git a/common/web/keyboard-processor/build.sh b/common/web/keyboard-processor/build.sh index 3921063bb93..964370c2fbf 100755 --- a/common/web/keyboard-processor/build.sh +++ b/common/web/keyboard-processor/build.sh @@ -17,6 +17,7 @@ BUNDLE_CMD="node ${KEYMAN_ROOT}/common/web/es-bundling/build/common-bundle.mjs" builder_describe \ "Compiles the web-oriented utility function module." \ "@/web/src/tools/testing/recorder-core test" \ + "@/web/src/engine/js-processor test" \ "@/common/web/keyman-version" \ "@/common/web/es-bundling" \ "@/common/web/types" \ @@ -64,10 +65,10 @@ function do_build() { --platform node # Tests - builder_echo "Bundle tests" - ${BUNDLE_CMD} "${KEYMAN_ROOT}/common/web/keyboard-processor/build/tests/dom/cases/domKeyboardLoader.spec.js" \ - --out "${KEYMAN_ROOT}/common/web/keyboard-processor/build/tests/dom/domKeyboardLoader.spec.mjs" \ - --format esm + # builder_echo "Bundle tests" + # ${BUNDLE_CMD} "${KEYMAN_ROOT}/common/web/keyboard-processor/build/tests/dom/cases/domKeyboardLoader.spec.js" \ + # --out "${KEYMAN_ROOT}/common/web/keyboard-processor/build/tests/dom/domKeyboardLoader.spec.mjs" \ + # --format esm # Declaration bundling. builder_echo "Declaration bundling" @@ -92,4 +93,4 @@ function do_test() { builder_run_action configure do_configure builder_run_action clean rm -rf ./build builder_run_action build do_build -builder_run_action test do_test +# builder_run_action test do_test diff --git a/common/web/keyboard-processor/src/index.ts b/common/web/keyboard-processor/src/index.ts index f800691cfac..c719d7ee8e8 100644 --- a/common/web/keyboard-processor/src/index.ts +++ b/common/web/keyboard-processor/src/index.ts @@ -27,20 +27,14 @@ export { default as StateKeyMap } from "./keyboards/stateKeyMap.js"; export { default as Codes } from "./text/codes.js"; export * from "./text/codes.js"; export * from "./text/deadkeys.js"; -export { default as DefaultRules } from "./text/defaultRules.js"; -export * from "./text/defaultRules.js"; -export { default as KeyboardInterface } from "./text/kbdInterface.js"; -export * from "./text/kbdInterface.js"; -export { default as KeyboardProcessor } from "./text/keyboardProcessor.js"; -export * from "./text/keyboardProcessor.js"; export { default as KeyEvent } from "./text/keyEvent.js"; export * from "./text/keyEvent.js"; export { default as KeyMapping } from "./text/keyMapping.js"; export { default as OutputTarget } from "./text/outputTarget.js"; export * from "./text/outputTarget.js"; -export { default as RuleBehavior } from "./text/ruleBehavior.js"; export * from "./text/stringDivergence.js"; export * from "./text/systemStores.js"; +export * from "./text/ruleBehavior.interface.js"; export * from "@keymanapp/web-utils"; @@ -48,4 +42,4 @@ export * from "@keymanapp/web-utils"; // 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; \ No newline at end of file +export default undefined; diff --git a/common/web/keyboard-processor/src/keyboards/keyboard.ts b/common/web/keyboard-processor/src/keyboards/keyboard.ts index 5312d825a65..6ca5f790fdc 100644 --- a/common/web/keyboard-processor/src/keyboards/keyboard.ts +++ b/common/web/keyboard-processor/src/keyboards/keyboard.ts @@ -6,11 +6,83 @@ import type OutputTarget from "../text/outputTarget.js"; import { ModifierKeyConstants, TouchLayout } from "@keymanapp/common-types"; type TouchLayoutSpec = TouchLayout.TouchLayoutPlatform & { isDefault?: boolean}; -import type { ComplexKeyboardStore } from "../text/kbdInterface.js"; +import type { ComplexKeyboardStore, KeyboardStore } from "../text/systemStores.js"; import { Version, DeviceSpec } from "@keymanapp/web-utils"; import StateKeyMap from "./stateKeyMap.js"; +export class RuleDeadkey { + /** Discriminant field - 'd' for Deadkey. + */ + t: 'd'; + + /** + * Value: the deadkey's ID. + */ + d: number; // For 'd'eadkey; also reflects the Deadkey class's 'd' property. +} + +export class StoreBeep { + /** Discriminant field - 'b' for `beep` + */ + ['t']: 'b'; +} + +export type RuleChar = string; + +export class ContextAny { + /** Discriminant field - 'a' for `any()`. + */ + ['t']: 'a'; + + /** + * Value: the store to search. + */ + ['a']: KeyboardStore; // For 'a'ny statement. + + /** + * If set to true, negates the 'any'. + */ + ['n']: boolean | 0 | 1; +} + +export class RuleIndex { + /** Discriminant field - 'i' for `index()`. + */ + ['t']: 'i'; + + /** + * Value: the Store from which to output + */ + ['i']: KeyboardStore; + + /** + * Offset: the offset in context for the corresponding `any()`. + */ + ['o']: number; +} + +export class ContextEx { + /** Discriminant field - 'c' for `context()`. + */ + ['t']: 'c'; + + /** + * Value: The offset into the current rule's context to be matched. + */ + ['c']: number; // For 'c'ontext statement. +} + +export class ContextNul { + /** Discriminant field - 'n' for `nul` + */ + ['t']: 'n'; +} + + + +export type StoreNonCharEntry = RuleDeadkey | StoreBeep; + /** * Stores preprocessed properties of a keyboard for quick retrieval later. */ diff --git a/common/web/keyboard-processor/src/keyboards/keyboardHarness.ts b/common/web/keyboard-processor/src/keyboards/keyboardHarness.ts index 671c8fefd7c..109d2090673 100644 --- a/common/web/keyboard-processor/src/keyboards/keyboardHarness.ts +++ b/common/web/keyboard-processor/src/keyboards/keyboardHarness.ts @@ -1,5 +1,6 @@ import Keyboard from "./keyboard.js"; import Codes from "../text/codes.js"; +import { DeviceSpec } from '@keymanapp/web-utils'; /** * Defines members of the top-level `keyman` global object necessary to guarantee @@ -40,6 +41,8 @@ export const MinimalKeymanGlobal: KeyboardKeymanGlobal = { export class KeyboardHarness { public readonly _jsGlobal: any; public readonly keymanGlobal: KeyboardKeymanGlobal; + activeDevice: DeviceSpec; + /** * Constructs and configures a harness for receiving dynamically-loaded Keyman keyboards. diff --git a/common/web/keyboard-processor/src/text/keyEvent.ts b/common/web/keyboard-processor/src/text/keyEvent.ts index a38992a3a14..7c507cc1703 100644 --- a/common/web/keyboard-processor/src/text/keyEvent.ts +++ b/common/web/keyboard-processor/src/text/keyEvent.ts @@ -10,18 +10,30 @@ import type Keyboard from "../keyboards/keyboard.js"; import { type DeviceSpec } from "@keymanapp/web-utils"; import Codes from './codes.js'; -import DefaultRules from './defaultRules.js'; import { ActiveKeyBase } from "../index.js"; +interface DefaultRulesInterface { + forAny(Lkc: KeyEvent, isMnemonic: boolean): string; +} + +export class BASE_DEFAULT_RULES { + private static _instance: DefaultRulesInterface; + + // Prevent direct instantiation. + private constructor() { } + + public static forAny(Lkc: KeyEvent, isMnemonic: boolean): string { + return this._instance.forAny(Lkc, isMnemonic); + } + + public static set instance(value: DefaultRulesInterface) { + this._instance = value; + } +} + // Represents a probability distribution over a keyboard's keys. // Defined here to avoid compilation issues. -export type KeyDistribution = {keySpec: ActiveKeyBase, p: number}[]; - -/** - * A simple instance of the standard 'default rules' for keystroke processing from the - * DefaultRules base class. - */ -const BASE_DEFAULT_RULES = new DefaultRules(); +export type KeyDistribution = { keySpec: ActiveKeyBase, p: number }[]; export interface KeyEventSpec { @@ -188,4 +200,4 @@ export default class KeyEvent implements KeyEventSpec { } } } -}; \ No newline at end of file +}; diff --git a/common/web/keyboard-processor/src/text/ruleBehavior.interface.ts b/common/web/keyboard-processor/src/text/ruleBehavior.interface.ts new file mode 100644 index 00000000000..29f81bcc8c1 --- /dev/null +++ b/common/web/keyboard-processor/src/text/ruleBehavior.interface.ts @@ -0,0 +1,12 @@ +import { type Transcription } from './outputTarget.js'; + +/** + * Represents the commands and state changes that result from a matched keyboard rule. + */ +export interface RuleBehaviorInterface { + /** + * The before-and-after Transform from matching a keyboard rule. May be `null` + * if no keyboard rules were matched for the keystroke. + */ + transcription: Transcription; +} diff --git a/common/web/keyboard-processor/src/text/systemStores.ts b/common/web/keyboard-processor/src/text/systemStores.ts index 13184baafec..a2f7abff344 100644 --- a/common/web/keyboard-processor/src/text/systemStores.ts +++ b/common/web/keyboard-processor/src/text/systemStores.ts @@ -1,5 +1,31 @@ -import type KeyboardInterface from "./kbdInterface.js"; -import { SystemStoreIDs } from "./kbdInterface.js"; +import { type KeyboardHarness } from "../keyboards/keyboardHarness.js"; +import { StoreNonCharEntry } from '../keyboards/keyboard.js'; + +export enum SystemStoreIDs { + TSS_LAYER = 33, + TSS_PLATFORM = 31, + TSS_NEWLAYER = 42, + TSS_OLDLAYER = 43 +} + +/* +* Type alias definitions to reflect the parameters of the fullContextMatch() callback (KMW 10+). +* No constructors or methods since keyboards will not utilize the same backing prototype, and +* property names are shorthanded to promote minification. +*/ +type PlainKeyboardStore = string; + +export type KeyboardStoreElement = (string | StoreNonCharEntry); +export type ComplexKeyboardStore = KeyboardStoreElement[]; + +export type KeyboardStore = PlainKeyboardStore | ComplexKeyboardStore; + +export type VariableStore = { [name: string]: string }; + +export interface VariableStoreSerializer { + loadStore(keyboardID: string, storeName: string): VariableStore; + saveStore(keyboardID: string, storeName: string, storeMap: VariableStore): void; +} /** * Defines common behaviors associated with system stores. @@ -61,9 +87,9 @@ export class MutableSystemStore extends SystemStore { * Handles checks against the current platform. */ export class PlatformSystemStore extends SystemStore { - private readonly kbdInterface: KeyboardInterface; + private readonly kbdInterface: KeyboardHarness; - constructor(keyboardInterface: KeyboardInterface) { + constructor(keyboardInterface: KeyboardHarness) { super(SystemStoreIDs.TSS_PLATFORM); this.kbdInterface = keyboardInterface; @@ -131,4 +157,4 @@ export class PlatformSystemStore extends SystemStore { // Everything we checked against was valid and had matches - it's a match! return true; } -} \ No newline at end of file +} diff --git a/common/web/keyboard-processor/tests/dom/readme.md b/common/web/keyboard-processor/tests/dom/readme.md deleted file mode 100644 index 153b7f4a1e8..00000000000 --- a/common/web/keyboard-processor/tests/dom/readme.md +++ /dev/null @@ -1,5 +0,0 @@ -Automated tests in this subfolder and its children are designed to facilitate simple, browser-independent -unit tests that are DOM-reliant. - -Tests for anything that may reasonably vary depending upon the browser used to run the code should go under -the "integrated" folder instead. \ No newline at end of file diff --git a/common/web/keyboard-processor/tests/dom/web-test-runner.CI.config.mjs b/common/web/keyboard-processor/tests/dom/web-test-runner.CI.config.mjs deleted file mode 100644 index d18a8a9cb09..00000000000 --- a/common/web/keyboard-processor/tests/dom/web-test-runner.CI.config.mjs +++ /dev/null @@ -1,13 +0,0 @@ -// @ts-check -import BASE_CONFIG from './web-test-runner.config.mjs'; -import teamcityReporter from '@keymanapp/common-test-resources/test-runner-TC-reporter.mjs'; -import { sessionStabilityReporter } from '@keymanapp/common-test-resources/test-runner-stability-reporter.mjs'; - -/** @type {import('@web/test-runner').TestRunnerConfig} */ -export default { - ...BASE_CONFIG, - reporters: [ - teamcityReporter(), /* custom-written, for CI-friendly reports */ - sessionStabilityReporter({ciMode: true}) - ] -} \ No newline at end of file diff --git a/common/web/keyboard-processor/tests/dom/web-test-runner.config.mjs b/common/web/keyboard-processor/tests/dom/web-test-runner.config.mjs deleted file mode 100644 index 76651182acb..00000000000 --- a/common/web/keyboard-processor/tests/dom/web-test-runner.config.mjs +++ /dev/null @@ -1,62 +0,0 @@ -// @ts-check -import { devices, playwrightLauncher } from '@web/test-runner-playwright'; -import { esbuildPlugin } from '@web/dev-server-esbuild'; -import { defaultReporter, summaryReporter } from '@web/test-runner'; -import { LauncherWrapper, sessionStabilityReporter } from '@keymanapp/common-test-resources/test-runner-stability-reporter.mjs'; -import { importMapsPlugin } from '@web/dev-server-import-maps'; -import { dirname, resolve } from 'path'; -import { fileURLToPath } from 'url'; - -const dir = dirname(fileURLToPath(import.meta.url)); -const KEYMAN_ROOT = resolve(dir, '../../../../..'); - -/** @type {import('@web/test-runner').TestRunnerConfig} */ -export default { - // debug: true, - browsers: [ - new LauncherWrapper(playwrightLauncher({ product: 'chromium' })), - new LauncherWrapper(playwrightLauncher({ product: 'firefox' })), - new LauncherWrapper(playwrightLauncher({ product: 'webkit', concurrency: 1 })), - ], - concurrency: 10, - nodeResolve: true, - files: [ - 'build/tests/dom/**/*.spec.mjs' - ], - middleware: [ - // Rewrites short-hand paths for test resources, making them fully relative to the repo root. - function rewriteResourcePath(context, next) { - if(context.url.startsWith('/resources/')) { - context.url = '/common/test' + context.url; - } - - return next(); - } - ], - plugins: [ - esbuildPlugin({ts: true, target: 'auto'}), - importMapsPlugin({ - inject: { - importMap: { - // Redirects `eventemitter3` imports to the bundled ESM library. The standard import is an - // ESM wrapper around the CommonJS implementation, and WTR fails when it hits the CommonJS. - imports: { - 'eventemitter3': '/node_modules/eventemitter3/dist/eventemitter3.esm.js' - } - } - } - }) - ], - reporters: [ - summaryReporter({}), /* local-dev mocha-style */ - sessionStabilityReporter({}), - defaultReporter({}) - ], - /* - Un-comment the next two lines for easy interactive debugging; it'll launch the - test page in your preferred browser. - */ - // open: true, - // manual: true, - rootDir: KEYMAN_ROOT -} diff --git a/common/web/keyboard-processor/tests/tsconfig.json b/common/web/keyboard-processor/tests/tsconfig.json deleted file mode 100644 index 0e978545b81..00000000000 --- a/common/web/keyboard-processor/tests/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "baseUrl": "../", - "outDir": "../build/tests/", - "tsBuildInfoFile": "../build/tests/tsconfig.tsbuildinfo", - "rootDir": "./" - }, - "include": [ "./dom/**/*.ts"], - "exclude": [] -} diff --git a/common/web/keyboard-processor/tsconfig.all.json b/common/web/keyboard-processor/tsconfig.all.json index dabb262d9cb..79f10644d10 100644 --- a/common/web/keyboard-processor/tsconfig.all.json +++ b/common/web/keyboard-processor/tsconfig.all.json @@ -9,7 +9,6 @@ "references": [ { "path": "./src/keyboards/loaders/tsconfig.dom.json" }, { "path": "./src/keyboards/loaders/tsconfig.node.json" }, - { "path": "./tests/tsconfig.json" }, ], // Actual main-body compilation is in tsconfig.json. This config is just a wrapper // to trigger all three components at once. diff --git a/web/README.md b/web/README.md index 1249805165e..775f303df5c 100644 --- a/web/README.md +++ b/web/README.md @@ -82,6 +82,7 @@ title: Dependency Graph graph TD; OSK["/web/src/engine/osk"]; KP["@keymanapp/keyboard-processor
(/common/web/keyboard-processor)"]; + JSProc["/web/src/engine/js-processor"]; OSK-->KP; WebUtils["@keymanapp/web-utils
(/common/web/utils)"]; KP---->WebUtils; @@ -107,6 +108,7 @@ graph TD; Fully headless components`"] direction LR KP; + JSProc-->KP; WebUtils; PredText; Gestures; @@ -127,9 +129,9 @@ graph TD; OSK-->Gestures; Interfaces["/web/src/engine/interfaces"]; Interfaces-->KP; + Interfaces-->JSProc; OSK-->Interfaces; CommonEngine["/web/src/engine/main"]; - CommonEngine-->Interfaces; CommonEngine-->Device; CommonEngine-->KeyboardCache; CommonEngine-->OSK; diff --git a/web/build.sh b/web/build.sh index 7248f5c35af..6f4737710a3 100755 --- a/web/build.sh +++ b/web/build.sh @@ -27,6 +27,7 @@ builder_describe "Builds engine modules for Keyman Engine for Web (KMW)." \ ":engine/dom-utils A common subset of function used for DOM calculations, layout, etc" \ ":engine/events Specialized classes utilized to support KMW API events" \ ":engine/element-wrappers Subset used to integrate with website elements" \ + ":engine/js-processor Build JS processor for KMW" \ ":engine/main Builds all common code used by KMW's app/-level targets" \ ":engine/osk Builds the Web OSK module" \ ":engine/package-cache Subset used to collate keyboards and request them from the cloud" \ @@ -57,6 +58,7 @@ builder_describe_outputs \ build:engine/dom-utils "/web/build/engine/dom-utils/obj/index.js" \ build:engine/events "/web/build/engine/events/lib/index.mjs" \ build:engine/element-wrappers "/web/build/engine/element-wrappers/lib/index.mjs" \ + build:engine/js-processor "/web/build/engine/js-processor/lib/index.mjs" \ build:engine/main "/web/build/engine/main/lib/index.mjs" \ build:engine/osk "/web/build/engine/osk/lib/index.mjs" \ build:engine/package-cache "/web/build/engine/package-cache/lib/index.mjs" \ diff --git a/web/package.json b/web/package.json index 458ea85de01..4baff29490d 100644 --- a/web/package.json +++ b/web/package.json @@ -37,6 +37,11 @@ "types": "./build/engine/events/obj/index.d.ts", "import": "./build/engine/events/obj/index.js" }, + "./engine/js-processor": { + "es6-bundling": "./src/engine/js-processor/src/index.ts", + "types": "./build/engine/js-processor/obj/index.d.ts", + "import": "./build/engine/js-processor/obj/index.js" + }, "./engine/package-cache": { "es6-bundling": "./src/engine/package-cache/src/index.ts", "types": "./build/engine/package-cache/obj/index.d.ts", diff --git a/web/src/app/browser/src/beepHandler.ts b/web/src/app/browser/src/beepHandler.ts index 3659f8d7fdb..eb6d6583ee4 100644 --- a/web/src/app/browser/src/beepHandler.ts +++ b/web/src/app/browser/src/beepHandler.ts @@ -1,4 +1,4 @@ -import { type KeyboardInterface } from '@keymanapp/keyboard-processor'; +import { type KeyboardInterface } from 'keyman/engine/js-processor'; import { DesignIFrame, OutputTarget } from 'keyman/engine/element-wrappers'; // Utility object used to handle beep (keyboard error response) operations. diff --git a/web/src/app/browser/src/configuration.ts b/web/src/app/browser/src/configuration.ts index 07be8264e78..4f2f2684388 100644 --- a/web/src/app/browser/src/configuration.ts +++ b/web/src/app/browser/src/configuration.ts @@ -1,7 +1,8 @@ import { EngineConfiguration, InitOptionSpec, InitOptionDefaults } from "keyman/engine/main"; import { OutputTarget as DOMOutputTarget } from 'keyman/engine/element-wrappers'; -import { isEmptyTransform, OutputTarget, RuleBehavior } from '@keymanapp/keyboard-processor'; +import { isEmptyTransform, OutputTarget } from '@keymanapp/keyboard-processor'; +import { RuleBehavior } from 'keyman/engine/js-processor'; import { AlertHost } from "./utils/alertHost.js"; import { whenDocumentReady } from "./utils/documentReady.js"; diff --git a/web/src/app/browser/src/defaultBrowserRules.ts b/web/src/app/browser/src/defaultBrowserRules.ts index 1ac48016892..fc084ec3f49 100644 --- a/web/src/app/browser/src/defaultBrowserRules.ts +++ b/web/src/app/browser/src/defaultBrowserRules.ts @@ -1,10 +1,10 @@ import { ModifierKeyConstants } from '@keymanapp/common-types'; import { Codes, - DefaultRules, type KeyEvent, type OutputTarget } from '@keymanapp/keyboard-processor'; +import { DefaultRules } from 'keyman/engine/js-processor'; import ContextManager from './contextManager.js'; diff --git a/web/src/app/browser/src/hardwareEventKeyboard.ts b/web/src/app/browser/src/hardwareEventKeyboard.ts index 29e867aa13c..f6874fc77b7 100644 --- a/web/src/app/browser/src/hardwareEventKeyboard.ts +++ b/web/src/app/browser/src/hardwareEventKeyboard.ts @@ -1,4 +1,5 @@ -import { Codes, DeviceSpec, KeyEvent, KeyMapping, Keyboard, KeyboardProcessor } from '@keymanapp/keyboard-processor'; +import { Codes, DeviceSpec, KeyEvent, KeyMapping, Keyboard } from '@keymanapp/keyboard-processor'; +import { KeyboardProcessor } from 'keyman/engine/js-processor'; import { ModifierKeyConstants } from '@keymanapp/common-types'; import { HardKeyboard, processForMnemonicsAndLegacy } from 'keyman/engine/main'; diff --git a/web/src/app/webview/src/keymanEngine.ts b/web/src/app/webview/src/keymanEngine.ts index ba98f8c4776..2f073505484 100644 --- a/web/src/app/webview/src/keymanEngine.ts +++ b/web/src/app/webview/src/keymanEngine.ts @@ -1,4 +1,5 @@ -import { DefaultRules, DeviceSpec, RuleBehavior } from '@keymanapp/keyboard-processor' +import { DeviceSpec } from '@keymanapp/keyboard-processor' +import { DefaultRules, RuleBehavior } from 'keyman/engine/js-processor'; import { KeymanEngine as KeymanEngineBase, KeyboardInterface } from 'keyman/engine/main'; import { AnchoredOSKView, ViewConfiguration, StaticActivator } from 'keyman/engine/osk'; import { getAbsoluteX, getAbsoluteY } from 'keyman/engine/dom-utils'; diff --git a/web/src/engine/events/src/keyEventSource.interface.ts b/web/src/engine/events/src/keyEventSource.interface.ts index d3c39fa49d7..22621d2de01 100644 --- a/web/src/engine/events/src/keyEventSource.interface.ts +++ b/web/src/engine/events/src/keyEventSource.interface.ts @@ -1,7 +1,7 @@ import { EventEmitter } from "eventemitter3"; -import { type KeyEvent, type RuleBehavior } from "@keymanapp/keyboard-processor"; +import { type KeyEvent, type RuleBehaviorInterface } from "@keymanapp/keyboard-processor"; -export type KeyEventResultCallback = (result: RuleBehavior, error?: Error) => void; +export type KeyEventResultCallback = (result: RuleBehaviorInterface, error?: Error) => void; export type KeyEventHandler = (event: KeyEvent, callback?: KeyEventResultCallback) => void; interface EventMap { diff --git a/web/src/engine/interfaces/build.sh b/web/src/engine/interfaces/build.sh index ca61e648653..528083d4d81 100755 --- a/web/src/engine/interfaces/build.sh +++ b/web/src/engine/interfaces/build.sh @@ -15,6 +15,7 @@ SUBPROJECT_NAME=engine/interfaces builder_describe "Builds configuration subclasses used by the Keyman Engine for Web (KMW)." \ "@/common/web/es-bundling" \ "@/common/web/keyboard-processor" \ + "@/web/src/engine/js-processor" \ "clean" \ "configure" \ "build" \ diff --git a/web/src/engine/interfaces/src/prediction/predictionContext.ts b/web/src/engine/interfaces/src/prediction/predictionContext.ts index d47bf4b8e2d..90427c3020f 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 { type LanguageProcessorSpec , ReadySuggestions, type InvalidateSourceEnum, StateChangeHandler } from './languageProcessor.interface.js'; -import { type KeyboardProcessor, type OutputTarget } from "@keymanapp/keyboard-processor"; +import { type OutputTarget } from "@keymanapp/keyboard-processor"; +import { type KeyboardProcessor } from 'keyman/engine/js-processor'; interface PredictionContextEventMap { update: (suggestions: Suggestion[]) => void; diff --git a/web/src/engine/interfaces/tsconfig.json b/web/src/engine/interfaces/tsconfig.json index d5a193e0213..634e62bada2 100644 --- a/web/src/engine/interfaces/tsconfig.json +++ b/web/src/engine/interfaces/tsconfig.json @@ -13,5 +13,6 @@ "references": [ { "path": "../../../../common/web/keyboard-processor" }, + { "path": "../js-processor" } ] } diff --git a/web/src/engine/js-processor/build.sh b/web/src/engine/js-processor/build.sh new file mode 100755 index 00000000000..57adbd1dd21 --- /dev/null +++ b/web/src/engine/js-processor/build.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" +. "${THIS_SCRIPT%/*}/../../../../resources/build/builder.inc.sh" +## END STANDARD BUILD SCRIPT INCLUDE + +SUBPROJECT_NAME=engine/js-processor + +. "${KEYMAN_ROOT}/web/common.inc.sh" +. "${KEYMAN_ROOT}/resources/shellHelperFunctions.sh" + +# ################################ Main script ################################ + +builder_describe "Builds configuration subclasses used by the Keyman Engine for Web (KMW)." \ + "clean" \ + "configure" \ + "build" \ + "test" \ + "--ci+ Set to utilize CI-based test configurations & reporting." + +builder_describe_outputs \ + configure "/node_modules" \ + build "/web/build/${SUBPROJECT_NAME}/lib/index.mjs" + +builder_parse "$@" + +#### Build action definitions #### + +do_build () { + compile "${SUBPROJECT_NAME}" + + ${BUNDLE_CMD} "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/index.js" \ + --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/index.mjs" \ + --format esm +} + +builder_run_action configure verify_npm_setup +builder_run_action clean rm -rf "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}" +builder_run_action build do_build diff --git a/common/web/keyboard-processor/src/text/defaultRules.ts b/web/src/engine/js-processor/src/defaultRules.ts similarity index 91% rename from common/web/keyboard-processor/src/text/defaultRules.ts rename to web/src/engine/js-processor/src/defaultRules.ts index 931eb5200b2..edaf440bf9a 100644 --- a/common/web/keyboard-processor/src/text/defaultRules.ts +++ b/web/src/engine/js-processor/src/defaultRules.ts @@ -1,18 +1,11 @@ -// TODO: Move to separate folder: 'codes' -// We should start splitting off code needed by keyboards even without a KeyboardProcessor active. -// There's an upcoming `/common/web/types` package that 'codes' and 'keyboards' may fit well within. - -import { ModifierKeyConstants} from '@keymanapp/common-types'; -import Codes from "./codes.js"; -import type KeyEvent from "./keyEvent.js"; -import type OutputTarget from "./outputTarget.js"; - -// The only members referenced are to produce warning and error logs. A little abstraction -// via an optional 'logger' interface can maintain it while facilitating a the split alluded -// to above. -// -// Alternatively, we could just... not take in the parameter at all, which'd also facilitate -// the future modularization effort. +/* + * Keyman is copyright (C) SIL International. MIT License. + * + * Implementation of default rules + */ + +import { ModifierKeyConstants } from '@keymanapp/common-types'; +import { BASE_DEFAULT_RULES, Codes, type KeyEvent, type OutputTarget } from "@keymanapp/keyboard-processor"; import RuleBehavior from "./ruleBehavior.js"; export enum EmulationKeystrokes { @@ -191,7 +184,7 @@ export default class DefaultRules { // check if exact match to SHIFT's code. Only the 'default' and 'shift' layers should have default key outputs. // TODO: Extend to allow AltGr as well - better mnemonic support. - if(keyShiftState == ModifierKeyConstants.K_SHIFTFLAG) { + if (keyShiftState == ModifierKeyConstants.K_SHIFTFLAG) { keyShiftState = 1; } else if(keyShiftState != 0) { if(ruleBehavior) { @@ -224,3 +217,9 @@ export default class DefaultRules { return null; } } + +/** + * A simple instance of the standard 'default rules' for keystroke processing from the + * DefaultRules base class. + */ +BASE_DEFAULT_RULES.instance = new DefaultRules(); diff --git a/web/src/engine/js-processor/src/index.ts b/web/src/engine/js-processor/src/index.ts new file mode 100644 index 00000000000..1c51de80d94 --- /dev/null +++ b/web/src/engine/js-processor/src/index.ts @@ -0,0 +1,7 @@ +export { default as DefaultRules } from "./defaultRules.js"; +export * from "./defaultRules.js"; +export { default as KeyboardProcessor } from "./keyboardProcessor.js"; +export * from "./keyboardProcessor.js"; +export { default as RuleBehavior } from "./ruleBehavior.js"; +export * from './kbdInterface.js'; +export { default as KeyboardInterface } from "./kbdInterface.js"; diff --git a/common/web/keyboard-processor/src/text/kbdInterface.ts b/web/src/engine/js-processor/src/kbdInterface.ts similarity index 94% rename from common/web/keyboard-processor/src/text/kbdInterface.ts rename to web/src/engine/js-processor/src/kbdInterface.ts index 438d328f0dc..2b34eadce9d 100644 --- a/common/web/keyboard-processor/src/text/kbdInterface.ts +++ b/web/src/engine/js-processor/src/kbdInterface.ts @@ -7,18 +7,8 @@ import { type DeviceSpec } from "@keymanapp/web-utils"; import { ModifierKeyConstants } from '@keymanapp/common-types'; - -import Codes from "./codes.js"; -import type KeyEvent from "./keyEvent.js"; -import type { Deadkey } from "./deadkeys.js"; -import KeyMapping from "./keyMapping.js"; -import { SystemStore, MutableSystemStore, PlatformSystemStore } from "./systemStores.js"; -import type { VariableStoreSerializer } from "./keyboardProcessor.js"; -import type OutputTarget from "./outputTarget.js"; -import { Mock } from "./outputTarget.js"; +import { Codes, type KeyEvent, type Deadkey, ComplexKeyboardStore, type KeyboardStore, KeyboardStoreElement, KeyMapping, SystemStoreIDs, SystemStore, MutableSystemStore, PlatformSystemStore, type OutputTarget, Mock, Keyboard, VariableStore, VariableStoreDictionary, VariableStoreSerializer, KeyboardHarness, KeyboardKeymanGlobal, RuleDeadkey, ContextAny, RuleIndex, ContextEx, ContextNul, RuleChar } from "@keymanapp/keyboard-processor"; import RuleBehavior from "./ruleBehavior.js"; -import Keyboard, { VariableStoreDictionary } from "../keyboards/keyboard.js"; -import { KeyboardHarness, KeyboardKeymanGlobal } from "../keyboards/keyboardHarness.js"; //#endregion @@ -30,93 +20,9 @@ export class KeyInformation { modifiers: number; } -/* -* Type alias definitions to reflect the parameters of the fullContextMatch() callback (KMW 10+). -* No constructors or methods since keyboards will not utilize the same backing prototype, and -* property names are shorthanded to promote minification. -*/ -type PlainKeyboardStore = string; - -export type KeyboardStoreElement = (string|StoreNonCharEntry); -export type ComplexKeyboardStore = KeyboardStoreElement[]; - -type KeyboardStore = PlainKeyboardStore | ComplexKeyboardStore; - -export type VariableStore = {[name: string]: string}; - -type RuleChar = string; - -class RuleDeadkey { - /** Discriminant field - 'd' for Deadkey. - */ - t: 'd'; - - /** - * Value: the deadkey's ID. - */ - d: number; // For 'd'eadkey; also reflects the Deadkey class's 'd' property. -} - -class ContextAny { - /** Discriminant field - 'a' for `any()`. - */ - ['t']: 'a'; - - /** - * Value: the store to search. - */ - ['a']: KeyboardStore; // For 'a'ny statement. - - /** - * If set to true, negates the 'any'. - */ - ['n']: boolean|0|1; -} - -class RuleIndex { - /** Discriminant field - 'i' for `index()`. - */ - ['t']: 'i'; - - /** - * Value: the Store from which to output - */ - ['i']: KeyboardStore; - - /** - * Offset: the offset in context for the corresponding `any()`. - */ - ['o']: number; -} - -class ContextEx { - /** Discriminant field - 'c' for `context()`. - */ - ['t']: 'c'; - - /** - * Value: The offset into the current rule's context to be matched. - */ - ['c']: number; // For 'c'ontext statement. -} - -class ContextNul { - /** Discriminant field - 'n' for `nul` - */ - ['t']: 'n'; -} - -class StoreBeep { - /** Discriminant field - 'b' for `beep` - */ - ['t']: 'b'; -} - type ContextNonCharEntry = RuleDeadkey | ContextAny | RuleIndex | ContextEx | ContextNul; type ContextEntry = RuleChar | ContextNonCharEntry; -type StoreNonCharEntry = RuleDeadkey | StoreBeep; - /** * Cache of context storing and retrieving return values from KC * Must be reset prior to each keystroke and after any text changes @@ -183,13 +89,6 @@ class CachedContextEx { } }; -export enum SystemStoreIDs { - TSS_LAYER = 33, - TSS_PLATFORM = 31, - TSS_NEWLAYER = 42, - TSS_OLDLAYER = 43 -} - //#endregion export default class KeyboardInterface extends KeyboardHarness { diff --git a/common/web/keyboard-processor/src/text/keyboardProcessor.ts b/web/src/engine/js-processor/src/keyboardProcessor.ts similarity index 96% rename from common/web/keyboard-processor/src/text/keyboardProcessor.ts rename to web/src/engine/js-processor/src/keyboardProcessor.ts index 836c9912a64..1a6d216dced 100644 --- a/common/web/keyboard-processor/src/text/keyboardProcessor.ts +++ b/web/src/engine/js-processor/src/keyboardProcessor.ts @@ -1,23 +1,21 @@ +/* + * Keyman is copyright (C) SIL International. MIT License. + * + * Implementation of the JavaScript keyboard processor + */ + // #region Big ol' list of imports import { EventEmitter } from 'eventemitter3'; - -import Codes from "./codes.js"; -import type Keyboard from "../keyboards/keyboard.js"; -import { MinimalKeymanGlobal } from '../keyboards/keyboardHarness.js'; -import KeyEvent from "./keyEvent.js"; -import { Layouts } from "../keyboards/defaultLayouts.js"; -import type { MutableSystemStore } from "./systemStores.js"; - +import { ModifierKeyConstants } from '@keymanapp/common-types'; +import { + Codes, type Keyboard, MinimalKeymanGlobal, KeyEvent, Layouts, type MutableSystemStore, + type OutputTarget, Mock, SystemStoreIDs, +} from "@keymanapp/keyboard-processor"; import DefaultRules, { EmulationKeystrokes } from "./defaultRules.js"; -import type OutputTarget from "./outputTarget.js"; -import { Mock } from "./outputTarget.js"; - -import KeyboardInterface, { SystemStoreIDs, VariableStore } from "./kbdInterface.js"; import RuleBehavior from "./ruleBehavior.js"; - +import KeyboardInterface from './kbdInterface.js'; import { DeviceSpec, globalObject } from "@keymanapp/web-utils"; -import { ModifierKeyConstants } from '@keymanapp/common-types'; // #endregion @@ -26,11 +24,6 @@ import { ModifierKeyConstants } from '@keymanapp/common-types'; export type BeepHandler = (outputTarget: OutputTarget) => void; export type LogMessageHandler = (str: string) => void; -export interface VariableStoreSerializer { - loadStore(keyboardID: string, storeName: string): VariableStore; - saveStore(keyboardID: string, storeName: string, storeMap: VariableStore): void; -} - export interface ProcessorInitOptions { baseLayout?: string; keyboardInterface?: KeyboardInterface; @@ -277,7 +270,8 @@ export default class KeyboardProcessor extends EventEmitter { const lockNames = ['CAPS', 'NUM_LOCK', 'SCROLL_LOCK'] as const; const lockKeys = ['K_CAPS', 'K_NUMLOCK', 'K_SCROLL'] as const; - const lockModifiers = [ ModifierKeyConstants.CAPITALFLAG, ModifierKeyConstants.NUMLOCKFLAG, ModifierKeyConstants.SCROLLFLAG] as const; + const lockModifiers = [ModifierKeyConstants.CAPITALFLAG, ModifierKeyConstants.NUMLOCKFLAG, ModifierKeyConstants.SCROLLFLAG] as const; + if(!this.activeKeyboard) { return true; @@ -329,6 +323,8 @@ export default class KeyboardProcessor extends EventEmitter { const lockModifiers = [ModifierKeyConstants.CAPITALFLAG, ModifierKeyConstants.NUMLOCKFLAG, ModifierKeyConstants.SCROLLFLAG] as const; const noLockModifers = [ModifierKeyConstants.NOTCAPITALFLAG, ModifierKeyConstants.NOTNUMLOCKFLAG, ModifierKeyConstants.NOTSCROLLFLAG] as const; + + for(let i=0; i < lockKeys.length; i++) { const key = lockKeys[i]; const flag = this.stateKeys[key]; diff --git a/common/web/keyboard-processor/src/text/ruleBehavior.ts b/web/src/engine/js-processor/src/ruleBehavior.ts similarity index 96% rename from common/web/keyboard-processor/src/text/ruleBehavior.ts rename to web/src/engine/js-processor/src/ruleBehavior.ts index e5d669e9092..aced7065d2d 100644 --- a/common/web/keyboard-processor/src/text/ruleBehavior.ts +++ b/web/src/engine/js-processor/src/ruleBehavior.ts @@ -1,9 +1,7 @@ /// import KeyboardProcessor from "./keyboardProcessor.js"; -import OutputTarget, { Mock, type Transcription } from "./outputTarget.js"; -import { VariableStoreDictionary } from "../keyboards/keyboard.js"; -import type { VariableStore } from "./kbdInterface.js"; +import { OutputTarget, Mock, type Transcription, VariableStoreDictionary, type VariableStore } from "@keymanapp/keyboard-processor"; /** * Represents the commands and state changes that result from a matched keyboard rule. diff --git a/web/src/engine/js-processor/tsconfig.json b/web/src/engine/js-processor/tsconfig.json new file mode 100644 index 00000000000..a57467139bd --- /dev/null +++ b/web/src/engine/js-processor/tsconfig.json @@ -0,0 +1,13 @@ +{ + // While the actual references themselves are headless, it compiles against the DOM-reliant OSK module. + "extends": "../../tsconfig.dom.json", + + "compilerOptions": { + "baseUrl": "./", + "outDir": "../../../build/engine/js-processor/obj/", + "tsBuildInfoFile": "../../../build/engine/js-processor/obj/tsconfig.tsbuildinfo", + "rootDir": "./src" + }, + + "include": [ "**/*.ts" ], +} diff --git a/web/src/engine/main/build.sh b/web/src/engine/main/build.sh index cceb9b4b8b7..4e6ca67db11 100755 --- a/web/src/engine/main/build.sh +++ b/web/src/engine/main/build.sh @@ -18,6 +18,7 @@ builder_describe "Builds the Keyman Engine for Web's common top-level base class "@/common/predictive-text" \ "@/web/src/engine/interfaces build" \ "@/web/src/engine/device-detect build" \ + "@/web/src/engine/js-processor build" \ "@/web/src/engine/package-cache build" \ "@/web/src/engine/osk build" \ "@/developer/src/kmc-model test" \ diff --git a/web/src/engine/main/src/contextManagerBase.ts b/web/src/engine/main/src/contextManagerBase.ts index c3f95810033..e745dbe312b 100644 --- a/web/src/engine/main/src/contextManagerBase.ts +++ b/web/src/engine/main/src/contextManagerBase.ts @@ -1,5 +1,6 @@ import { EventEmitter } from 'eventemitter3'; -import { ManagedPromise, type Keyboard, type KeyboardInterface, type OutputTarget } from '@keymanapp/keyboard-processor'; +import { ManagedPromise, type Keyboard, type OutputTarget } from '@keymanapp/keyboard-processor'; +import { type KeyboardInterface } from 'keyman/engine/js-processor'; import { StubAndKeyboardCache, type KeyboardStub } from 'keyman/engine/package-cache'; import { PredictionContext } from 'keyman/engine/interfaces'; import { EngineConfiguration } from './engineConfiguration.js'; diff --git a/web/src/engine/main/src/engineConfiguration.ts b/web/src/engine/main/src/engineConfiguration.ts index c66d3bd805d..bb82844c565 100644 --- a/web/src/engine/main/src/engineConfiguration.ts +++ b/web/src/engine/main/src/engineConfiguration.ts @@ -1,6 +1,7 @@ import { EventEmitter } from "eventemitter3"; -import { DeviceSpec, KeyboardProperties, ManagedPromise, OutputTarget, physicalKeyDeviceAlias, RuleBehavior, SpacebarText } from "@keymanapp/keyboard-processor"; +import { DeviceSpec, KeyboardProperties, ManagedPromise, OutputTarget, physicalKeyDeviceAlias, SpacebarText } from "@keymanapp/keyboard-processor"; +import { RuleBehavior } from 'keyman/engine/js-processor'; import { PathConfiguration, PathOptionDefaults, PathOptionSpec } from "keyman/engine/interfaces"; import { Device } from "keyman/engine/device-detect"; import { KeyboardStub } from "keyman/engine/package-cache"; diff --git a/web/src/engine/main/src/hardKeyboard.ts b/web/src/engine/main/src/hardKeyboard.ts index a07904f4a6b..7dc9b5e3572 100644 --- a/web/src/engine/main/src/hardKeyboard.ts +++ b/web/src/engine/main/src/hardKeyboard.ts @@ -1,5 +1,6 @@ import { EventEmitter } from "eventemitter3"; -import { Keyboard, KeyMapping, KeyEvent, type RuleBehavior, Codes } from "@keymanapp/keyboard-processor"; +import { Keyboard, KeyMapping, KeyEvent, Codes } from "@keymanapp/keyboard-processor"; +import { type RuleBehavior } from 'keyman/engine/js-processor'; import { KeyEventSourceInterface } from 'keyman/engine/events'; import { ModifierKeyConstants } from '@keymanapp/common-types'; diff --git a/web/src/engine/main/src/headless/inputProcessor.ts b/web/src/engine/main/src/headless/inputProcessor.ts index 7b89a0e242a..a96170457e0 100644 --- a/web/src/engine/main/src/headless/inputProcessor.ts +++ b/web/src/engine/main/src/headless/inputProcessor.ts @@ -12,15 +12,13 @@ import { Codes, isEmptyTransform, type Keyboard, - KeyboardInterface, - KeyboardProcessor, type KeyEvent, Mock, type OutputTarget, - type ProcessorInitOptions, - RuleBehavior, SystemStoreIDs, } from "@keymanapp/keyboard-processor"; +import { KeyboardInterface, KeyboardProcessor, RuleBehavior, type ProcessorInitOptions } from 'keyman/engine/js-processor'; + import { TranscriptionCache } from "./transcriptionCache.js"; export class InputProcessor { diff --git a/web/src/engine/main/src/keyboardInterface.ts b/web/src/engine/main/src/keyboardInterface.ts index a18bafecd07..d966c26bad4 100644 --- a/web/src/engine/main/src/keyboardInterface.ts +++ b/web/src/engine/main/src/keyboardInterface.ts @@ -1,6 +1,5 @@ -import { - KeyboardInterface as KeyboardInterfaceBase, KeyboardObject, -} from "@keymanapp/keyboard-processor"; +import { KeyboardObject } from "@keymanapp/keyboard-processor"; +import { KeyboardInterface as KeyboardInterfaceBase } from 'keyman/engine/js-processor'; import { KeyboardStub, RawKeyboardStub, toUnprefixedKeyboardId as unprefixed } from 'keyman/engine/package-cache'; import { ContextManagerBase } from './contextManagerBase.js'; diff --git a/web/src/engine/main/src/keymanEngine.ts b/web/src/engine/main/src/keymanEngine.ts index eaa54e59945..86ff9d5898d 100644 --- a/web/src/engine/main/src/keymanEngine.ts +++ b/web/src/engine/main/src/keymanEngine.ts @@ -1,4 +1,5 @@ -import { type Keyboard, KeyboardKeymanGlobal, ProcessorInitOptions } from "@keymanapp/keyboard-processor"; +import { type KeyEvent, type Keyboard, KeyboardKeymanGlobal } from "@keymanapp/keyboard-processor"; +import { ProcessorInitOptions, RuleBehavior } from 'keyman/engine/js-processor'; import { DOMKeyboardLoader as KeyboardLoader } from "@keymanapp/keyboard-processor/dom-keyboard-loader"; import { InputProcessor } from './headless/inputProcessor.js'; import { OSKView } from "keyman/engine/osk"; @@ -10,7 +11,7 @@ import KeyboardInterface from "./keyboardInterface.js"; import { ContextManagerBase } from "./contextManagerBase.js"; import HardKeyboardBase from "./hardKeyboard.js"; import { LegacyAPIEvents } from "./legacyAPIEvents.js"; -import { KeyEventHandler, EventNames, EventListener, LegacyEventEmitter } from "keyman/engine/events"; +import { EventNames, EventListener, LegacyEventEmitter } from "keyman/engine/events"; import DOMCloudRequester from "keyman/engine/package-cache/dom-requester"; import KEYMAN_VERSION from "@keymanapp/keyman-version"; @@ -29,6 +30,9 @@ function determineBaseLayout(): string { } } +export type KeyEventFullResultCallback = (result: RuleBehavior, error?: Error) => void; +export type KeyEventFullHandler = (event: KeyEvent, callback?: KeyEventFullResultCallback) => void; + export default class KeymanEngine< Configuration extends EngineConfiguration, ContextManager extends ContextManagerBase, @@ -47,7 +51,7 @@ export default class KeymanEngine< protected keyEventRefocus?: () => void; - private keyEventListener: KeyEventHandler = (event, callback) => { + private keyEventListener: KeyEventFullHandler = (event, callback) => { const outputTarget = this.contextManager.activeTarget; if(!this.contextManager.activeKeyboard || !outputTarget) { diff --git a/web/src/engine/main/tsconfig.json b/web/src/engine/main/tsconfig.json index 9711d06a777..e3b2b0616cc 100644 --- a/web/src/engine/main/tsconfig.json +++ b/web/src/engine/main/tsconfig.json @@ -15,5 +15,6 @@ { "path": "../osk" }, { "path": "../package-cache" }, { "path": "../interfaces" }, + { "path": "../js-processor" } ] } diff --git a/common/web/keyboard-processor/tests/dom/cases/domKeyboardLoader.spec.ts b/web/src/test/auto/dom/cases/keyboard-processor/domKeyboardLoader.spec.ts similarity index 95% rename from common/web/keyboard-processor/tests/dom/cases/domKeyboardLoader.spec.ts rename to web/src/test/auto/dom/cases/keyboard-processor/domKeyboardLoader.spec.ts index 1965adc8534..63414662fae 100644 --- a/common/web/keyboard-processor/tests/dom/cases/domKeyboardLoader.spec.ts +++ b/web/src/test/auto/dom/cases/keyboard-processor/domKeyboardLoader.spec.ts @@ -1,7 +1,8 @@ import { assert } from 'chai'; import { DOMKeyboardLoader } from '@keymanapp/keyboard-processor/dom-keyboard-loader'; -import { extendString, KeyboardHarness, Keyboard, KeyboardInterface, MinimalKeymanGlobal, Mock, DeviceSpec, KeyboardKeymanGlobal } from '@keymanapp/keyboard-processor'; +import { extendString, KeyboardHarness, Keyboard, MinimalKeymanGlobal, Mock, DeviceSpec, KeyboardKeymanGlobal } from '@keymanapp/keyboard-processor'; +import { KeyboardInterface } from 'keyman/engine/js-processor'; declare let window: typeof globalThis; // KeymanEngine from the web/ folder... when available. diff --git a/web/src/test/auto/dom/kbdLoader.ts b/web/src/test/auto/dom/kbdLoader.ts index 629ade205e9..2254011857f 100644 --- a/web/src/test/auto/dom/kbdLoader.ts +++ b/web/src/test/auto/dom/kbdLoader.ts @@ -4,11 +4,11 @@ import { import { Keyboard, - KeyboardInterface, KeyboardProperties, MinimalKeymanGlobal } from '@keymanapp/keyboard-processor'; +import { KeyboardInterface } from 'keyman/engine/js-processor'; import { KeyboardStub } from 'keyman/engine/package-cache'; const loader = new DOMKeyboardLoader(new KeyboardInterface(window, MinimalKeymanGlobal)); diff --git a/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js b/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js index ba4808e66a7..97ce24d0363 100644 --- a/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js +++ b/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js @@ -4,7 +4,8 @@ import sinon from 'sinon'; import { LanguageProcessor, TranscriptionCache } from 'keyman/engine/main'; import { PredictionContext } from 'keyman/engine/interfaces'; import { Worker as LMWorker } from "@keymanapp/lexical-model-layer/node"; -import { DeviceSpec, KeyboardProcessor, Mock } from '@keymanapp/keyboard-processor'; +import { DeviceSpec, Mock } from '@keymanapp/keyboard-processor'; +import { KeyboardProcessor } from 'keyman/engine/js-processor'; function compileDummyModel(suggestionSets) { return ` diff --git a/web/src/tools/testing/recorder-core/src/nodeProctor.ts b/web/src/tools/testing/recorder-core/src/nodeProctor.ts index 6f6d7fd6a0d..852002d4b3a 100644 --- a/web/src/tools/testing/recorder-core/src/nodeProctor.ts +++ b/web/src/tools/testing/recorder-core/src/nodeProctor.ts @@ -8,8 +8,9 @@ import { RecordedSyntheticKeystroke } from "./index.js"; -import { KeyboardInterface, KeyEvent, KeyEventSpec, KeyboardProcessor, Mock, type OutputTarget, KeyboardHarness } from "@keymanapp/keyboard-processor"; +import { KeyEvent, KeyEventSpec, Mock, type OutputTarget, KeyboardHarness } from "@keymanapp/keyboard-processor"; import { DeviceSpec } from "@keymanapp/web-utils"; +import { KeyboardInterface, KeyboardProcessor } from 'keyman/engine/js-processor'; export default class NodeProctor extends Proctor { private keyboardWithHarness: KeyboardHarness; diff --git a/web/src/tools/testing/recorder-core/tsconfig.json b/web/src/tools/testing/recorder-core/tsconfig.json index a7bd08c3745..38af26e1a42 100644 --- a/web/src/tools/testing/recorder-core/tsconfig.json +++ b/web/src/tools/testing/recorder-core/tsconfig.json @@ -17,6 +17,7 @@ { "path": "../../../../../common/web/keyman-version" }, { "path": "../../../../../common/web/utils/" }, { "path": "../../../../../common/web/keyboard-processor/" }, - { "path": "../../../../../common/web/lm-message-types" } + { "path": "../../../../../common/web/lm-message-types" }, + { "path": "../../../engine/js-processor" } ], } From 786a1063ea93a8dbd9d2fc70c535dadbc04fbaf8 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 9 Aug 2024 14:51:45 +0700 Subject: [PATCH 07/65] fix(android): Add SEND, NEXT, PREVIOUS actions --- .../com/keyman/engine/KMKeyboardJSHandler.java | 15 +++++++++++++++ .../main/java/com/keyman/engine/KMManager.java | 17 ++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java index 66af2ebe07d..3a995560c6f 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java @@ -167,11 +167,26 @@ public void run() { ic.performEditorAction(EditorInfo.IME_ACTION_SEARCH); break; + // Send action + case SEND : + ic.performEditorAction(EditorInfo.IME_ACTION_SEND); + break; + + // Next action + case NEXT : + ic.performEditorAction(EditorInfo.IME_ACTION_NEXT); + break; + // Done action case DONE : ic.performEditorAction(EditorInfo.IME_ACTION_DONE); break; + // Previous action + case PREVIOUS : + ic.performEditorAction(EditorInfo.IME_ACTION_PREVIOUS); + break; + // Messaging apps case NEWLINE : // Send newline without advancing cursor diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java index adf9d30737d..0bbe93b9320 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java @@ -184,8 +184,11 @@ public String toString() { public enum EnterModeType { GO, // Go action SEARCH, // Search action - NEWLINE, // Send newline character + SEND, // Send action + NEXT, // Next action DONE, // Done action + PREVIOUS, // Previous action + NEWLINE, // Send newline character DEFAULT, // Default ENTER action } @@ -1287,10 +1290,22 @@ public static void setEnterMode(int imeOptions, int inputType) { value = EnterModeType.SEARCH; break; + case EditorInfo.IME_ACTION_SEND: + value = EnterModeType.SEND; + break; + + case EditorInfo.IME_ACTION_NEXT: + value = EnterModeType.NEXT; + break; + case EditorInfo.IME_ACTION_DONE: value = EnterModeType.DONE; break; + case EditorInfo.IME_ACTION_PREVIOUS: + value = EnterModeType.PREVIOUS; + break; + default: value = EnterModeType.DEFAULT; } From b8e961b979088275a08bcbe9f3bedef13c78aa8d Mon Sep 17 00:00:00 2001 From: rc-swag <58423624+rc-swag@users.noreply.github.com> Date: Mon, 12 Aug 2024 14:52:55 +1000 Subject: [PATCH 08/65] fix(windows): splash screen useses new start keyman string The new string just has %1$s place holder to then hard code in Keyman. xslt substitues %1$s to %0:s the template rule matching is on that. --- windows/src/desktop/kmshell/xml/splash.xsl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/windows/src/desktop/kmshell/xml/splash.xsl b/windows/src/desktop/kmshell/xml/splash.xsl index 51514e91118..956447d0201 100644 --- a/windows/src/desktop/kmshell/xml/splash.xsl +++ b/windows/src/desktop/kmshell/xml/splash.xsl @@ -30,7 +30,13 @@
-
+
+ + + + + +
From bba694c306d17a841b2e86606de86638bbfa4397 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Mon, 12 Aug 2024 19:33:29 +0200 Subject: [PATCH 09/65] refactor(web): work around global in interface --- .../keyboard-processor/src/text/keyEvent.ts | 19 +++++-------------- .../engine/js-processor/src/defaultRules.ts | 12 ++++-------- 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/common/web/keyboard-processor/src/text/keyEvent.ts b/common/web/keyboard-processor/src/text/keyEvent.ts index 7c507cc1703..2d0ee493229 100644 --- a/common/web/keyboard-processor/src/text/keyEvent.ts +++ b/common/web/keyboard-processor/src/text/keyEvent.ts @@ -12,23 +12,14 @@ import { type DeviceSpec } from "@keymanapp/web-utils"; import Codes from './codes.js'; import { ActiveKeyBase } from "../index.js"; -interface DefaultRulesInterface { +export interface DefaultRulesInterface { forAny(Lkc: KeyEvent, isMnemonic: boolean): string; } -export class BASE_DEFAULT_RULES { - private static _instance: DefaultRulesInterface; +let defaultRules: DefaultRulesInterface; - // Prevent direct instantiation. - private constructor() { } - - public static forAny(Lkc: KeyEvent, isMnemonic: boolean): string { - return this._instance.forAny(Lkc, isMnemonic); - } - - public static set instance(value: DefaultRulesInterface) { - this._instance = value; - } +export function setDefaultRules(rules: DefaultRulesInterface) { + defaultRules = rules; } // Represents a probability distribution over a keyboard's keys. @@ -168,7 +159,7 @@ export default class KeyEvent implements KeyEventSpec { // the actual keyname instead. mappingEvent.kName = 'K_xxxx'; mappingEvent.Lmodifiers = (shifted ? 0x10 : 0); // mnemonic lookups only exist for default & shift layers. - var mappedChar: string = BASE_DEFAULT_RULES.forAny(mappingEvent, true); + var mappedChar: string = defaultRules.forAny(mappingEvent, true); /* First, save a backup of the original code. This one won't needlessly trigger keyboard * rules, but allows us to replicate/emulate commands after rule processing if needed. diff --git a/web/src/engine/js-processor/src/defaultRules.ts b/web/src/engine/js-processor/src/defaultRules.ts index edaf440bf9a..3d56a2dad8c 100644 --- a/web/src/engine/js-processor/src/defaultRules.ts +++ b/web/src/engine/js-processor/src/defaultRules.ts @@ -5,7 +5,7 @@ */ import { ModifierKeyConstants } from '@keymanapp/common-types'; -import { BASE_DEFAULT_RULES, Codes, type KeyEvent, type OutputTarget } from "@keymanapp/keyboard-processor"; +import { Codes, type KeyEvent, type OutputTarget, setDefaultRules } from "@keymanapp/keyboard-processor"; import RuleBehavior from "./ruleBehavior.js"; export enum EmulationKeystrokes { @@ -13,11 +13,13 @@ export enum EmulationKeystrokes { Backspace = '\b' } + /** * Defines a collection of static library functions that define KeymanWeb's default (implied) keyboard rule behaviors. */ export default class DefaultRules { public constructor() { + setDefaultRules(this); } codeForEvent(Lkc: KeyEvent) { @@ -28,7 +30,7 @@ export default class DefaultRules { * Serves as a default keycode lookup table. This may be referenced safely by mnemonic handling without fear of side-effects. * Also used by Processor.defaultRuleBehavior to generate output after filtering for special cases. */ - public forAny(Lkc: KeyEvent, isMnemonic: boolean, ruleBehavior?: RuleBehavior) { + public forAny(Lkc: KeyEvent, isMnemonic: boolean, ruleBehavior?: RuleBehavior): string { var char = ''; // A pretty simple table of lookups, corresponding VERY closely to the original defaultKeyOutput. @@ -217,9 +219,3 @@ export default class DefaultRules { return null; } } - -/** - * A simple instance of the standard 'default rules' for keystroke processing from the - * DefaultRules base class. - */ -BASE_DEFAULT_RULES.instance = new DefaultRules(); From 46ecfd446676445cf880c7bc0d3c857c80bc2809 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Wed, 7 Aug 2024 19:39:42 +0200 Subject: [PATCH 10/65] =?UTF-8?q?refactor(web):=20move=20remaining=20parts?= =?UTF-8?q?=20of=20`keyboard-processor`=20=E2=86=92=20`keyboard`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit move parts of `common/web/keyboard-processor/` → `web/src/engine/keyboard/`. Fixes: #12110 --- common/web/keyboard-processor/package.json | 69 ------------------- .../src/keyboards/loaders/tsconfig.dom.json | 13 ---- .../src/keyboards/loaders/tsconfig.node.json | 14 ---- common/web/keyboard-processor/tsconfig.json | 18 ----- .../keyman-touch-layout-file.ts | 2 +- package-lock.json | 23 ------- tsconfig.base.json | 1 - tsconfig.json | 1 - web/README.md | 2 +- web/build.sh | 2 + web/ci.sh | 2 +- web/package.json | 16 ++++- web/src/app/browser/src/configuration.ts | 2 +- web/src/app/browser/src/contextManager.ts | 2 +- .../app/browser/src/defaultBrowserRules.ts | 2 +- .../app/browser/src/hardwareEventKeyboard.ts | 2 +- web/src/app/browser/src/keymanEngine.ts | 2 +- web/src/app/webview/src/contextManager.ts | 2 +- web/src/app/webview/src/keymanEngine.ts | 2 +- web/src/app/webview/src/oskConfiguration.ts | 2 +- .../app/webview/src/passthroughKeyboard.ts | 2 +- .../attachment/src/pageContextAttachment.ts | 2 +- web/src/engine/dom-utils/build.sh | 2 +- web/src/engine/dom-utils/src/stylesheets.ts | 2 +- web/src/engine/dom-utils/tsconfig.json | 2 +- web/src/engine/element-wrappers/build.sh | 2 +- web/src/engine/element-wrappers/readme.md | 2 +- .../element-wrappers/src/outputTarget.ts | 2 +- web/src/engine/element-wrappers/tsconfig.json | 2 +- web/src/engine/events/build.sh | 2 +- .../events/src/keyEventSource.interface.ts | 2 +- web/src/engine/events/tsconfig.json | 2 +- web/src/engine/interfaces/build.sh | 2 +- .../prediction/languageProcessor.interface.ts | 2 +- .../src/prediction/predictionContext.ts | 2 +- web/src/engine/interfaces/tsconfig.json | 2 +- .../engine/js-processor/src/defaultRules.ts | 3 +- .../engine/js-processor/src/kbdInterface.ts | 4 +- .../js-processor/src/keyboardProcessor.ts | 2 +- .../engine/js-processor/src/ruleBehavior.ts | 2 +- .../src/engine/keyboard}/.c8rc.json | 0 .../src/engine/keyboard}/.gitignore | 0 .../src/engine/keyboard}/README.md | 3 +- .../src/engine/keyboard}/build.sh | 43 ++++++------ .../src/engine/keyboard/src}/codes.ts | 0 .../src/engine/keyboard/src}/deadkeys.ts | 0 .../src/engine/keyboard}/src/index.ts | 22 +++--- .../src/engine/keyboard/src}/keyEvent.ts | 4 +- .../src/engine/keyboard/src}/keyMapping.ts | 0 .../keyboard}/src/keyboards/activeLayout.ts | 8 +-- .../keyboard}/src/keyboards/defaultLayouts.ts | 2 +- .../keyboard}/src/keyboards/keyboard.ts | 8 +-- .../src/keyboards/keyboardHarness.ts | 2 +- .../src/keyboards/keyboardLoaderBase.ts | 0 .../src/keyboards/keyboardProperties.ts | 0 .../keyboards/loaders/dom-keyboard-loader.ts | 0 .../keyboards/loaders/domKeyboardLoader.ts | 2 +- .../keyboards/loaders/node-keyboard-loader.ts | 0 .../keyboards/loaders/nodeKeyboardLoader.ts | 2 +- .../src/keyboards/loaders/tsconfig.dom.json | 13 ++++ .../src/keyboards/loaders/tsconfig.node.json | 14 ++++ .../keyboard}/src/keyboards/spacebarText.ts | 0 .../keyboard}/src/keyboards/stateKeyMap.ts | 2 +- .../src/engine/keyboard/src}/outputTarget.ts | 0 .../keyboard/src}/ruleBehavior.interface.ts | 0 .../engine/keyboard/src}/stringDivergence.ts | 0 .../src/engine/keyboard/src}/systemStores.ts | 4 +- .../keyboard}/tests/node/basic-engine.js | 7 +- .../engine/keyboard}/tests/node/basic-init.js | 4 +- .../keyboard}/tests/node/bundled-module.js | 6 +- .../engine/keyboard}/tests/node/chirality.js | 7 +- .../engine/keyboard}/tests/node/deadkeys.js | 7 +- .../keyboard}/tests/node/engine/context.js | 5 +- .../tests/node/engine/notany_context.js | 5 +- .../keyboard}/tests/node/engine/stores.js | 3 +- .../node/engine/unmatched_final_group.js | 7 +- .../keyboard}/tests/node/keyboard-loading.js | 5 +- .../tests/node/keyboard-properties.js | 2 +- .../src/engine/keyboard}/tests/node/mocks.js | 2 +- .../tests/node/non-positional-rules.js | 5 +- .../tests/node/specialized-backspace.js | 5 +- .../keyboard}/tests/node/transcriptions.js | 2 +- .../src/engine/keyboard}/tsconfig.all.json | 6 +- web/src/engine/keyboard/tsconfig.json | 12 ++++ web/src/engine/main/build.sh | 2 +- web/src/engine/main/src/contextManagerBase.ts | 2 +- .../engine/main/src/engineConfiguration.ts | 2 +- web/src/engine/main/src/hardKeyboard.ts | 2 +- .../engine/main/src/headless/contextWindow.ts | 2 +- .../main/src/headless/inputProcessor.ts | 2 +- .../main/src/headless/languageProcessor.ts | 2 +- .../main/src/headless/transcriptionCache.ts | 2 +- web/src/engine/main/src/keyboardInterface.ts | 2 +- web/src/engine/main/src/keymanEngine.ts | 6 +- .../main/src/variableStoreCookieSerializer.ts | 2 +- web/src/engine/osk/build.sh | 2 +- web/src/engine/osk/src/banner/banner.ts | 2 +- .../engine/osk/src/banner/bannerController.ts | 2 +- .../engine/osk/src/banner/suggestionBanner.ts | 2 +- .../engine/osk/src/components/helpPageView.ts | 2 +- web/src/engine/osk/src/components/titleBar.ts | 2 +- web/src/engine/osk/src/correctionLayout.ts | 2 +- web/src/engine/osk/src/corrections.ts | 2 +- web/src/engine/osk/src/index.ts | 2 +- .../osk/src/input/gestures/browser/flick.ts | 2 +- .../src/input/gestures/browser/modipress.ts | 2 +- .../src/input/gestures/browser/multitap.ts | 2 +- .../src/input/gestures/browser/oskSubKey.ts | 2 +- .../src/input/gestures/browser/subkeyPopup.ts | 2 +- .../osk/src/input/gestures/gestureHandler.ts | 2 +- .../osk/src/input/gestures/heldRepeater.ts | 2 +- .../osk/src/input/gestures/specsForLayout.ts | 2 +- web/src/engine/osk/src/keyElement.ts | 2 +- .../src/keyboard-layout/gesturePreviewHost.ts | 2 +- .../osk/src/keyboard-layout/oskBaseKey.ts | 2 +- .../engine/osk/src/keyboard-layout/oskKey.ts | 2 +- .../osk/src/keyboard-layout/oskLayer.ts | 2 +- .../osk/src/keyboard-layout/oskLayerGroup.ts | 2 +- .../engine/osk/src/keyboard-layout/oskRow.ts | 2 +- .../engine/osk/src/views/anchoredOskView.ts | 2 +- .../engine/osk/src/views/floatingOskView.ts | 2 +- .../engine/osk/src/views/inlinedOskView.ts | 2 +- web/src/engine/osk/src/views/oskView.ts | 2 +- web/src/engine/osk/src/visualKeyboard.ts | 2 +- .../package-cache/src/cloud/queryEngine.ts | 2 +- .../src/cloud/requesterInterface.ts | 2 +- .../package-cache/src/domCloudRequester.ts | 2 +- .../src/keyboardRequisitioner.ts | 2 +- .../engine/package-cache/src/keyboardStub.ts | 2 +- .../package-cache/src/nodeCloudRequester.ts | 2 +- .../package-cache/src/stubAndKeyboardCache.ts | 2 +- .../dom/cases/browser/contextManager.spec.ts | 4 +- .../element_interfaces.spec.ts | 4 +- .../element-wrappers/target_mocks.spec.ts | 2 +- .../domKeyboardLoader.spec.ts | 4 +- .../packages/keyboardRequisitioner.spec.ts | 4 +- web/src/test/auto/dom/kbdLoader.ts | 4 +- .../hardware-event-processing.tests.ts | 4 +- .../prediction/predictionContext.spec.js | 2 +- .../main/headless/inputProcessor.spec.js | 8 +-- .../main/headless/languageProcessor.spec.js | 6 +- .../gestures/browser/subkeyPopup.tests.ts | 2 +- .../package-cache/keyboardRequisitioner.js | 4 +- .../package-cache/stubAndKeyboardCache.js | 4 +- .../test/manual/web/chirality/chirality.js | 6 +- web/src/test/manual/web/osk/kbdLoader.mjs | 6 +- web/src/tools/build.sh | 2 +- .../tools/testing/recorder-core/package.json | 1 - .../tools/testing/recorder-core/src/index.ts | 4 +- .../testing/recorder-core/src/nodeProctor.ts | 2 +- .../testing/recorder-core/src/proctor.ts | 4 +- .../tools/testing/recorder-core/tsconfig.json | 4 +- .../tools/testing/recorder/browserProctor.ts | 2 +- web/src/tools/testing/recorder/build.sh | 2 +- web/src/tools/testing/recorder/scribe.ts | 2 +- web/src/tools/testing/recorder/tsconfig.json | 2 +- 156 files changed, 277 insertions(+), 351 deletions(-) delete mode 100644 common/web/keyboard-processor/package.json delete mode 100644 common/web/keyboard-processor/src/keyboards/loaders/tsconfig.dom.json delete mode 100644 common/web/keyboard-processor/src/keyboards/loaders/tsconfig.node.json delete mode 100644 common/web/keyboard-processor/tsconfig.json rename {common/web/keyboard-processor => web/src/engine/keyboard}/.c8rc.json (100%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/.gitignore (100%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/README.md (92%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/build.sh (54%) rename {common/web/keyboard-processor/src/text => web/src/engine/keyboard/src}/codes.ts (100%) rename {common/web/keyboard-processor/src/text => web/src/engine/keyboard/src}/deadkeys.ts (100%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/src/index.ts (70%) rename {common/web/keyboard-processor/src/text => web/src/engine/keyboard/src}/keyEvent.ts (98%) rename {common/web/keyboard-processor/src/text => web/src/engine/keyboard/src}/keyMapping.ts (100%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/src/keyboards/activeLayout.ts (99%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/src/keyboards/defaultLayouts.ts (99%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/src/keyboards/keyboard.ts (99%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/src/keyboards/keyboardHarness.ts (99%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/src/keyboards/keyboardLoaderBase.ts (100%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/src/keyboards/keyboardProperties.ts (100%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/src/keyboards/loaders/dom-keyboard-loader.ts (100%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/src/keyboards/loaders/domKeyboardLoader.ts (97%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/src/keyboards/loaders/node-keyboard-loader.ts (100%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/src/keyboards/loaders/nodeKeyboardLoader.ts (95%) create mode 100644 web/src/engine/keyboard/src/keyboards/loaders/tsconfig.dom.json create mode 100644 web/src/engine/keyboard/src/keyboards/loaders/tsconfig.node.json rename {common/web/keyboard-processor => web/src/engine/keyboard}/src/keyboards/spacebarText.ts (100%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/src/keyboards/stateKeyMap.ts (65%) rename {common/web/keyboard-processor/src/text => web/src/engine/keyboard/src}/outputTarget.ts (100%) rename {common/web/keyboard-processor/src/text => web/src/engine/keyboard/src}/ruleBehavior.interface.ts (100%) rename {common/web/keyboard-processor/src/text => web/src/engine/keyboard/src}/stringDivergence.ts (100%) rename {common/web/keyboard-processor/src/text => web/src/engine/keyboard/src}/systemStores.ts (96%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/tests/node/basic-engine.js (87%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/tests/node/basic-init.js (92%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/tests/node/bundled-module.js (91%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/tests/node/chirality.js (97%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/tests/node/deadkeys.js (87%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/tests/node/engine/context.js (99%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/tests/node/engine/notany_context.js (94%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/tests/node/engine/stores.js (94%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/tests/node/engine/unmatched_final_group.js (84%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/tests/node/keyboard-loading.js (96%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/tests/node/keyboard-properties.js (98%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/tests/node/mocks.js (98%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/tests/node/non-positional-rules.js (97%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/tests/node/specialized-backspace.js (98%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/tests/node/transcriptions.js (99%) rename {common/web/keyboard-processor => web/src/engine/keyboard}/tsconfig.all.json (66%) create mode 100644 web/src/engine/keyboard/tsconfig.json rename web/src/test/auto/dom/cases/{keyboard-processor => keyboard}/domKeyboardLoader.spec.ts (95%) diff --git a/common/web/keyboard-processor/package.json b/common/web/keyboard-processor/package.json deleted file mode 100644 index 3f0a5958970..00000000000 --- a/common/web/keyboard-processor/package.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "name": "@keymanapp/keyboard-processor", - "description": "Core module for Keyman keyboard support in KeymanWeb.", - "repository": { - "type": "git", - "url": "git+https://github.com/keymanapp/keyman.git" - }, - "keywords": [ - "input", - "languages", - "keyboards" - ], - "author": "SIL International", - "license": "MIT", - "bugs": { - "url": "https://github.com/keymanapp/keyman/issues" - }, - "homepage": "https://github.com/keymanapp/keyman#readme", - "devDependencies": { - "@keymanapp/resources-gosh": "*", - "c8": "^7.12.0", - "mocha": "^10.0.0", - "mocha-teamcity-reporter": "^4.0.0", - "typescript": "^5.4.5" - }, - "scripts": { - "build": "gosh build.sh", - "clean": "gosh build.sh clean", - "test": "gosh build.sh test" - }, - "dependencies": { - "@keymanapp/common-types": "*", - "@keymanapp/models-types": "*", - "@keymanapp/keyman-version": "*", - "@keymanapp/web-utils": "*" - }, - "type": "module", - "main": "./build/obj/index.js", - "types": "./build/obj/index.d.ts", - "exports": { - ".": { - "es6-bundling": "./src/index.ts", - "default": "./build/obj/index.js" - }, - "./node-keyboard-loader": { - "es6-bundling": "./src/keyboards/loaders/node-keyboard-loader.ts", - "types": "./build/obj/keyboards/loaders/node-keyboard-loader.d.ts", - "import": "./build/obj/keyboards/loaders/node-keyboard-loader.js" - }, - "./dom-keyboard-loader": { - "es6-bundling": "./src/keyboards/loaders/dom-keyboard-loader.ts", - "types": "./build/obj/keyboards/loaders/dom-keyboard-loader.d.ts", - "import": "./build/obj/keyboards/loaders/dom-keyboard-loader.js" - }, - "./lib": { - "types": "./build/lib/index.d.ts", - "import": "./build/lib/index.mjs" - }, - "./lib/node-keyboard-loader": { - "types": "./build/lib/node-keyboard-loader.d.ts", - "import": "./build/lib/node-keyboard-loader.mjs" - }, - "./lib/dom-keyboard-loader": { - "types": "./build/lib/dom-keyboard-loader.d.ts", - "import": "./build/lib/dom-keyboard-loader.mjs" - }, - "./obj/*.js": "./build/obj/*.js" - } -} diff --git a/common/web/keyboard-processor/src/keyboards/loaders/tsconfig.dom.json b/common/web/keyboard-processor/src/keyboards/loaders/tsconfig.dom.json deleted file mode 100644 index 7ba2abe026a..00000000000 --- a/common/web/keyboard-processor/src/keyboards/loaders/tsconfig.dom.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../../../tsconfig.kmw-main-base.json", - "compilerOptions": { - "baseUrl": "../../../", - "outDir": "../../../build/obj/keyboards/loaders/", - "tsBuildInfoFile": "../../../build/obj/keyboards/loaders/tsconfig.dom.tsbuildinfo", - "rootDir": "." - }, - "references": [ - { "path": "../../../tsconfig.json" } - ], - "include": ["dom-keyboard-loader.ts", "domKeyboardLoader.ts"], -} diff --git a/common/web/keyboard-processor/src/keyboards/loaders/tsconfig.node.json b/common/web/keyboard-processor/src/keyboards/loaders/tsconfig.node.json deleted file mode 100644 index 0be3f169ad3..00000000000 --- a/common/web/keyboard-processor/src/keyboards/loaders/tsconfig.node.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "../../../../tsconfig.kmw-main-base.json", - "compilerOptions": { - "types": [ "node" ], - "baseUrl": "../../../", - "outDir": "../../../build/obj/keyboards/loaders/", - "tsBuildInfoFile": "../../../build/obj/keyboards/loaders/tsconfig.node.tsbuildinfo", - "rootDir": "." - }, - "references": [ - { "path": "../../../tsconfig.json" } - ], - "include": ["node-keyboard-loader.ts", "nodeKeyboardLoader.ts"], -} diff --git a/common/web/keyboard-processor/tsconfig.json b/common/web/keyboard-processor/tsconfig.json deleted file mode 100644 index 728935b74f6..00000000000 --- a/common/web/keyboard-processor/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -// Is used by the keyboard-loader submodules. -{ - "extends": "../tsconfig.kmw-main-base.json", - "compilerOptions": { - "baseUrl": "./", - "outDir": "build/obj/", - "tsBuildInfoFile": "build/obj/tsconfig.tsbuildinfo", - "rootDir": "./src/" - }, - "references": [ - { "path": "../types" }, - { "path": "../../models/types" }, - { "path": "../keyman-version/" }, - { "path": "../utils/" } - ], - "include": [ "./src/**/*.ts"], - "exclude": ["./src/keyboards/loaders/**/*.ts"] -} diff --git a/common/web/types/src/keyman-touch-layout/keyman-touch-layout-file.ts b/common/web/types/src/keyman-touch-layout/keyman-touch-layout-file.ts index 757316a70a9..786d9213e2b 100644 --- a/common/web/types/src/keyman-touch-layout/keyman-touch-layout-file.ts +++ b/common/web/types/src/keyman-touch-layout/keyman-touch-layout-file.ts @@ -58,7 +58,7 @@ export const PRIVATE_USE_IDS = [ ] as const; /* A map of key field names with values matching the `typeof` the corresponding property - * exists in common/web/keyboard-processor, keyboards/activeLayout.ts. + * exists in /web/src/engine/keyboard/src/keyboards/activeLayout.ts. * * Make sure that when one is updated, the other also is. TS types are compile-time only, * so the run-time-accessible mapping in activeLayout.ts cannot be auto-generated by TS. */ diff --git a/package-lock.json b/package-lock.json index 6b1a73ef408..ae0082784f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -191,23 +191,6 @@ "typescript": "^5.4.5" } }, - "common/web/keyboard-processor": { - "name": "@keymanapp/keyboard-processor", - "license": "MIT", - "dependencies": { - "@keymanapp/common-types": "*", - "@keymanapp/keyman-version": "*", - "@keymanapp/models-types": "*", - "@keymanapp/web-utils": "*" - }, - "devDependencies": { - "@keymanapp/resources-gosh": "*", - "c8": "^7.12.0", - "mocha": "^10.0.0", - "mocha-teamcity-reporter": "^4.0.0", - "typescript": "^5.4.5" - } - }, "common/web/keyman-version": { "name": "@keymanapp/keyman-version", "license": "MIT", @@ -249,7 +232,6 @@ "name": "@keymanapp/recorder-core", "license": "MIT", "dependencies": { - "@keymanapp/keyboard-processor": "*", "@keymanapp/keyman-version": "*", "@keymanapp/models-types": "*", "@keymanapp/web-utils": "*" @@ -2785,10 +2767,6 @@ "resolved": "common/tools/hextobin", "link": true }, - "node_modules/@keymanapp/keyboard-processor": { - "resolved": "common/web/keyboard-processor", - "link": true - }, "node_modules/@keymanapp/keyman-version": { "resolved": "common/web/keyman-version", "link": true @@ -14548,7 +14526,6 @@ "name": "keyman", "license": "MIT", "dependencies": { - "@keymanapp/keyboard-processor": "*", "@keymanapp/keyman-version": "*", "@keymanapp/lexical-model-layer": "*", "@keymanapp/models-types": "*", diff --git a/tsconfig.base.json b/tsconfig.base.json index e34839a52ce..c4e0599eef6 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -26,7 +26,6 @@ "paths": { "@keymanapp/common-types": ["./common/web/types/src/main"], - "@keymanapp/keyboard-processor": ["./common/web/keyboard-processor/src"], "@keymanapp/keyman": ["./web" ], "@keymanapp/models-types": ["./common/models/types"], "@keymanapp/models-templates": ["./common/models/templates"], diff --git a/tsconfig.json b/tsconfig.json index 093cec46f4a..8e6596a2312 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,6 @@ { "path": "./common/web/gesture-recognizer/tsconfig.json" }, { "path": "./common/web/gesture-recognizer/src/tools/unit-test-resources/tsconfig.json" }, - { "path": "./common/web/keyboard-processor/tsconfig.json" }, { "path": "./common/web/keyman-version" }, { "path": "./common/web/lm-message-types/" }, { "path": "./common/web/lm-worker/" }, diff --git a/web/README.md b/web/README.md index 775f303df5c..1a30362e9bc 100644 --- a/web/README.md +++ b/web/README.md @@ -81,7 +81,7 @@ title: Dependency Graph %%{init: {"flowchart": {"htmlLabels": false}} }%% graph TD; OSK["/web/src/engine/osk"]; - KP["@keymanapp/keyboard-processor
(/common/web/keyboard-processor)"]; + KP["/web/src/engine/keyboard"]; JSProc["/web/src/engine/js-processor"]; OSK-->KP; WebUtils["@keymanapp/web-utils
(/common/web/utils)"]; diff --git a/web/build.sh b/web/build.sh index 6f4737710a3..c3e17e9d433 100755 --- a/web/build.sh +++ b/web/build.sh @@ -28,6 +28,7 @@ builder_describe "Builds engine modules for Keyman Engine for Web (KMW)." \ ":engine/events Specialized classes utilized to support KMW API events" \ ":engine/element-wrappers Subset used to integrate with website elements" \ ":engine/js-processor Build JS processor for KMW" \ + ":engine/keyboard Builds KMW's keyboard-loading and caching code" \ ":engine/main Builds all common code used by KMW's app/-level targets" \ ":engine/osk Builds the Web OSK module" \ ":engine/package-cache Subset used to collate keyboards and request them from the cloud" \ @@ -59,6 +60,7 @@ builder_describe_outputs \ build:engine/events "/web/build/engine/events/lib/index.mjs" \ build:engine/element-wrappers "/web/build/engine/element-wrappers/lib/index.mjs" \ build:engine/js-processor "/web/build/engine/js-processor/lib/index.mjs" \ + build:engine/keyboard "/web/build/engine/keyboard/lib/index.mjs" \ build:engine/main "/web/build/engine/main/lib/index.mjs" \ build:engine/osk "/web/build/engine/osk/lib/index.mjs" \ build:engine/package-cache "/web/build/engine/package-cache/lib/index.mjs" \ diff --git a/web/ci.sh b/web/ci.sh index 6e5bc3b06ac..5e26a1e30e2 100755 --- a/web/ci.sh +++ b/web/ci.sh @@ -85,7 +85,7 @@ if builder_start_action test; then # No --reporter option exists yet for the headless modules. - "$KEYMAN_ROOT/common/web/keyboard-processor/build.sh" test $OPTIONS + "$KEYMAN_ROOT/web/src/engine/keyboard/build.sh" test $OPTIONS "$KEYMAN_ROOT/common/web/gesture-recognizer/test.sh" $OPTIONS ./build.sh test $OPTIONS diff --git a/web/package.json b/web/package.json index 4baff29490d..b5727dd0095 100644 --- a/web/package.json +++ b/web/package.json @@ -42,6 +42,21 @@ "types": "./build/engine/js-processor/obj/index.d.ts", "import": "./build/engine/js-processor/obj/index.js" }, + "./engine/keyboard": { + "es6-bundling": "./src/engine/keyboard/src/index.ts", + "types": "./build/engine/keyboard/obj/index.d.ts", + "import": "./build/engine/keyboard/obj/index.js" + }, + "./engine/keyboard/node-keyboard-loader": { + "es6-bundling": "./src/engine/keyboard/src/keyboards/loaders/node-keyboard-loader.ts", + "types": "./build/engine/keyboard/obj/keyboards/loaders/node-keyboard-loader.d.ts", + "import": "./build/engine/keyboard/obj/keyboards/loaders/node-keyboard-loader.js" + }, + "./engine/keyboard/dom-keyboard-loader": { + "es6-bundling": "./src/engine/keyboard/src/keyboards/loaders/dom-keyboard-loader.ts", + "types": "./build/engine/keyboard/obj/keyboards/loaders/dom-keyboard-loader.d.ts", + "import": "./build/engine/keyboard/obj/keyboards/loaders/dom-keyboard-loader.js" + }, "./engine/package-cache": { "es6-bundling": "./src/engine/package-cache/src/index.ts", "types": "./build/engine/package-cache/obj/index.d.ts", @@ -104,7 +119,6 @@ "test": "gosh ./test.sh" }, "dependencies": { - "@keymanapp/keyboard-processor": "*", "@keymanapp/keyman-version": "*", "@keymanapp/lexical-model-layer": "*", "@keymanapp/models-types": "*", diff --git a/web/src/app/browser/src/configuration.ts b/web/src/app/browser/src/configuration.ts index 4f2f2684388..35983ac30c6 100644 --- a/web/src/app/browser/src/configuration.ts +++ b/web/src/app/browser/src/configuration.ts @@ -1,7 +1,7 @@ import { EngineConfiguration, InitOptionSpec, InitOptionDefaults } from "keyman/engine/main"; import { OutputTarget as DOMOutputTarget } from 'keyman/engine/element-wrappers'; -import { isEmptyTransform, OutputTarget } from '@keymanapp/keyboard-processor'; +import { isEmptyTransform, OutputTarget } from 'keyman/engine/keyboard'; import { RuleBehavior } from 'keyman/engine/js-processor'; import { AlertHost } from "./utils/alertHost.js"; import { whenDocumentReady } from "./utils/documentReady.js"; diff --git a/web/src/app/browser/src/contextManager.ts b/web/src/app/browser/src/contextManager.ts index 1511269bbe8..f17a17a5299 100644 --- a/web/src/app/browser/src/contextManager.ts +++ b/web/src/app/browser/src/contextManager.ts @@ -1,4 +1,4 @@ -import { type Keyboard, KeyboardScriptError } from '@keymanapp/keyboard-processor'; +import { type Keyboard, KeyboardScriptError } from 'keyman/engine/keyboard'; import { type KeyboardStub } from 'keyman/engine/package-cache'; import { CookieSerializer } from 'keyman/engine/dom-utils'; import { eventOutputTarget, outputTargetForElement, PageContextAttachment } from 'keyman/engine/attachment'; diff --git a/web/src/app/browser/src/defaultBrowserRules.ts b/web/src/app/browser/src/defaultBrowserRules.ts index fc084ec3f49..0d40e476c7c 100644 --- a/web/src/app/browser/src/defaultBrowserRules.ts +++ b/web/src/app/browser/src/defaultBrowserRules.ts @@ -3,7 +3,7 @@ import { Codes, type KeyEvent, type OutputTarget -} from '@keymanapp/keyboard-processor'; +} from 'keyman/engine/keyboard'; import { DefaultRules } from 'keyman/engine/js-processor'; import ContextManager from './contextManager.js'; diff --git a/web/src/app/browser/src/hardwareEventKeyboard.ts b/web/src/app/browser/src/hardwareEventKeyboard.ts index f6874fc77b7..0bb594e8975 100644 --- a/web/src/app/browser/src/hardwareEventKeyboard.ts +++ b/web/src/app/browser/src/hardwareEventKeyboard.ts @@ -1,4 +1,4 @@ -import { Codes, DeviceSpec, KeyEvent, KeyMapping, Keyboard } from '@keymanapp/keyboard-processor'; +import { Codes, DeviceSpec, KeyEvent, KeyMapping, Keyboard } from 'keyman/engine/keyboard'; import { KeyboardProcessor } from 'keyman/engine/js-processor'; import { ModifierKeyConstants } from '@keymanapp/common-types'; diff --git a/web/src/app/browser/src/keymanEngine.ts b/web/src/app/browser/src/keymanEngine.ts index d807c415eb3..dc912f257be 100644 --- a/web/src/app/browser/src/keymanEngine.ts +++ b/web/src/app/browser/src/keymanEngine.ts @@ -7,7 +7,7 @@ import { VisualKeyboard } from 'keyman/engine/osk'; import { ErrorStub, KeyboardStub, CloudQueryResult, toPrefixedKeyboardId as prefixed } from 'keyman/engine/package-cache'; -import { DeviceSpec, Keyboard, KeyboardObject } from "@keymanapp/keyboard-processor"; +import { DeviceSpec, Keyboard, KeyboardObject } from "keyman/engine/keyboard"; import * as views from './viewsAnchorpoint.js'; import { BrowserConfiguration, BrowserInitOptionDefaults, BrowserInitOptionSpec } from './configuration.js'; diff --git a/web/src/app/webview/src/contextManager.ts b/web/src/app/webview/src/contextManager.ts index b0c322ea29d..de413481420 100644 --- a/web/src/app/webview/src/contextManager.ts +++ b/web/src/app/webview/src/contextManager.ts @@ -1,4 +1,4 @@ -import { type Keyboard, Mock, OutputTarget, Transcription, findCommonSubstringEndIndex, isEmptyTransform, TextTransform } from '@keymanapp/keyboard-processor'; +import { type Keyboard, Mock, OutputTarget, Transcription, findCommonSubstringEndIndex, isEmptyTransform, TextTransform } from 'keyman/engine/keyboard'; import { KeyboardStub } from 'keyman/engine/package-cache'; import { ContextManagerBase } from 'keyman/engine/main'; import { WebviewConfiguration } from './configuration.js'; diff --git a/web/src/app/webview/src/keymanEngine.ts b/web/src/app/webview/src/keymanEngine.ts index 2f073505484..642f9afb7e6 100644 --- a/web/src/app/webview/src/keymanEngine.ts +++ b/web/src/app/webview/src/keymanEngine.ts @@ -1,4 +1,4 @@ -import { DeviceSpec } from '@keymanapp/keyboard-processor' +import { DeviceSpec } from 'keyman/engine/keyboard' import { DefaultRules, RuleBehavior } from 'keyman/engine/js-processor'; import { KeymanEngine as KeymanEngineBase, KeyboardInterface } from 'keyman/engine/main'; import { AnchoredOSKView, ViewConfiguration, StaticActivator } from 'keyman/engine/osk'; diff --git a/web/src/app/webview/src/oskConfiguration.ts b/web/src/app/webview/src/oskConfiguration.ts index 26ceeb28721..9250b5a2a1d 100644 --- a/web/src/app/webview/src/oskConfiguration.ts +++ b/web/src/app/webview/src/oskConfiguration.ts @@ -1,5 +1,5 @@ import { OSKView } from "keyman/engine/osk"; -import { DeviceSpec } from "@keymanapp/keyboard-processor"; +import { DeviceSpec } from "keyman/engine/keyboard"; import { type EmbeddedGestureConfig } from "keyman/engine/osk"; import { GlobeHint } from './osk/globeHint.js'; diff --git a/web/src/app/webview/src/passthroughKeyboard.ts b/web/src/app/webview/src/passthroughKeyboard.ts index d74ab7f99a7..25dec7a8e68 100644 --- a/web/src/app/webview/src/passthroughKeyboard.ts +++ b/web/src/app/webview/src/passthroughKeyboard.ts @@ -1,4 +1,4 @@ -import { DeviceSpec, Keyboard, KeyEvent, ManagedPromise } from '@keymanapp/keyboard-processor'; +import { DeviceSpec, Keyboard, KeyEvent, ManagedPromise } from 'keyman/engine/keyboard'; import { HardKeyboard, processForMnemonicsAndLegacy } from 'keyman/engine/main'; diff --git a/web/src/engine/attachment/src/pageContextAttachment.ts b/web/src/engine/attachment/src/pageContextAttachment.ts index d63c113d5e2..4325c88f15d 100644 --- a/web/src/engine/attachment/src/pageContextAttachment.ts +++ b/web/src/engine/attachment/src/pageContextAttachment.ts @@ -1,6 +1,6 @@ import { EventEmitter } from 'eventemitter3'; -import { DeviceSpec, InternalKeyboardFont } from "@keymanapp/keyboard-processor"; +import { DeviceSpec, InternalKeyboardFont } from "keyman/engine/keyboard"; import { Input, nestedInstanceOf, wrapElement } from "keyman/engine/element-wrappers"; import { arrayFromNodeList, diff --git a/web/src/engine/dom-utils/build.sh b/web/src/engine/dom-utils/build.sh index 74b46051c42..d2e424db209 100755 --- a/web/src/engine/dom-utils/build.sh +++ b/web/src/engine/dom-utils/build.sh @@ -16,7 +16,7 @@ SUBPROJECT_NAME=engine/dom-utils builder_describe "Builds DOM-utility modules used by the Keyman Engine for Web (KMW)." \ "@/common/web/utils" \ - "@/common/web/keyboard-processor" \ + "@/web/src/engine/keyboard" \ "clean" \ "configure" \ "build" \ diff --git a/web/src/engine/dom-utils/src/stylesheets.ts b/web/src/engine/dom-utils/src/stylesheets.ts index 7312a62f055..977f253ff79 100644 --- a/web/src/engine/dom-utils/src/stylesheets.ts +++ b/web/src/engine/dom-utils/src/stylesheets.ts @@ -1,5 +1,5 @@ import { DeviceSpec, ManagedPromise } from '@keymanapp/web-utils'; -import { type InternalKeyboardFont as KeyboardFont } from '@keymanapp/keyboard-processor'; +import { type InternalKeyboardFont as KeyboardFont } from 'keyman/engine/keyboard'; type FontFamilyStyleMap = {[family: string]: HTMLStyleElement}; diff --git a/web/src/engine/dom-utils/tsconfig.json b/web/src/engine/dom-utils/tsconfig.json index c0b4a7d79dd..dadf4db5c8c 100644 --- a/web/src/engine/dom-utils/tsconfig.json +++ b/web/src/engine/dom-utils/tsconfig.json @@ -11,7 +11,7 @@ "include": [ "src/**/*.ts" ], "references": [ - { "path": "../../../../common/web/keyboard-processor" }, + { "path": "../keyboard" }, { "path": "../../../../common/web/utils" } ] } diff --git a/web/src/engine/element-wrappers/build.sh b/web/src/engine/element-wrappers/build.sh index cfcc58a44f2..1d0f5802132 100755 --- a/web/src/engine/element-wrappers/build.sh +++ b/web/src/engine/element-wrappers/build.sh @@ -13,7 +13,7 @@ SUBPROJECT_NAME=engine/element-wrappers # ################################ Main script ################################ builder_describe "Builds DOM-based OutputTarget subclasses used by the Keyman Engine for Web (KMW)." \ - "@/common/web/keyboard-processor" \ + "@/web/src/engine/keyboard" \ "clean" \ "configure" \ "build" \ diff --git a/web/src/engine/element-wrappers/readme.md b/web/src/engine/element-wrappers/readme.md index 1237237c7be..2a7685edbcb 100644 --- a/web/src/engine/element-wrappers/readme.md +++ b/web/src/engine/element-wrappers/readme.md @@ -1,4 +1,4 @@ ## engine/element-wrappers This submodule provides a subset of the main engine's Web-oriented code that's used to 'wrap' webpage -elements as part of KMW attachment and interface the element with the `keyboard-processor` submodule. \ No newline at end of file +elements as part of KMW attachment and interface the element with the `keyboard` submodule. \ No newline at end of file diff --git a/web/src/engine/element-wrappers/src/outputTarget.ts b/web/src/engine/element-wrappers/src/outputTarget.ts index 3a288c13471..5d0f2e38ce2 100644 --- a/web/src/engine/element-wrappers/src/outputTarget.ts +++ b/web/src/engine/element-wrappers/src/outputTarget.ts @@ -1,4 +1,4 @@ -import { OutputTarget as OutputTargetBase } from "@keymanapp/keyboard-processor"; +import { OutputTarget as OutputTargetBase } from "keyman/engine/keyboard"; import { EventEmitter } from 'eventemitter3'; export default abstract class OutputTarget extends OutputTargetBase { diff --git a/web/src/engine/element-wrappers/tsconfig.json b/web/src/engine/element-wrappers/tsconfig.json index ab6aa238a80..15a58bbf2a8 100644 --- a/web/src/engine/element-wrappers/tsconfig.json +++ b/web/src/engine/element-wrappers/tsconfig.json @@ -11,6 +11,6 @@ "include": [ "src/**/*.ts" ], "references": [ - { "path": "../../../../common/web/keyboard-processor" } + { "path": "../keyboard" } ] } diff --git a/web/src/engine/events/build.sh b/web/src/engine/events/build.sh index 438d075c2ce..1b8993f5705 100755 --- a/web/src/engine/events/build.sh +++ b/web/src/engine/events/build.sh @@ -14,7 +14,7 @@ SUBPROJECT_NAME=engine/events builder_describe "Builds specialized event-related modules utilized by Keyman Engine for Web." \ "@/common/web/utils build" \ - "@/common/web/keyboard-processor build" \ + "@/web/src/engine/keyboard build" \ "clean" \ "configure" \ "build" \ diff --git a/web/src/engine/events/src/keyEventSource.interface.ts b/web/src/engine/events/src/keyEventSource.interface.ts index 22621d2de01..8f12893b282 100644 --- a/web/src/engine/events/src/keyEventSource.interface.ts +++ b/web/src/engine/events/src/keyEventSource.interface.ts @@ -1,5 +1,5 @@ import { EventEmitter } from "eventemitter3"; -import { type KeyEvent, type RuleBehaviorInterface } from "@keymanapp/keyboard-processor"; +import { type KeyEvent, type RuleBehaviorInterface } from "keyman/engine/keyboard"; export type KeyEventResultCallback = (result: RuleBehaviorInterface, error?: Error) => void; export type KeyEventHandler = (event: KeyEvent, callback?: KeyEventResultCallback) => void; diff --git a/web/src/engine/events/tsconfig.json b/web/src/engine/events/tsconfig.json index bb25ac9c99b..5d0a45bbab9 100644 --- a/web/src/engine/events/tsconfig.json +++ b/web/src/engine/events/tsconfig.json @@ -12,6 +12,6 @@ "references": [ { "path": "../../../../common/web/utils" }, - { "path": "../../../../common/web/keyboard-processor" } + { "path": "../keyboard" } ] } diff --git a/web/src/engine/interfaces/build.sh b/web/src/engine/interfaces/build.sh index 528083d4d81..568bd7940d6 100755 --- a/web/src/engine/interfaces/build.sh +++ b/web/src/engine/interfaces/build.sh @@ -14,7 +14,7 @@ SUBPROJECT_NAME=engine/interfaces builder_describe "Builds configuration subclasses used by the Keyman Engine for Web (KMW)." \ "@/common/web/es-bundling" \ - "@/common/web/keyboard-processor" \ + "@/web/src/engine/keyboard" \ "@/web/src/engine/js-processor" \ "clean" \ "configure" \ diff --git a/web/src/engine/interfaces/src/prediction/languageProcessor.interface.ts b/web/src/engine/interfaces/src/prediction/languageProcessor.interface.ts index 7265d51f463..84e78519879 100644 --- a/web/src/engine/interfaces/src/prediction/languageProcessor.interface.ts +++ b/web/src/engine/interfaces/src/prediction/languageProcessor.interface.ts @@ -1,7 +1,7 @@ /// import { EventEmitter } from "eventemitter3"; -import { OutputTarget } from "@keymanapp/keyboard-processor"; +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 90427c3020f..dabeb366da2 100644 --- a/web/src/engine/interfaces/src/prediction/predictionContext.ts +++ b/web/src/engine/interfaces/src/prediction/predictionContext.ts @@ -1,6 +1,6 @@ import { EventEmitter } from "eventemitter3"; import { type LanguageProcessorSpec , ReadySuggestions, type InvalidateSourceEnum, StateChangeHandler } from './languageProcessor.interface.js'; -import { type OutputTarget } from "@keymanapp/keyboard-processor"; +import { type OutputTarget } from "keyman/engine/keyboard"; import { type KeyboardProcessor } from 'keyman/engine/js-processor'; interface PredictionContextEventMap { diff --git a/web/src/engine/interfaces/tsconfig.json b/web/src/engine/interfaces/tsconfig.json index 634e62bada2..e53a8086820 100644 --- a/web/src/engine/interfaces/tsconfig.json +++ b/web/src/engine/interfaces/tsconfig.json @@ -12,7 +12,7 @@ "include": [ "**/*.ts" ], "references": [ - { "path": "../../../../common/web/keyboard-processor" }, + { "path": "../keyboard" }, { "path": "../js-processor" } ] } diff --git a/web/src/engine/js-processor/src/defaultRules.ts b/web/src/engine/js-processor/src/defaultRules.ts index 3d56a2dad8c..60409a5fe59 100644 --- a/web/src/engine/js-processor/src/defaultRules.ts +++ b/web/src/engine/js-processor/src/defaultRules.ts @@ -5,7 +5,7 @@ */ import { ModifierKeyConstants } from '@keymanapp/common-types'; -import { Codes, type KeyEvent, type OutputTarget, setDefaultRules } from "@keymanapp/keyboard-processor"; +import { Codes, type KeyEvent, type OutputTarget, setDefaultRules } from 'keyman/engine/keyboard'; import RuleBehavior from "./ruleBehavior.js"; export enum EmulationKeystrokes { @@ -13,7 +13,6 @@ export enum EmulationKeystrokes { Backspace = '\b' } - /** * Defines a collection of static library functions that define KeymanWeb's default (implied) keyboard rule behaviors. */ diff --git a/web/src/engine/js-processor/src/kbdInterface.ts b/web/src/engine/js-processor/src/kbdInterface.ts index 2b34eadce9d..2bc283010cd 100644 --- a/web/src/engine/js-processor/src/kbdInterface.ts +++ b/web/src/engine/js-processor/src/kbdInterface.ts @@ -7,7 +7,7 @@ import { type DeviceSpec } from "@keymanapp/web-utils"; import { ModifierKeyConstants } from '@keymanapp/common-types'; -import { Codes, type KeyEvent, type Deadkey, ComplexKeyboardStore, type KeyboardStore, KeyboardStoreElement, KeyMapping, SystemStoreIDs, SystemStore, MutableSystemStore, PlatformSystemStore, type OutputTarget, Mock, Keyboard, VariableStore, VariableStoreDictionary, VariableStoreSerializer, KeyboardHarness, KeyboardKeymanGlobal, RuleDeadkey, ContextAny, RuleIndex, ContextEx, ContextNul, RuleChar } from "@keymanapp/keyboard-processor"; +import { Codes, type KeyEvent, type Deadkey, ComplexKeyboardStore, type KeyboardStore, KeyboardStoreElement, KeyMapping, SystemStoreIDs, SystemStore, MutableSystemStore, PlatformSystemStore, type OutputTarget, Mock, Keyboard, VariableStore, VariableStoreDictionary, VariableStoreSerializer, KeyboardHarness, KeyboardKeymanGlobal, RuleDeadkey, ContextAny, RuleIndex, ContextEx, ContextNul, RuleChar } from "keyman/engine/keyboard"; import RuleBehavior from "./ruleBehavior.js"; //#endregion @@ -1076,6 +1076,6 @@ export default class KeyboardInterface extends KeyboardHarness { } (function() { - // This will be the only call within the keyboard-processor module. + // This will be the only call within the keyboard module. KeyboardInterface.__publishShorthandAPI(); }()); diff --git a/web/src/engine/js-processor/src/keyboardProcessor.ts b/web/src/engine/js-processor/src/keyboardProcessor.ts index 1a6d216dced..5886ee0a775 100644 --- a/web/src/engine/js-processor/src/keyboardProcessor.ts +++ b/web/src/engine/js-processor/src/keyboardProcessor.ts @@ -11,7 +11,7 @@ import { ModifierKeyConstants } from '@keymanapp/common-types'; import { Codes, type Keyboard, MinimalKeymanGlobal, KeyEvent, Layouts, type MutableSystemStore, type OutputTarget, Mock, SystemStoreIDs, -} from "@keymanapp/keyboard-processor"; +} from "keyman/engine/keyboard"; import DefaultRules, { EmulationKeystrokes } from "./defaultRules.js"; import RuleBehavior from "./ruleBehavior.js"; import KeyboardInterface from './kbdInterface.js'; diff --git a/web/src/engine/js-processor/src/ruleBehavior.ts b/web/src/engine/js-processor/src/ruleBehavior.ts index aced7065d2d..29764425f5f 100644 --- a/web/src/engine/js-processor/src/ruleBehavior.ts +++ b/web/src/engine/js-processor/src/ruleBehavior.ts @@ -1,7 +1,7 @@ /// import KeyboardProcessor from "./keyboardProcessor.js"; -import { OutputTarget, Mock, type Transcription, VariableStoreDictionary, type VariableStore } from "@keymanapp/keyboard-processor"; +import { OutputTarget, Mock, type Transcription, VariableStoreDictionary, type VariableStore } from "keyman/engine/keyboard"; /** * Represents the commands and state changes that result from a matched keyboard rule. diff --git a/common/web/keyboard-processor/.c8rc.json b/web/src/engine/keyboard/.c8rc.json similarity index 100% rename from common/web/keyboard-processor/.c8rc.json rename to web/src/engine/keyboard/.c8rc.json diff --git a/common/web/keyboard-processor/.gitignore b/web/src/engine/keyboard/.gitignore similarity index 100% rename from common/web/keyboard-processor/.gitignore rename to web/src/engine/keyboard/.gitignore diff --git a/common/web/keyboard-processor/README.md b/web/src/engine/keyboard/README.md similarity index 92% rename from common/web/keyboard-processor/README.md rename to web/src/engine/keyboard/README.md index 8ac9b8f9d05..a2a4eb89944 100644 --- a/common/web/keyboard-processor/README.md +++ b/web/src/engine/keyboard/README.md @@ -1,5 +1,6 @@ # Keyman: Keyboard Processor Module -The Original Code is (C) 2017-2020 SIL International + +The Original Code is (C) 2017-2024 SIL International The Keyboard Processor module is an internal component of KeymanWeb, seen within this repo at /web/. diff --git a/common/web/keyboard-processor/build.sh b/web/src/engine/keyboard/build.sh similarity index 54% rename from common/web/keyboard-processor/build.sh rename to web/src/engine/keyboard/build.sh index 964370c2fbf..649e38a213f 100755 --- a/common/web/keyboard-processor/build.sh +++ b/web/src/engine/keyboard/build.sh @@ -1,23 +1,23 @@ #!/usr/bin/env bash # -# Compile KeymanWeb's 'keyboard-processor' module, one of the components of Web's 'core' module. +# Compile KeymanWeb's 'keyboard' module, one of the components of Web's 'core' module. # ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" -. "${THIS_SCRIPT%/*}/../../../resources/build/builder.inc.sh" +. "${THIS_SCRIPT%/*}/../../../../resources/build/builder.inc.sh" ## END STANDARD BUILD SCRIPT INCLUDE -. "${KEYMAN_ROOT}/resources/shellHelperFunctions.sh" +SUBPROJECT_NAME=engine/keyboard -BUNDLE_CMD="node ${KEYMAN_ROOT}/common/web/es-bundling/build/common-bundle.mjs" +. "${KEYMAN_ROOT}/web/common.inc.sh" +. "${KEYMAN_ROOT}/resources/shellHelperFunctions.sh" ################################ Main script ################################ builder_describe \ "Compiles the web-oriented utility function module." \ "@/web/src/tools/testing/recorder-core test" \ - "@/web/src/engine/js-processor test" \ "@/common/web/keyman-version" \ "@/common/web/es-bundling" \ "@/common/web/types" \ @@ -30,7 +30,7 @@ builder_describe \ builder_describe_outputs \ configure /node_modules \ - build /common/web/keyboard-processor/build/lib/index.mjs + build /web/build/engine/keyboard/lib/index.mjs builder_parse "$@" @@ -42,39 +42,41 @@ function do_configure() { playwright install } +BUILD_DIR="${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}" + function do_build() { tsc --build "${THIS_SCRIPT_PATH}/tsconfig.all.json" # Base product - the main keyboard processor builder_echo "Bundle base product - the main keyboard processor" - ${BUNDLE_CMD} "${KEYMAN_ROOT}/common/web/keyboard-processor/build/obj/index.js" \ - --out "${KEYMAN_ROOT}/common/web/keyboard-processor/build/lib/index.mjs" \ + ${BUNDLE_CMD} "${BUILD_DIR}/obj/index.js" \ + --out "${BUILD_DIR}/lib/index.mjs" \ --format esm # The DOM-oriented keyboard loader builder_echo "Bundle the DOM-oriented keyboard loader" - ${BUNDLE_CMD} "${KEYMAN_ROOT}/common/web/keyboard-processor/build/obj/keyboards/loaders/dom-keyboard-loader.js" \ - --out "${KEYMAN_ROOT}/common/web/keyboard-processor/build/lib/dom-keyboard-loader.mjs" \ + ${BUNDLE_CMD} "${BUILD_DIR}/obj/keyboards/loaders/dom-keyboard-loader.js" \ + --out "${BUILD_DIR}/lib/dom-keyboard-loader.mjs" \ --format esm # The Node-oriented keyboard loader builder_echo "Bundle the Node-oriented keyboard loader" - ${BUNDLE_CMD} "${KEYMAN_ROOT}/common/web/keyboard-processor/build/obj/keyboards/loaders/node-keyboard-loader.js" \ - --out "${KEYMAN_ROOT}/common/web/keyboard-processor/build/lib/node-keyboard-loader.mjs" \ + ${BUNDLE_CMD} "${BUILD_DIR}/obj/keyboards/loaders/node-keyboard-loader.js" \ + --out "${BUILD_DIR}/lib/node-keyboard-loader.mjs" \ --format esm \ --platform node - # Tests + # # Tests # builder_echo "Bundle tests" - # ${BUNDLE_CMD} "${KEYMAN_ROOT}/common/web/keyboard-processor/build/tests/dom/cases/domKeyboardLoader.spec.js" \ - # --out "${KEYMAN_ROOT}/common/web/keyboard-processor/build/tests/dom/domKeyboardLoader.spec.mjs" \ + # ${BUNDLE_CMD} "${BUILD_DIR}/tests/dom/cases/domKeyboardLoader.spec.js" \ + # --out "${BUILD_DIR}/tests/dom/domKeyboardLoader.spec.mjs" \ # --format esm # Declaration bundling. builder_echo "Declaration bundling" - tsc --emitDeclarationOnly --outFile ./build/lib/index.d.ts - tsc --emitDeclarationOnly --outFile ./build/lib/dom-keyboard-loader.d.ts -p src/keyboards/loaders/tsconfig.dom.json - tsc --emitDeclarationOnly --outFile ./build/lib/node-keyboard-loader.d.ts -p src/keyboards/loaders/tsconfig.node.json + tsc --emitDeclarationOnly --outFile "${BUILD_DIR}/lib/index.d.ts" + tsc --emitDeclarationOnly --outFile "${BUILD_DIR}/lib/dom-keyboard-loader.d.ts" -p src/keyboards/loaders/tsconfig.dom.json + tsc --emitDeclarationOnly --outFile "${BUILD_DIR}/lib/node-keyboard-loader.d.ts" -p src/keyboards/loaders/tsconfig.node.json } function do_test() { @@ -87,10 +89,9 @@ function do_test() { fi c8 mocha --recursive $MOCHA_FLAGS ./tests/node/ - web-test-runner --config tests/dom/web-test-runner${WTR_CONFIG}.config.mjs } builder_run_action configure do_configure -builder_run_action clean rm -rf ./build +builder_run_action clean rm -rf "${BUILD_DIR}" builder_run_action build do_build -# builder_run_action test do_test +builder_run_action test do_test diff --git a/common/web/keyboard-processor/src/text/codes.ts b/web/src/engine/keyboard/src/codes.ts similarity index 100% rename from common/web/keyboard-processor/src/text/codes.ts rename to web/src/engine/keyboard/src/codes.ts diff --git a/common/web/keyboard-processor/src/text/deadkeys.ts b/web/src/engine/keyboard/src/deadkeys.ts similarity index 100% rename from common/web/keyboard-processor/src/text/deadkeys.ts rename to web/src/engine/keyboard/src/deadkeys.ts diff --git a/common/web/keyboard-processor/src/index.ts b/web/src/engine/keyboard/src/index.ts similarity index 70% rename from common/web/keyboard-processor/src/index.ts rename to web/src/engine/keyboard/src/index.ts index c719d7ee8e8..2871801f448 100644 --- a/common/web/keyboard-processor/src/index.ts +++ b/web/src/engine/keyboard/src/index.ts @@ -24,17 +24,17 @@ export { export { default as SpacebarText } from "./keyboards/spacebarText.js"; export { default as StateKeyMap } from "./keyboards/stateKeyMap.js"; -export { default as Codes } from "./text/codes.js"; -export * from "./text/codes.js"; -export * from "./text/deadkeys.js"; -export { default as KeyEvent } from "./text/keyEvent.js"; -export * from "./text/keyEvent.js"; -export { default as KeyMapping } from "./text/keyMapping.js"; -export { default as OutputTarget } from "./text/outputTarget.js"; -export * from "./text/outputTarget.js"; -export * from "./text/stringDivergence.js"; -export * from "./text/systemStores.js"; -export * from "./text/ruleBehavior.interface.js"; +export { default as Codes } from "./codes.js"; +export * from "./codes.js"; +export * from "./deadkeys.js"; +export { default as KeyEvent } from "./keyEvent.js"; +export * from "./keyEvent.js"; +export { default as KeyMapping } from "./keyMapping.js"; +export { default as OutputTarget } from "./outputTarget.js"; +export * from "./outputTarget.js"; +export * from "./stringDivergence.js"; +export * from "./systemStores.js"; +export * from "./ruleBehavior.interface.js"; export * from "@keymanapp/web-utils"; diff --git a/common/web/keyboard-processor/src/text/keyEvent.ts b/web/src/engine/keyboard/src/keyEvent.ts similarity index 98% rename from common/web/keyboard-processor/src/text/keyEvent.ts rename to web/src/engine/keyboard/src/keyEvent.ts index 2d0ee493229..0a128d725f9 100644 --- a/common/web/keyboard-processor/src/text/keyEvent.ts +++ b/web/src/engine/keyboard/src/keyEvent.ts @@ -6,11 +6,11 @@ // a key event. The most straightforward way to integrate Web OSK events on other platforms is to have // other platforms recognize and utilize this type. -import type Keyboard from "../keyboards/keyboard.js"; +import type Keyboard from "./keyboards/keyboard.js"; import { type DeviceSpec } from "@keymanapp/web-utils"; import Codes from './codes.js'; -import { ActiveKeyBase } from "../index.js"; +import { ActiveKeyBase } from './keyboards/activeLayout.js'; export interface DefaultRulesInterface { forAny(Lkc: KeyEvent, isMnemonic: boolean): string; diff --git a/common/web/keyboard-processor/src/text/keyMapping.ts b/web/src/engine/keyboard/src/keyMapping.ts similarity index 100% rename from common/web/keyboard-processor/src/text/keyMapping.ts rename to web/src/engine/keyboard/src/keyMapping.ts diff --git a/common/web/keyboard-processor/src/keyboards/activeLayout.ts b/web/src/engine/keyboard/src/keyboards/activeLayout.ts similarity index 99% rename from common/web/keyboard-processor/src/keyboards/activeLayout.ts rename to web/src/engine/keyboard/src/keyboards/activeLayout.ts index 7b293db93c3..c440511f172 100644 --- a/common/web/keyboard-processor/src/keyboards/activeLayout.ts +++ b/web/src/engine/keyboard/src/keyboards/activeLayout.ts @@ -1,6 +1,6 @@ -import Codes from "../text/codes.js"; -import KeyEvent, { KeyEventSpec } from "../text/keyEvent.js"; -import KeyMapping from "../text/keyMapping.js"; +import Codes from "../codes.js"; +import KeyEvent, { KeyEventSpec } from "../keyEvent.js"; +import KeyMapping from "../keyMapping.js"; import { ButtonClasses, Layouts } from "./defaultLayouts.js"; import type { LayoutKey, LayoutSubKey, LayoutRow, LayoutLayer, LayoutFormFactor, ButtonClass } from "./defaultLayouts.js"; import type Keyboard from "./keyboard.js"; @@ -105,7 +105,7 @@ export class ActiveKeyBase { pad: ActiveKeyBase.DEFAULT_PAD }; - /** WARNING - DO NOT USE DIRECTLY outside of @keymanapp/keyboard-processor! */ + /** WARNING - DO NOT USE DIRECTLY outside of keyman/engine/keyboard! */ id: TouchLayout.TouchLayoutKeyId; text: string; hint?: string; diff --git a/common/web/keyboard-processor/src/keyboards/defaultLayouts.ts b/web/src/engine/keyboard/src/keyboards/defaultLayouts.ts similarity index 99% rename from common/web/keyboard-processor/src/keyboards/defaultLayouts.ts rename to web/src/engine/keyboard/src/keyboards/defaultLayouts.ts index 109da53a0e5..3b97659d4bb 100644 --- a/common/web/keyboard-processor/src/keyboards/defaultLayouts.ts +++ b/web/src/engine/keyboard/src/keyboards/defaultLayouts.ts @@ -16,7 +16,7 @@ import ButtonClasses = TouchLayout.TouchLayoutKeySp; export { ButtonClasses }; -import Codes from "../text/codes.js"; +import Codes from "../codes.js"; import type Keyboard from "./keyboard.js"; export interface EncodedVisualKeyboard { diff --git a/common/web/keyboard-processor/src/keyboards/keyboard.ts b/web/src/engine/keyboard/src/keyboards/keyboard.ts similarity index 99% rename from common/web/keyboard-processor/src/keyboards/keyboard.ts rename to web/src/engine/keyboard/src/keyboards/keyboard.ts index 6ca5f790fdc..17bec4ad70e 100644 --- a/common/web/keyboard-processor/src/keyboards/keyboard.ts +++ b/web/src/engine/keyboard/src/keyboards/keyboard.ts @@ -1,12 +1,12 @@ -import Codes from "../text/codes.js"; +import Codes from "../codes.js"; import { EncodedVisualKeyboard, LayoutSpec, Layouts } from "./defaultLayouts.js"; import { ActiveKey, ActiveLayout, ActiveSubKey } from "./activeLayout.js"; -import KeyEvent from "../text/keyEvent.js"; -import type OutputTarget from "../text/outputTarget.js"; +import KeyEvent from "../keyEvent.js"; +import type OutputTarget from "../outputTarget.js"; import { ModifierKeyConstants, TouchLayout } from "@keymanapp/common-types"; type TouchLayoutSpec = TouchLayout.TouchLayoutPlatform & { isDefault?: boolean}; -import type { ComplexKeyboardStore, KeyboardStore } from "../text/systemStores.js"; +import type { ComplexKeyboardStore, KeyboardStore } from "../systemStores.js"; import { Version, DeviceSpec } from "@keymanapp/web-utils"; import StateKeyMap from "./stateKeyMap.js"; diff --git a/common/web/keyboard-processor/src/keyboards/keyboardHarness.ts b/web/src/engine/keyboard/src/keyboards/keyboardHarness.ts similarity index 99% rename from common/web/keyboard-processor/src/keyboards/keyboardHarness.ts rename to web/src/engine/keyboard/src/keyboards/keyboardHarness.ts index 109d2090673..bb2e2d5ccb1 100644 --- a/common/web/keyboard-processor/src/keyboards/keyboardHarness.ts +++ b/web/src/engine/keyboard/src/keyboards/keyboardHarness.ts @@ -1,5 +1,5 @@ import Keyboard from "./keyboard.js"; -import Codes from "../text/codes.js"; +import Codes from "../codes.js"; import { DeviceSpec } from '@keymanapp/web-utils'; /** diff --git a/common/web/keyboard-processor/src/keyboards/keyboardLoaderBase.ts b/web/src/engine/keyboard/src/keyboards/keyboardLoaderBase.ts similarity index 100% rename from common/web/keyboard-processor/src/keyboards/keyboardLoaderBase.ts rename to web/src/engine/keyboard/src/keyboards/keyboardLoaderBase.ts diff --git a/common/web/keyboard-processor/src/keyboards/keyboardProperties.ts b/web/src/engine/keyboard/src/keyboards/keyboardProperties.ts similarity index 100% rename from common/web/keyboard-processor/src/keyboards/keyboardProperties.ts rename to web/src/engine/keyboard/src/keyboards/keyboardProperties.ts diff --git a/common/web/keyboard-processor/src/keyboards/loaders/dom-keyboard-loader.ts b/web/src/engine/keyboard/src/keyboards/loaders/dom-keyboard-loader.ts similarity index 100% rename from common/web/keyboard-processor/src/keyboards/loaders/dom-keyboard-loader.ts rename to web/src/engine/keyboard/src/keyboards/loaders/dom-keyboard-loader.ts diff --git a/common/web/keyboard-processor/src/keyboards/loaders/domKeyboardLoader.ts b/web/src/engine/keyboard/src/keyboards/loaders/domKeyboardLoader.ts similarity index 97% rename from common/web/keyboard-processor/src/keyboards/loaders/domKeyboardLoader.ts rename to web/src/engine/keyboard/src/keyboards/loaders/domKeyboardLoader.ts index ea9cddecd42..fcb2c764cd6 100644 --- a/common/web/keyboard-processor/src/keyboards/loaders/domKeyboardLoader.ts +++ b/web/src/engine/keyboard/src/keyboards/loaders/domKeyboardLoader.ts @@ -2,7 +2,7 @@ /// -import { Keyboard, KeyboardHarness, KeyboardLoaderBase, KeyboardLoadErrorBuilder, MinimalKeymanGlobal } from '@keymanapp/keyboard-processor'; +import { Keyboard, KeyboardHarness, KeyboardLoaderBase, KeyboardLoadErrorBuilder, MinimalKeymanGlobal } from 'keyman/engine/keyboard'; import { ManagedPromise } from '@keymanapp/web-utils'; diff --git a/common/web/keyboard-processor/src/keyboards/loaders/node-keyboard-loader.ts b/web/src/engine/keyboard/src/keyboards/loaders/node-keyboard-loader.ts similarity index 100% rename from common/web/keyboard-processor/src/keyboards/loaders/node-keyboard-loader.ts rename to web/src/engine/keyboard/src/keyboards/loaders/node-keyboard-loader.ts diff --git a/common/web/keyboard-processor/src/keyboards/loaders/nodeKeyboardLoader.ts b/web/src/engine/keyboard/src/keyboards/loaders/nodeKeyboardLoader.ts similarity index 95% rename from common/web/keyboard-processor/src/keyboards/loaders/nodeKeyboardLoader.ts rename to web/src/engine/keyboard/src/keyboards/loaders/nodeKeyboardLoader.ts index 143e1c16c11..b9f6a7cdfef 100644 --- a/common/web/keyboard-processor/src/keyboards/loaders/nodeKeyboardLoader.ts +++ b/web/src/engine/keyboard/src/keyboards/loaders/nodeKeyboardLoader.ts @@ -1,4 +1,4 @@ -import { Keyboard, KeyboardHarness, KeyboardLoaderBase, KeyboardLoadErrorBuilder, MinimalKeymanGlobal } from '@keymanapp/keyboard-processor'; +import { Keyboard, KeyboardHarness, KeyboardLoaderBase, KeyboardLoadErrorBuilder, MinimalKeymanGlobal } from 'keyman/engine/keyboard'; import vm from 'vm'; import fs from 'fs'; diff --git a/web/src/engine/keyboard/src/keyboards/loaders/tsconfig.dom.json b/web/src/engine/keyboard/src/keyboards/loaders/tsconfig.dom.json new file mode 100644 index 00000000000..1dd122f5485 --- /dev/null +++ b/web/src/engine/keyboard/src/keyboards/loaders/tsconfig.dom.json @@ -0,0 +1,13 @@ +{ + "extends": "../../../../../../tsconfig.base.json", + "compilerOptions": { + "baseUrl": "../../../", + "outDir": "../../../../../../build/engine/keyboard/obj/keyboards/loaders/", + "tsBuildInfoFile": "../../../../../../build/engine/keyboard/obj/keyboards/loaders/tsconfig.dom.tsbuildinfo", + "rootDir": "." + }, + "references": [ + { "path": "../../../tsconfig.json" } + ], + "include": ["dom-keyboard-loader.ts", "domKeyboardLoader.ts"], +} diff --git a/web/src/engine/keyboard/src/keyboards/loaders/tsconfig.node.json b/web/src/engine/keyboard/src/keyboards/loaders/tsconfig.node.json new file mode 100644 index 00000000000..4a06decf4c4 --- /dev/null +++ b/web/src/engine/keyboard/src/keyboards/loaders/tsconfig.node.json @@ -0,0 +1,14 @@ +{ + "extends": "../../../../../../tsconfig.base.json", + "compilerOptions": { + "types": [ "node" ], + "baseUrl": "../../../", + "outDir": "../../../../../../build/engine/keyboard/obj/keyboards/loaders/", + "tsBuildInfoFile": "../../../../../../build/engine/keyboard/obj/keyboards/loaders/tsconfig.node.tsbuildinfo", + "rootDir": "." + }, + "references": [ + { "path": "../../../tsconfig.json" } + ], + "include": ["node-keyboard-loader.ts", "nodeKeyboardLoader.ts"], +} diff --git a/common/web/keyboard-processor/src/keyboards/spacebarText.ts b/web/src/engine/keyboard/src/keyboards/spacebarText.ts similarity index 100% rename from common/web/keyboard-processor/src/keyboards/spacebarText.ts rename to web/src/engine/keyboard/src/keyboards/spacebarText.ts diff --git a/common/web/keyboard-processor/src/keyboards/stateKeyMap.ts b/web/src/engine/keyboard/src/keyboards/stateKeyMap.ts similarity index 65% rename from common/web/keyboard-processor/src/keyboards/stateKeyMap.ts rename to web/src/engine/keyboard/src/keyboards/stateKeyMap.ts index c8e9ee8b763..e82ff417c4e 100644 --- a/common/web/keyboard-processor/src/keyboards/stateKeyMap.ts +++ b/web/src/engine/keyboard/src/keyboards/stateKeyMap.ts @@ -1,5 +1,5 @@ /** - * Provided by @keymanapp/keyboard-processor's `KeyboardProcessor` class and utilized by the OSK + * Provided by keyman/engine/keyboard's `KeyboardProcessor` class and utilized by the OSK * to provide state feedback on any corresponding keys visible in the OSK. */ export default interface StateKeyMap { diff --git a/common/web/keyboard-processor/src/text/outputTarget.ts b/web/src/engine/keyboard/src/outputTarget.ts similarity index 100% rename from common/web/keyboard-processor/src/text/outputTarget.ts rename to web/src/engine/keyboard/src/outputTarget.ts diff --git a/common/web/keyboard-processor/src/text/ruleBehavior.interface.ts b/web/src/engine/keyboard/src/ruleBehavior.interface.ts similarity index 100% rename from common/web/keyboard-processor/src/text/ruleBehavior.interface.ts rename to web/src/engine/keyboard/src/ruleBehavior.interface.ts diff --git a/common/web/keyboard-processor/src/text/stringDivergence.ts b/web/src/engine/keyboard/src/stringDivergence.ts similarity index 100% rename from common/web/keyboard-processor/src/text/stringDivergence.ts rename to web/src/engine/keyboard/src/stringDivergence.ts diff --git a/common/web/keyboard-processor/src/text/systemStores.ts b/web/src/engine/keyboard/src/systemStores.ts similarity index 96% rename from common/web/keyboard-processor/src/text/systemStores.ts rename to web/src/engine/keyboard/src/systemStores.ts index a2f7abff344..24f3e8cc36b 100644 --- a/common/web/keyboard-processor/src/text/systemStores.ts +++ b/web/src/engine/keyboard/src/systemStores.ts @@ -1,5 +1,5 @@ -import { type KeyboardHarness } from "../keyboards/keyboardHarness.js"; -import { StoreNonCharEntry } from '../keyboards/keyboard.js'; +import { type KeyboardHarness } from "./keyboards/keyboardHarness.js"; +import { StoreNonCharEntry } from './keyboards/keyboard.js'; export enum SystemStoreIDs { TSS_LAYER = 33, diff --git a/common/web/keyboard-processor/tests/node/basic-engine.js b/web/src/engine/keyboard/tests/node/basic-engine.js similarity index 87% rename from common/web/keyboard-processor/tests/node/basic-engine.js rename to web/src/engine/keyboard/tests/node/basic-engine.js index 1e7ff3a205e..33d90b6567e 100644 --- a/common/web/keyboard-processor/tests/node/basic-engine.js +++ b/web/src/engine/keyboard/tests/node/basic-engine.js @@ -4,8 +4,9 @@ import fs from 'fs'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { KeyboardInterface, MinimalKeymanGlobal } from '@keymanapp/keyboard-processor'; -import { NodeKeyboardLoader } from '@keymanapp/keyboard-processor/node-keyboard-loader'; +import { MinimalKeymanGlobal } from 'keyman/engine/keyboard'; +import { KeyboardInterface } from 'keyman/engine/js-processor'; +import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; import { KeyboardTest, NodeProctor } from '@keymanapp/recorder-core'; describe('Engine - Basic Simulation', function() { @@ -24,7 +25,7 @@ describe('Engine - Basic Simulation', function() { before(async function() { // -- START: Standard Recorder-based unit test loading boilerplate -- let keyboardLoader = new NodeKeyboardLoader(new KeyboardInterface({}, MinimalKeymanGlobal)); - let keyboard = await keyboardLoader.loadKeyboardFromPath('../../test/' + testSuite.keyboard.filename); + let keyboard = await keyboardLoader.loadKeyboardFromPath('../../../../common/test/' + testSuite.keyboard.filename); keyboardWithHarness = keyboardLoader.harness; keyboardWithHarness.activeKeyboard = keyboard; diff --git a/common/web/keyboard-processor/tests/node/basic-init.js b/web/src/engine/keyboard/tests/node/basic-init.js similarity index 92% rename from common/web/keyboard-processor/tests/node/basic-init.js rename to web/src/engine/keyboard/tests/node/basic-init.js index 8f04a6a6e8b..cabdb9d4322 100644 --- a/common/web/keyboard-processor/tests/node/basic-init.js +++ b/web/src/engine/keyboard/tests/node/basic-init.js @@ -3,8 +3,8 @@ import { assert } from 'chai'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { KeyboardProcessor } from '@keymanapp/keyboard-processor'; -import { NodeKeyboardLoader } from '@keymanapp/keyboard-processor/node-keyboard-loader'; +import { KeyboardProcessor } from 'keyman/engine/js-processor'; +import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; global.keyman = {}; // So that keyboard-based checks against the global `keyman` succeed. // 10.0+ dependent keyboards, like khmer_angkor, will otherwise fail to load. diff --git a/common/web/keyboard-processor/tests/node/bundled-module.js b/web/src/engine/keyboard/tests/node/bundled-module.js similarity index 91% rename from common/web/keyboard-processor/tests/node/bundled-module.js rename to web/src/engine/keyboard/tests/node/bundled-module.js index bfff937b626..cfc54480b68 100644 --- a/common/web/keyboard-processor/tests/node/bundled-module.js +++ b/web/src/engine/keyboard/tests/node/bundled-module.js @@ -1,5 +1,5 @@ import { assert } from "chai"; -import * as Package from "../../build/lib/index.mjs"; +import * as Package from "keyman/engine/keyboard"; // A few small tests to ensure that the ES Module bundle was successfully constructed and is usable. @@ -13,9 +13,9 @@ var toSupplementaryPairString = function(code){ let u = toSupplementaryPairString; describe('Bundled ES Module', function() { - describe('KeyboardProcessor', function () { + describe('Keyboard', function () { it('should initialize without errors', function () { - let kp = new Package.KeyboardProcessor(); + let kp = new Package.Keyboard(); assert.isNotNull(kp); }); }); diff --git a/common/web/keyboard-processor/tests/node/chirality.js b/web/src/engine/keyboard/tests/node/chirality.js similarity index 97% rename from common/web/keyboard-processor/tests/node/chirality.js rename to web/src/engine/keyboard/tests/node/chirality.js index 70dca3d47fd..d812a21635d 100644 --- a/common/web/keyboard-processor/tests/node/chirality.js +++ b/web/src/engine/keyboard/tests/node/chirality.js @@ -4,8 +4,9 @@ import fs from 'fs'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { KeyboardInterface, MinimalKeymanGlobal } from '@keymanapp/keyboard-processor'; -import { NodeKeyboardLoader } from '@keymanapp/keyboard-processor/node-keyboard-loader'; +import { MinimalKeymanGlobal } from 'keyman/engine/keyboard'; +import { KeyboardInterface } from 'keyman/engine/js-processor'; +import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; import { KeyboardTest, NodeProctor } from '@keymanapp/recorder-core'; import { ModifierKeyConstants } from '@keymanapp/common-types'; @@ -25,7 +26,7 @@ describe('Engine - Chirality', function() { before(async function() { // -- START: Standard Recorder-based unit test loading boilerplate -- let keyboardLoader = new NodeKeyboardLoader(new KeyboardInterface({}, MinimalKeymanGlobal)); - let keyboard = await keyboardLoader.loadKeyboardFromPath('../../test/' + testSuite.keyboard.filename); + let keyboard = await keyboardLoader.loadKeyboardFromPath('../../../../common/test/' + testSuite.keyboard.filename); keyboardWithHarness = keyboardLoader.harness; keyboardWithHarness.activeKeyboard = keyboard; diff --git a/common/web/keyboard-processor/tests/node/deadkeys.js b/web/src/engine/keyboard/tests/node/deadkeys.js similarity index 87% rename from common/web/keyboard-processor/tests/node/deadkeys.js rename to web/src/engine/keyboard/tests/node/deadkeys.js index e2fe70837eb..51bf2aebf56 100644 --- a/common/web/keyboard-processor/tests/node/deadkeys.js +++ b/web/src/engine/keyboard/tests/node/deadkeys.js @@ -4,8 +4,9 @@ import fs from 'fs'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { KeyboardInterface, MinimalKeymanGlobal } from '@keymanapp/keyboard-processor'; -import { NodeKeyboardLoader } from '@keymanapp/keyboard-processor/node-keyboard-loader'; +import { MinimalKeymanGlobal } from 'keyman/engine/keyboard'; +import { KeyboardInterface } from 'keyman/engine/js-processor'; +import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; import { KeyboardTest, NodeProctor } from '@keymanapp/recorder-core'; describe('Engine - Deadkeys', function() { @@ -24,7 +25,7 @@ describe('Engine - Deadkeys', function() { before(async function() { // -- START: Standard Recorder-based unit test loading boilerplate -- let keyboardLoader = new NodeKeyboardLoader(new KeyboardInterface({}, MinimalKeymanGlobal)); - let keyboard = await keyboardLoader.loadKeyboardFromPath('../../test/' + testSuite.keyboard.filename); + let keyboard = await keyboardLoader.loadKeyboardFromPath('../../../../common/test/' + testSuite.keyboard.filename); keyboardWithHarness = keyboardLoader.harness; keyboardWithHarness.activeKeyboard = keyboard; diff --git a/common/web/keyboard-processor/tests/node/engine/context.js b/web/src/engine/keyboard/tests/node/engine/context.js similarity index 99% rename from common/web/keyboard-processor/tests/node/engine/context.js rename to web/src/engine/keyboard/tests/node/engine/context.js index a1fe5863df9..3b318607a0d 100644 --- a/common/web/keyboard-processor/tests/node/engine/context.js +++ b/web/src/engine/keyboard/tests/node/engine/context.js @@ -3,8 +3,9 @@ import { assert } from 'chai'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { KeyboardInterface, KeyboardProcessor, MinimalKeymanGlobal, Mock } from '@keymanapp/keyboard-processor'; -import { NodeKeyboardLoader } from '@keymanapp/keyboard-processor/node-keyboard-loader'; +import { MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; +import { KeyboardInterface, KeyboardProcessor } from 'keyman/engine/js-processor'; +import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; import { NodeProctor, RecordedKeystrokeSequence } from '@keymanapp/recorder-core'; diff --git a/common/web/keyboard-processor/tests/node/engine/notany_context.js b/web/src/engine/keyboard/tests/node/engine/notany_context.js similarity index 94% rename from common/web/keyboard-processor/tests/node/engine/notany_context.js rename to web/src/engine/keyboard/tests/node/engine/notany_context.js index 2329463d465..1fc2ec01297 100644 --- a/common/web/keyboard-processor/tests/node/engine/notany_context.js +++ b/web/src/engine/keyboard/tests/node/engine/notany_context.js @@ -3,8 +3,9 @@ import { assert } from 'chai'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { KeyboardInterface, MinimalKeymanGlobal, Mock } from '@keymanapp/keyboard-processor'; -import { NodeKeyboardLoader } from '@keymanapp/keyboard-processor/node-keyboard-loader'; +import { MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; +import { KeyboardInterface } from 'keyman/engine/js-processor'; +import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; import { NodeProctor, RecordedKeystrokeSequence } from '@keymanapp/recorder-core'; import { extendString } from '@keymanapp/web-utils'; diff --git a/common/web/keyboard-processor/tests/node/engine/stores.js b/web/src/engine/keyboard/tests/node/engine/stores.js similarity index 94% rename from common/web/keyboard-processor/tests/node/engine/stores.js rename to web/src/engine/keyboard/tests/node/engine/stores.js index ade1c2bd471..8174cbe0779 100644 --- a/common/web/keyboard-processor/tests/node/engine/stores.js +++ b/web/src/engine/keyboard/tests/node/engine/stores.js @@ -1,6 +1,7 @@ import { assert } from 'chai'; -import { Keyboard, KeyboardProcessor } from '@keymanapp/keyboard-processor'; +import { Keyboard } from 'keyman/engine/keyboard'; +import { KeyboardProcessor } from 'keyman/engine/js-processor'; import { extendString } from '@keymanapp/web-utils'; extendString(); diff --git a/common/web/keyboard-processor/tests/node/engine/unmatched_final_group.js b/web/src/engine/keyboard/tests/node/engine/unmatched_final_group.js similarity index 84% rename from common/web/keyboard-processor/tests/node/engine/unmatched_final_group.js rename to web/src/engine/keyboard/tests/node/engine/unmatched_final_group.js index 81f9765da4c..cf2f1e88034 100644 --- a/common/web/keyboard-processor/tests/node/engine/unmatched_final_group.js +++ b/web/src/engine/keyboard/tests/node/engine/unmatched_final_group.js @@ -4,8 +4,9 @@ import fs from 'fs'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { KeyboardInterface, MinimalKeymanGlobal } from '@keymanapp/keyboard-processor'; -import { NodeKeyboardLoader } from '@keymanapp/keyboard-processor/node-keyboard-loader'; +import { MinimalKeymanGlobal } from 'keyman/engine/keyboard'; +import { KeyboardInterface } from 'keyman/engine/js-processor'; +import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; import { KeyboardTest, NodeProctor } from '@keymanapp/recorder-core'; describe('Engine - Unmatched Final Groups', function() { @@ -23,7 +24,7 @@ describe('Engine - Unmatched Final Groups', function() { before(async function() { // -- START: Standard Recorder-based unit test loading boilerplate -- let keyboardLoader = new NodeKeyboardLoader(new KeyboardInterface({}, MinimalKeymanGlobal)); - const keyboard = await keyboardLoader.loadKeyboardFromPath('../../test/' + testSuite.keyboard.filename); + const keyboard = await keyboardLoader.loadKeyboardFromPath('../../../../common/test/' + testSuite.keyboard.filename); keyboardWithHarness = keyboardLoader.harness; keyboardWithHarness.activeKeyboard = keyboard; diff --git a/common/web/keyboard-processor/tests/node/keyboard-loading.js b/web/src/engine/keyboard/tests/node/keyboard-loading.js similarity index 96% rename from common/web/keyboard-processor/tests/node/keyboard-loading.js rename to web/src/engine/keyboard/tests/node/keyboard-loading.js index 500780dfedb..6152f1b0de8 100644 --- a/common/web/keyboard-processor/tests/node/keyboard-loading.js +++ b/web/src/engine/keyboard/tests/node/keyboard-loading.js @@ -4,8 +4,9 @@ import fs from 'fs'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { KeyboardHarness, KeyboardInterface, KeyboardLoaderBase, MinimalKeymanGlobal, Mock } from '@keymanapp/keyboard-processor'; -import { NodeKeyboardLoader } from '@keymanapp/keyboard-processor/node-keyboard-loader'; +import { KeyboardHarness, MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; +import { KeyboardInterface } from 'keyman/engine/js-processor'; +import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; describe('Headless keyboard loading', function() { const laoPath = require.resolve('@keymanapp/common-test-resources/keyboards/lao_2008_basic.js'); diff --git a/common/web/keyboard-processor/tests/node/keyboard-properties.js b/web/src/engine/keyboard/tests/node/keyboard-properties.js similarity index 98% rename from common/web/keyboard-processor/tests/node/keyboard-properties.js rename to web/src/engine/keyboard/tests/node/keyboard-properties.js index b6ec2dbf8d2..f23d56e3b52 100644 --- a/common/web/keyboard-processor/tests/node/keyboard-properties.js +++ b/web/src/engine/keyboard/tests/node/keyboard-properties.js @@ -5,7 +5,7 @@ import path from 'path'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { KeyboardProperties, SpacebarText } from '@keymanapp/keyboard-processor'; +import { KeyboardProperties, SpacebarText } from 'keyman/engine/keyboard'; describe('Keyboard Properties', function() { let commonResourcesPackage = '@keymanapp/common-test-resources'; diff --git a/common/web/keyboard-processor/tests/node/mocks.js b/web/src/engine/keyboard/tests/node/mocks.js similarity index 98% rename from common/web/keyboard-processor/tests/node/mocks.js rename to web/src/engine/keyboard/tests/node/mocks.js index 9a84e2a8cc0..b02f259886f 100644 --- a/common/web/keyboard-processor/tests/node/mocks.js +++ b/web/src/engine/keyboard/tests/node/mocks.js @@ -1,5 +1,5 @@ import { assert } from 'chai'; -import { Mock } from '@keymanapp/keyboard-processor'; +import { Mock } from 'keyman/engine/keyboard'; describe('Mocks', function() { describe('app|les', () => { diff --git a/common/web/keyboard-processor/tests/node/non-positional-rules.js b/web/src/engine/keyboard/tests/node/non-positional-rules.js similarity index 97% rename from common/web/keyboard-processor/tests/node/non-positional-rules.js rename to web/src/engine/keyboard/tests/node/non-positional-rules.js index aba54643aee..2ab62a4840c 100644 --- a/common/web/keyboard-processor/tests/node/non-positional-rules.js +++ b/web/src/engine/keyboard/tests/node/non-positional-rules.js @@ -4,8 +4,9 @@ import { ModifierKeyConstants } from '@keymanapp/common-types'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { Codes, KeyboardInterface, KeyEvent, MinimalKeymanGlobal, Mock } from '@keymanapp/keyboard-processor'; -import { NodeKeyboardLoader } from '@keymanapp/keyboard-processor/node-keyboard-loader'; +import { Codes, KeyEvent, MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; +import { KeyboardInterface } from 'keyman/engine/js-processor'; +import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; // Compare and contrast the unit tests here with those for app/browser key-event unit testing // in the hardware-event-processing set; the output objects there should have the same format diff --git a/common/web/keyboard-processor/tests/node/specialized-backspace.js b/web/src/engine/keyboard/tests/node/specialized-backspace.js similarity index 98% rename from common/web/keyboard-processor/tests/node/specialized-backspace.js rename to web/src/engine/keyboard/tests/node/specialized-backspace.js index db2be071e8f..967701c63a1 100644 --- a/common/web/keyboard-processor/tests/node/specialized-backspace.js +++ b/web/src/engine/keyboard/tests/node/specialized-backspace.js @@ -4,8 +4,9 @@ import fs from 'fs'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { Codes, KeyboardInterface, KeyboardProcessor, KeyEvent, MinimalKeymanGlobal, Mock } from '@keymanapp/keyboard-processor'; -import { NodeKeyboardLoader } from '@keymanapp/keyboard-processor/node-keyboard-loader'; +import { Codes, KeyEvent, MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; +import { KeyboardInterface, KeyboardProcessor } from 'keyman/engine/js-processor'; +import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; import { ModifierKeyConstants } from '@keymanapp/common-types'; diff --git a/common/web/keyboard-processor/tests/node/transcriptions.js b/web/src/engine/keyboard/tests/node/transcriptions.js similarity index 99% rename from common/web/keyboard-processor/tests/node/transcriptions.js rename to web/src/engine/keyboard/tests/node/transcriptions.js index b071532bf2a..569b36d3cd6 100644 --- a/common/web/keyboard-processor/tests/node/transcriptions.js +++ b/web/src/engine/keyboard/tests/node/transcriptions.js @@ -1,6 +1,6 @@ import { assert } from 'chai'; -import { Mock, findCommonSubstringEndIndex } from '@keymanapp/keyboard-processor'; +import { Mock, findCommonSubstringEndIndex } from 'keyman/engine/keyboard'; import { extendString } from '@keymanapp/web-utils'; extendString(); // Ensure KMW's string-extension functionality is available. diff --git a/common/web/keyboard-processor/tsconfig.all.json b/web/src/engine/keyboard/tsconfig.all.json similarity index 66% rename from common/web/keyboard-processor/tsconfig.all.json rename to web/src/engine/keyboard/tsconfig.all.json index 79f10644d10..1ee44d3e70e 100644 --- a/common/web/keyboard-processor/tsconfig.all.json +++ b/web/src/engine/keyboard/tsconfig.all.json @@ -1,9 +1,9 @@ { - "extends": "../tsconfig.kmw-main-base.json", + "extends": "../../../tsconfig.base.json", "compilerOptions": { "baseUrl": "./", - "outDir": "build/obj/", - "tsBuildInfoFile": "build/obj/tsconfig.all.tsbuildinfo", + "outDir": "../../../build/engine/keyboard/obj/", + "tsBuildInfoFile": "../../../build/engine/keyboard/obj/tsconfig.all.tsbuildinfo", "rootDir": "./src/" }, "references": [ diff --git a/web/src/engine/keyboard/tsconfig.json b/web/src/engine/keyboard/tsconfig.json new file mode 100644 index 00000000000..84d96c8591f --- /dev/null +++ b/web/src/engine/keyboard/tsconfig.json @@ -0,0 +1,12 @@ +// Is used by the keyboard-loader submodules. +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "baseUrl": "./", + "outDir": "../../../build/engine/keyboard/obj/", + "tsBuildInfoFile": "../../../build/engine/keyboard/obj/tsconfig.tsbuildinfo", + "rootDir": "./src/" + }, + "include": [ "./src/**/*.ts"], + "exclude": ["./src/keyboards/loaders/**/*.ts"] +} diff --git a/web/src/engine/main/build.sh b/web/src/engine/main/build.sh index 4e6ca67db11..15eaf770f2e 100755 --- a/web/src/engine/main/build.sh +++ b/web/src/engine/main/build.sh @@ -14,7 +14,7 @@ SUBPROJECT_NAME=engine/main builder_describe "Builds the Keyman Engine for Web's common top-level base classes." \ "@/common/web/keyman-version" \ - "@/common/web/keyboard-processor" \ + "@/web/src/engine/keyboard" \ "@/common/predictive-text" \ "@/web/src/engine/interfaces build" \ "@/web/src/engine/device-detect build" \ diff --git a/web/src/engine/main/src/contextManagerBase.ts b/web/src/engine/main/src/contextManagerBase.ts index e745dbe312b..f20dd19d007 100644 --- a/web/src/engine/main/src/contextManagerBase.ts +++ b/web/src/engine/main/src/contextManagerBase.ts @@ -1,5 +1,5 @@ import { EventEmitter } from 'eventemitter3'; -import { ManagedPromise, type Keyboard, type OutputTarget } from '@keymanapp/keyboard-processor'; +import { ManagedPromise, type Keyboard, type OutputTarget } from 'keyman/engine/keyboard'; import { type KeyboardInterface } from 'keyman/engine/js-processor'; import { StubAndKeyboardCache, type KeyboardStub } from 'keyman/engine/package-cache'; import { PredictionContext } from 'keyman/engine/interfaces'; diff --git a/web/src/engine/main/src/engineConfiguration.ts b/web/src/engine/main/src/engineConfiguration.ts index bb82844c565..d6f6f0d6987 100644 --- a/web/src/engine/main/src/engineConfiguration.ts +++ b/web/src/engine/main/src/engineConfiguration.ts @@ -1,6 +1,6 @@ import { EventEmitter } from "eventemitter3"; -import { DeviceSpec, KeyboardProperties, ManagedPromise, OutputTarget, physicalKeyDeviceAlias, SpacebarText } from "@keymanapp/keyboard-processor"; +import { DeviceSpec, KeyboardProperties, ManagedPromise, OutputTarget, physicalKeyDeviceAlias, SpacebarText } from "keyman/engine/keyboard"; import { RuleBehavior } from 'keyman/engine/js-processor'; import { PathConfiguration, PathOptionDefaults, PathOptionSpec } from "keyman/engine/interfaces"; import { Device } from "keyman/engine/device-detect"; diff --git a/web/src/engine/main/src/hardKeyboard.ts b/web/src/engine/main/src/hardKeyboard.ts index 7dc9b5e3572..2e917ad77df 100644 --- a/web/src/engine/main/src/hardKeyboard.ts +++ b/web/src/engine/main/src/hardKeyboard.ts @@ -1,5 +1,5 @@ import { EventEmitter } from "eventemitter3"; -import { Keyboard, KeyMapping, KeyEvent, Codes } from "@keymanapp/keyboard-processor"; +import { Keyboard, KeyMapping, KeyEvent, Codes } from "keyman/engine/keyboard"; import { type RuleBehavior } from 'keyman/engine/js-processor'; import { KeyEventSourceInterface } from 'keyman/engine/events'; import { ModifierKeyConstants } from '@keymanapp/common-types'; diff --git a/web/src/engine/main/src/headless/contextWindow.ts b/web/src/engine/main/src/headless/contextWindow.ts index 2adb4f0b6a6..b3337c29e53 100644 --- a/web/src/engine/main/src/headless/contextWindow.ts +++ b/web/src/engine/main/src/headless/contextWindow.ts @@ -1,4 +1,4 @@ -import { Mock } from "@keymanapp/keyboard-processor"; +import { Mock } from "keyman/engine/keyboard"; export default class ContextWindow implements Context { // Used to limit the range of context replicated for use of keyboard rules within diff --git a/web/src/engine/main/src/headless/inputProcessor.ts b/web/src/engine/main/src/headless/inputProcessor.ts index a96170457e0..13eb67c2dc0 100644 --- a/web/src/engine/main/src/headless/inputProcessor.ts +++ b/web/src/engine/main/src/headless/inputProcessor.ts @@ -16,7 +16,7 @@ import { Mock, type OutputTarget, SystemStoreIDs, -} from "@keymanapp/keyboard-processor"; +} from "keyman/engine/keyboard"; import { KeyboardInterface, KeyboardProcessor, RuleBehavior, type ProcessorInitOptions } from 'keyman/engine/js-processor'; import { TranscriptionCache } from "./transcriptionCache.js"; diff --git a/web/src/engine/main/src/headless/languageProcessor.ts b/web/src/engine/main/src/headless/languageProcessor.ts index 30a676bb6aa..8f93d39d873 100644 --- a/web/src/engine/main/src/headless/languageProcessor.ts +++ b/web/src/engine/main/src/headless/languageProcessor.ts @@ -1,6 +1,6 @@ import { EventEmitter } from "eventemitter3"; import { LMLayer } from "@keymanapp/lexical-model-layer/web"; -import { OutputTarget, Transcription, Mock } from "@keymanapp/keyboard-processor"; +import { OutputTarget, Transcription, Mock } from "keyman/engine/keyboard"; import { LanguageProcessorEventMap, ModelSpec, StateChangeEnum, ReadySuggestions } from 'keyman/engine/interfaces'; import ContextWindow from "./contextWindow.js"; import { TranscriptionCache } from "./transcriptionCache.js"; diff --git a/web/src/engine/main/src/headless/transcriptionCache.ts b/web/src/engine/main/src/headless/transcriptionCache.ts index c173009171c..9430bde5ee8 100644 --- a/web/src/engine/main/src/headless/transcriptionCache.ts +++ b/web/src/engine/main/src/headless/transcriptionCache.ts @@ -1,4 +1,4 @@ -import { Transcription } from "@keymanapp/keyboard-processor"; +import { Transcription } from "keyman/engine/keyboard"; const TRANSCRIPTION_BUFFER_SIZE = 10; diff --git a/web/src/engine/main/src/keyboardInterface.ts b/web/src/engine/main/src/keyboardInterface.ts index d966c26bad4..9d922477b20 100644 --- a/web/src/engine/main/src/keyboardInterface.ts +++ b/web/src/engine/main/src/keyboardInterface.ts @@ -1,4 +1,4 @@ -import { KeyboardObject } from "@keymanapp/keyboard-processor"; +import { KeyboardObject } from "keyman/engine/keyboard"; import { KeyboardInterface as KeyboardInterfaceBase } from 'keyman/engine/js-processor'; import { KeyboardStub, RawKeyboardStub, toUnprefixedKeyboardId as unprefixed } from 'keyman/engine/package-cache'; diff --git a/web/src/engine/main/src/keymanEngine.ts b/web/src/engine/main/src/keymanEngine.ts index 86ff9d5898d..b91920e70d3 100644 --- a/web/src/engine/main/src/keymanEngine.ts +++ b/web/src/engine/main/src/keymanEngine.ts @@ -1,6 +1,6 @@ -import { type KeyEvent, type Keyboard, KeyboardKeymanGlobal } from "@keymanapp/keyboard-processor"; +import { type KeyEvent, type Keyboard, KeyboardKeymanGlobal } from "keyman/engine/keyboard"; import { ProcessorInitOptions, RuleBehavior } from 'keyman/engine/js-processor'; -import { DOMKeyboardLoader as KeyboardLoader } from "@keymanapp/keyboard-processor/dom-keyboard-loader"; +import { DOMKeyboardLoader as KeyboardLoader } from "keyman/engine/keyboard/dom-keyboard-loader"; import { InputProcessor } from './headless/inputProcessor.js'; import { OSKView } from "keyman/engine/osk"; import { KeyboardRequisitioner, ModelCache, toUnprefixedKeyboardId as unprefixed } from "keyman/engine/package-cache"; @@ -244,7 +244,7 @@ export default class KeymanEngine< this.contextManager.configure({ resetContext: (target) => { // Could reset the target's deadkeys here, but it's really more of a 'core' task. - // So we delegate that to keyboard-processor. + // So we delegate that to keyboard. if(this.osk) { this.osk.batchLayoutAfter(() => { this.core.resetContext(target); diff --git a/web/src/engine/main/src/variableStoreCookieSerializer.ts b/web/src/engine/main/src/variableStoreCookieSerializer.ts index 35b51150c0e..87a5c8b6ff7 100644 --- a/web/src/engine/main/src/variableStoreCookieSerializer.ts +++ b/web/src/engine/main/src/variableStoreCookieSerializer.ts @@ -1,4 +1,4 @@ -import { VariableStore, VariableStoreSerializer } from "@keymanapp/keyboard-processor"; +import { VariableStore, VariableStoreSerializer } from "keyman/engine/keyboard"; import { CookieSerializer } from "keyman/engine/dom-utils"; // While there's little reason we couldn't store all of a keyboard's store values within diff --git a/web/src/engine/osk/build.sh b/web/src/engine/osk/build.sh index 4538b79d923..0d676a2d3ef 100755 --- a/web/src/engine/osk/build.sh +++ b/web/src/engine/osk/build.sh @@ -13,7 +13,7 @@ SUBPROJECT_NAME=engine/osk # ################################ Main script ################################ builder_describe "Builds the Keyman Engine for Web's On-Screen Keyboard package (OSK)." \ - "@/common/web/keyboard-processor build" \ + "@/web/src/engine/keyboard build" \ "@/common/web/gesture-recognizer build" \ "@/web/src/engine/interfaces build" \ "@/web/src/engine/dom-utils build" \ diff --git a/web/src/engine/osk/src/banner/banner.ts b/web/src/engine/osk/src/banner/banner.ts index 39b3ddc708c..e38b6b6625d 100644 --- a/web/src/engine/osk/src/banner/banner.ts +++ b/web/src/engine/osk/src/banner/banner.ts @@ -1,4 +1,4 @@ -import { Keyboard, KeyboardProperties } from '@keymanapp/keyboard-processor'; +import { Keyboard, KeyboardProperties } from 'keyman/engine/keyboard'; import { createUnselectableElement } from 'keyman/engine/dom-utils'; // Base class for a banner above the keyboard in the OSK diff --git a/web/src/engine/osk/src/banner/bannerController.ts b/web/src/engine/osk/src/banner/bannerController.ts index a53ea2f9e92..7fbc8ceb9bb 100644 --- a/web/src/engine/osk/src/banner/bannerController.ts +++ b/web/src/engine/osk/src/banner/bannerController.ts @@ -6,7 +6,7 @@ import { BannerView } from './bannerView.js'; import { Banner } from './banner.js'; import { BlankBanner } from './blankBanner.js'; import { HTMLBanner } from './htmlBanner.js'; -import { Keyboard, KeyboardProperties } from '@keymanapp/keyboard-processor'; +import { Keyboard, KeyboardProperties } from 'keyman/engine/keyboard'; export class BannerController { private container: BannerView; diff --git a/web/src/engine/osk/src/banner/suggestionBanner.ts b/web/src/engine/osk/src/banner/suggestionBanner.ts index adf6a5ea200..34455fd0619 100644 --- a/web/src/engine/osk/src/banner/suggestionBanner.ts +++ b/web/src/engine/osk/src/banner/suggestionBanner.ts @@ -13,7 +13,7 @@ import { import { BANNER_GESTURE_SET } from './bannerGestureSet.js'; -import { DeviceSpec, Keyboard, KeyboardProperties, timedPromise } from '@keymanapp/keyboard-processor'; +import { DeviceSpec, Keyboard, KeyboardProperties, timedPromise } from 'keyman/engine/keyboard'; import { Banner } from './banner.js'; import { ParsedLengthStyle } from '../lengthStyle.js'; import { getFontSizeStyle } from '../fontSizeUtils.js'; diff --git a/web/src/engine/osk/src/components/helpPageView.ts b/web/src/engine/osk/src/components/helpPageView.ts index 7c66708be9a..af489a2686f 100644 --- a/web/src/engine/osk/src/components/helpPageView.ts +++ b/web/src/engine/osk/src/components/helpPageView.ts @@ -1,4 +1,4 @@ -import { Keyboard } from '@keymanapp/keyboard-processor'; +import { Keyboard } from 'keyman/engine/keyboard'; import KeyboardView from './keyboardView.interface.js'; import { ParsedLengthStyle } from "../lengthStyle.js"; diff --git a/web/src/engine/osk/src/components/titleBar.ts b/web/src/engine/osk/src/components/titleBar.ts index 815b8a1e4e0..dd4eba3df7f 100644 --- a/web/src/engine/osk/src/components/titleBar.ts +++ b/web/src/engine/osk/src/components/titleBar.ts @@ -1,6 +1,6 @@ import { EventEmitter } from 'eventemitter3'; -import { Keyboard } from '@keymanapp/keyboard-processor'; +import { Keyboard } from 'keyman/engine/keyboard'; import OSKViewComponent from './oskViewComponent.interface.js'; import { ParsedLengthStyle } from '../lengthStyle.js'; diff --git a/web/src/engine/osk/src/correctionLayout.ts b/web/src/engine/osk/src/correctionLayout.ts index c3c0ffa8865..ba5f902ff47 100644 --- a/web/src/engine/osk/src/correctionLayout.ts +++ b/web/src/engine/osk/src/correctionLayout.ts @@ -1,4 +1,4 @@ -import { ActiveKey, ActiveKeyBase, ActiveLayer, ActiveRow, Codes } from "@keymanapp/keyboard-processor"; +import { ActiveKey, ActiveKeyBase, ActiveLayer, ActiveRow, Codes } from "keyman/engine/keyboard"; /** * Defines correction-layout mappings for keys to be considered by diff --git a/web/src/engine/osk/src/corrections.ts b/web/src/engine/osk/src/corrections.ts index 39c5ae2ef37..808e1c6dce5 100644 --- a/web/src/engine/osk/src/corrections.ts +++ b/web/src/engine/osk/src/corrections.ts @@ -1,4 +1,4 @@ -import { ActiveKeyBase, KeyDistribution } from "@keymanapp/keyboard-processor"; +import { ActiveKeyBase, KeyDistribution } from "keyman/engine/keyboard"; import { CorrectionLayout } from "./correctionLayout.js"; /** diff --git a/web/src/engine/osk/src/index.ts b/web/src/engine/osk/src/index.ts index 388ea32750b..380377257db 100644 --- a/web/src/engine/osk/src/index.ts +++ b/web/src/engine/osk/src/index.ts @@ -1,4 +1,4 @@ -export { Codes, DeviceSpec, Keyboard, KeyboardProperties, SpacebarText } from '@keymanapp/keyboard-processor'; +export { Codes, DeviceSpec, Keyboard, KeyboardProperties, SpacebarText } from 'keyman/engine/keyboard'; export { default as OSKView } from './views/oskView.js'; export { default as FloatingOSKView, FloatingOSKViewConfiguration } from './views/floatingOskView.js'; diff --git a/web/src/engine/osk/src/input/gestures/browser/flick.ts b/web/src/engine/osk/src/input/gestures/browser/flick.ts index c83a85121ed..91d20718714 100644 --- a/web/src/engine/osk/src/input/gestures/browser/flick.ts +++ b/web/src/engine/osk/src/input/gestures/browser/flick.ts @@ -1,7 +1,7 @@ import { type KeyElement } from '../../../keyElement.js'; import VisualKeyboard from '../../../visualKeyboard.js'; -import { ActiveKey, ActiveKeyBase, ActiveSubKey, KeyDistribution, KeyEvent } from '@keymanapp/keyboard-processor'; +import { ActiveKey, ActiveKeyBase, ActiveSubKey, KeyDistribution, KeyEvent } from 'keyman/engine/keyboard'; import { ConfigChangeClosure, CumulativePathStats, GestureRecognizerConfiguration, GestureSequence, GestureSource, GestureSourceSubview, InputSample, RecognitionZoneSource } from '@keymanapp/gesture-recognizer'; import { GestureHandler } from '../gestureHandler.js'; import { distributionFromDistanceMaps } from '../../../corrections.js'; diff --git a/web/src/engine/osk/src/input/gestures/browser/modipress.ts b/web/src/engine/osk/src/input/gestures/browser/modipress.ts index f3670944a46..3ffd4c206c9 100644 --- a/web/src/engine/osk/src/input/gestures/browser/modipress.ts +++ b/web/src/engine/osk/src/input/gestures/browser/modipress.ts @@ -1,7 +1,7 @@ import { type KeyElement } from '../../../keyElement.js'; import VisualKeyboard from '../../../visualKeyboard.js'; -import { KeyDistribution, ActiveKeyBase } from '@keymanapp/keyboard-processor'; +import { KeyDistribution, ActiveKeyBase } from 'keyman/engine/keyboard'; import { GestureSequence } from '@keymanapp/gesture-recognizer'; import { GestureHandler } from '../gestureHandler.js'; diff --git a/web/src/engine/osk/src/input/gestures/browser/multitap.ts b/web/src/engine/osk/src/input/gestures/browser/multitap.ts index 23c4898ff0f..99e50810f9c 100644 --- a/web/src/engine/osk/src/input/gestures/browser/multitap.ts +++ b/web/src/engine/osk/src/input/gestures/browser/multitap.ts @@ -1,7 +1,7 @@ import { type KeyElement } from '../../../keyElement.js'; import VisualKeyboard from '../../../visualKeyboard.js'; -import { ActiveSubKey, ActiveKey, KeyDistribution, ActiveKeyBase } from '@keymanapp/keyboard-processor'; +import { ActiveSubKey, ActiveKey, KeyDistribution, ActiveKeyBase } from 'keyman/engine/keyboard'; import { GestureSequence, GestureStageReport } from '@keymanapp/gesture-recognizer'; import { GestureHandler } from '../gestureHandler.js'; import { distributionFromDistanceMaps } from '../../../corrections.js'; diff --git a/web/src/engine/osk/src/input/gestures/browser/oskSubKey.ts b/web/src/engine/osk/src/input/gestures/browser/oskSubKey.ts index 7640c3b20e7..abf3a9fb801 100644 --- a/web/src/engine/osk/src/input/gestures/browser/oskSubKey.ts +++ b/web/src/engine/osk/src/input/gestures/browser/oskSubKey.ts @@ -1,4 +1,4 @@ -import { ActiveSubKey } from '@keymanapp/keyboard-processor'; +import { ActiveSubKey } from 'keyman/engine/keyboard'; import OSKKey from '../../../keyboard-layout/oskKey.js'; import { KeyData, KeyElement, link } from '../../../keyElement.js'; import VisualKeyboard from '../../../visualKeyboard.js'; diff --git a/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts b/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts index e9388e96f2a..d33d3192116 100644 --- a/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts +++ b/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts @@ -3,7 +3,7 @@ import { type KeyElement } from '../../../keyElement.js'; import OSKBaseKey from '../../../keyboard-layout/oskBaseKey.js'; import VisualKeyboard from '../../../visualKeyboard.js'; -import { DeviceSpec, ActiveSubKey, KeyDistribution, ActiveKeyBase } from '@keymanapp/keyboard-processor'; +import { DeviceSpec, ActiveSubKey, KeyDistribution, ActiveKeyBase } from 'keyman/engine/keyboard'; import { ConfigChangeClosure, GestureRecognizerConfiguration, GestureSequence, PaddedZoneSource, RecognitionZoneSource } from '@keymanapp/gesture-recognizer'; import { GestureHandler } from '../gestureHandler.js'; import { CorrectionLayout, CorrectionLayoutEntry } from '../../../correctionLayout.js'; diff --git a/web/src/engine/osk/src/input/gestures/gestureHandler.ts b/web/src/engine/osk/src/input/gestures/gestureHandler.ts index 4c45c39e776..3c585de6465 100644 --- a/web/src/engine/osk/src/input/gestures/gestureHandler.ts +++ b/web/src/engine/osk/src/input/gestures/gestureHandler.ts @@ -1,4 +1,4 @@ -import { ActiveKeyBase, KeyDistribution } from "@keymanapp/keyboard-processor"; +import { ActiveKeyBase, KeyDistribution } from "keyman/engine/keyboard"; export interface GestureHandler { /** diff --git a/web/src/engine/osk/src/input/gestures/heldRepeater.ts b/web/src/engine/osk/src/input/gestures/heldRepeater.ts index 0f74677ddab..025d8989125 100644 --- a/web/src/engine/osk/src/input/gestures/heldRepeater.ts +++ b/web/src/engine/osk/src/input/gestures/heldRepeater.ts @@ -1,5 +1,5 @@ import { GestureSequence } from "@keymanapp/gesture-recognizer"; -import { KeyDistribution } from "@keymanapp/keyboard-processor"; +import { KeyDistribution } from "keyman/engine/keyboard"; import { KeyElement } from "../../keyElement.js"; import { GestureHandler } from './gestureHandler.js'; diff --git a/web/src/engine/osk/src/input/gestures/specsForLayout.ts b/web/src/engine/osk/src/input/gestures/specsForLayout.ts index 943d8e91b96..57489609979 100644 --- a/web/src/engine/osk/src/input/gestures/specsForLayout.ts +++ b/web/src/engine/osk/src/input/gestures/specsForLayout.ts @@ -12,7 +12,7 @@ import ButtonClasses = TouchLayout.TouchLayoutKeySp; import { ActiveLayout, deepCopy -} from '@keymanapp/keyboard-processor'; +} from 'keyman/engine/keyboard'; import { type KeyElement } from '../../keyElement.js'; diff --git a/web/src/engine/osk/src/keyElement.ts b/web/src/engine/osk/src/keyElement.ts index 01ae3a0c99d..c913bdfbff5 100644 --- a/web/src/engine/osk/src/keyElement.ts +++ b/web/src/engine/osk/src/keyElement.ts @@ -1,4 +1,4 @@ -import { ActiveSubKey } from '@keymanapp/keyboard-processor'; +import { ActiveSubKey } from 'keyman/engine/keyboard'; import OSKKey from "./keyboard-layout/oskKey.js"; export class KeyData { diff --git a/web/src/engine/osk/src/keyboard-layout/gesturePreviewHost.ts b/web/src/engine/osk/src/keyboard-layout/gesturePreviewHost.ts index 321de328b83..32a30c3f5d7 100644 --- a/web/src/engine/osk/src/keyboard-layout/gesturePreviewHost.ts +++ b/web/src/engine/osk/src/keyboard-layout/gesturePreviewHost.ts @@ -1,4 +1,4 @@ -import { ActiveKeyBase } from "@keymanapp/keyboard-processor"; +import { ActiveKeyBase } from "keyman/engine/keyboard"; import { EventEmitter } from "eventemitter3"; import { KeyElement } from "../keyElement.js"; diff --git a/web/src/engine/osk/src/keyboard-layout/oskBaseKey.ts b/web/src/engine/osk/src/keyboard-layout/oskBaseKey.ts index e48253df60d..3d70ed40100 100644 --- a/web/src/engine/osk/src/keyboard-layout/oskBaseKey.ts +++ b/web/src/engine/osk/src/keyboard-layout/oskBaseKey.ts @@ -1,4 +1,4 @@ -import { ActiveKey, Codes } from '@keymanapp/keyboard-processor'; +import { ActiveKey, Codes } from 'keyman/engine/keyboard'; import OSKKey, { KeyLayoutParams, renameSpecialKey } from './oskKey.js'; import { KeyData, KeyElement, link } from '../keyElement.js'; diff --git a/web/src/engine/osk/src/keyboard-layout/oskKey.ts b/web/src/engine/osk/src/keyboard-layout/oskKey.ts index 6404658ef67..2b9381afe30 100644 --- a/web/src/engine/osk/src/keyboard-layout/oskKey.ts +++ b/web/src/engine/osk/src/keyboard-layout/oskKey.ts @@ -1,4 +1,4 @@ -import { ActiveKey, ActiveSubKey, ButtonClass, ButtonClasses, DeviceSpec } from '@keymanapp/keyboard-processor'; +import { ActiveKey, ActiveSubKey, ButtonClass, ButtonClasses, DeviceSpec } from 'keyman/engine/keyboard'; // At present, we don't use @keymanapp/keyman. Just `keyman`. (Refer to /web/package.json.) import specialChars from '../specialCharacters.js'; diff --git a/web/src/engine/osk/src/keyboard-layout/oskLayer.ts b/web/src/engine/osk/src/keyboard-layout/oskLayer.ts index 61c43f22cf8..a08d2921a55 100644 --- a/web/src/engine/osk/src/keyboard-layout/oskLayer.ts +++ b/web/src/engine/osk/src/keyboard-layout/oskLayer.ts @@ -1,4 +1,4 @@ -import { ActiveLayer, ActiveLayout } from '@keymanapp/keyboard-processor'; +import { ActiveLayer, ActiveLayout } from 'keyman/engine/keyboard'; import OSKRow from './oskRow.js'; import OSKBaseKey from './oskBaseKey.js'; diff --git a/web/src/engine/osk/src/keyboard-layout/oskLayerGroup.ts b/web/src/engine/osk/src/keyboard-layout/oskLayerGroup.ts index 5f4a3f45a3b..4bf4bc01b49 100644 --- a/web/src/engine/osk/src/keyboard-layout/oskLayerGroup.ts +++ b/web/src/engine/osk/src/keyboard-layout/oskLayerGroup.ts @@ -1,4 +1,4 @@ -import { type DeviceSpec, Keyboard, ActiveLayout, ButtonClasses } from '@keymanapp/keyboard-processor'; +import { type DeviceSpec, Keyboard, ActiveLayout, ButtonClasses } from 'keyman/engine/keyboard'; import { InputSample } from '@keymanapp/gesture-recognizer'; diff --git a/web/src/engine/osk/src/keyboard-layout/oskRow.ts b/web/src/engine/osk/src/keyboard-layout/oskRow.ts index 8012e8438a1..91c6409cd77 100644 --- a/web/src/engine/osk/src/keyboard-layout/oskRow.ts +++ b/web/src/engine/osk/src/keyboard-layout/oskRow.ts @@ -1,4 +1,4 @@ -import { ActiveKey, ActiveLayer, ActiveRow } from '@keymanapp/keyboard-processor'; +import { ActiveKey, ActiveLayer, ActiveRow } from 'keyman/engine/keyboard'; import OSKBaseKey from './oskBaseKey.js'; import { ParsedLengthStyle } from '../lengthStyle.js'; diff --git a/web/src/engine/osk/src/views/anchoredOskView.ts b/web/src/engine/osk/src/views/anchoredOskView.ts index fe2670c0b90..25ab819e3cd 100644 --- a/web/src/engine/osk/src/views/anchoredOskView.ts +++ b/web/src/engine/osk/src/views/anchoredOskView.ts @@ -1,4 +1,4 @@ -import { DeviceSpec } from '@keymanapp/keyboard-processor'; +import { DeviceSpec } from 'keyman/engine/keyboard'; import { landscapeView } from 'keyman/engine/dom-utils'; import OSKView, { OSKPos, OSKRect } from './oskView.js'; diff --git a/web/src/engine/osk/src/views/floatingOskView.ts b/web/src/engine/osk/src/views/floatingOskView.ts index c296bd374bf..ba186fc99e2 100644 --- a/web/src/engine/osk/src/views/floatingOskView.ts +++ b/web/src/engine/osk/src/views/floatingOskView.ts @@ -1,4 +1,4 @@ -import { DeviceSpec, ManagedPromise, Version } from '@keymanapp/keyboard-processor'; +import { DeviceSpec, ManagedPromise, Version } from 'keyman/engine/keyboard'; import { getAbsoluteX, getAbsoluteY, landscapeView } from 'keyman/engine/dom-utils'; import { EmitterListenerSpy } from 'keyman/engine/events'; diff --git a/web/src/engine/osk/src/views/inlinedOskView.ts b/web/src/engine/osk/src/views/inlinedOskView.ts index 06f89c0a921..d4dc48fd664 100644 --- a/web/src/engine/osk/src/views/inlinedOskView.ts +++ b/web/src/engine/osk/src/views/inlinedOskView.ts @@ -1,4 +1,4 @@ -import { DeviceSpec } from '@keymanapp/keyboard-processor'; +import { DeviceSpec } from 'keyman/engine/keyboard'; import OSKView, { OSKPos, OSKRect } from './oskView.js'; import VisualKeyboard from '../visualKeyboard.js'; diff --git a/web/src/engine/osk/src/views/oskView.ts b/web/src/engine/osk/src/views/oskView.ts index afdc99f882a..c9dc3755d75 100644 --- a/web/src/engine/osk/src/views/oskView.ts +++ b/web/src/engine/osk/src/views/oskView.ts @@ -19,7 +19,7 @@ import { type MinimalCodesInterface, type MutableSystemStore, type SystemStoreMutationHandler -} from '@keymanapp/keyboard-processor'; +} from 'keyman/engine/keyboard'; import { createUnselectableElement, getAbsoluteX, getAbsoluteY, StylesheetManager } from 'keyman/engine/dom-utils'; import { EventListener, KeyEventHandler, KeyEventSourceInterface, LegacyEventEmitter } from 'keyman/engine/events'; diff --git a/web/src/engine/osk/src/visualKeyboard.ts b/web/src/engine/osk/src/visualKeyboard.ts index fac43d51250..796e5566cfb 100644 --- a/web/src/engine/osk/src/visualKeyboard.ts +++ b/web/src/engine/osk/src/visualKeyboard.ts @@ -15,7 +15,7 @@ import { timedPromise, ActiveKeyBase, isEmptyTransform -} from '@keymanapp/keyboard-processor'; +} from 'keyman/engine/keyboard'; import { buildCorrectiveLayout } from './correctionLayout.js'; import { distributionFromDistanceMaps, keyTouchDistances } from './corrections.js'; diff --git a/web/src/engine/package-cache/src/cloud/queryEngine.ts b/web/src/engine/package-cache/src/cloud/queryEngine.ts index eb989d2f00a..5f38c32aead 100644 --- a/web/src/engine/package-cache/src/cloud/queryEngine.ts +++ b/web/src/engine/package-cache/src/cloud/queryEngine.ts @@ -3,7 +3,7 @@ import { EventEmitter } from 'eventemitter3'; import { PathConfiguration } from 'keyman/engine/interfaces'; import { default as KeyboardStub, ErrorStub, KeyboardAPISpec, mergeAndResolveStubPromises } from '../keyboardStub.js'; -import { LanguageAPIPropertySpec, ManagedPromise, Version } from '@keymanapp/keyboard-processor'; +import { LanguageAPIPropertySpec, ManagedPromise, Version } from 'keyman/engine/keyboard'; import CloudRequesterInterface from './requesterInterface.js'; // For when the API call straight-up times out. diff --git a/web/src/engine/package-cache/src/cloud/requesterInterface.ts b/web/src/engine/package-cache/src/cloud/requesterInterface.ts index c0f8e6baf14..6c612d9cb20 100644 --- a/web/src/engine/package-cache/src/cloud/requesterInterface.ts +++ b/web/src/engine/package-cache/src/cloud/requesterInterface.ts @@ -1,4 +1,4 @@ -import { ManagedPromise } from '@keymanapp/keyboard-processor'; +import { ManagedPromise } from 'keyman/engine/keyboard'; export default interface CloudRequesterInterface { request(query: string): { diff --git a/web/src/engine/package-cache/src/domCloudRequester.ts b/web/src/engine/package-cache/src/domCloudRequester.ts index ee80b0f0638..fe671d101ff 100644 --- a/web/src/engine/package-cache/src/domCloudRequester.ts +++ b/web/src/engine/package-cache/src/domCloudRequester.ts @@ -1,4 +1,4 @@ -import { ManagedPromise } from '@keymanapp/keyboard-processor'; +import { ManagedPromise } from 'keyman/engine/keyboard'; import CloudRequesterInterface from './cloud/requesterInterface.js'; import { CLOUD_MALFORMED_OBJECT_ERR, CLOUD_TIMEOUT_ERR, CLOUD_STUB_REGISTRATION_ERR } from './cloud/queryEngine.js'; diff --git a/web/src/engine/package-cache/src/keyboardRequisitioner.ts b/web/src/engine/package-cache/src/keyboardRequisitioner.ts index 13cc7ecef83..fb2807de6ff 100644 --- a/web/src/engine/package-cache/src/keyboardRequisitioner.ts +++ b/web/src/engine/package-cache/src/keyboardRequisitioner.ts @@ -3,7 +3,7 @@ import { KeyboardLoaderBase as KeyboardLoader, LanguageAPIPropertySpec, RawKeyboardMetadata -} from "@keymanapp/keyboard-processor"; +} from "keyman/engine/keyboard"; import { PathConfiguration } from "keyman/engine/interfaces"; // TODO: is cleanup needed here, to use local paths instead? diff --git a/web/src/engine/package-cache/src/keyboardStub.ts b/web/src/engine/package-cache/src/keyboardStub.ts index 474d4cc9eff..a2b1d87d6fa 100644 --- a/web/src/engine/package-cache/src/keyboardStub.ts +++ b/web/src/engine/package-cache/src/keyboardStub.ts @@ -3,7 +3,7 @@ import { type KeyboardAPIPropertyMultilangSpec as APICompoundKeyboard, KeyboardProperties, type LanguageAPIPropertySpec, -} from '@keymanapp/keyboard-processor'; +} from 'keyman/engine/keyboard'; import { toPrefixedKeyboardId as prefixed } from './stubAndKeyboardCache.js'; diff --git a/web/src/engine/package-cache/src/nodeCloudRequester.ts b/web/src/engine/package-cache/src/nodeCloudRequester.ts index bd9ff851597..e8461ff20d7 100644 --- a/web/src/engine/package-cache/src/nodeCloudRequester.ts +++ b/web/src/engine/package-cache/src/nodeCloudRequester.ts @@ -1,4 +1,4 @@ -import { ManagedPromise } from '@keymanapp/keyboard-processor'; +import { ManagedPromise } from 'keyman/engine/keyboard'; import CloudRequesterInterface from './cloud/requesterInterface.js'; import { CLOUD_TIMEOUT_ERR, diff --git a/web/src/engine/package-cache/src/stubAndKeyboardCache.ts b/web/src/engine/package-cache/src/stubAndKeyboardCache.ts index 9fd70e74724..67d62446bee 100644 --- a/web/src/engine/package-cache/src/stubAndKeyboardCache.ts +++ b/web/src/engine/package-cache/src/stubAndKeyboardCache.ts @@ -1,4 +1,4 @@ -import { Keyboard, KeyboardLoaderBase as KeyboardLoader } from "@keymanapp/keyboard-processor"; +import { Keyboard, KeyboardLoaderBase as KeyboardLoader } from "keyman/engine/keyboard"; import { EventEmitter } from "eventemitter3"; import KeyboardStub from "./keyboardStub.js"; diff --git a/web/src/test/auto/dom/cases/browser/contextManager.spec.ts b/web/src/test/auto/dom/cases/browser/contextManager.spec.ts index f31cc453185..291c299b2b0 100644 --- a/web/src/test/auto/dom/cases/browser/contextManager.spec.ts +++ b/web/src/test/auto/dom/cases/browser/contextManager.spec.ts @@ -5,8 +5,8 @@ import { import { LegacyEventEmitter } from 'keyman/engine/events'; import { StubAndKeyboardCache, toPrefixedKeyboardId as prefixed } from 'keyman/engine/package-cache'; -import { KeyboardHarness, MinimalKeymanGlobal } from '@keymanapp/keyboard-processor'; -import { DOMKeyboardLoader } from '@keymanapp/keyboard-processor/dom-keyboard-loader'; +import { KeyboardHarness, MinimalKeymanGlobal } from 'keyman/engine/keyboard'; +import { DOMKeyboardLoader } from 'keyman/engine/keyboard/dom-keyboard-loader'; import { loadKeyboardsFromStubs } from '../../kbdLoader.js'; import { DeviceSpec, ManagedPromise, timedPromise } from '@keymanapp/web-utils'; diff --git a/web/src/test/auto/dom/cases/element-wrappers/element_interfaces.spec.ts b/web/src/test/auto/dom/cases/element-wrappers/element_interfaces.spec.ts index cee86cc35e3..813ce789110 100644 --- a/web/src/test/auto/dom/cases/element-wrappers/element_interfaces.spec.ts +++ b/web/src/test/auto/dom/cases/element-wrappers/element_interfaces.spec.ts @@ -1,6 +1,6 @@ import { assert } from 'chai'; -import { extendString, Mock } from '@keymanapp/keyboard-processor'; +import { extendString, Mock } from 'keyman/engine/keyboard'; import * as wrappers from 'keyman/engine/element-wrappers'; import { DynamicElements } from '../../test_utils.js'; @@ -1385,7 +1385,7 @@ describe('Element Input/Output Interfacing', function () { // Unique to the Mock type - element interface cloning tests. Is element state properly copied? // As those require a very different setup, they're in the target_mocks.js test case file instead. - // Basic text-retrieval unit tests are now done headlessly in @keymanapp/keyboard-processor. + // Basic text-retrieval unit tests are now done headlessly in keyman/engine/keyboard. describe('Text Mutation', function () { describe('deleteCharsBeforeCaret', function () { diff --git a/web/src/test/auto/dom/cases/element-wrappers/target_mocks.spec.ts b/web/src/test/auto/dom/cases/element-wrappers/target_mocks.spec.ts index e850efaa550..85116eaa8ac 100644 --- a/web/src/test/auto/dom/cases/element-wrappers/target_mocks.spec.ts +++ b/web/src/test/auto/dom/cases/element-wrappers/target_mocks.spec.ts @@ -1,6 +1,6 @@ import { assert } from 'chai'; -import { extendString, Mock } from '@keymanapp/keyboard-processor'; +import { extendString, Mock } from 'keyman/engine/keyboard'; import { Input } from 'keyman/engine/element-wrappers'; import { DEFAULT_BROWSER_TIMEOUT } from '@keymanapp/common-test-resources/test-timeouts.mjs'; diff --git a/web/src/test/auto/dom/cases/keyboard-processor/domKeyboardLoader.spec.ts b/web/src/test/auto/dom/cases/keyboard/domKeyboardLoader.spec.ts similarity index 95% rename from web/src/test/auto/dom/cases/keyboard-processor/domKeyboardLoader.spec.ts rename to web/src/test/auto/dom/cases/keyboard/domKeyboardLoader.spec.ts index 63414662fae..bcf4afcf650 100644 --- a/web/src/test/auto/dom/cases/keyboard-processor/domKeyboardLoader.spec.ts +++ b/web/src/test/auto/dom/cases/keyboard/domKeyboardLoader.spec.ts @@ -1,7 +1,7 @@ import { assert } from 'chai'; -import { DOMKeyboardLoader } from '@keymanapp/keyboard-processor/dom-keyboard-loader'; -import { extendString, KeyboardHarness, Keyboard, MinimalKeymanGlobal, Mock, DeviceSpec, KeyboardKeymanGlobal } from '@keymanapp/keyboard-processor'; +import { DOMKeyboardLoader } from 'keyman/engine/keyboard/dom-keyboard-loader'; +import { extendString, KeyboardHarness, Keyboard, MinimalKeymanGlobal, Mock, DeviceSpec, KeyboardKeymanGlobal } from 'keyman/engine/keyboard'; import { KeyboardInterface } from 'keyman/engine/js-processor'; declare let window: typeof globalThis; diff --git a/web/src/test/auto/dom/cases/packages/keyboardRequisitioner.spec.ts b/web/src/test/auto/dom/cases/packages/keyboardRequisitioner.spec.ts index ab585bc9e07..7ad8356a322 100644 --- a/web/src/test/auto/dom/cases/packages/keyboardRequisitioner.spec.ts +++ b/web/src/test/auto/dom/cases/packages/keyboardRequisitioner.spec.ts @@ -1,8 +1,8 @@ import { assert } from 'chai'; import sinon from 'sinon'; -import { KeyboardHarness, MinimalKeymanGlobal } from '@keymanapp/keyboard-processor'; -import { DOMKeyboardLoader } from '@keymanapp/keyboard-processor/dom-keyboard-loader'; +import { KeyboardHarness, MinimalKeymanGlobal } from 'keyman/engine/keyboard'; +import { DOMKeyboardLoader } from 'keyman/engine/keyboard/dom-keyboard-loader'; import { PathConfiguration } from 'keyman/engine/interfaces'; import { CloudQueryEngine, KeyboardRequisitioner, type KeyboardStub } from 'keyman/engine/package-cache'; import DOMCloudRequester from 'keyman/engine/package-cache/dom-requester'; diff --git a/web/src/test/auto/dom/kbdLoader.ts b/web/src/test/auto/dom/kbdLoader.ts index 2254011857f..8b5c081c758 100644 --- a/web/src/test/auto/dom/kbdLoader.ts +++ b/web/src/test/auto/dom/kbdLoader.ts @@ -1,12 +1,12 @@ import { DOMKeyboardLoader -} from '@keymanapp/keyboard-processor/dom-keyboard-loader'; +} from 'keyman/engine/keyboard/dom-keyboard-loader'; import { Keyboard, KeyboardProperties, MinimalKeymanGlobal -} from '@keymanapp/keyboard-processor'; +} from 'keyman/engine/keyboard'; import { KeyboardInterface } from 'keyman/engine/js-processor'; import { KeyboardStub } from 'keyman/engine/package-cache'; diff --git a/web/src/test/auto/headless/app/browser/hardware-event-processing.tests.ts b/web/src/test/auto/headless/app/browser/hardware-event-processing.tests.ts index 447b2b1806e..d00425362d1 100644 --- a/web/src/test/auto/headless/app/browser/hardware-event-processing.tests.ts +++ b/web/src/test/auto/headless/app/browser/hardware-event-processing.tests.ts @@ -4,14 +4,14 @@ import { preprocessKeyboardEvent } from 'keyman/app/browser'; import { processForMnemonicsAndLegacy } from 'keyman/engine/main'; import { PhysicalInputEventSpec } from '@keymanapp/recorder-core'; import { DeviceSpec } from '@keymanapp/web-utils'; -import { Codes, Keyboard, KeyEvent } from '@keymanapp/keyboard-processor'; +import { Codes, Keyboard, KeyEvent } from 'keyman/engine/keyboard'; const ModifierCodes = Codes.modifierCodes; const KeyCodes = Codes.keyCodes; const DUMMY_DEVICE = new DeviceSpec('chrome', 'desktop', 'windows', false); -// Compare and contrast the unit tests here with those for keyboard-processor unit testing +// Compare and contrast the unit tests here with those for keyboard unit testing // in the non-positional-rules set; the output objects here should have the same format // as the inputs for rules as used there. diff --git a/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js b/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js index 97ce24d0363..39ab4aea59d 100644 --- a/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js +++ b/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js @@ -4,7 +4,7 @@ import sinon from 'sinon'; import { LanguageProcessor, TranscriptionCache } from 'keyman/engine/main'; import { PredictionContext } from 'keyman/engine/interfaces'; import { Worker as LMWorker } from "@keymanapp/lexical-model-layer/node"; -import { DeviceSpec, Mock } from '@keymanapp/keyboard-processor'; +import { DeviceSpec, Mock } from 'keyman/engine/keyboard'; import { KeyboardProcessor } from 'keyman/engine/js-processor'; function compileDummyModel(suggestionSets) { diff --git a/web/src/test/auto/headless/engine/main/headless/inputProcessor.spec.js b/web/src/test/auto/headless/engine/main/headless/inputProcessor.spec.js index d1b728e6253..f3f6622f9a8 100644 --- a/web/src/test/auto/headless/engine/main/headless/inputProcessor.spec.js +++ b/web/src/test/auto/headless/engine/main/headless/inputProcessor.spec.js @@ -5,8 +5,8 @@ import { createRequire } from 'module'; const require = createRequire(import.meta.url); import { InputProcessor } from 'keyman/engine/main'; -import { KeyboardInterface, MinimalKeymanGlobal, Mock } from '@keymanapp/keyboard-processor'; -import { NodeKeyboardLoader } from '@keymanapp/keyboard-processor/node-keyboard-loader'; +import { KeyboardInterface, MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; +import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; import { KeyboardTest } from '@keymanapp/recorder-core'; import { Worker } from '@keymanapp/lexical-model-layer/node'; @@ -48,8 +48,8 @@ describe('InputProcessor', function() { assert.isUndefined(core.activeKeyboard); // No keyboard should be loaded yet. assert.isUndefined(core.activeModel); // Same for the model. - // These checks are lifted from the keyboard-processor init checks found in - // common/web/keyboard-processor/tests/cases/basic-init.js. + // These checks are lifted from the keyboard init checks found in + // common/web/keyboard/tests/cases/basic-init.js. assert.equal('us', core.keyboardProcessor.baseLayout, 'KeyboardProcessor has unexpected base layout') assert.isNotNull(global.KeymanWeb, 'KeymanWeb global was not automatically installed'); assert.equal('default', core.keyboardProcessor.layerId, 'Default layer is not set to "default"'); diff --git a/web/src/test/auto/headless/engine/main/headless/languageProcessor.spec.js b/web/src/test/auto/headless/engine/main/headless/languageProcessor.spec.js index a0eec4c5319..6f2f321edf1 100644 --- a/web/src/test/auto/headless/engine/main/headless/languageProcessor.spec.js +++ b/web/src/test/auto/headless/engine/main/headless/languageProcessor.spec.js @@ -2,7 +2,7 @@ import { assert } from 'chai'; import { LanguageProcessor, TranscriptionCache } from 'keyman/engine/main'; import { SourcemappedWorker as LMWorker } from "@keymanapp/lexical-model-layer/node"; -import { Mock } from '@keymanapp/keyboard-processor'; +import { Mock } from 'keyman/engine/keyboard'; /* * Unit tests for the Dummy prediction model. @@ -43,8 +43,8 @@ describe('LanguageProcessor', function() { it('has expected default values after initialization', function () { let languageProcessor = new LanguageProcessor(worker, new TranscriptionCache()); - // These checks are lifted from the keyboard-processor init checks found in - // common/web/keyboard-processor/tests/cases/basic-init.js. + // These checks are lifted from the keyboard init checks found in + // engine/keyboard/tests/cases/basic-init.js. assert.isDefined(languageProcessor.lmEngine); assert.isUndefined(languageProcessor.activeModel); assert.isFalse(languageProcessor.isActive); diff --git a/web/src/test/auto/headless/engine/osk/input/gestures/browser/subkeyPopup.tests.ts b/web/src/test/auto/headless/engine/osk/input/gestures/browser/subkeyPopup.tests.ts index b70c17d7dc1..72679897f37 100644 --- a/web/src/test/auto/headless/engine/osk/input/gestures/browser/subkeyPopup.tests.ts +++ b/web/src/test/auto/headless/engine/osk/input/gestures/browser/subkeyPopup.tests.ts @@ -4,7 +4,7 @@ import { JSDOM } from 'jsdom'; import sinon from 'sinon'; import { GesturePath, GestureSequence, GestureSource, GestureSourceSubview } from '@keymanapp/gesture-recognizer'; -import { ActiveSubKey, DeviceSpec } from '@keymanapp/keyboard-processor'; +import { ActiveSubKey, DeviceSpec } from 'keyman/engine/keyboard'; import { DEFAULT_GESTURE_PARAMS, KeyElement, VisualKeyboard } from 'keyman/engine/osk'; import { OSKBaseKey, OSKRow, SubkeyPopup, link } from 'keyman/engine/osk/internals'; diff --git a/web/src/test/auto/headless/engine/package-cache/keyboardRequisitioner.js b/web/src/test/auto/headless/engine/package-cache/keyboardRequisitioner.js index b2d64c05538..2ca0578790e 100644 --- a/web/src/test/auto/headless/engine/package-cache/keyboardRequisitioner.js +++ b/web/src/test/auto/headless/engine/package-cache/keyboardRequisitioner.js @@ -2,8 +2,8 @@ import { assert } from 'chai'; import sinon from 'sinon'; import fs from 'fs'; -import { KeyboardHarness, ManagedPromise, MinimalKeymanGlobal } from '@keymanapp/keyboard-processor'; -import { NodeKeyboardLoader } from '@keymanapp/keyboard-processor/node-keyboard-loader'; +import { KeyboardHarness, ManagedPromise, MinimalKeymanGlobal } from 'keyman/engine/keyboard'; +import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; import { KeyboardRequisitioner, toPrefixedKeyboardId as prefixed diff --git a/web/src/test/auto/headless/engine/package-cache/stubAndKeyboardCache.js b/web/src/test/auto/headless/engine/package-cache/stubAndKeyboardCache.js index 03f6fbf5c5a..f49bb1238f6 100644 --- a/web/src/test/auto/headless/engine/package-cache/stubAndKeyboardCache.js +++ b/web/src/test/auto/headless/engine/package-cache/stubAndKeyboardCache.js @@ -4,8 +4,8 @@ import fs from 'fs'; import { KeyboardStub, StubAndKeyboardCache } from 'keyman/engine/package-cache'; -import { NodeKeyboardLoader } from '@keymanapp/keyboard-processor/node-keyboard-loader'; -import { KeyboardHarness, MinimalKeymanGlobal } from '@keymanapp/keyboard-processor'; +import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; +import { KeyboardHarness, MinimalKeymanGlobal } from 'keyman/engine/keyboard'; import path from 'path'; diff --git a/web/src/test/manual/web/chirality/chirality.js b/web/src/test/manual/web/chirality/chirality.js index eaf349463c1..68740ffc308 100644 --- a/web/src/test/manual/web/chirality/chirality.js +++ b/web/src/test/manual/web/chirality/chirality.js @@ -10,10 +10,10 @@ */ function Keyboard_chirality() { - // Refer to $KEYMAN_ROOT/common/web/keyboard-processor/src/text/codes.ts, same method name. + // Refer to $KEYMAN_ROOT/web/src/engine/keyboard/src/text/codes.ts, same method name. // May be moved within common/web/types at some point in the future. var getModifierState = function(layerId) { - // Refer to C:\keymanapp\keyman\common\web\keyboard-processor\src\keyboards\keyboardHarness.ts, + // Refer to C:\keymanapp\keyman\web\src\engine\keyboard\src\keyboards\keyboardHarness.ts, // `MinimalKeyboardHarness`. let osk = keyman.osk; // Codes endpoint, as part of the standard keyboard harness. @@ -86,7 +86,7 @@ function Keyboard_chirality() { this.g0 = function (t, e) { var k = KeymanWeb, r = 0, m = 0; - // Refer to C:\keymanapp\keyman\common\web\keyboard-processor\src\keyboards\keyboardHarness.ts, + // Refer to C:\keymanapp\keyman\web\src\engine\keyboard\src\keyboards\keyboardHarness.ts, // `MinimalKeyboardHarness`. var Constants = keyman.osk; // Holds anchor points for relevant Codes properties. diff --git a/web/src/test/manual/web/osk/kbdLoader.mjs b/web/src/test/manual/web/osk/kbdLoader.mjs index a9db786c33d..edf2d3a6484 100644 --- a/web/src/test/manual/web/osk/kbdLoader.mjs +++ b/web/src/test/manual/web/osk/kbdLoader.mjs @@ -1,16 +1,16 @@ import { Keyboard, KeyboardProperties, Codes } from '../../../../../build/engine/osk/lib/index.mjs'; // // The following block would be sufficient to replace the `loadKeyboardFromPath` func below... -// // were it not for common/web/keyboard-processor being outside of the standard `localhost` config +// // were it not for web/src/engine/keyboard/ being outside of the standard `localhost` config // // used for manual Web testing. // import { // DOMKeyboardLoader -// } from '../../../../../../common/web/keyboard-processor/build/lib/dom-keyboard-loader.mjs'; +// } from '../../../keyboard/build/lib/dom-keyboard-loader.mjs'; // import { // KeyboardInterface, // MinimalKeymanGlobal -// } from '../../../../../../common/web/keyboard-processor/build/lib/index.mjs'; +// } from '../../../keyboard/build/lib/index.mjs'; // // This script may or may not be temporary; the KMW "KeyboardManager" class may be spun off in a manner // // that could replace this. diff --git a/web/src/tools/build.sh b/web/src/tools/build.sh index 24d455bc8fd..b7670418ab3 100755 --- a/web/src/tools/build.sh +++ b/web/src/tools/build.sh @@ -14,7 +14,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" builder_describe "Builds the Keyman Engine for Web's development & unit-testing tools" \ "@/common/web/keyman-version" \ - "@/common/web/keyboard-processor" \ + "@/web/src/engine/keyboard" \ "configure" \ "clean" \ "build" \ diff --git a/web/src/tools/testing/recorder-core/package.json b/web/src/tools/testing/recorder-core/package.json index 4812d8a7787..426595e567e 100644 --- a/web/src/tools/testing/recorder-core/package.json +++ b/web/src/tools/testing/recorder-core/package.json @@ -19,7 +19,6 @@ }, "homepage": "https://github.com/keymanapp/keyman#readme", "dependencies": { - "@keymanapp/keyboard-processor": "*", "@keymanapp/models-types": "*", "@keymanapp/keyman-version": "*", "@keymanapp/web-utils": "*" diff --git a/web/src/tools/testing/recorder-core/src/index.ts b/web/src/tools/testing/recorder-core/src/index.ts index 94c2c9dc4d8..caa0262f6b9 100644 --- a/web/src/tools/testing/recorder-core/src/index.ts +++ b/web/src/tools/testing/recorder-core/src/index.ts @@ -1,5 +1,5 @@ -import { type OutputTarget } from "@keymanapp/keyboard-processor"; -import { KeyDistribution, KeyEvent, Mock } from "@keymanapp/keyboard-processor"; +import { type OutputTarget } from "keyman/engine/keyboard"; +import { KeyDistribution, KeyEvent, Mock } from "keyman/engine/keyboard"; import Proctor from "./proctor.js"; diff --git a/web/src/tools/testing/recorder-core/src/nodeProctor.ts b/web/src/tools/testing/recorder-core/src/nodeProctor.ts index 852002d4b3a..e9a08530c8f 100644 --- a/web/src/tools/testing/recorder-core/src/nodeProctor.ts +++ b/web/src/tools/testing/recorder-core/src/nodeProctor.ts @@ -8,7 +8,7 @@ import { RecordedSyntheticKeystroke } from "./index.js"; -import { KeyEvent, KeyEventSpec, Mock, type OutputTarget, KeyboardHarness } from "@keymanapp/keyboard-processor"; +import { KeyEvent, KeyEventSpec, Mock, type OutputTarget, KeyboardHarness } from "keyman/engine/keyboard"; import { DeviceSpec } from "@keymanapp/web-utils"; import { KeyboardInterface, KeyboardProcessor } from 'keyman/engine/js-processor'; diff --git a/web/src/tools/testing/recorder-core/src/proctor.ts b/web/src/tools/testing/recorder-core/src/proctor.ts index 940fa4a76b1..0242b911a1c 100644 --- a/web/src/tools/testing/recorder-core/src/proctor.ts +++ b/web/src/tools/testing/recorder-core/src/proctor.ts @@ -1,5 +1,5 @@ import { type DeviceSpec } from "@keymanapp/web-utils"; -import { type OutputTarget } from "@keymanapp/keyboard-processor"; +import { type OutputTarget } from "keyman/engine/keyboard"; import type { KeyboardTest, TestSet, TestSequence } from "./index.js"; @@ -9,7 +9,7 @@ export type AssertCallback = (s1: any, s2: any, msg?: string) => void; * Facilitates running Recorder-generated tests on various platforms. * * Note that DOM-aware KeymanWeb will implement a Browser-based version, while - * keyboard-processor and input-processor will use a Node-based version instead. + * keyboard and input-processor will use a Node-based version instead. */ export default abstract class Proctor { device: DeviceSpec; diff --git a/web/src/tools/testing/recorder-core/tsconfig.json b/web/src/tools/testing/recorder-core/tsconfig.json index 38af26e1a42..920536eeee2 100644 --- a/web/src/tools/testing/recorder-core/tsconfig.json +++ b/web/src/tools/testing/recorder-core/tsconfig.json @@ -16,8 +16,8 @@ "references": [ { "path": "../../../../../common/web/keyman-version" }, { "path": "../../../../../common/web/utils/" }, - { "path": "../../../../../common/web/keyboard-processor/" }, { "path": "../../../../../common/web/lm-message-types" }, - { "path": "../../../engine/js-processor" } + { "path": "../../../engine/js-processor" }, + { "path": "../../../engine/keyboard" }, ], } diff --git a/web/src/tools/testing/recorder/browserProctor.ts b/web/src/tools/testing/recorder/browserProctor.ts index 40e7247423a..73e5a80ea7f 100644 --- a/web/src/tools/testing/recorder/browserProctor.ts +++ b/web/src/tools/testing/recorder/browserProctor.ts @@ -4,7 +4,7 @@ import { type DeviceSpec } from "@keymanapp/web-utils"; -import { type OutputTarget } from "@keymanapp/keyboard-processor"; +import { type OutputTarget } from "keyman/engine/keyboard"; import { type KeymanEngine } from 'keyman/app/browser'; diff --git a/web/src/tools/testing/recorder/build.sh b/web/src/tools/testing/recorder/build.sh index 28cc43a767d..91f27d09e57 100755 --- a/web/src/tools/testing/recorder/build.sh +++ b/web/src/tools/testing/recorder/build.sh @@ -16,7 +16,7 @@ SUBPROJECT_NAME=tools/testing/recorder builder_describe "Builds the Keyman Engine for Web's test-sequence recording tool" \ "@/common/web/keyman-version" \ - "@/common/web/keyboard-processor" \ + "@/web/src/engine/keyboard" \ "@../recorder-core" \ "clean" \ "configure" \ diff --git a/web/src/tools/testing/recorder/scribe.ts b/web/src/tools/testing/recorder/scribe.ts index 371afadeefe..c266f1a5ccf 100644 --- a/web/src/tools/testing/recorder/scribe.ts +++ b/web/src/tools/testing/recorder/scribe.ts @@ -1,7 +1,7 @@ import { EventEmitter } from "eventemitter3"; -import type { KeyEvent } from "@keymanapp/keyboard-processor"; +import type { KeyEvent } from "keyman/engine/keyboard"; import { Constraint, diff --git a/web/src/tools/testing/recorder/tsconfig.json b/web/src/tools/testing/recorder/tsconfig.json index 63cb543efa1..f5974b5738b 100644 --- a/web/src/tools/testing/recorder/tsconfig.json +++ b/web/src/tools/testing/recorder/tsconfig.json @@ -12,9 +12,9 @@ "references": [ { "path": "../../../../../common/web/keyman-version" }, { "path": "../../../../../common/web/utils" }, - { "path": "../../../../../common/web/keyboard-processor" }, { "path": "../../../../../common/web/lm-message-types" }, { "path": "../../../../../web/src/app/browser" }, { "path": "../recorder-core" }, + { "path": "../../../engine/keyboard" }, ] } From fe289e4133ab211b2bc14868fdf262e9f0dc3f8f Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 9 Aug 2024 07:13:38 +0700 Subject: [PATCH 11/65] feat(android): Add menu to customize longpress delay time --- .../kMAPro/src/main/AndroidManifest.xml | 5 + .../kmapro/AdjustLongpressDelayActivity.java | 150 ++++++++++++++++++ .../kmapro/KeymanSettingsFragment.java | 11 +- .../main/res/drawable/ic_action_timelapse.xml | 5 + .../preference_duration_icon_layout.xml | 5 + .../kMAPro/src/main/res/values/strings.xml | 3 + 6 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java create mode 100644 android/KMAPro/kMAPro/src/main/res/drawable/ic_action_timelapse.xml create mode 100644 android/KMAPro/kMAPro/src/main/res/layout/preference_duration_icon_layout.xml diff --git a/android/KMAPro/kMAPro/src/main/AndroidManifest.xml b/android/KMAPro/kMAPro/src/main/AndroidManifest.xml index 7196abdb229..3ba7eaf9fca 100644 --- a/android/KMAPro/kMAPro/src/main/AndroidManifest.xml +++ b/android/KMAPro/kMAPro/src/main/AndroidManifest.xml @@ -297,6 +297,11 @@ android:configChanges="orientation" android:label="@string/app_name" android:theme="@style/AppTheme.Base" /> + diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java new file mode 100644 index 00000000000..e18912abe9d --- /dev/null +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java @@ -0,0 +1,150 @@ +/** + * Copyright (C) SIL International. All rights reserved. + */ +package com.tavultesoft.kmapro; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.widget.Toolbar; +import androidx.core.content.ContextCompat; + +import com.keyman.engine.BaseActivity; +import com.keyman.engine.KMManager; + +/** + * Settings menu for adjusting the longpress delay time. The value for the current longpress delay time + * is saved in shared preferences. + */ +public class AdjustLongpressDelayActivity extends BaseActivity { + private static final String TAG = "AdjustLongpressDelay"; + public static final String adjustLongpressDelayKey = "AdjustLongpressDelay"; + + private static Button resetButton = null; + private static ImageView sampleKeyboard = null; + + // Keeps track of the adjusted keyboard height for saving + private static SharedPreferences.Editor editor = null; + private static int currentHeight = 0; + private static ViewGroup.LayoutParams layoutParams; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + final Context context = this; + + setContentView(R.layout.activity_adjust_keyboard_height); + + Toolbar toolbar = (Toolbar) findViewById(R.id.titlebar); + setSupportActionBar(toolbar); + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setTitle(null); + actionBar.setDisplayUseLogoEnabled(false); + actionBar.setDisplayShowHomeEnabled(false); + actionBar.setDisplayShowTitleEnabled(false); + actionBar.setDisplayShowCustomEnabled(true); + actionBar.setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(this, R.color.keyman_blue))); + } + + TextView adjustKeyboardHeightActivityTitle = (TextView) findViewById(R.id.bar_title); + adjustKeyboardHeightActivityTitle.setWidth((int) getResources().getDimension(R.dimen.package_label_width)); + + String titleStr = getString(R.string.adjust_keyboard_height); + adjustKeyboardHeightActivityTitle.setTextColor(ContextCompat.getColor(this, R.color.ms_white)); + adjustKeyboardHeightActivityTitle.setText(titleStr); + + SharedPreferences prefs = context.getSharedPreferences(context.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); + editor = prefs.edit(); + + sampleKeyboard = (ImageView) findViewById(R.id.sample_keyboard); + layoutParams = sampleKeyboard.getLayoutParams(); + currentHeight = KMManager.getKeyboardHeight(context); + refreshSampleKeyboard(context); + + resetButton = (Button) findViewById(R.id.reset_to_defaults); + resetButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + // Clear the keyboard height preferences to reset + editor.remove(KMManager.KMKey_KeyboardHeightPortrait); + editor.remove(KMManager.KMKey_KeyboardHeightLandscape); + editor.commit(); + + // Restore default height + currentHeight = KMManager.getKeyboardHeight(context); + refreshSampleKeyboard(context); + } + }); + + sampleKeyboard.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent event) { + int y = (int)event.getY(); + + switch(event.getAction()) { + case MotionEvent.ACTION_MOVE: + // Update currentHeight as the user drags (moves) + // Increasing the keyboard height is a negative y + currentHeight -= y; + + // Apply lower and upper bounds on currentHeight + int defaultHeight = (int) context.getResources().getDimension(R.dimen.keyboard_height); + currentHeight = Math.max(defaultHeight/2, currentHeight); + currentHeight = Math.min(defaultHeight*2, currentHeight); + + refreshSampleKeyboard(context); + break; + case MotionEvent.ACTION_UP: + // Save the currentHeight when the user releases + int orientation = KMManager.getOrientation(context); + String keyboardHeightKey = (orientation == Configuration.ORIENTATION_LANDSCAPE) ? + KMManager.KMKey_KeyboardHeightLandscape : KMManager.KMKey_KeyboardHeightPortrait; + editor.putInt(keyboardHeightKey, currentHeight); + editor.commit(); + break; + } + return true; + } + }); + } + + /** + * Refresh the layout for the sample keyboard + * @param context + */ + private void refreshSampleKeyboard(Context context) { + layoutParams.height = currentHeight; + sampleKeyboard.setLayoutParams(layoutParams); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + + layoutParams = sampleKeyboard.getLayoutParams(); + + // When the user rotates the device, restore currentHeight + currentHeight = KMManager.getKeyboardHeight(this); + refreshSampleKeyboard(this); + } + + @Override + public void onBackPressed() { + // Apply the adjusted height on exit + KMManager.applyKeyboardHeight(this, currentHeight); + + super.onBackPressed(); + } + +} \ No newline at end of file diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java index 72c54aa0d02..f825909bd2a 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java @@ -28,7 +28,7 @@ public class KeymanSettingsFragment extends PreferenceFragmentCompat { private static Context context; private Preference languagesPreference, installKeyboardOrDictionary, displayLanguagePreference, - adjustKeyboardHeight; + adjustKeyboardHeight, adjustLongpressDelay; private ListPreference spacebarTextPreference; private CheckBoxPreference setSystemKeyboardPreference; private CheckBoxPreference setDefaultKeyboardPreference; @@ -99,6 +99,7 @@ public boolean onPreferenceClick(Preference preference) { }); setDefaultKeyboardPreference.setOnPreferenceChangeListener(checkBlocker); + adjustKeyboardHeight = new Preference(context); adjustKeyboardHeight.setKey(AdjustKeyboardHeightActivity.adjustKeyboardHeightKey); adjustKeyboardHeight.setTitle(getString(R.string.adjust_keyboard_height)); @@ -106,6 +107,13 @@ public boolean onPreferenceClick(Preference preference) { Intent adjustKeyboardHeightIntent = new Intent(context, AdjustKeyboardHeightActivity.class); adjustKeyboardHeight.setIntent(adjustKeyboardHeightIntent); + adjustLongpressDelay = new Preference(context); + adjustLongpressDelay.setKey(AdjustLongpressDelayActivity.adjustLongpressDelayKey); + adjustLongpressDelay.setTitle(getString(R.string.adjust_longpress_delay)); + adjustLongpressDelay.setWidgetLayoutResource(R.layout.preference_duration_icon_layout); + Intent adjustLongpressDelayIntent = new Intent(context, AdjustLongpressDelayActivity.class); + adjustLongpressDelay.setIntent(adjustLongpressDelayIntent); + /* Spacebar Caption Preference */ spacebarTextPreference = new ListPreference(context); @@ -197,6 +205,7 @@ as part of the default onClick() used by SwitchPreference. screen.addPreference(setDefaultKeyboardPreference); screen.addPreference(adjustKeyboardHeight); + screen.addPreference(adjustLongpressDelay); screen.addPreference(spacebarTextPreference); screen.addPreference(hapticFeedbackPreference); diff --git a/android/KMAPro/kMAPro/src/main/res/drawable/ic_action_timelapse.xml b/android/KMAPro/kMAPro/src/main/res/drawable/ic_action_timelapse.xml new file mode 100644 index 00000000000..80dc29e33f9 --- /dev/null +++ b/android/KMAPro/kMAPro/src/main/res/drawable/ic_action_timelapse.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android/KMAPro/kMAPro/src/main/res/layout/preference_duration_icon_layout.xml b/android/KMAPro/kMAPro/src/main/res/layout/preference_duration_icon_layout.xml new file mode 100644 index 00000000000..c8fd3a48f98 --- /dev/null +++ b/android/KMAPro/kMAPro/src/main/res/layout/preference_duration_icon_layout.xml @@ -0,0 +1,5 @@ + + diff --git a/android/KMAPro/kMAPro/src/main/res/values/strings.xml b/android/KMAPro/kMAPro/src/main/res/values/strings.xml index 3cec4f2558c..9f3db9af116 100644 --- a/android/KMAPro/kMAPro/src/main/res/values/strings.xml +++ b/android/KMAPro/kMAPro/src/main/res/values/strings.xml @@ -113,6 +113,9 @@ Adjust keyboard height + + Adjust longpress delay + Spacebar caption From 24370848c56d3dfe231c5dd58d3aea40035c762d Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 9 Aug 2024 12:55:35 +0700 Subject: [PATCH 12/65] feat(android): Start menu for adjusting longpress delay --- .../kmapro/AdjustLongpressDelayActivity.java | 161 +++++++++--------- .../kmapro/KeymanSettingsFragment.java | 2 - .../activity_adjust_longpress_delay.xml | 61 +++++++ .../kMAPro/src/main/res/values/dimens.xml | 1 + .../kMAPro/src/main/res/values/strings.xml | 11 ++ .../java/com/keyman/engine/KMManager.java | 13 ++ 6 files changed, 166 insertions(+), 83 deletions(-) create mode 100644 android/KMAPro/kMAPro/src/main/res/layout/activity_adjust_longpress_delay.xml diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java index e18912abe9d..c7a8f59aadb 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java @@ -5,14 +5,10 @@ import android.content.Context; import android.content.SharedPreferences; -import android.content.res.Configuration; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; -import android.view.MotionEvent; import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.ImageView; +import android.widget.SeekBar; import android.widget.TextView; import androidx.appcompat.app.ActionBar; @@ -24,19 +20,36 @@ /** * Settings menu for adjusting the longpress delay time. The value for the current longpress delay time - * is saved in shared preferences. + * is saved in shared preferences as an integer (milliseconds). */ public class AdjustLongpressDelayActivity extends BaseActivity { private static final String TAG = "AdjustLongpressDelay"; public static final String adjustLongpressDelayKey = "AdjustLongpressDelay"; + private static SharedPreferences.Editor editor = null; - private static Button resetButton = null; - private static ImageView sampleKeyboard = null; + // Keeps track of the adjusted longpress delay time for saving. + // Internally use milliseconds, but GUI displays seconds + private static int currentDelayTime = 500; // ms + private static int minLongpressTime = 300; // ms + private static int maxLongpressTime = 1500; // ms + private static int delayTimeIncrement = 200; // ms - // Keeps track of the adjusted keyboard height for saving - private static SharedPreferences.Editor editor = null; - private static int currentHeight = 0; - private static ViewGroup.LayoutParams layoutParams; + /** + * Convert currentDelayTime to progress + * @return int + */ + private int delayTimeToProgress() { + return (currentDelayTime / delayTimeIncrement) - 1; + } + + /** + * Convert progress to currentDelayTime + * @param progress + * @return int (milliseconds) + */ + private int progressToDelayTime(int progress) { + return (progress + 1) * delayTimeIncrement + 100; + } @Override protected void onCreate(Bundle savedInstanceState) { @@ -44,107 +57,93 @@ protected void onCreate(Bundle savedInstanceState) { final Context context = this; - setContentView(R.layout.activity_adjust_keyboard_height); - + setContentView(R.layout.activity_adjust_longpress_delay); Toolbar toolbar = (Toolbar) findViewById(R.id.titlebar); setSupportActionBar(toolbar); ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setTitle(null); actionBar.setDisplayUseLogoEnabled(false); - actionBar.setDisplayShowHomeEnabled(false); + actionBar.setDisplayHomeAsUpEnabled(true); + actionBar.setDisplayShowHomeEnabled(true); actionBar.setDisplayShowTitleEnabled(false); actionBar.setDisplayShowCustomEnabled(true); actionBar.setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(this, R.color.keyman_blue))); } - TextView adjustKeyboardHeightActivityTitle = (TextView) findViewById(R.id.bar_title); - adjustKeyboardHeightActivityTitle.setWidth((int) getResources().getDimension(R.dimen.package_label_width)); + TextView adjustLongpressDelayActivityTitle = (TextView) findViewById(R.id.bar_title); - String titleStr = getString(R.string.adjust_keyboard_height); - adjustKeyboardHeightActivityTitle.setTextColor(ContextCompat.getColor(this, R.color.ms_white)); - adjustKeyboardHeightActivityTitle.setText(titleStr); + String titleStr = getString(R.string.adjust_longpress_delay); + adjustLongpressDelayActivityTitle.setTextColor(ContextCompat.getColor(this, R.color.ms_white)); + adjustLongpressDelayActivityTitle.setText(titleStr); SharedPreferences prefs = context.getSharedPreferences(context.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); editor = prefs.edit(); + currentDelayTime = KMManager.getLongpressDelay(this); - sampleKeyboard = (ImageView) findViewById(R.id.sample_keyboard); - layoutParams = sampleKeyboard.getLayoutParams(); - currentHeight = KMManager.getKeyboardHeight(context); - refreshSampleKeyboard(context); + TextView adjustLongpressDelayText = (TextView) findViewById(R.id.delayTimeText); + String longpressDelayText = String.format(getString(R.string.longpress_delay_time), (float)(currentDelayTime/1000.0)); + adjustLongpressDelayText.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); + adjustLongpressDelayText.setText(longpressDelayText); - resetButton = (Button) findViewById(R.id.reset_to_defaults); - resetButton.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - // Clear the keyboard height preferences to reset - editor.remove(KMManager.KMKey_KeyboardHeightPortrait); - editor.remove(KMManager.KMKey_KeyboardHeightLandscape); - editor.commit(); + final SeekBar seekBar = (SeekBar) findViewById(R.id.seekBar); + seekBar.setProgress(delayTimeToProgress()); + seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // Do nothing + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // Do nothing + } - // Restore default height - currentHeight = KMManager.getKeyboardHeight(context); - refreshSampleKeyboard(context); + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + currentDelayTime = progressToDelayTime(progress); + String longpressDelayText = String.format(getString(R.string.longpress_delay_time), (float)(currentDelayTime/1000.0)); + adjustLongpressDelayText.setText(longpressDelayText); + + editor.putInt(KMManager.KMKey_LongpressDelay, currentDelayTime); + editor.commit(); } }); - sampleKeyboard.setOnTouchListener(new View.OnTouchListener() { + findViewById(R.id.delayTimeDownButton).setOnClickListener(new View.OnClickListener() { @Override - public boolean onTouch(View view, MotionEvent event) { - int y = (int)event.getY(); - - switch(event.getAction()) { - case MotionEvent.ACTION_MOVE: - // Update currentHeight as the user drags (moves) - // Increasing the keyboard height is a negative y - currentHeight -= y; - - // Apply lower and upper bounds on currentHeight - int defaultHeight = (int) context.getResources().getDimension(R.dimen.keyboard_height); - currentHeight = Math.max(defaultHeight/2, currentHeight); - currentHeight = Math.min(defaultHeight*2, currentHeight); - - refreshSampleKeyboard(context); - break; - case MotionEvent.ACTION_UP: - // Save the currentHeight when the user releases - int orientation = KMManager.getOrientation(context); - String keyboardHeightKey = (orientation == Configuration.ORIENTATION_LANDSCAPE) ? - KMManager.KMKey_KeyboardHeightLandscape : KMManager.KMKey_KeyboardHeightPortrait; - editor.putInt(keyboardHeightKey, currentHeight); - editor.commit(); - break; + public void onClick(View v) { + if (currentDelayTime > minLongpressTime) { + currentDelayTime -= delayTimeIncrement; + seekBar.setProgress(delayTimeToProgress()); } - return true; } }); - } - /** - * Refresh the layout for the sample keyboard - * @param context - */ - private void refreshSampleKeyboard(Context context) { - layoutParams.height = currentHeight; - sampleKeyboard.setLayoutParams(layoutParams); + findViewById(R.id.delayTimeUpButton).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (currentDelayTime < maxLongpressTime) { + currentDelayTime += delayTimeIncrement; + seekBar.setProgress(delayTimeToProgress()); + } + } + }); } @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - - layoutParams = sampleKeyboard.getLayoutParams(); + public void onBackPressed() { + // Apply the adjusted longpress delay on exit + KMManager.setLongpressDelay(this, currentDelayTime); - // When the user rotates the device, restore currentHeight - currentHeight = KMManager.getKeyboardHeight(this); - refreshSampleKeyboard(this); + super.onBackPressed(); } @Override - public void onBackPressed() { - // Apply the adjusted height on exit - KMManager.applyKeyboardHeight(this, currentHeight); - - super.onBackPressed(); + public boolean onSupportNavigateUp() { + onBackPressed(); + return true; } -} \ No newline at end of file +} diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java index f825909bd2a..95bb7774b0b 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java @@ -196,8 +196,6 @@ as part of the default onClick() used by SwitchPreference. sendCrashReportPreference.setSummaryOff(getString(R.string.show_send_crash_report_off)); sendCrashReportPreference.setDefaultValue(true); - - screen.addPreference(languagesPreference); screen.addPreference(installKeyboardOrDictionary); screen.addPreference(displayLanguagePreference); diff --git a/android/KMAPro/kMAPro/src/main/res/layout/activity_adjust_longpress_delay.xml b/android/KMAPro/kMAPro/src/main/res/layout/activity_adjust_longpress_delay.xml new file mode 100644 index 00000000000..ed0bed54a9b --- /dev/null +++ b/android/KMAPro/kMAPro/src/main/res/layout/activity_adjust_longpress_delay.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + diff --git a/android/KMAPro/kMAPro/src/main/res/values/dimens.xml b/android/KMAPro/kMAPro/src/main/res/values/dimens.xml index cfcc2f4917f..60e89def04b 100644 --- a/android/KMAPro/kMAPro/src/main/res/values/dimens.xml +++ b/android/KMAPro/kMAPro/src/main/res/values/dimens.xml @@ -23,4 +23,5 @@ 32dp 16dp 0dp + 24sp diff --git a/android/KMAPro/kMAPro/src/main/res/values/strings.xml b/android/KMAPro/kMAPro/src/main/res/values/strings.xml index 9f3db9af116..a1f9e7240d7 100644 --- a/android/KMAPro/kMAPro/src/main/res/values/strings.xml +++ b/android/KMAPro/kMAPro/src/main/res/values/strings.xml @@ -201,6 +201,17 @@ Reset to Defaults + + Delay Time: %1$.1f seconds + + + Delay time longer + + + Delay time shorter + + + Longpress delay time slider Search or type URL diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java index aa1c43626a7..645cf5ee0f9 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java @@ -248,6 +248,8 @@ public String toString() { public static final String KMKey_KeyboardHeightPortrait = "keyboardHeightPortrait"; public static final String KMKey_KeyboardHeightLandscape = "keyboardHeightLandscape"; + public static final String KMKey_LongpressDelay = "longpressDelay"; + public static final String KMKey_CustomHelpLink = "CustomHelpLink"; public static final String KMKey_KMPLink = "kmp"; public static final String KMKey_UserKeyboardIndex = "UserKeyboardIndex"; @@ -2010,6 +2012,17 @@ public static int getOrientation(Context context) { return Configuration.ORIENTATION_UNDEFINED; } + public static int getLongpressDelay(Context context) { + int defaultDelay = 500; // default longpress delay in KeymanWeb (ms) + SharedPreferences prefs = context.getSharedPreferences(context.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); + + return prefs.getInt(KMManager.KMKey_LongpressDelay, defaultDelay); + } + + public static void setLongpressDelay(Context context, int longpressDelay) { + + } + public static int getBannerHeight(Context context) { int bannerHeight = 0; if (InAppKeyboard != null && InAppKeyboard.getBanner() != BannerType.BLANK) { From dedc18e15698249860ced0291a20eef2a9b9982c Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 13 Aug 2024 17:14:51 +0200 Subject: [PATCH 13/65] refactor(web): move some files around MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - move `systemStore.ts` → `js-processor` - move `keyEventSource.interface.ts` → `osk` - move `defaultRules.ts` → back to `keyboard-processor` - in `KeyboardProcessor` pass `ruleBehavior` as parameter to `forAny`, looks like that accidentally got omitted previously Addresses code review comments. --- common/web/keyboard-processor/src/index.ts | 4 +- .../src/keyboards/keyboard.ts | 74 +------------------ .../src/text}/defaultRules.ts | 35 ++++----- .../keyboard-processor/src/text/keyEvent.ts | 19 ++--- .../src/text/ruleBehavior.interface.ts | 12 --- .../app/browser/src/defaultBrowserRules.ts | 2 +- web/src/app/webview/src/keymanEngine.ts | 4 +- web/src/engine/events/src/index.ts | 1 - web/src/engine/js-processor/src/index.ts | 3 +- .../engine/js-processor/src/kbdInterface.ts | 73 +++++++++++++++++- .../js-processor/src/keyboardProcessor.ts | 8 +- .../engine/js-processor/src/ruleBehavior.ts | 3 +- .../engine/js-processor/src}/systemStores.ts | 4 +- web/src/engine/main/src/hardKeyboard.ts | 2 +- .../main/src/headless/inputProcessor.ts | 3 +- .../main/src/variableStoreCookieSerializer.ts | 2 +- web/src/engine/osk/src/index.ts | 1 + .../src/views}/keyEventSource.interface.ts | 5 +- web/src/engine/osk/src/views/oskView.ts | 8 +- web/src/engine/osk/src/visualKeyboard.ts | 2 +- 20 files changed, 125 insertions(+), 140 deletions(-) rename {web/src/engine/js-processor/src => common/web/keyboard-processor/src/text}/defaultRules.ts (88%) delete mode 100644 common/web/keyboard-processor/src/text/ruleBehavior.interface.ts rename {common/web/keyboard-processor/src/text => web/src/engine/js-processor/src}/systemStores.ts (96%) rename web/src/engine/{events/src => osk/src/views}/keyEventSource.interface.ts (63%) diff --git a/common/web/keyboard-processor/src/index.ts b/common/web/keyboard-processor/src/index.ts index c719d7ee8e8..d9d0b2137f0 100644 --- a/common/web/keyboard-processor/src/index.ts +++ b/common/web/keyboard-processor/src/index.ts @@ -27,14 +27,14 @@ export { default as StateKeyMap } from "./keyboards/stateKeyMap.js"; export { default as Codes } from "./text/codes.js"; export * from "./text/codes.js"; export * from "./text/deadkeys.js"; +export { default as DefaultRules } from "./text/defaultRules.js"; +export * from "./text/defaultRules.js"; export { default as KeyEvent } from "./text/keyEvent.js"; export * from "./text/keyEvent.js"; export { default as KeyMapping } from "./text/keyMapping.js"; export { default as OutputTarget } from "./text/outputTarget.js"; export * from "./text/outputTarget.js"; export * from "./text/stringDivergence.js"; -export * from "./text/systemStores.js"; -export * from "./text/ruleBehavior.interface.js"; export * from "@keymanapp/web-utils"; diff --git a/common/web/keyboard-processor/src/keyboards/keyboard.ts b/common/web/keyboard-processor/src/keyboards/keyboard.ts index 6ca5f790fdc..d791d6ea75e 100644 --- a/common/web/keyboard-processor/src/keyboards/keyboard.ts +++ b/common/web/keyboard-processor/src/keyboards/keyboard.ts @@ -6,82 +6,10 @@ import type OutputTarget from "../text/outputTarget.js"; import { ModifierKeyConstants, TouchLayout } from "@keymanapp/common-types"; type TouchLayoutSpec = TouchLayout.TouchLayoutPlatform & { isDefault?: boolean}; -import type { ComplexKeyboardStore, KeyboardStore } from "../text/systemStores.js"; - import { Version, DeviceSpec } from "@keymanapp/web-utils"; import StateKeyMap from "./stateKeyMap.js"; -export class RuleDeadkey { - /** Discriminant field - 'd' for Deadkey. - */ - t: 'd'; - - /** - * Value: the deadkey's ID. - */ - d: number; // For 'd'eadkey; also reflects the Deadkey class's 'd' property. -} - -export class StoreBeep { - /** Discriminant field - 'b' for `beep` - */ - ['t']: 'b'; -} - -export type RuleChar = string; - -export class ContextAny { - /** Discriminant field - 'a' for `any()`. - */ - ['t']: 'a'; - - /** - * Value: the store to search. - */ - ['a']: KeyboardStore; // For 'a'ny statement. - - /** - * If set to true, negates the 'any'. - */ - ['n']: boolean | 0 | 1; -} - -export class RuleIndex { - /** Discriminant field - 'i' for `index()`. - */ - ['t']: 'i'; - - /** - * Value: the Store from which to output - */ - ['i']: KeyboardStore; - - /** - * Offset: the offset in context for the corresponding `any()`. - */ - ['o']: number; -} - -export class ContextEx { - /** Discriminant field - 'c' for `context()`. - */ - ['t']: 'c'; - - /** - * Value: The offset into the current rule's context to be matched. - */ - ['c']: number; // For 'c'ontext statement. -} - -export class ContextNul { - /** Discriminant field - 'n' for `nul` - */ - ['t']: 'n'; -} - - - -export type StoreNonCharEntry = RuleDeadkey | StoreBeep; +type ComplexKeyboardStore = ( string | { t: 'd', d: number } | { ['t']: 'b' })[]; /** * Stores preprocessed properties of a keyboard for quick retrieval later. diff --git a/web/src/engine/js-processor/src/defaultRules.ts b/common/web/keyboard-processor/src/text/defaultRules.ts similarity index 88% rename from web/src/engine/js-processor/src/defaultRules.ts rename to common/web/keyboard-processor/src/text/defaultRules.ts index 3d56a2dad8c..94acb02688e 100644 --- a/web/src/engine/js-processor/src/defaultRules.ts +++ b/common/web/keyboard-processor/src/text/defaultRules.ts @@ -5,23 +5,24 @@ */ import { ModifierKeyConstants } from '@keymanapp/common-types'; -import { Codes, type KeyEvent, type OutputTarget, setDefaultRules } from "@keymanapp/keyboard-processor"; -import RuleBehavior from "./ruleBehavior.js"; +import Codes from './codes.js'; +import type KeyEvent from './keyEvent.js'; +import type OutputTarget from './outputTarget.js'; export enum EmulationKeystrokes { Enter = '\n', Backspace = '\b' } +export class LogMessages { + errorLog?: string; + warningLog?: string; +} /** * Defines a collection of static library functions that define KeymanWeb's default (implied) keyboard rule behaviors. */ export default class DefaultRules { - public constructor() { - setDefaultRules(this); - } - codeForEvent(Lkc: KeyEvent) { return Codes.keyCodes[Lkc.kName] || Lkc.Lcode;; } @@ -30,7 +31,7 @@ export default class DefaultRules { * Serves as a default keycode lookup table. This may be referenced safely by mnemonic handling without fear of side-effects. * Also used by Processor.defaultRuleBehavior to generate output after filtering for special cases. */ - public forAny(Lkc: KeyEvent, isMnemonic: boolean, ruleBehavior?: RuleBehavior): string { + public forAny(Lkc: KeyEvent, isMnemonic: boolean, logMessages?: LogMessages): string { var char = ''; // A pretty simple table of lookups, corresponding VERY closely to the original defaultKeyOutput. @@ -38,9 +39,9 @@ export default class DefaultRules { return char; } else if(!isMnemonic && ((char = this.forNumpadKeys(Lkc)) != null)) { return char; - } else if((char = this.forUnicodeKeynames(Lkc, ruleBehavior)) != null) { + } else if((char = this.forUnicodeKeynames(Lkc, logMessages)) != null) { return char; - } else if((char = this.forBaseKeys(Lkc, ruleBehavior)) != null) { + } else if((char = this.forBaseKeys(Lkc, logMessages)) != null) { return char; } else { // // For headless and embeddded, we may well allow '\t'. It's DOM mode that has other uses. @@ -147,7 +148,7 @@ export default class DefaultRules { // Test for fall back to U_xxxxxx key id // For this first test, we ignore the keyCode and use the keyName - public forUnicodeKeynames(Lkc: KeyEvent, ruleBehavior?: RuleBehavior) { + public forUnicodeKeynames(Lkc: KeyEvent, logMessages?: LogMessages) { const keyName = Lkc.kName; // Test for fall back to U_xxxxxx key id @@ -164,8 +165,8 @@ export default class DefaultRules { // Code points [U_0000 - U_001F] and [U_0080 - U_009F] refer to Unicode C0 and C1 control codes. // Check the codePoint number and do not allow output of these codes via U_xxxxxx shortcuts. // Also handles invalid identifiers (e.g. `U_ghij`) for which parseInt returns NaN - if(ruleBehavior) { - ruleBehavior.errorLog = ("Suppressing Unicode control code in " + keyName); + if(logMessages) { + logMessages.errorLog = ("Suppressing Unicode control code in " + keyName); } // We'll attempt to add valid chars continue; @@ -180,7 +181,7 @@ export default class DefaultRules { // 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, ruleBehavior?: RuleBehavior) { + public forBaseKeys(Lkc: KeyEvent, logMessages?: LogMessages) { let n = Lkc.Lcode; let keyShiftState = Lkc.Lmodifiers; @@ -189,8 +190,8 @@ export default class DefaultRules { if (keyShiftState == ModifierKeyConstants.K_SHIFTFLAG) { keyShiftState = 1; } else if(keyShiftState != 0) { - if(ruleBehavior) { - ruleBehavior.warningLog = "KMW only defines default key output for the 'default' and 'shift' layers!"; + if(logMessages) { + logMessages.warningLog = "KMW only defines default key output for the 'default' and 'shift' layers!"; } return null; } @@ -211,8 +212,8 @@ export default class DefaultRules { return keyShiftState ? '|' : '\\'; } } catch (e) { - if(ruleBehavior) { - ruleBehavior.errorLog = "Error detected with default mapping for key: code = " + n + ", shift state = " + (keyShiftState == 1 ? 'shift' : 'default'); + if(logMessages) { + logMessages.errorLog = "Error detected with default mapping for key: code = " + n + ", shift state = " + (keyShiftState == 1 ? 'shift' : 'default'); } } diff --git a/common/web/keyboard-processor/src/text/keyEvent.ts b/common/web/keyboard-processor/src/text/keyEvent.ts index 2d0ee493229..7d6483d0e9f 100644 --- a/common/web/keyboard-processor/src/text/keyEvent.ts +++ b/common/web/keyboard-processor/src/text/keyEvent.ts @@ -10,22 +10,19 @@ import type Keyboard from "../keyboards/keyboard.js"; import { type DeviceSpec } from "@keymanapp/web-utils"; import Codes from './codes.js'; +import DefaultRules from "./defaultRules.js"; import { ActiveKeyBase } from "../index.js"; -export interface DefaultRulesInterface { - forAny(Lkc: KeyEvent, isMnemonic: boolean): string; -} - -let defaultRules: DefaultRulesInterface; - -export function setDefaultRules(rules: DefaultRulesInterface) { - defaultRules = rules; -} - // Represents a probability distribution over a keyboard's keys. // Defined here to avoid compilation issues. export type KeyDistribution = { keySpec: ActiveKeyBase, p: number }[]; +/** + * A simple instance of the standard 'default rules' for keystroke processing from the + * DefaultRules base class. + */ +const BASE_DEFAULT_RULES = new DefaultRules(); + export interface KeyEventSpec { Lcode: number; @@ -159,7 +156,7 @@ export default class KeyEvent implements KeyEventSpec { // the actual keyname instead. mappingEvent.kName = 'K_xxxx'; mappingEvent.Lmodifiers = (shifted ? 0x10 : 0); // mnemonic lookups only exist for default & shift layers. - var mappedChar: string = defaultRules.forAny(mappingEvent, true); + var mappedChar: string = BASE_DEFAULT_RULES.forAny(mappingEvent, true); /* First, save a backup of the original code. This one won't needlessly trigger keyboard * rules, but allows us to replicate/emulate commands after rule processing if needed. diff --git a/common/web/keyboard-processor/src/text/ruleBehavior.interface.ts b/common/web/keyboard-processor/src/text/ruleBehavior.interface.ts deleted file mode 100644 index 29f81bcc8c1..00000000000 --- a/common/web/keyboard-processor/src/text/ruleBehavior.interface.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { type Transcription } from './outputTarget.js'; - -/** - * Represents the commands and state changes that result from a matched keyboard rule. - */ -export interface RuleBehaviorInterface { - /** - * The before-and-after Transform from matching a keyboard rule. May be `null` - * if no keyboard rules were matched for the keystroke. - */ - transcription: Transcription; -} diff --git a/web/src/app/browser/src/defaultBrowserRules.ts b/web/src/app/browser/src/defaultBrowserRules.ts index fc084ec3f49..1ac48016892 100644 --- a/web/src/app/browser/src/defaultBrowserRules.ts +++ b/web/src/app/browser/src/defaultBrowserRules.ts @@ -1,10 +1,10 @@ import { ModifierKeyConstants } from '@keymanapp/common-types'; import { Codes, + DefaultRules, type KeyEvent, type OutputTarget } from '@keymanapp/keyboard-processor'; -import { DefaultRules } from 'keyman/engine/js-processor'; import ContextManager from './contextManager.js'; diff --git a/web/src/app/webview/src/keymanEngine.ts b/web/src/app/webview/src/keymanEngine.ts index 2f073505484..dfae058a650 100644 --- a/web/src/app/webview/src/keymanEngine.ts +++ b/web/src/app/webview/src/keymanEngine.ts @@ -1,5 +1,5 @@ -import { DeviceSpec } from '@keymanapp/keyboard-processor' -import { DefaultRules, RuleBehavior } from 'keyman/engine/js-processor'; +import { DeviceSpec, DefaultRules } from '@keymanapp/keyboard-processor' +import { RuleBehavior } from 'keyman/engine/js-processor'; import { KeymanEngine as KeymanEngineBase, KeyboardInterface } from 'keyman/engine/main'; import { AnchoredOSKView, ViewConfiguration, StaticActivator } from 'keyman/engine/osk'; import { getAbsoluteX, getAbsoluteY } from 'keyman/engine/dom-utils'; diff --git a/web/src/engine/events/src/index.ts b/web/src/engine/events/src/index.ts index 2d95307bc9f..ee5674b66c8 100644 --- a/web/src/engine/events/src/index.ts +++ b/web/src/engine/events/src/index.ts @@ -1,4 +1,3 @@ export { DomEventTracker } from './domEventTracker.js'; export { EmitterListenerSpy } from './emitterListenerSpy.js'; -export * from './keyEventSource.interface.js'; export * from './legacyEventEmitter.js'; \ No newline at end of file diff --git a/web/src/engine/js-processor/src/index.ts b/web/src/engine/js-processor/src/index.ts index 1c51de80d94..f87a044bd73 100644 --- a/web/src/engine/js-processor/src/index.ts +++ b/web/src/engine/js-processor/src/index.ts @@ -1,7 +1,6 @@ -export { default as DefaultRules } from "./defaultRules.js"; -export * from "./defaultRules.js"; export { default as KeyboardProcessor } from "./keyboardProcessor.js"; export * from "./keyboardProcessor.js"; export { default as RuleBehavior } from "./ruleBehavior.js"; export * from './kbdInterface.js'; export { default as KeyboardInterface } from "./kbdInterface.js"; +export * from "./systemStores.js"; diff --git a/web/src/engine/js-processor/src/kbdInterface.ts b/web/src/engine/js-processor/src/kbdInterface.ts index 2b34eadce9d..6272637d049 100644 --- a/web/src/engine/js-processor/src/kbdInterface.ts +++ b/web/src/engine/js-processor/src/kbdInterface.ts @@ -7,8 +7,9 @@ import { type DeviceSpec } from "@keymanapp/web-utils"; import { ModifierKeyConstants } from '@keymanapp/common-types'; -import { Codes, type KeyEvent, type Deadkey, ComplexKeyboardStore, type KeyboardStore, KeyboardStoreElement, KeyMapping, SystemStoreIDs, SystemStore, MutableSystemStore, PlatformSystemStore, type OutputTarget, Mock, Keyboard, VariableStore, VariableStoreDictionary, VariableStoreSerializer, KeyboardHarness, KeyboardKeymanGlobal, RuleDeadkey, ContextAny, RuleIndex, ContextEx, ContextNul, RuleChar } from "@keymanapp/keyboard-processor"; +import { Codes, type KeyEvent, type Deadkey, KeyMapping, type OutputTarget, Mock, Keyboard, KeyboardHarness, KeyboardKeymanGlobal, VariableStoreDictionary } from "@keymanapp/keyboard-processor"; import RuleBehavior from "./ruleBehavior.js"; +import { ComplexKeyboardStore, type KeyboardStore, KeyboardStoreElement, SystemStoreIDs, SystemStore, MutableSystemStore, PlatformSystemStore, VariableStore, VariableStoreSerializer } from "./systemStores.js"; //#endregion @@ -20,9 +21,79 @@ export class KeyInformation { modifiers: number; } +type RuleChar = string; + +class RuleDeadkey { + /** Discriminant field - 'd' for Deadkey. + */ + t: 'd'; + + /** + * Value: the deadkey's ID. + */ + d: number; // For 'd'eadkey; also reflects the Deadkey class's 'd' property. +} + +class ContextAny { + /** Discriminant field - 'a' for `any()`. + */ + ['t']: 'a'; + + /** + * Value: the store to search. + */ + ['a']: KeyboardStore; // For 'a'ny statement. + + /** + * If set to true, negates the 'any'. + */ + ['n']: boolean | 0 | 1; +} + +class RuleIndex { + /** Discriminant field - 'i' for `index()`. + */ + ['t']: 'i'; + + /** + * Value: the Store from which to output + */ + ['i']: KeyboardStore; + + /** + * Offset: the offset in context for the corresponding `any()`. + */ + ['o']: number; +} + +class ContextEx { + /** Discriminant field - 'c' for `context()`. + */ + ['t']: 'c'; + + /** + * Value: The offset into the current rule's context to be matched. + */ + ['c']: number; // For 'c'ontext statement. +} + +class ContextNul { + /** Discriminant field - 'n' for `nul` + */ + ['t']: 'n'; +} + +class StoreBeep { + /** Discriminant field - 'b' for `beep` + */ + ['t']: 'b'; +} + type ContextNonCharEntry = RuleDeadkey | ContextAny | RuleIndex | ContextEx | ContextNul; type ContextEntry = RuleChar | ContextNonCharEntry; +export type StoreNonCharEntry = RuleDeadkey | StoreBeep; + /** * Cache of context storing and retrieving return values from KC * Must be reset prior to each keystroke and after any text changes diff --git a/web/src/engine/js-processor/src/keyboardProcessor.ts b/web/src/engine/js-processor/src/keyboardProcessor.ts index 1a6d216dced..12efa4e9516 100644 --- a/web/src/engine/js-processor/src/keyboardProcessor.ts +++ b/web/src/engine/js-processor/src/keyboardProcessor.ts @@ -9,13 +9,13 @@ import { EventEmitter } from 'eventemitter3'; import { ModifierKeyConstants } from '@keymanapp/common-types'; import { - Codes, type Keyboard, MinimalKeymanGlobal, KeyEvent, Layouts, type MutableSystemStore, - type OutputTarget, Mock, SystemStoreIDs, + Codes, type Keyboard, MinimalKeymanGlobal, KeyEvent, Layouts, + type OutputTarget, Mock, DefaultRules, EmulationKeystrokes } from "@keymanapp/keyboard-processor"; -import DefaultRules, { EmulationKeystrokes } from "./defaultRules.js"; import RuleBehavior from "./ruleBehavior.js"; import KeyboardInterface from './kbdInterface.js'; import { DeviceSpec, globalObject } from "@keymanapp/web-utils"; +import { type MutableSystemStore, SystemStoreIDs } from "./systemStores.js"; // #endregion @@ -167,7 +167,7 @@ export default class KeyboardProcessor extends EventEmitter { let isMnemonic = this.activeKeyboard && this.activeKeyboard.isMnemonic; if(!matched) { - if((char = this.defaultRules.forAny(Lkc, isMnemonic)) != null) { + if((char = this.defaultRules.forAny(Lkc, isMnemonic, ruleBehavior)) != null) { special = this.defaultRules.forSpecialEmulation(Lkc) if(special == EmulationKeystrokes.Backspace) { // A browser's default backspace may fail to delete both parts of an SMP character. diff --git a/web/src/engine/js-processor/src/ruleBehavior.ts b/web/src/engine/js-processor/src/ruleBehavior.ts index aced7065d2d..08881eabcc0 100644 --- a/web/src/engine/js-processor/src/ruleBehavior.ts +++ b/web/src/engine/js-processor/src/ruleBehavior.ts @@ -1,7 +1,8 @@ /// import KeyboardProcessor from "./keyboardProcessor.js"; -import { OutputTarget, Mock, type Transcription, VariableStoreDictionary, type VariableStore } from "@keymanapp/keyboard-processor"; +import { OutputTarget, Mock, type Transcription, VariableStoreDictionary } from "@keymanapp/keyboard-processor"; +import { type VariableStore } from "./systemStores.js"; /** * Represents the commands and state changes that result from a matched keyboard rule. diff --git a/common/web/keyboard-processor/src/text/systemStores.ts b/web/src/engine/js-processor/src/systemStores.ts similarity index 96% rename from common/web/keyboard-processor/src/text/systemStores.ts rename to web/src/engine/js-processor/src/systemStores.ts index a2f7abff344..9d02dbddbc4 100644 --- a/common/web/keyboard-processor/src/text/systemStores.ts +++ b/web/src/engine/js-processor/src/systemStores.ts @@ -1,5 +1,5 @@ -import { type KeyboardHarness } from "../keyboards/keyboardHarness.js"; -import { StoreNonCharEntry } from '../keyboards/keyboard.js'; +import { type KeyboardHarness } from '@keymanapp/keyboard-processor'; +import { StoreNonCharEntry } from './kbdInterface.js'; export enum SystemStoreIDs { TSS_LAYER = 33, diff --git a/web/src/engine/main/src/hardKeyboard.ts b/web/src/engine/main/src/hardKeyboard.ts index 7dc9b5e3572..491073f7294 100644 --- a/web/src/engine/main/src/hardKeyboard.ts +++ b/web/src/engine/main/src/hardKeyboard.ts @@ -1,7 +1,7 @@ import { EventEmitter } from "eventemitter3"; import { Keyboard, KeyMapping, KeyEvent, Codes } from "@keymanapp/keyboard-processor"; import { type RuleBehavior } from 'keyman/engine/js-processor'; -import { KeyEventSourceInterface } from 'keyman/engine/events'; +import { KeyEventSourceInterface } from 'keyman/engine/osk'; import { ModifierKeyConstants } from '@keymanapp/common-types'; interface EventMap { diff --git a/web/src/engine/main/src/headless/inputProcessor.ts b/web/src/engine/main/src/headless/inputProcessor.ts index a96170457e0..99a31db609b 100644 --- a/web/src/engine/main/src/headless/inputProcessor.ts +++ b/web/src/engine/main/src/headless/inputProcessor.ts @@ -15,9 +15,8 @@ import { type KeyEvent, Mock, type OutputTarget, - SystemStoreIDs, } from "@keymanapp/keyboard-processor"; -import { KeyboardInterface, KeyboardProcessor, RuleBehavior, type ProcessorInitOptions } from 'keyman/engine/js-processor'; +import { KeyboardInterface, KeyboardProcessor, RuleBehavior, type ProcessorInitOptions, SystemStoreIDs } from 'keyman/engine/js-processor'; import { TranscriptionCache } from "./transcriptionCache.js"; diff --git a/web/src/engine/main/src/variableStoreCookieSerializer.ts b/web/src/engine/main/src/variableStoreCookieSerializer.ts index 35b51150c0e..62c250329aa 100644 --- a/web/src/engine/main/src/variableStoreCookieSerializer.ts +++ b/web/src/engine/main/src/variableStoreCookieSerializer.ts @@ -1,4 +1,4 @@ -import { VariableStore, VariableStoreSerializer } from "@keymanapp/keyboard-processor"; +import { VariableStore, VariableStoreSerializer } from 'keyman/engine/js-processor'; import { CookieSerializer } from "keyman/engine/dom-utils"; // While there's little reason we couldn't store all of a keyboard's store values within diff --git a/web/src/engine/osk/src/index.ts b/web/src/engine/osk/src/index.ts index 388ea32750b..f2a543e175c 100644 --- a/web/src/engine/osk/src/index.ts +++ b/web/src/engine/osk/src/index.ts @@ -4,6 +4,7 @@ export { default as OSKView } from './views/oskView.js'; export { default as FloatingOSKView, FloatingOSKViewConfiguration } from './views/floatingOskView.js'; export { default as AnchoredOSKView } from './views/anchoredOskView.js'; export { default as InlinedOSKView } from './views/inlinedOskView.js'; +export { type KeyEventResultCallback, type KeyEventHandler, KeyEventSourceInterface } from './views/keyEventSource.interface.js'; export { BannerController } from './banner/bannerController.js'; // Is referenced by at least one desktop UI module. export { FloatingOSKCookie as FloatingOSKViewCookie } from './views/floatingOskCookie.js'; diff --git a/web/src/engine/events/src/keyEventSource.interface.ts b/web/src/engine/osk/src/views/keyEventSource.interface.ts similarity index 63% rename from web/src/engine/events/src/keyEventSource.interface.ts rename to web/src/engine/osk/src/views/keyEventSource.interface.ts index 22621d2de01..36a065bd32c 100644 --- a/web/src/engine/events/src/keyEventSource.interface.ts +++ b/web/src/engine/osk/src/views/keyEventSource.interface.ts @@ -1,7 +1,8 @@ import { EventEmitter } from "eventemitter3"; -import { type KeyEvent, type RuleBehaviorInterface } from "@keymanapp/keyboard-processor"; +import { type KeyEvent } from "@keymanapp/keyboard-processor"; +import { type RuleBehavior } from 'keyman/engine/js-processor'; -export type KeyEventResultCallback = (result: RuleBehaviorInterface, error?: Error) => void; +export type KeyEventResultCallback = (result: RuleBehavior, error?: Error) => void; export type KeyEventHandler = (event: KeyEvent, callback?: KeyEventResultCallback) => void; interface EventMap { diff --git a/web/src/engine/osk/src/views/oskView.ts b/web/src/engine/osk/src/views/oskView.ts index afdc99f882a..09b3cbc8278 100644 --- a/web/src/engine/osk/src/views/oskView.ts +++ b/web/src/engine/osk/src/views/oskView.ts @@ -16,16 +16,16 @@ import { Keyboard, KeyboardProperties, ManagedPromise, - type MinimalCodesInterface, - type MutableSystemStore, - type SystemStoreMutationHandler + type MinimalCodesInterface } from '@keymanapp/keyboard-processor'; import { createUnselectableElement, getAbsoluteX, getAbsoluteY, StylesheetManager } from 'keyman/engine/dom-utils'; -import { EventListener, KeyEventHandler, KeyEventSourceInterface, LegacyEventEmitter } from 'keyman/engine/events'; +import { EventListener, LegacyEventEmitter } from 'keyman/engine/events'; +import { type MutableSystemStore, type SystemStoreMutationHandler } from 'keyman/engine/js-processor'; import Configuration from '../config/viewConfiguration.js'; import Activator, { StaticActivator } from './activator.js'; import TouchEventPromiseMap from './touchEventPromiseMap.js'; +import { KeyEventHandler, KeyEventSourceInterface } from './keyEventSource.interface.js'; // These will likely be eliminated from THIS file at some point.\ diff --git a/web/src/engine/osk/src/visualKeyboard.ts b/web/src/engine/osk/src/visualKeyboard.ts index fac43d51250..1136e696ba4 100644 --- a/web/src/engine/osk/src/visualKeyboard.ts +++ b/web/src/engine/osk/src/visualKeyboard.ts @@ -31,7 +31,7 @@ import { import { createStyleSheet, StylesheetManager } from 'keyman/engine/dom-utils'; -import { KeyEventHandler, KeyEventResultCallback } from 'keyman/engine/events'; +import { KeyEventHandler, KeyEventResultCallback } from './views/keyEventSource.interface.js'; import GlobeHint from './globehint.interface.js'; import KeyboardView from './components/keyboardView.interface.js'; From 3cdd84ff40b0c360682f9363c6e398b30cf4c67e Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 13 Aug 2024 19:00:38 +0200 Subject: [PATCH 14/65] refactor(web): move tests to `test/auto/headless` Addresses code review comments. --- web/src/engine/keyboard/build.sh | 14 +------------- .../auto/headless/engine/keyboard}/basic-engine.js | 2 +- .../auto/headless/engine/keyboard}/basic-init.js | 0 .../headless/engine/keyboard}/bundled-module.js | 0 .../auto/headless/engine/keyboard}/chirality.js | 2 +- .../auto/headless/engine/keyboard}/deadkeys.js | 2 +- .../headless/engine/keyboard}/engine/context.js | 0 .../engine/keyboard}/engine/notany_context.js | 0 .../headless/engine/keyboard}/engine/stores.js | 0 .../keyboard}/engine/unmatched_final_group.js | 2 +- .../headless/engine/keyboard}/keyboard-loading.js | 0 .../engine/keyboard}/keyboard-properties.js | 0 .../auto/headless/engine/keyboard}/mocks.js | 0 .../engine/keyboard}/non-positional-rules.js | 0 .../engine/keyboard}/specialized-backspace.js | 0 .../headless/engine/keyboard}/transcriptions.js | 0 16 files changed, 5 insertions(+), 17 deletions(-) rename web/src/{engine/keyboard/tests/node => test/auto/headless/engine/keyboard}/basic-engine.js (97%) rename web/src/{engine/keyboard/tests/node => test/auto/headless/engine/keyboard}/basic-init.js (100%) rename web/src/{engine/keyboard/tests/node => test/auto/headless/engine/keyboard}/bundled-module.js (100%) rename web/src/{engine/keyboard/tests/node => test/auto/headless/engine/keyboard}/chirality.js (99%) rename web/src/{engine/keyboard/tests/node => test/auto/headless/engine/keyboard}/deadkeys.js (97%) rename web/src/{engine/keyboard/tests/node => test/auto/headless/engine/keyboard}/engine/context.js (100%) rename web/src/{engine/keyboard/tests/node => test/auto/headless/engine/keyboard}/engine/notany_context.js (100%) rename web/src/{engine/keyboard/tests/node => test/auto/headless/engine/keyboard}/engine/stores.js (100%) rename web/src/{engine/keyboard/tests/node => test/auto/headless/engine/keyboard}/engine/unmatched_final_group.js (96%) rename web/src/{engine/keyboard/tests/node => test/auto/headless/engine/keyboard}/keyboard-loading.js (100%) rename web/src/{engine/keyboard/tests/node => test/auto/headless/engine/keyboard}/keyboard-properties.js (100%) rename web/src/{engine/keyboard/tests/node => test/auto/headless/engine/keyboard}/mocks.js (100%) rename web/src/{engine/keyboard/tests/node => test/auto/headless/engine/keyboard}/non-positional-rules.js (100%) rename web/src/{engine/keyboard/tests/node => test/auto/headless/engine/keyboard}/specialized-backspace.js (100%) rename web/src/{engine/keyboard/tests/node => test/auto/headless/engine/keyboard}/transcriptions.js (100%) diff --git a/web/src/engine/keyboard/build.sh b/web/src/engine/keyboard/build.sh index 649e38a213f..226a7d9d754 100755 --- a/web/src/engine/keyboard/build.sh +++ b/web/src/engine/keyboard/build.sh @@ -79,19 +79,7 @@ function do_build() { tsc --emitDeclarationOnly --outFile "${BUILD_DIR}/lib/node-keyboard-loader.d.ts" -p src/keyboards/loaders/tsconfig.node.json } -function do_test() { - local MOCHA_FLAGS= - local WTR_CONFIG= - if builder_has_option --ci; then - echo "Replacing user-friendly test reports with CI-friendly versions." - MOCHA_FLAGS="$MOCHA_FLAGS --reporter mocha-teamcity-reporter" - WTR_CONFIG=.CI - fi - - c8 mocha --recursive $MOCHA_FLAGS ./tests/node/ -} - builder_run_action configure do_configure builder_run_action clean rm -rf "${BUILD_DIR}" builder_run_action build do_build -builder_run_action test do_test +builder_run_action test test-headless "${SUBPROJECT_NAME}" "" diff --git a/web/src/engine/keyboard/tests/node/basic-engine.js b/web/src/test/auto/headless/engine/keyboard/basic-engine.js similarity index 97% rename from web/src/engine/keyboard/tests/node/basic-engine.js rename to web/src/test/auto/headless/engine/keyboard/basic-engine.js index 33d90b6567e..68eb5136e3d 100644 --- a/web/src/engine/keyboard/tests/node/basic-engine.js +++ b/web/src/test/auto/headless/engine/keyboard/basic-engine.js @@ -25,7 +25,7 @@ describe('Engine - Basic Simulation', function() { before(async function() { // -- START: Standard Recorder-based unit test loading boilerplate -- let keyboardLoader = new NodeKeyboardLoader(new KeyboardInterface({}, MinimalKeymanGlobal)); - let keyboard = await keyboardLoader.loadKeyboardFromPath('../../../../common/test/' + testSuite.keyboard.filename); + let keyboard = await keyboardLoader.loadKeyboardFromPath('../../../../../common/test/' + testSuite.keyboard.filename); keyboardWithHarness = keyboardLoader.harness; keyboardWithHarness.activeKeyboard = keyboard; diff --git a/web/src/engine/keyboard/tests/node/basic-init.js b/web/src/test/auto/headless/engine/keyboard/basic-init.js similarity index 100% rename from web/src/engine/keyboard/tests/node/basic-init.js rename to web/src/test/auto/headless/engine/keyboard/basic-init.js diff --git a/web/src/engine/keyboard/tests/node/bundled-module.js b/web/src/test/auto/headless/engine/keyboard/bundled-module.js similarity index 100% rename from web/src/engine/keyboard/tests/node/bundled-module.js rename to web/src/test/auto/headless/engine/keyboard/bundled-module.js diff --git a/web/src/engine/keyboard/tests/node/chirality.js b/web/src/test/auto/headless/engine/keyboard/chirality.js similarity index 99% rename from web/src/engine/keyboard/tests/node/chirality.js rename to web/src/test/auto/headless/engine/keyboard/chirality.js index d812a21635d..c2220b7f5d2 100644 --- a/web/src/engine/keyboard/tests/node/chirality.js +++ b/web/src/test/auto/headless/engine/keyboard/chirality.js @@ -26,7 +26,7 @@ describe('Engine - Chirality', function() { before(async function() { // -- START: Standard Recorder-based unit test loading boilerplate -- let keyboardLoader = new NodeKeyboardLoader(new KeyboardInterface({}, MinimalKeymanGlobal)); - let keyboard = await keyboardLoader.loadKeyboardFromPath('../../../../common/test/' + testSuite.keyboard.filename); + let keyboard = await keyboardLoader.loadKeyboardFromPath('../../../../../common/test/' + testSuite.keyboard.filename); keyboardWithHarness = keyboardLoader.harness; keyboardWithHarness.activeKeyboard = keyboard; diff --git a/web/src/engine/keyboard/tests/node/deadkeys.js b/web/src/test/auto/headless/engine/keyboard/deadkeys.js similarity index 97% rename from web/src/engine/keyboard/tests/node/deadkeys.js rename to web/src/test/auto/headless/engine/keyboard/deadkeys.js index 51bf2aebf56..fd5d1457d3d 100644 --- a/web/src/engine/keyboard/tests/node/deadkeys.js +++ b/web/src/test/auto/headless/engine/keyboard/deadkeys.js @@ -25,7 +25,7 @@ describe('Engine - Deadkeys', function() { before(async function() { // -- START: Standard Recorder-based unit test loading boilerplate -- let keyboardLoader = new NodeKeyboardLoader(new KeyboardInterface({}, MinimalKeymanGlobal)); - let keyboard = await keyboardLoader.loadKeyboardFromPath('../../../../common/test/' + testSuite.keyboard.filename); + let keyboard = await keyboardLoader.loadKeyboardFromPath('../../../../../common/test/' + testSuite.keyboard.filename); keyboardWithHarness = keyboardLoader.harness; keyboardWithHarness.activeKeyboard = keyboard; diff --git a/web/src/engine/keyboard/tests/node/engine/context.js b/web/src/test/auto/headless/engine/keyboard/engine/context.js similarity index 100% rename from web/src/engine/keyboard/tests/node/engine/context.js rename to web/src/test/auto/headless/engine/keyboard/engine/context.js diff --git a/web/src/engine/keyboard/tests/node/engine/notany_context.js b/web/src/test/auto/headless/engine/keyboard/engine/notany_context.js similarity index 100% rename from web/src/engine/keyboard/tests/node/engine/notany_context.js rename to web/src/test/auto/headless/engine/keyboard/engine/notany_context.js diff --git a/web/src/engine/keyboard/tests/node/engine/stores.js b/web/src/test/auto/headless/engine/keyboard/engine/stores.js similarity index 100% rename from web/src/engine/keyboard/tests/node/engine/stores.js rename to web/src/test/auto/headless/engine/keyboard/engine/stores.js diff --git a/web/src/engine/keyboard/tests/node/engine/unmatched_final_group.js b/web/src/test/auto/headless/engine/keyboard/engine/unmatched_final_group.js similarity index 96% rename from web/src/engine/keyboard/tests/node/engine/unmatched_final_group.js rename to web/src/test/auto/headless/engine/keyboard/engine/unmatched_final_group.js index cf2f1e88034..8bfee041ebe 100644 --- a/web/src/engine/keyboard/tests/node/engine/unmatched_final_group.js +++ b/web/src/test/auto/headless/engine/keyboard/engine/unmatched_final_group.js @@ -24,7 +24,7 @@ describe('Engine - Unmatched Final Groups', function() { before(async function() { // -- START: Standard Recorder-based unit test loading boilerplate -- let keyboardLoader = new NodeKeyboardLoader(new KeyboardInterface({}, MinimalKeymanGlobal)); - const keyboard = await keyboardLoader.loadKeyboardFromPath('../../../../common/test/' + testSuite.keyboard.filename); + const keyboard = await keyboardLoader.loadKeyboardFromPath('../../../../../common/test/' + testSuite.keyboard.filename); keyboardWithHarness = keyboardLoader.harness; keyboardWithHarness.activeKeyboard = keyboard; diff --git a/web/src/engine/keyboard/tests/node/keyboard-loading.js b/web/src/test/auto/headless/engine/keyboard/keyboard-loading.js similarity index 100% rename from web/src/engine/keyboard/tests/node/keyboard-loading.js rename to web/src/test/auto/headless/engine/keyboard/keyboard-loading.js diff --git a/web/src/engine/keyboard/tests/node/keyboard-properties.js b/web/src/test/auto/headless/engine/keyboard/keyboard-properties.js similarity index 100% rename from web/src/engine/keyboard/tests/node/keyboard-properties.js rename to web/src/test/auto/headless/engine/keyboard/keyboard-properties.js diff --git a/web/src/engine/keyboard/tests/node/mocks.js b/web/src/test/auto/headless/engine/keyboard/mocks.js similarity index 100% rename from web/src/engine/keyboard/tests/node/mocks.js rename to web/src/test/auto/headless/engine/keyboard/mocks.js diff --git a/web/src/engine/keyboard/tests/node/non-positional-rules.js b/web/src/test/auto/headless/engine/keyboard/non-positional-rules.js similarity index 100% rename from web/src/engine/keyboard/tests/node/non-positional-rules.js rename to web/src/test/auto/headless/engine/keyboard/non-positional-rules.js diff --git a/web/src/engine/keyboard/tests/node/specialized-backspace.js b/web/src/test/auto/headless/engine/keyboard/specialized-backspace.js similarity index 100% rename from web/src/engine/keyboard/tests/node/specialized-backspace.js rename to web/src/test/auto/headless/engine/keyboard/specialized-backspace.js diff --git a/web/src/engine/keyboard/tests/node/transcriptions.js b/web/src/test/auto/headless/engine/keyboard/transcriptions.js similarity index 100% rename from web/src/engine/keyboard/tests/node/transcriptions.js rename to web/src/test/auto/headless/engine/keyboard/transcriptions.js From 9d058c052ca32b9589b411877eaac62148855153 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 14 Aug 2024 08:22:38 +0700 Subject: [PATCH 15/65] feat(android): Add hooks for KeymanWeb call --- .../kmapro/AdjustLongpressDelayActivity.java | 2 +- .../KMEA/app/src/main/assets/android-host.js | 5 +++++ .../java/com/keyman/engine/KMManager.java | 19 ++++++++++++++++++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java index c7a8f59aadb..590bbdc2673 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java @@ -135,7 +135,7 @@ public void onClick(View v) { @Override public void onBackPressed() { // Apply the adjusted longpress delay on exit - KMManager.setLongpressDelay(this, currentDelayTime); + KMManager.setLongpressDelay(currentDelayTime); super.onBackPressed(); } diff --git a/android/KMEA/app/src/main/assets/android-host.js b/android/KMEA/app/src/main/assets/android-host.js index 9c786e17770..93ee0e4b0d3 100644 --- a/android/KMEA/app/src/main/assets/android-host.js +++ b/android/KMEA/app/src/main/assets/android-host.js @@ -112,6 +112,11 @@ function notifyHost(event, params) { }, 10); } +// Update the KeymanWeb longpress delay +// delay is in milliseconds +function setLongpressDelay(delay) { +} + // Update the KMW banner height // h is in dpi (different from iOS) function setBannerHeight(h) { diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java index 645cf5ee0f9..7723dcbc0dd 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java @@ -2012,6 +2012,11 @@ public static int getOrientation(Context context) { return Configuration.ORIENTATION_UNDEFINED; } + /** + * Get the long-press delay (in milliseconds) + * @param context + * @return int - long-press delay in milliseconds + */ public static int getLongpressDelay(Context context) { int defaultDelay = 500; // default longpress delay in KeymanWeb (ms) SharedPreferences prefs = context.getSharedPreferences(context.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); @@ -2019,8 +2024,20 @@ public static int getLongpressDelay(Context context) { return prefs.getInt(KMManager.KMKey_LongpressDelay, defaultDelay); } - public static void setLongpressDelay(Context context, int longpressDelay) { + /** + * Update KeymanWeb with the long-press delay (in milliseconds) + * @param longpressDelay - int long-press delay in milliseconds + */ + public static void setLongpressDelay(int longpressDelay) { + if (isKeyboardLoaded(KeyboardType.KEYBOARD_TYPE_INAPP)) { + InAppKeyboard.loadJavascript(KMString.format("setLongpressDelay(%d)", longpressDelay)); + } + + if (SystemKeyboard != null) { + SystemKeyboard.loadJavascript(KMString.format("setLongpressDelay(%d)", longpressDelay)); + } + Log.d(TAG, "setLongpressDelay(" + longpressDelay + ")"); } public static int getBannerHeight(Context context) { From 6a2c15d6a04b297acaa0cf553bcef8a7b21692f6 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 14 Aug 2024 08:24:23 +0700 Subject: [PATCH 16/65] chore(android): Cleanup logging --- android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java index 7723dcbc0dd..903620e19f4 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java @@ -2036,8 +2036,6 @@ public static void setLongpressDelay(int longpressDelay) { if (SystemKeyboard != null) { SystemKeyboard.loadJavascript(KMString.format("setLongpressDelay(%d)", longpressDelay)); } - - Log.d(TAG, "setLongpressDelay(" + longpressDelay + ")"); } public static int getBannerHeight(Context context) { From d728b33dc629741805d7a77d0363ff7161397bd5 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 14 Aug 2024 13:08:55 +0700 Subject: [PATCH 17/65] fix(android): Pass longpress delay to KeymanWeb --- .../src/main/java/com/keyman/android/SystemKeyboard.java | 6 ++++++ .../tavultesoft/kmapro/AdjustLongpressDelayActivity.java | 2 +- .../main/java/com/tavultesoft/kmapro/MainActivity.java | 8 +++++++- android/KMEA/app/src/main/assets/android-host.js | 4 ++++ .../app/src/main/java/com/keyman/engine/KMManager.java | 8 ++++++-- 5 files changed, 24 insertions(+), 4 deletions(-) diff --git a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java index c6885b2b564..eb44e0a3fa4 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java +++ b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java @@ -4,6 +4,7 @@ package com.keyman.android; +import com.tavultesoft.kmapro.AdjustLongpressDelayActivity; import com.tavultesoft.kmapro.BuildConfig; import com.tavultesoft.kmapro.DefaultLanguageResource; import com.tavultesoft.kmapro.KeymanSettingsActivity; @@ -79,6 +80,8 @@ public void onCreate() { // Set the system keyboard HTML banner BannerController.setHTMLBanner(this, KeyboardType.KEYBOARD_TYPE_SYSTEM); + int longpressDelay = KMManager.getLongpressDelay(this); + KMManager.setLongpressDelay(longpressDelay); boolean mayHaveHapticFeedback = prefs.getBoolean(KeymanSettingsActivity.hapticFeedbackKey, false); KMManager.setHapticFeedback(mayHaveHapticFeedback); @@ -244,6 +247,9 @@ public void onKeyboardLoaded(KeyboardType keyboardType) { if (exText != null) exText = null; } + // Initialize the longpress delay + int longpressDelay = KMManager.getLongpressDelay(this); + KMManager.setLongpressDelay(longpressDelay); } @Override diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java index 590bbdc2673..214fd370145 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java @@ -29,7 +29,7 @@ public class AdjustLongpressDelayActivity extends BaseActivity { // Keeps track of the adjusted longpress delay time for saving. // Internally use milliseconds, but GUI displays seconds - private static int currentDelayTime = 500; // ms + private static int currentDelayTime = KMManager.KMDefault_LongpressDelay; // ms private static int minLongpressTime = 300; // ms private static int maxLongpressTime = 1500; // ms private static int delayTimeIncrement = 200; // ms diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java index 1e5231f5215..b337d2315d9 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java @@ -472,7 +472,7 @@ public boolean onKeyUp(int keycode, KeyEvent e) { @Override public void onKeyboardLoaded(KeyboardType keyboardType) { - // Do nothing + checkLongpressDelay(); } @Override @@ -750,6 +750,12 @@ private void checkSendCrashReport() { KMManager.setMaySendCrashReport(maySendCrashReport); } + private void checkLongpressDelay() { + // Initialize the longpress delay + int longpressDelay = KMManager.getLongpressDelay(this); + KMManager.setLongpressDelay(longpressDelay); + } + private void checkHapticFeedback() { SharedPreferences prefs = getSharedPreferences(getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); boolean mayHaveHapticFeedback = prefs.getBoolean(KeymanSettingsActivity.hapticFeedbackKey, false); diff --git a/android/KMEA/app/src/main/assets/android-host.js b/android/KMEA/app/src/main/assets/android-host.js index 93ee0e4b0d3..b09dbf8beb8 100644 --- a/android/KMEA/app/src/main/assets/android-host.js +++ b/android/KMEA/app/src/main/assets/android-host.js @@ -115,6 +115,10 @@ function notifyHost(event, params) { // Update the KeymanWeb longpress delay // delay is in milliseconds function setLongpressDelay(delay) { + if (keyman.osk) { + keyman.osk.gestureParams.longpress.waitLength = delay; + console.debug('setLongpressDelay('+delay+')'); + } } // Update the KMW banner height diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java index 903620e19f4..d4fe9c404c4 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java @@ -295,6 +295,9 @@ public String toString() { public static final String KMDefault_DictionaryVersion = "0.1.4"; public static final String KMDefault_DictionaryKMP = KMDefault_DictionaryPackageID + FileUtils.MODELPACKAGE; + // Default KeymanWeb long-press delay + public static final int KMDefault_LongpressDelay = 500; // ms + // Keyman files protected static final String KMFilename_KeyboardHtml = "keyboard.html"; protected static final String KMFilename_JSEngine = "keymanweb-webview.js"; @@ -2018,10 +2021,11 @@ public static int getOrientation(Context context) { * @return int - long-press delay in milliseconds */ public static int getLongpressDelay(Context context) { - int defaultDelay = 500; // default longpress delay in KeymanWeb (ms) SharedPreferences prefs = context.getSharedPreferences(context.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); - return prefs.getInt(KMManager.KMKey_LongpressDelay, defaultDelay); + return prefs.getInt( + KMKey_LongpressDelay, + KMDefault_LongpressDelay); } /** From 2041b54abb009b4bc21cf3a9c2f9b2474f874315 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Wed, 14 Aug 2024 12:51:48 +0200 Subject: [PATCH 18/65] fix(web): allow `lm-worker` to build on Linux Linux' file system is case-sensitive. This change fixes building `lm-worker` on case-sensitive systems. --- common/web/lm-worker/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/web/lm-worker/build.sh b/common/web/lm-worker/build.sh index 22ffa9208c5..0343d151c8f 100755 --- a/common/web/lm-worker/build.sh +++ b/common/web/lm-worker/build.sh @@ -98,7 +98,7 @@ function do_test() { if builder_has_option --ci; then MOCHA_FLAGS="$MOCHA_FLAGS --reporter mocha-teamcity-reporter" - WTR_CONFIG=.ci + WTR_CONFIG=.CI fi if builder_has_option --debug; then From 6fad148466a4bfc0ae017b53c687408919087246 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Aug 2024 11:22:58 +0000 Subject: [PATCH 19/65] chore(deps): bump semver from 7.5.4 to 7.6.0 Bumps [semver](https://github.com/npm/node-semver) from 7.5.4 to 7.6.0. - [Release notes](https://github.com/npm/node-semver/releases) - [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md) - [Commits](https://github.com/npm/node-semver/compare/v7.5.4...v7.6.0) --- updated-dependencies: - dependency-name: semver dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- developer/src/common/web/utils/package.json | 2 +- developer/src/kmc-ldml/package.json | 2 +- developer/src/server/package.json | 2 +- resources/build/version/package.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/developer/src/common/web/utils/package.json b/developer/src/common/web/utils/package.json index 488051f8f0e..1ab9daddbf8 100644 --- a/developer/src/common/web/utils/package.json +++ b/developer/src/common/web/utils/package.json @@ -13,7 +13,7 @@ "@keymanapp/common-types": "*", "eventemitter3": "^5.0.0", "restructure": "^3.0.1", - "semver": "^7.5.2", + "semver": "^7.5.4", "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" }, diff --git a/developer/src/kmc-ldml/package.json b/developer/src/kmc-ldml/package.json index e423b9cd001..6f65eaf0e0a 100644 --- a/developer/src/kmc-ldml/package.json +++ b/developer/src/kmc-ldml/package.json @@ -29,7 +29,7 @@ "@keymanapp/developer-utils": "*", "@keymanapp/kmc-kmn": "*", "@keymanapp/ldml-keyboard-constants": "*", - "semver": "^7.5.2" + "semver": "^7.5.4" }, "devDependencies": { "@keymanapp/developer-test-helpers": "*", diff --git a/developer/src/server/package.json b/developer/src/server/package.json index b0e438ad15e..f3be3425f2a 100644 --- a/developer/src/server/package.json +++ b/developer/src/server/package.json @@ -18,7 +18,7 @@ "open": "^8.4.0", "restructure": "^3.0.1", "sax": ">=0.6.0", - "semver": "^7.5.2", + "semver": "^7.5.4", "ws": "^8.17.1", "xmlbuilder": "~11.0.0" }, diff --git a/resources/build/version/package.json b/resources/build/version/package.json index da551fef289..ef27eb0fa1d 100644 --- a/resources/build/version/package.json +++ b/resources/build/version/package.json @@ -11,7 +11,7 @@ "devDependencies": { "@types/semver": "^7.1.0", "@types/yargs": "^17.0.26", - "semver": "^7.5.2" + "semver": "^7.5.4" }, "files": [ "src" From cd901a7f6da7a928a93a445d64b1cf75631095fe Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 14 Aug 2024 13:45:14 +0200 Subject: [PATCH 20/65] docs: update .kmx documentation around bitmaps, modifier state Addresses: keymanapp/keyman#12163#issuecomment-2287675497 --- docs/file-formats/kmx-file-format.md | 58 +++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/docs/file-formats/kmx-file-format.md b/docs/file-formats/kmx-file-format.md index 6de14df56fe..67288bc123c 100644 --- a/docs/file-formats/kmx-file-format.md +++ b/docs/file-formats/kmx-file-format.md @@ -44,12 +44,14 @@ The very first section is a header that describes the remainder of the file. |44 | 32 | `StartGroup_Unicode` | index of starting Unicode `COMP_GROUP`, `0xFFFFFFFF` means unused | |48 | 32 | `dwFlags` | global flags for the keyboard, see description below | |52 | 32 | `dwHotKey` | default hotkey for keyboard, from [`&Hotkey`], see description below | -|56 | 32 | `dpBitmapOffset` | offset of keyboard icon, `0x0` if not present | +|56 | 32 | `dpBitmapOffset` | offset of keyboard icon | |60 | 32 | `dwBitmapSize` | size in bytes of keyboard icon, `0x0` if not present | This structure is present at the start of every .kmx file. The `KXTS` identifier can be used as a 'magic' to determine whether a binary file is a .kmx file. +Note that `dpBitmapOffset` should be ignored if `dwBitmapSize` is `0x0` -- it may be a non-zero value. + ### `dwFileVersion`: Minimum version of Keyman required to read the file The `dwFileVersion` property should be checked before attempting to read any @@ -220,7 +222,7 @@ file and is never written to the binary format. | ∆ | Bits | Name | Description | |----|------|--------------|------------------------------------------------------------------------------------------------| -| 0 | 16 | `Key` | Keyman virtual key for the rule, 0 if unused | +| 0 | 16 | `Key` | [Keyman virtual key], virtual character key, or character, for the rule, 0 if unused | | 2 | 16 | (unused) | padding, reserved | | 4 | 32 | `Line` | Line number for the rule, 0 if not compiled with debug information | | 8 | 32 | `ShiftFlags` | Modifier flags for the key, see description below | @@ -232,6 +234,58 @@ compiler expands `any()` statements found in the key part of a rule into multiple rules -- so the key part of the rule is always only ever matching a single key combination. +`ShiftFlags` contains a set of modifier and state key flags, and some additional +flags that determine how to interpret `Key`. + +### Modifier and state key flags + +The modifier and state key flags are: + +| Bit mask | Name | Description | +|--------------|------------------|-----------------------------------------------------------| +| `0x00000001` | `LCTRLFLAG` | Left Control key | +| `0x00000002` | `RCTRLFLAG` | Right Control key | +| `0x00000004` | `LALTFLAG` | Left Alt key (Option on macOS) | +| `0x00000008` | `RALTFLAG` | Right Alt key | +| `0x00000010` | `K_SHIFTFLAG` | Either Shift key | +| `0x00000020` | `K_CTRLFLAG` | Either Ctrl key | +| `0x00000040` | `K_ALTFLAG` | Either Alt key | +| `0x00000080` | `K_METAFLAG` | Either Meta key. Reserved, not for use in .kmx | +| `0x00000100` | `CAPITALFLAG` | Caps lock on | +| `0x00000200` | `NOTCAPITALFLAG` | Caps lock NOT on | +| `0x00000400` | `NUMLOCKFLAG` | Num lock on | +| `0x00000800` | `NOTNUMLOCKFLAG` | Num lock NOT on | +| `0x00001000` | `SCROLLFLAG` | Scroll lock on | +| `0x00002000` | `NOTSCROLLFLAG` | Scroll lock NOT on | + +* The chiral (left/right) modifier flags should not be used together with the + non-chiral flags. +* If neither `CAPITALFLAG` nor `NOTCAPITALFLAG` are set, then the state of the + Caps Lock key is ignored, and the same principle applies for Num lock and + Scroll lock. +* The Meta key may be the Windows key on Windows, or the + Command key on macOS. This flag is reserved for internal use, and + is not valid in a .kmx file. + +### Additional flags + +The meaning of `Key` is determined by the flags `ISVIRTUALKEY` and +`VIRTUALCHARKEY` in `ShiftFlags` (mask `0x0000C000`): + +* `0`: `Key` is a character on a key cap (US English unless the keyboard is a + mnemonic layout). All other shift flags are ignord +* `ISVIRTUALKEY`: `Key` is a US English virtual key +* `VIRTUALCHARKEY`: `Key` is a character on a key cap, combined with the shift + flags (US English unless the keyboard is a mnemonic layout) + +| Bit mask | Name | Description | +|--------------|------------------|-----------------------------------------------| +| `0x00004000` | `ISVIRTUALKEY` | `Key` is a virtual key | +| `0x00008000` | `VIRTUALCHARKEY` | Keyman 6.0+: `Key` is a Virtual character key | + +Note that the shift flags for key rules do not use the same values as hotkeys +for historical reasons. + ## Debug information for keyboards When debug information is present, it will be found in four places in compiled From 7459ab0bf849a6ff5a5cd6d45d4857edc0b8422b Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Wed, 14 Aug 2024 17:23:52 +0200 Subject: [PATCH 21/65] refactor(web): move tests Some tests test functionality defined in `js-processor`, so we move these to the appropriate location. Addresses code review comments. --- web/src/engine/js-processor/build.sh | 7 +- .../basic-engine.js | 0 .../{keyboard => js-processor}/basic-init.js | 0 .../bundled-module.js | 26 ++++-- .../{keyboard => js-processor}/chirality.js | 0 .../{keyboard => js-processor}/deadkeys.js | 0 .../engine/context.js | 0 .../engine/notany_context.js | 0 .../engine/stores.js | 0 .../engine/unmatched_final_group.js | 0 .../engine/js-processor/kbdInterface.tests.js | 91 +++++++++++++++++++ .../{keyboard => js-processor}/mocks.js | 0 .../non-positional-rules.js | 0 .../specialized-backspace.js | 0 .../transcriptions.js | 0 .../engine/keyboard/keyboard-loading.js | 74 +-------------- .../main/headless/inputProcessor.spec.js | 2 +- .../main/headless/languageProcessor.spec.js | 2 +- 18 files changed, 117 insertions(+), 85 deletions(-) rename web/src/test/auto/headless/engine/{keyboard => js-processor}/basic-engine.js (100%) rename web/src/test/auto/headless/engine/{keyboard => js-processor}/basic-init.js (100%) rename web/src/test/auto/headless/engine/{keyboard => js-processor}/bundled-module.js (71%) rename web/src/test/auto/headless/engine/{keyboard => js-processor}/chirality.js (100%) rename web/src/test/auto/headless/engine/{keyboard => js-processor}/deadkeys.js (100%) rename web/src/test/auto/headless/engine/{keyboard => js-processor}/engine/context.js (100%) rename web/src/test/auto/headless/engine/{keyboard => js-processor}/engine/notany_context.js (100%) rename web/src/test/auto/headless/engine/{keyboard => js-processor}/engine/stores.js (100%) rename web/src/test/auto/headless/engine/{keyboard => js-processor}/engine/unmatched_final_group.js (100%) create mode 100644 web/src/test/auto/headless/engine/js-processor/kbdInterface.tests.js rename web/src/test/auto/headless/engine/{keyboard => js-processor}/mocks.js (100%) rename web/src/test/auto/headless/engine/{keyboard => js-processor}/non-positional-rules.js (100%) rename web/src/test/auto/headless/engine/{keyboard => js-processor}/specialized-backspace.js (100%) rename web/src/test/auto/headless/engine/{keyboard => js-processor}/transcriptions.js (100%) diff --git a/web/src/engine/js-processor/build.sh b/web/src/engine/js-processor/build.sh index 57adbd1dd21..db00593166a 100755 --- a/web/src/engine/js-processor/build.sh +++ b/web/src/engine/js-processor/build.sh @@ -36,6 +36,7 @@ do_build () { --format esm } -builder_run_action configure verify_npm_setup -builder_run_action clean rm -rf "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}" -builder_run_action build do_build +builder_run_action configure verify_npm_setup +builder_run_action clean rm -rf "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}" +builder_run_action build do_build +builder_run_action test test-headless "${SUBPROJECT_NAME}" "" diff --git a/web/src/test/auto/headless/engine/keyboard/basic-engine.js b/web/src/test/auto/headless/engine/js-processor/basic-engine.js similarity index 100% rename from web/src/test/auto/headless/engine/keyboard/basic-engine.js rename to web/src/test/auto/headless/engine/js-processor/basic-engine.js diff --git a/web/src/test/auto/headless/engine/keyboard/basic-init.js b/web/src/test/auto/headless/engine/js-processor/basic-init.js similarity index 100% rename from web/src/test/auto/headless/engine/keyboard/basic-init.js rename to web/src/test/auto/headless/engine/js-processor/basic-init.js diff --git a/web/src/test/auto/headless/engine/keyboard/bundled-module.js b/web/src/test/auto/headless/engine/js-processor/bundled-module.js similarity index 71% rename from web/src/test/auto/headless/engine/keyboard/bundled-module.js rename to web/src/test/auto/headless/engine/js-processor/bundled-module.js index cfc54480b68..a6b80d50043 100644 --- a/web/src/test/auto/headless/engine/keyboard/bundled-module.js +++ b/web/src/test/auto/headless/engine/js-processor/bundled-module.js @@ -1,5 +1,6 @@ import { assert } from "chai"; -import * as Package from "keyman/engine/keyboard"; +import * as Package from "keyman/engine/js-processor"; +import * as Package2 from "keyman/engine/keyboard"; // A few small tests to ensure that the ES Module bundle was successfully constructed and is usable. @@ -12,10 +13,10 @@ var toSupplementaryPairString = function(code){ let u = toSupplementaryPairString; -describe('Bundled ES Module', function() { - describe('Keyboard', function () { +describe('Bundled ES Module for js-processor', function() { + describe('KeyboardProcessor', function () { it('should initialize without errors', function () { - let kp = new Package.Keyboard(); + let kp = new Package.KeyboardProcessor(); assert.isNotNull(kp); }); }); @@ -40,11 +41,20 @@ describe('Bundled ES Module', function() { } }); }); +}); + +describe('Bundled ES Module for keyboard', function () { + describe('Keyboard', function () { + it('should initialize without errors', function () { + let kp = new Package2.Keyboard(); + assert.isNotNull(kp); + }); + }); - describe("Imported `utils`", function() { + describe("Imported `utils`", function () { it("should include `utils` package's Version class", () => { - let v16 = new Package.Version([16, 1]); + let v16 = new Package2.Version([16, 1]); assert.equal(v16.toString(), "16.1"); }); - }) -}); \ No newline at end of file + }); +}); diff --git a/web/src/test/auto/headless/engine/keyboard/chirality.js b/web/src/test/auto/headless/engine/js-processor/chirality.js similarity index 100% rename from web/src/test/auto/headless/engine/keyboard/chirality.js rename to web/src/test/auto/headless/engine/js-processor/chirality.js diff --git a/web/src/test/auto/headless/engine/keyboard/deadkeys.js b/web/src/test/auto/headless/engine/js-processor/deadkeys.js similarity index 100% rename from web/src/test/auto/headless/engine/keyboard/deadkeys.js rename to web/src/test/auto/headless/engine/js-processor/deadkeys.js diff --git a/web/src/test/auto/headless/engine/keyboard/engine/context.js b/web/src/test/auto/headless/engine/js-processor/engine/context.js similarity index 100% rename from web/src/test/auto/headless/engine/keyboard/engine/context.js rename to web/src/test/auto/headless/engine/js-processor/engine/context.js diff --git a/web/src/test/auto/headless/engine/keyboard/engine/notany_context.js b/web/src/test/auto/headless/engine/js-processor/engine/notany_context.js similarity index 100% rename from web/src/test/auto/headless/engine/keyboard/engine/notany_context.js rename to web/src/test/auto/headless/engine/js-processor/engine/notany_context.js diff --git a/web/src/test/auto/headless/engine/keyboard/engine/stores.js b/web/src/test/auto/headless/engine/js-processor/engine/stores.js similarity index 100% rename from web/src/test/auto/headless/engine/keyboard/engine/stores.js rename to web/src/test/auto/headless/engine/js-processor/engine/stores.js diff --git a/web/src/test/auto/headless/engine/keyboard/engine/unmatched_final_group.js b/web/src/test/auto/headless/engine/js-processor/engine/unmatched_final_group.js similarity index 100% rename from web/src/test/auto/headless/engine/keyboard/engine/unmatched_final_group.js rename to web/src/test/auto/headless/engine/js-processor/engine/unmatched_final_group.js diff --git a/web/src/test/auto/headless/engine/js-processor/kbdInterface.tests.js b/web/src/test/auto/headless/engine/js-processor/kbdInterface.tests.js new file mode 100644 index 00000000000..03203a840f4 --- /dev/null +++ b/web/src/test/auto/headless/engine/js-processor/kbdInterface.tests.js @@ -0,0 +1,91 @@ +import { assert } from 'chai'; + +import { createRequire } from 'module'; +const require = createRequire(import.meta.url); + +import { MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; +import { KeyboardInterface } from 'keyman/engine/js-processor'; +import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; + +describe('Headless keyboard loading', function () { + const laoPath = require.resolve('@keymanapp/common-test-resources/keyboards/lao_2008_basic.js'); + const khmerPath = require.resolve('@keymanapp/common-test-resources/keyboards/khmer_angkor.js'); + const nonKeyboardPath = require.resolve('@keymanapp/common-test-resources/index.mjs'); + const ipaPath = require.resolve('@keymanapp/common-test-resources/keyboards/sil_ipa.js'); + // Common test suite setup. + + let device = { + formFactor: 'desktop', + OS: 'windows', + browser: 'native' + } + + describe('Full harness loading', () => { + it('successfully loads', async function () { + // -- START: Standard Recorder-based unit test loading boilerplate -- + let harness = new KeyboardInterface({}, MinimalKeymanGlobal); + let keyboardLoader = new NodeKeyboardLoader(harness); + let keyboard = await keyboardLoader.loadKeyboardFromPath(laoPath); + harness.activeKeyboard = keyboard; + // -- END: Standard Recorder-based unit test loading boilerplate -- + + // This part provides assurance that the keyboard properly loaded. + assert.equal(keyboard.id, "Keyboard_lao_2008_basic"); + }); + + it('can evaluate rules', async function () { + // -- START: Standard Recorder-based unit test loading boilerplate -- + let harness = new KeyboardInterface({}, MinimalKeymanGlobal); + let keyboardLoader = new NodeKeyboardLoader(harness); + let keyboard = await keyboardLoader.loadKeyboardFromPath(laoPath); + harness.activeKeyboard = keyboard; + // -- END: Standard Recorder-based unit test loading boilerplate -- + + // Runs a blank KeyEvent through the keyboard's rule processing. + harness.processKeystroke(new Mock(), keyboard.constructNullKeyEvent(device)); + }); + + it('does not change the active kehboard', async function () { + let harness = new KeyboardInterface({}, MinimalKeymanGlobal); + let keyboardLoader = new NodeKeyboardLoader(harness); + const lao_keyboard = await keyboardLoader.loadKeyboardFromPath(laoPath); + assert.isNotOk(harness.activeKeyboard); + assert.isOk(lao_keyboard); + + // This part provides assurance that the keyboard properly loaded. + assert.equal(lao_keyboard.id, "Keyboard_lao_2008_basic"); + + harness.activeKeyboard = lao_keyboard; + + const khmer_keyboard = await keyboardLoader.loadKeyboardFromPath(khmerPath); + assert.strictEqual(lao_keyboard, harness.activeKeyboard); + + assert.equal(khmer_keyboard.id, "Keyboard_khmer_angkor"); + }); + + it('throws distinct errors', async function () { + const invalidPath = 'totally_invalid_path.js'; + + let harness = new KeyboardInterface({}, MinimalKeymanGlobal); + let keyboardLoader = new NodeKeyboardLoader(harness); + let missingError; + try { + await keyboardLoader.loadKeyboardFromPath(invalidPath); + } catch (err) { + missingError = err; + } + assert.isOk(missingError); + + let scriptLoadError; + try { + await keyboardLoader.loadKeyboardFromPath(nonKeyboardPath); + } catch (err) { + scriptLoadError = err; + } + assert.isOk(scriptLoadError); + + // The main test: do the errors match? + assert.notEqual(scriptLoadError.message, missingError.message); + }); + }) +}); diff --git a/web/src/test/auto/headless/engine/keyboard/mocks.js b/web/src/test/auto/headless/engine/js-processor/mocks.js similarity index 100% rename from web/src/test/auto/headless/engine/keyboard/mocks.js rename to web/src/test/auto/headless/engine/js-processor/mocks.js diff --git a/web/src/test/auto/headless/engine/keyboard/non-positional-rules.js b/web/src/test/auto/headless/engine/js-processor/non-positional-rules.js similarity index 100% rename from web/src/test/auto/headless/engine/keyboard/non-positional-rules.js rename to web/src/test/auto/headless/engine/js-processor/non-positional-rules.js diff --git a/web/src/test/auto/headless/engine/keyboard/specialized-backspace.js b/web/src/test/auto/headless/engine/js-processor/specialized-backspace.js similarity index 100% rename from web/src/test/auto/headless/engine/keyboard/specialized-backspace.js rename to web/src/test/auto/headless/engine/js-processor/specialized-backspace.js diff --git a/web/src/test/auto/headless/engine/keyboard/transcriptions.js b/web/src/test/auto/headless/engine/js-processor/transcriptions.js similarity index 100% rename from web/src/test/auto/headless/engine/keyboard/transcriptions.js rename to web/src/test/auto/headless/engine/js-processor/transcriptions.js diff --git a/web/src/test/auto/headless/engine/keyboard/keyboard-loading.js b/web/src/test/auto/headless/engine/keyboard/keyboard-loading.js index 6152f1b0de8..1dc2baad9bf 100644 --- a/web/src/test/auto/headless/engine/keyboard/keyboard-loading.js +++ b/web/src/test/auto/headless/engine/keyboard/keyboard-loading.js @@ -1,5 +1,4 @@ import { assert } from 'chai'; -import fs from 'fs'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); @@ -41,7 +40,7 @@ describe('Headless keyboard loading', function() { it('successfully loads (has variable stores)', async () => { // -- START: Standard Recorder-based unit test loading boilerplate -- - let harness = new KeyboardInterface({}, MinimalKeymanGlobal); + let harness = new KeyboardHarness({}, MinimalKeymanGlobal); let keyboardLoader = new NodeKeyboardLoader(harness); let keyboard = await keyboardLoader.loadKeyboardFromPath(ipaPath); // -- END: Standard Recorder-based unit test loading boilerplate -- @@ -92,73 +91,4 @@ describe('Headless keyboard loading', function() { assert.isFalse(mobileLayout.hasMultitaps); }); }); - - describe('Full harness loading', () => { - it('successfully loads', async function() { - // -- START: Standard Recorder-based unit test loading boilerplate -- - let harness = new KeyboardInterface({}, MinimalKeymanGlobal); - let keyboardLoader = new NodeKeyboardLoader(harness); - let keyboard = await keyboardLoader.loadKeyboardFromPath(laoPath); - harness.activeKeyboard = keyboard; - // -- END: Standard Recorder-based unit test loading boilerplate -- - - // This part provides assurance that the keyboard properly loaded. - assert.equal(keyboard.id, "Keyboard_lao_2008_basic"); - }); - - it('can evaluate rules', async function() { - // -- START: Standard Recorder-based unit test loading boilerplate -- - let harness = new KeyboardInterface({}, MinimalKeymanGlobal); - let keyboardLoader = new NodeKeyboardLoader(harness); - let keyboard = await keyboardLoader.loadKeyboardFromPath(laoPath); - harness.activeKeyboard = keyboard; - // -- END: Standard Recorder-based unit test loading boilerplate -- - - // Runs a blank KeyEvent through the keyboard's rule processing. - harness.processKeystroke(new Mock(), keyboard.constructNullKeyEvent(device)); - }); - - it('does not change the active kehboard', async function() { - let harness = new KeyboardInterface({}, MinimalKeymanGlobal); - let keyboardLoader = new NodeKeyboardLoader(harness); - const lao_keyboard = await keyboardLoader.loadKeyboardFromPath(laoPath); - assert.isNotOk(harness.activeKeyboard); - assert.isOk(lao_keyboard); - - // This part provides assurance that the keyboard properly loaded. - assert.equal(lao_keyboard.id, "Keyboard_lao_2008_basic"); - - harness.activeKeyboard = lao_keyboard; - - const khmer_keyboard = await keyboardLoader.loadKeyboardFromPath(khmerPath); - assert.strictEqual(lao_keyboard, harness.activeKeyboard); - - assert.equal(khmer_keyboard.id, "Keyboard_khmer_angkor"); - }); - - it('throws distinct errors', async function() { - const invalidPath = 'totally_invalid_path.js'; - - let harness = new KeyboardInterface({}, MinimalKeymanGlobal); - let keyboardLoader = new NodeKeyboardLoader(harness); - let missingError; - try { - await keyboardLoader.loadKeyboardFromPath(invalidPath); - } catch (err) { - missingError = err; - } - assert.isOk(missingError); - - let scriptLoadError; - try { - await keyboardLoader.loadKeyboardFromPath(nonKeyboardPath); - } catch (err) { - scriptLoadError = err; - } - assert.isOk(scriptLoadError); - - // The main test: do the errors match? - assert.notEqual(scriptLoadError.message, missingError.message); - }); - }) -}); \ No newline at end of file +}); diff --git a/web/src/test/auto/headless/engine/main/headless/inputProcessor.spec.js b/web/src/test/auto/headless/engine/main/headless/inputProcessor.spec.js index f3f6622f9a8..56aa2f3e5ed 100644 --- a/web/src/test/auto/headless/engine/main/headless/inputProcessor.spec.js +++ b/web/src/test/auto/headless/engine/main/headless/inputProcessor.spec.js @@ -49,7 +49,7 @@ describe('InputProcessor', function() { assert.isUndefined(core.activeModel); // Same for the model. // These checks are lifted from the keyboard init checks found in - // common/web/keyboard/tests/cases/basic-init.js. + // web/src/test/auto/headless/engine/js-processor/basic-init.js. assert.equal('us', core.keyboardProcessor.baseLayout, 'KeyboardProcessor has unexpected base layout') assert.isNotNull(global.KeymanWeb, 'KeymanWeb global was not automatically installed'); assert.equal('default', core.keyboardProcessor.layerId, 'Default layer is not set to "default"'); diff --git a/web/src/test/auto/headless/engine/main/headless/languageProcessor.spec.js b/web/src/test/auto/headless/engine/main/headless/languageProcessor.spec.js index 6f2f321edf1..e4572de21d0 100644 --- a/web/src/test/auto/headless/engine/main/headless/languageProcessor.spec.js +++ b/web/src/test/auto/headless/engine/main/headless/languageProcessor.spec.js @@ -44,7 +44,7 @@ describe('LanguageProcessor', function() { let languageProcessor = new LanguageProcessor(worker, new TranscriptionCache()); // These checks are lifted from the keyboard init checks found in - // engine/keyboard/tests/cases/basic-init.js. + // web/src/test/auto/headless/engine/js-processor/basic-init.js. assert.isDefined(languageProcessor.lmEngine); assert.isUndefined(languageProcessor.activeModel); assert.isFalse(languageProcessor.isActive); From 89abdbd64c8555bdba88ded14925d2607da653bc Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Wed, 14 Aug 2024 18:13:01 +0200 Subject: [PATCH 22/65] refactor(web): move some files around MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - move `outputTarget.ts` → `js-processor` - move `deadkeys.ts` → `js-processor` - move `stringDivergence.ts` → `js-processor` - split `Mock` into `mock.ts` - create `keyboard/outputTarget.interface.ts` --- web/README.md | 2 +- web/src/app/browser/src/configuration.ts | 3 +- .../app/browser/src/defaultBrowserRules.ts | 4 +- web/src/app/webview/src/contextManager.ts | 3 +- web/src/engine/element-wrappers/build.sh | 2 +- .../element-wrappers/src/outputTarget.ts | 2 +- .../prediction/languageProcessor.interface.ts | 2 +- .../src/prediction/predictionContext.ts | 3 +- .../src/deadkeys.ts | 0 web/src/engine/js-processor/src/index.ts | 5 + .../engine/js-processor/src/kbdInterface.ts | 5 +- .../js-processor/src/keyboardProcessor.ts | 4 +- web/src/engine/js-processor/src/mock.ts | 157 +++++++++++++++++ .../src/outputTarget.ts | 159 +----------------- .../engine/js-processor/src/ruleBehavior.ts | 4 +- .../src/stringDivergence.ts | 0 web/src/engine/keyboard/src/defaultRules.ts | 2 +- web/src/engine/keyboard/src/index.ts | 4 - .../engine/keyboard/src/keyboards/keyboard.ts | 2 +- .../keyboard/src/outputTarget.interface.ts | 104 ++++++++++++ web/src/engine/main/src/contextManagerBase.ts | 4 +- .../engine/main/src/engineConfiguration.ts | 4 +- .../engine/main/src/headless/contextWindow.ts | 2 +- .../main/src/headless/inputProcessor.ts | 12 +- .../main/src/headless/languageProcessor.ts | 2 +- .../main/src/headless/transcriptionCache.ts | 2 +- web/src/engine/osk/src/visualKeyboard.ts | 4 +- .../element_interfaces.spec.ts | 3 +- .../element-wrappers/target_mocks.spec.ts | 3 +- .../cases/keyboard/domKeyboardLoader.spec.ts | 4 +- .../prediction/predictionContext.spec.js | 4 +- .../engine/js-processor/engine/context.js | 4 +- .../js-processor/engine/notany_context.js | 4 +- .../engine/js-processor/kbdInterface.tests.js | 4 +- .../headless/engine/js-processor/mocks.js | 2 +- .../js-processor/non-positional-rules.js | 4 +- .../js-processor/specialized-backspace.js | 4 +- .../engine/js-processor/transcriptions.js | 2 +- .../engine/keyboard/keyboard-loading.js | 4 +- .../tools/testing/recorder-core/src/index.ts | 4 +- .../testing/recorder-core/src/nodeProctor.ts | 3 +- .../testing/recorder-core/src/proctor.ts | 2 +- .../tools/testing/recorder/browserProctor.ts | 2 +- 43 files changed, 334 insertions(+), 216 deletions(-) rename web/src/engine/{keyboard => js-processor}/src/deadkeys.ts (100%) create mode 100644 web/src/engine/js-processor/src/mock.ts rename web/src/engine/{keyboard => js-processor}/src/outputTarget.ts (69%) rename web/src/engine/{keyboard => js-processor}/src/stringDivergence.ts (100%) create mode 100644 web/src/engine/keyboard/src/outputTarget.interface.ts diff --git a/web/README.md b/web/README.md index 1a30362e9bc..7cd9e02f002 100644 --- a/web/README.md +++ b/web/README.md @@ -119,7 +119,7 @@ graph TD; Device["/web/src/engine/device-detect"]; Device----->WebUtils; Elements["/web/src/engine/element-wrappers"]; - Elements-->KP; + Elements-->JSProc; KeyboardCache["/web/src/engine/package-cache"]; KeyboardCache-->Interfaces; DomUtils["/web/src/engine/dom-utils"]; diff --git a/web/src/app/browser/src/configuration.ts b/web/src/app/browser/src/configuration.ts index 35983ac30c6..df2153df828 100644 --- a/web/src/app/browser/src/configuration.ts +++ b/web/src/app/browser/src/configuration.ts @@ -1,8 +1,7 @@ import { EngineConfiguration, InitOptionSpec, InitOptionDefaults } from "keyman/engine/main"; import { OutputTarget as DOMOutputTarget } from 'keyman/engine/element-wrappers'; -import { isEmptyTransform, OutputTarget } from 'keyman/engine/keyboard'; -import { RuleBehavior } from 'keyman/engine/js-processor'; +import { isEmptyTransform, OutputTarget, RuleBehavior } from 'keyman/engine/js-processor'; import { AlertHost } from "./utils/alertHost.js"; import { whenDocumentReady } from "./utils/documentReady.js"; diff --git a/web/src/app/browser/src/defaultBrowserRules.ts b/web/src/app/browser/src/defaultBrowserRules.ts index 46f80664f7e..4f0ffbe012e 100644 --- a/web/src/app/browser/src/defaultBrowserRules.ts +++ b/web/src/app/browser/src/defaultBrowserRules.ts @@ -2,9 +2,9 @@ import { ModifierKeyConstants } from '@keymanapp/common-types'; import { Codes, DefaultRules, - type KeyEvent, - type OutputTarget + type KeyEvent } from 'keyman/engine/keyboard'; +import { type OutputTarget } from 'keyman/engine/js-processor'; import ContextManager from './contextManager.js'; diff --git a/web/src/app/webview/src/contextManager.ts b/web/src/app/webview/src/contextManager.ts index de413481420..2b242de39c6 100644 --- a/web/src/app/webview/src/contextManager.ts +++ b/web/src/app/webview/src/contextManager.ts @@ -1,4 +1,5 @@ -import { type Keyboard, Mock, OutputTarget, Transcription, findCommonSubstringEndIndex, isEmptyTransform, TextTransform } from 'keyman/engine/keyboard'; +import { type Keyboard } from 'keyman/engine/keyboard'; +import { Mock, OutputTarget, Transcription, findCommonSubstringEndIndex, isEmptyTransform, TextTransform } from 'keyman/engine/js-processor'; import { KeyboardStub } from 'keyman/engine/package-cache'; import { ContextManagerBase } from 'keyman/engine/main'; import { WebviewConfiguration } from './configuration.js'; diff --git a/web/src/engine/element-wrappers/build.sh b/web/src/engine/element-wrappers/build.sh index 1d0f5802132..e188c7dd414 100755 --- a/web/src/engine/element-wrappers/build.sh +++ b/web/src/engine/element-wrappers/build.sh @@ -13,7 +13,7 @@ SUBPROJECT_NAME=engine/element-wrappers # ################################ Main script ################################ builder_describe "Builds DOM-based OutputTarget subclasses used by the Keyman Engine for Web (KMW)." \ - "@/web/src/engine/keyboard" \ + "@/web/src/engine/js-processor" \ "clean" \ "configure" \ "build" \ diff --git a/web/src/engine/element-wrappers/src/outputTarget.ts b/web/src/engine/element-wrappers/src/outputTarget.ts index 5d0f2e38ce2..43623af7812 100644 --- a/web/src/engine/element-wrappers/src/outputTarget.ts +++ b/web/src/engine/element-wrappers/src/outputTarget.ts @@ -1,4 +1,4 @@ -import { OutputTarget as OutputTargetBase } from "keyman/engine/keyboard"; +import { OutputTarget as OutputTargetBase } from "keyman/engine/js-processor"; import { EventEmitter } from 'eventemitter3'; export default abstract class OutputTarget extends OutputTargetBase { diff --git a/web/src/engine/interfaces/src/prediction/languageProcessor.interface.ts b/web/src/engine/interfaces/src/prediction/languageProcessor.interface.ts index 84e78519879..df5ebae8968 100644 --- a/web/src/engine/interfaces/src/prediction/languageProcessor.interface.ts +++ b/web/src/engine/interfaces/src/prediction/languageProcessor.interface.ts @@ -1,7 +1,7 @@ /// import { EventEmitter } from "eventemitter3"; -import { OutputTarget } from "keyman/engine/keyboard"; +import { OutputTarget } from "keyman/engine/js-processor"; 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 dabeb366da2..221875e62cb 100644 --- a/web/src/engine/interfaces/src/prediction/predictionContext.ts +++ b/web/src/engine/interfaces/src/prediction/predictionContext.ts @@ -1,7 +1,6 @@ import { EventEmitter } from "eventemitter3"; import { type LanguageProcessorSpec , ReadySuggestions, type InvalidateSourceEnum, StateChangeHandler } from './languageProcessor.interface.js'; -import { type OutputTarget } from "keyman/engine/keyboard"; -import { type KeyboardProcessor } from 'keyman/engine/js-processor'; +import { type KeyboardProcessor, type OutputTarget } from 'keyman/engine/js-processor'; interface PredictionContextEventMap { update: (suggestions: Suggestion[]) => void; diff --git a/web/src/engine/keyboard/src/deadkeys.ts b/web/src/engine/js-processor/src/deadkeys.ts similarity index 100% rename from web/src/engine/keyboard/src/deadkeys.ts rename to web/src/engine/js-processor/src/deadkeys.ts diff --git a/web/src/engine/js-processor/src/index.ts b/web/src/engine/js-processor/src/index.ts index f87a044bd73..1755499119c 100644 --- a/web/src/engine/js-processor/src/index.ts +++ b/web/src/engine/js-processor/src/index.ts @@ -4,3 +4,8 @@ export { default as RuleBehavior } from "./ruleBehavior.js"; export * from './kbdInterface.js'; export { default as KeyboardInterface } from "./kbdInterface.js"; export * from "./systemStores.js"; +export * from "./deadkeys.js"; +export { default as OutputTarget } from "./outputTarget.js"; +export * from "./outputTarget.js"; +export { Mock } from "./mock.js"; +export * from "./stringDivergence.js"; diff --git a/web/src/engine/js-processor/src/kbdInterface.ts b/web/src/engine/js-processor/src/kbdInterface.ts index 73332dc8c83..b39b2baea25 100644 --- a/web/src/engine/js-processor/src/kbdInterface.ts +++ b/web/src/engine/js-processor/src/kbdInterface.ts @@ -7,7 +7,10 @@ import { type DeviceSpec } from "@keymanapp/web-utils"; import { ModifierKeyConstants } from '@keymanapp/common-types'; -import { Codes, type KeyEvent, type Deadkey, KeyMapping, type OutputTarget, Mock, Keyboard, KeyboardHarness, KeyboardKeymanGlobal, VariableStoreDictionary } from "keyman/engine/keyboard"; +import { Codes, type KeyEvent, KeyMapping, Keyboard, KeyboardHarness, KeyboardKeymanGlobal, VariableStoreDictionary } from "keyman/engine/keyboard"; +import type OutputTarget from './outputTarget.js'; +import { type Deadkey } from './deadkeys.js'; +import { Mock } from "./mock.js"; import RuleBehavior from "./ruleBehavior.js"; import { ComplexKeyboardStore, type KeyboardStore, KeyboardStoreElement, SystemStoreIDs, SystemStore, MutableSystemStore, PlatformSystemStore, VariableStore, VariableStoreSerializer } from "./systemStores.js"; diff --git a/web/src/engine/js-processor/src/keyboardProcessor.ts b/web/src/engine/js-processor/src/keyboardProcessor.ts index 861ecadb369..dea537dfdf6 100644 --- a/web/src/engine/js-processor/src/keyboardProcessor.ts +++ b/web/src/engine/js-processor/src/keyboardProcessor.ts @@ -10,8 +10,10 @@ import { EventEmitter } from 'eventemitter3'; import { ModifierKeyConstants } from '@keymanapp/common-types'; import { Codes, type Keyboard, MinimalKeymanGlobal, KeyEvent, Layouts, - type OutputTarget, Mock, DefaultRules, EmulationKeystrokes + DefaultRules, EmulationKeystrokes } from "keyman/engine/keyboard"; +import { Mock } from "./mock.js"; +import type OutputTarget from "./outputTarget.js"; import RuleBehavior from "./ruleBehavior.js"; import KeyboardInterface from './kbdInterface.js'; import { DeviceSpec, globalObject } from "@keymanapp/web-utils"; diff --git a/web/src/engine/js-processor/src/mock.ts b/web/src/engine/js-processor/src/mock.ts new file mode 100644 index 00000000000..151d8313caa --- /dev/null +++ b/web/src/engine/js-processor/src/mock.ts @@ -0,0 +1,157 @@ +import OutputTarget from './outputTarget.js'; + +// Due to some interesting requirements on compile ordering in TS, +// this needs to be in the same file as OutputTarget now. +export class Mock extends OutputTarget { + text: string; + + selStart: number; + selEnd: number; + selForward: boolean = true; + + constructor(text?: string, caretPos?: number); + constructor(text?: string, selStart?: number, selEnd?: number); + constructor(text?: string, selStart?: number, selEnd?: number) { + super(); + + this.text = text ? text : ""; + var defaultLength = this.text._kmwLength(); + + // Ensures that `caretPos == 0` is handled correctly. + this.selStart = typeof selStart == "number" ? selStart : defaultLength; + + // If no selection-end is set, selection length is implied to be 0. + this.selEnd = typeof selEnd == "number" ? selEnd : this.selStart; + + this.selForward = this.selEnd >= this.selStart; + } + + // Clones the state of an existing EditableElement, creating a Mock version of its state. + static from(outputTarget: OutputTarget, readonly?: boolean) { + let clone: Mock; + + if (outputTarget instanceof Mock) { + // Avoids the need to run expensive kmwstring.ts / `_kmwLength()` + // calculations when deep-copying Mock instances. + let priorMock = outputTarget as Mock; + clone = new Mock(priorMock.text, priorMock.selStart, priorMock.selEnd); + } else { + const text = outputTarget.getText(); + const textLen = text._kmwLength(); + + // If !hasSelection() + let selectionStart: number = textLen; + let selectionEnd: number = 0; + + if (outputTarget.hasSelection()) { + let beforeText = outputTarget.getTextBeforeCaret(); + let afterText = outputTarget.getTextAfterCaret(); + selectionStart = beforeText._kmwLength(); + selectionEnd = textLen - afterText._kmwLength(); + } + + // readonly group or not, the returned Mock remains the same. + // New-context events should act as if the caret were at the earlier-in-context + // side of the selection, same as standard keyboard rules. + clone = new Mock(text, selectionStart, selectionEnd); + } + + // Also duplicate deadkey state! (Needed for fat-finger ops.) + clone.setDeadkeys(outputTarget.deadkeys()); + + return clone; + } + + clearSelection(): void { + this.text = this.getTextBeforeCaret() + this.getTextAfterCaret(); + this.selEnd = this.selStart; + this.selForward = true; + } + + invalidateSelection(): void { + return; + } + + isSelectionEmpty(): boolean { + return this.selStart == this.selEnd; + } + + hasSelection(): boolean { + return true; + } + + getDeadkeyCaret(): number { + return this.selStart; + } + + setSelection(start: number, end?: number) { + this.selStart = start; + this.selEnd = typeof end == 'number' ? end : start; + + this.selForward = end >= start; + if (!this.selForward) { + let temp = this.selStart; + this.selStart = this.selEnd; + this.selEnd = temp; + } + } + + getTextBeforeCaret(): string { + return this.text.kmwSubstr(0, this.selStart); + } + + getSelectedText(): string { + return this.text.kmwSubstr(this.selStart, this.selEnd - this.selStart); + } + + getTextAfterCaret(): string { + return this.text.kmwSubstr(this.selEnd); + } + + getText(): string { + return this.text; + } + + deleteCharsBeforeCaret(dn: number): void { + if (dn >= 0) { + if (dn > this.selStart) { + dn = this.selStart; + } + this.adjustDeadkeys(-dn); + this.text = this.text.kmwSubstr(0, this.selStart - dn) + this.text.kmwSubstr(this.selStart); + this.selStart -= dn; + this.selEnd -= dn; + } + } + + insertTextBeforeCaret(s: string): void { + this.adjustDeadkeys(s._kmwLength()); + this.text = this.getTextBeforeCaret() + s + this.text.kmwSubstr(this.selStart); + this.selStart += s.kmwLength(); + this.selEnd += s.kmwLength(); + } + + handleNewlineAtCaret(): void { + this.insertTextBeforeCaret('\n'); + } + + protected setTextAfterCaret(s: string): void { + this.text = this.getTextBeforeCaret() + s; + } + + /** + * Indicates if this Mock represents an identical context to that of another Mock. + * @param other + * @returns + */ + isEqual(other: Mock) { + return this.text == other.text + && this.selStart == other.selStart + && this.selEnd == other.selEnd + && this.deadkeys().equal(other.deadkeys()); + } + + doInputEvent() { + // Mock isn't backed by an element, so it won't have any event listeners. + } +} diff --git a/web/src/engine/keyboard/src/outputTarget.ts b/web/src/engine/js-processor/src/outputTarget.ts similarity index 69% rename from web/src/engine/keyboard/src/outputTarget.ts rename to web/src/engine/js-processor/src/outputTarget.ts index 63c4c8a042f..f48647092c7 100644 --- a/web/src/engine/keyboard/src/outputTarget.ts +++ b/web/src/engine/js-processor/src/outputTarget.ts @@ -2,11 +2,12 @@ import { extendString } from "@keymanapp/web-utils"; import { findCommonSubstringEndIndex } from "./stringDivergence.js"; +import { Mock } from "./mock.js"; extendString(); // Defines deadkey management in a manner attachable to each element interface. -import type KeyEvent from "./keyEvent.js"; +import { type KeyEvent } from 'keyman/engine/keyboard'; import { Deadkey, DeadkeyTracker } from "./deadkeys.js"; // Also relies on string-extensions provided by the web-utils package. @@ -307,159 +308,3 @@ export default abstract class OutputTarget { */ abstract doInputEvent(): void; } - -// Due to some interesting requirements on compile ordering in TS, -// this needs to be in the same file as OutputTarget now. -export class Mock extends OutputTarget { - text: string; - - selStart: number; - selEnd: number; - selForward: boolean = true; - - constructor(text?: string, caretPos?: number); - constructor(text?: string, selStart?: number, selEnd?: number); - constructor(text?: string, selStart?: number, selEnd?: number) { - super(); - - this.text = text ? text : ""; - var defaultLength = this.text._kmwLength(); - - // Ensures that `caretPos == 0` is handled correctly. - this.selStart = typeof selStart == "number" ? selStart : defaultLength; - - // If no selection-end is set, selection length is implied to be 0. - this.selEnd = typeof selEnd == "number" ? selEnd : this.selStart; - - this.selForward = this.selEnd >= this.selStart; - } - - // Clones the state of an existing EditableElement, creating a Mock version of its state. - static from(outputTarget: OutputTarget, readonly?: boolean) { - let clone: Mock; - - if(outputTarget instanceof Mock) { - // Avoids the need to run expensive kmwstring.ts / `_kmwLength()` - // calculations when deep-copying Mock instances. - let priorMock = outputTarget as Mock; - clone = new Mock(priorMock.text, priorMock.selStart, priorMock.selEnd); - } else { - const text = outputTarget.getText(); - const textLen = text._kmwLength(); - - // If !hasSelection() - let selectionStart: number = textLen; - let selectionEnd: number = 0; - - if(outputTarget.hasSelection()) { - let beforeText = outputTarget.getTextBeforeCaret(); - let afterText = outputTarget.getTextAfterCaret(); - selectionStart = beforeText._kmwLength(); - selectionEnd = textLen - afterText._kmwLength(); - } - - // readonly group or not, the returned Mock remains the same. - // New-context events should act as if the caret were at the earlier-in-context - // side of the selection, same as standard keyboard rules. - clone = new Mock(text, selectionStart, selectionEnd); - } - - // Also duplicate deadkey state! (Needed for fat-finger ops.) - clone.setDeadkeys(outputTarget.deadkeys()); - - return clone; - } - - clearSelection(): void { - this.text = this.getTextBeforeCaret() + this.getTextAfterCaret(); - this.selEnd = this.selStart; - this.selForward = true; - } - - invalidateSelection(): void { - return; - } - - isSelectionEmpty(): boolean { - return this.selStart == this.selEnd; - } - - hasSelection(): boolean { - return true; - } - - getDeadkeyCaret(): number { - return this.selStart; - } - - setSelection(start: number, end?: number) { - this.selStart = start; - this.selEnd = typeof end == 'number' ? end : start; - - this.selForward = end >= start; - if(!this.selForward) { - let temp = this.selStart; - this.selStart = this.selEnd; - this.selEnd = temp; - } - } - - getTextBeforeCaret(): string { - return this.text.kmwSubstr(0, this.selStart); - } - - getSelectedText(): string { - return this.text.kmwSubstr(this.selStart, this.selEnd - this.selStart); - } - - getTextAfterCaret(): string { - return this.text.kmwSubstr(this.selEnd); - } - - getText(): string { - return this.text; - } - - deleteCharsBeforeCaret(dn: number): void { - if(dn >= 0) { - if(dn > this.selStart) { - dn = this.selStart; - } - this.adjustDeadkeys(-dn); - this.text = this.text.kmwSubstr(0, this.selStart - dn) + this.text.kmwSubstr(this.selStart); - this.selStart -= dn; - this.selEnd -= dn; - } - } - - insertTextBeforeCaret(s: string): void { - this.adjustDeadkeys(s._kmwLength()); - this.text = this.getTextBeforeCaret() + s + this.text.kmwSubstr(this.selStart); - this.selStart += s.kmwLength(); - this.selEnd += s.kmwLength(); - } - - handleNewlineAtCaret(): void { - this.insertTextBeforeCaret('\n'); - } - - protected setTextAfterCaret(s: string): void { - this.text = this.getTextBeforeCaret() + s; - } - - /** - * Indicates if this Mock represents an identical context to that of another Mock. - * @param other - * @returns - */ - isEqual(other: Mock) { - return this.text == other.text - && this.selStart == other.selStart - && this.selEnd == other.selEnd - && this.deadkeys().equal(other.deadkeys()); - } - - doInputEvent() { - // Mock isn't backed by an element, so it won't have any event listeners. - } -} \ No newline at end of file diff --git a/web/src/engine/js-processor/src/ruleBehavior.ts b/web/src/engine/js-processor/src/ruleBehavior.ts index 0c0f6c0db5d..a6b2c9973a1 100644 --- a/web/src/engine/js-processor/src/ruleBehavior.ts +++ b/web/src/engine/js-processor/src/ruleBehavior.ts @@ -1,7 +1,9 @@ /// import KeyboardProcessor from "./keyboardProcessor.js"; -import { OutputTarget, Mock, type Transcription, VariableStoreDictionary } from "keyman/engine/keyboard"; +import { VariableStoreDictionary } from "keyman/engine/keyboard"; +import OutputTarget, { type Transcription } from './outputTarget.js'; +import { Mock } from "./mock.js"; import { type VariableStore } from "./systemStores.js"; /** diff --git a/web/src/engine/keyboard/src/stringDivergence.ts b/web/src/engine/js-processor/src/stringDivergence.ts similarity index 100% rename from web/src/engine/keyboard/src/stringDivergence.ts rename to web/src/engine/js-processor/src/stringDivergence.ts diff --git a/web/src/engine/keyboard/src/defaultRules.ts b/web/src/engine/keyboard/src/defaultRules.ts index 94acb02688e..5512114d937 100644 --- a/web/src/engine/keyboard/src/defaultRules.ts +++ b/web/src/engine/keyboard/src/defaultRules.ts @@ -7,7 +7,7 @@ import { ModifierKeyConstants } from '@keymanapp/common-types'; import Codes from './codes.js'; import type KeyEvent from './keyEvent.js'; -import type OutputTarget from './outputTarget.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 1963ed01c63..f5a4edea71d 100644 --- a/web/src/engine/keyboard/src/index.ts +++ b/web/src/engine/keyboard/src/index.ts @@ -26,15 +26,11 @@ export { default as StateKeyMap } from "./keyboards/stateKeyMap.js"; export { default as Codes } from "./codes.js"; export * from "./codes.js"; -export * from "./deadkeys.js"; export { default as DefaultRules } from "./defaultRules.js"; export * from "./defaultRules.js"; export { default as KeyEvent } from "./keyEvent.js"; export * from "./keyEvent.js"; export { default as KeyMapping } from "./keyMapping.js"; -export { default as OutputTarget } from "./outputTarget.js"; -export * from "./outputTarget.js"; -export * from "./stringDivergence.js"; export * from "@keymanapp/web-utils"; diff --git a/web/src/engine/keyboard/src/keyboards/keyboard.ts b/web/src/engine/keyboard/src/keyboards/keyboard.ts index 0c0ff75512a..42463cd6e7f 100644 --- a/web/src/engine/keyboard/src/keyboards/keyboard.ts +++ b/web/src/engine/keyboard/src/keyboards/keyboard.ts @@ -2,7 +2,7 @@ import Codes from "../codes.js"; import { EncodedVisualKeyboard, LayoutSpec, Layouts } from "./defaultLayouts.js"; import { ActiveKey, ActiveLayout, ActiveSubKey } from "./activeLayout.js"; import KeyEvent from "../keyEvent.js"; -import type OutputTarget from "../outputTarget.js"; +import { type OutputTarget } from "../outputTarget.interface.js"; import { ModifierKeyConstants, TouchLayout } from "@keymanapp/common-types"; type TouchLayoutSpec = TouchLayout.TouchLayoutPlatform & { isDefault?: boolean}; diff --git a/web/src/engine/keyboard/src/outputTarget.interface.ts b/web/src/engine/keyboard/src/outputTarget.interface.ts new file mode 100644 index 00000000000..410094c812c --- /dev/null +++ b/web/src/engine/keyboard/src/outputTarget.interface.ts @@ -0,0 +1,104 @@ +export interface OutputTarget { + /** + * Signifies that this OutputTarget has no default key processing behaviors. This should be false + * for OutputTargets backed by web elements like HTMLInputElement or HTMLTextAreaElement. + */ + get isSynthetic(): boolean; + + resetContext(): void; + + hasDeadkeyMatch(n: number, d: number): boolean; + + insertDeadkeyBeforeCaret(d: number): void; + + /** + * Clears any selected text within the wrapper's element(s). + * Silently does nothing if no such text exists. + */ + clearSelection(): void; + + /** + * Clears any cached selection-related state values. + */ + invalidateSelection(): void; + + /** + * Indicates whether or not the underlying element has its own selection (input, textarea) + * or is part of (or possesses) the DOM's active selection. Don't confuse with isSelectionEmpty(). + * + * TODO: rename to supportsOwnSelection + */ + hasSelection(): boolean; + + /** + * Returns true if there is no current selection -- that is, the selection range is empty + */ + isSelectionEmpty(): boolean; + + /** + * Returns an index corresponding to the caret's position for use with deadkeys. + */ + getDeadkeyCaret(): number; + + /** + * Relative to the caret, gets the current context within the wrapper's element. + */ + getTextBeforeCaret(): string; + + /** + * Gets the element's-currently selected text. + */ + getSelectedText(): string; + + /** + * Relative to the caret (and/or active selection), gets the element's text after the caret, + * excluding any actively selected text that would be immediately replaced upon text entry. + */ + getTextAfterCaret(): string; + + /** + * Gets the element's full text, including any text that is actively selected. + */ + getText(): string; + + /** + * Performs context deletions (from the left of the caret) as needed by the KeymanWeb engine and + * corrects the location of any affected deadkeys. + * + * Does not delete deadkeys (b/c KMW 1 & 2 behavior maintenance). + * @param dn The number of characters to delete. If negative, context will be left unchanged. + */ + deleteCharsBeforeCaret(dn: number): void; + + /** + * Inserts text immediately before the caret's current position, moving the caret after the + * newly inserted text in the process along with any affected deadkeys. + * + * @param s Text to insert before the caret's current position. + */ + insertTextBeforeCaret(s: string): void; + + /** + * Allows element-specific handling for ENTER key inputs. Conceptually, this should usually + * correspond to `insertTextBeforeCaret('\n'), but actual implementation will vary greatly among + * elements. + */ + handleNewlineAtCaret(): void; + + /** + * Saves element-specific state properties prone to mutation, enabling restoration after + * text-output operations. + */ + saveProperties(): void; + + /** + * Restores previously-saved element-specific state properties. Designed for use after text-output + * ops to facilitate more-seamless web-dev and user interactions. + */ + restoreProperties(): void; + + /** + * Generates a synthetic event on the underlying element, signalling that its value has changed. + */ + doInputEvent(): void; +} diff --git a/web/src/engine/main/src/contextManagerBase.ts b/web/src/engine/main/src/contextManagerBase.ts index f20dd19d007..5c774aa72d0 100644 --- a/web/src/engine/main/src/contextManagerBase.ts +++ b/web/src/engine/main/src/contextManagerBase.ts @@ -1,6 +1,6 @@ import { EventEmitter } from 'eventemitter3'; -import { ManagedPromise, type Keyboard, type OutputTarget } from 'keyman/engine/keyboard'; -import { type KeyboardInterface } from 'keyman/engine/js-processor'; +import { ManagedPromise, type Keyboard } from 'keyman/engine/keyboard'; +import { type KeyboardInterface, type OutputTarget } from 'keyman/engine/js-processor'; import { StubAndKeyboardCache, type KeyboardStub } from 'keyman/engine/package-cache'; import { PredictionContext } from 'keyman/engine/interfaces'; import { EngineConfiguration } from './engineConfiguration.js'; diff --git a/web/src/engine/main/src/engineConfiguration.ts b/web/src/engine/main/src/engineConfiguration.ts index d6f6f0d6987..050a7be11e5 100644 --- a/web/src/engine/main/src/engineConfiguration.ts +++ b/web/src/engine/main/src/engineConfiguration.ts @@ -1,7 +1,7 @@ import { EventEmitter } from "eventemitter3"; -import { DeviceSpec, KeyboardProperties, ManagedPromise, OutputTarget, physicalKeyDeviceAlias, SpacebarText } from "keyman/engine/keyboard"; -import { RuleBehavior } from 'keyman/engine/js-processor'; +import { DeviceSpec, KeyboardProperties, ManagedPromise, physicalKeyDeviceAlias, SpacebarText } from "keyman/engine/keyboard"; +import { OutputTarget, RuleBehavior } from 'keyman/engine/js-processor'; import { PathConfiguration, PathOptionDefaults, PathOptionSpec } from "keyman/engine/interfaces"; import { Device } from "keyman/engine/device-detect"; import { KeyboardStub } from "keyman/engine/package-cache"; diff --git a/web/src/engine/main/src/headless/contextWindow.ts b/web/src/engine/main/src/headless/contextWindow.ts index b3337c29e53..9fcd1458b2a 100644 --- a/web/src/engine/main/src/headless/contextWindow.ts +++ b/web/src/engine/main/src/headless/contextWindow.ts @@ -1,4 +1,4 @@ -import { Mock } from "keyman/engine/keyboard"; +import { Mock } from "keyman/engine/js-processor"; export default class ContextWindow implements Context { // Used to limit the range of context replicated for use of keyboard rules within diff --git a/web/src/engine/main/src/headless/inputProcessor.ts b/web/src/engine/main/src/headless/inputProcessor.ts index 9ff0c4b81c8..6d8904c563d 100644 --- a/web/src/engine/main/src/headless/inputProcessor.ts +++ b/web/src/engine/main/src/headless/inputProcessor.ts @@ -7,16 +7,18 @@ import { LanguageProcessor } from "./languageProcessor.js"; import type { ModelSpec } from "keyman/engine/interfaces"; import { globalObject, DeviceSpec } from "@keymanapp/web-utils"; +import { Codes, type Keyboard, type KeyEvent } from "keyman/engine/keyboard"; import { type Alternate, - Codes, isEmptyTransform, - type Keyboard, - type KeyEvent, + KeyboardInterface, + KeyboardProcessor, Mock, type OutputTarget, -} from "keyman/engine/keyboard"; -import { KeyboardInterface, KeyboardProcessor, RuleBehavior, type ProcessorInitOptions, SystemStoreIDs } from 'keyman/engine/js-processor'; + RuleBehavior, + type ProcessorInitOptions, + SystemStoreIDs +} from 'keyman/engine/js-processor'; import { TranscriptionCache } from "./transcriptionCache.js"; diff --git a/web/src/engine/main/src/headless/languageProcessor.ts b/web/src/engine/main/src/headless/languageProcessor.ts index 8f93d39d873..c1c1721484b 100644 --- a/web/src/engine/main/src/headless/languageProcessor.ts +++ b/web/src/engine/main/src/headless/languageProcessor.ts @@ -1,6 +1,6 @@ import { EventEmitter } from "eventemitter3"; import { LMLayer } from "@keymanapp/lexical-model-layer/web"; -import { OutputTarget, Transcription, Mock } from "keyman/engine/keyboard"; +import { OutputTarget, Transcription, Mock } from "keyman/engine/js-processor"; import { LanguageProcessorEventMap, ModelSpec, StateChangeEnum, ReadySuggestions } from 'keyman/engine/interfaces'; import ContextWindow from "./contextWindow.js"; import { TranscriptionCache } from "./transcriptionCache.js"; diff --git a/web/src/engine/main/src/headless/transcriptionCache.ts b/web/src/engine/main/src/headless/transcriptionCache.ts index 9430bde5ee8..af05853e174 100644 --- a/web/src/engine/main/src/headless/transcriptionCache.ts +++ b/web/src/engine/main/src/headless/transcriptionCache.ts @@ -1,4 +1,4 @@ -import { Transcription } from "keyman/engine/keyboard"; +import { Transcription } from "keyman/engine/js-processor"; const TRANSCRIPTION_BUFFER_SIZE = 10; diff --git a/web/src/engine/osk/src/visualKeyboard.ts b/web/src/engine/osk/src/visualKeyboard.ts index dd898e1ee97..e88cf2ac740 100644 --- a/web/src/engine/osk/src/visualKeyboard.ts +++ b/web/src/engine/osk/src/visualKeyboard.ts @@ -13,9 +13,9 @@ import { StateKeyMap, ActiveSubKey, timedPromise, - ActiveKeyBase, - isEmptyTransform + ActiveKeyBase } from 'keyman/engine/keyboard'; +import { isEmptyTransform } from 'keyman/engine/js-processor'; import { buildCorrectiveLayout } from './correctionLayout.js'; import { distributionFromDistanceMaps, keyTouchDistances } from './corrections.js'; diff --git a/web/src/test/auto/dom/cases/element-wrappers/element_interfaces.spec.ts b/web/src/test/auto/dom/cases/element-wrappers/element_interfaces.spec.ts index 813ce789110..cdfc8814af3 100644 --- a/web/src/test/auto/dom/cases/element-wrappers/element_interfaces.spec.ts +++ b/web/src/test/auto/dom/cases/element-wrappers/element_interfaces.spec.ts @@ -1,6 +1,7 @@ import { assert } from 'chai'; -import { extendString, Mock } from 'keyman/engine/keyboard'; +import { extendString } from 'keyman/engine/keyboard'; +import { Mock } from 'keyman/engine/js-processor'; import * as wrappers from 'keyman/engine/element-wrappers'; import { DynamicElements } from '../../test_utils.js'; diff --git a/web/src/test/auto/dom/cases/element-wrappers/target_mocks.spec.ts b/web/src/test/auto/dom/cases/element-wrappers/target_mocks.spec.ts index 85116eaa8ac..707d8638997 100644 --- a/web/src/test/auto/dom/cases/element-wrappers/target_mocks.spec.ts +++ b/web/src/test/auto/dom/cases/element-wrappers/target_mocks.spec.ts @@ -1,6 +1,7 @@ import { assert } from 'chai'; -import { extendString, Mock } from 'keyman/engine/keyboard'; +import { extendString } from 'keyman/engine/keyboard'; +import { Mock } from 'keyman/engine/js-processor'; import { Input } from 'keyman/engine/element-wrappers'; import { DEFAULT_BROWSER_TIMEOUT } from '@keymanapp/common-test-resources/test-timeouts.mjs'; diff --git a/web/src/test/auto/dom/cases/keyboard/domKeyboardLoader.spec.ts b/web/src/test/auto/dom/cases/keyboard/domKeyboardLoader.spec.ts index bcf4afcf650..da610402eb0 100644 --- a/web/src/test/auto/dom/cases/keyboard/domKeyboardLoader.spec.ts +++ b/web/src/test/auto/dom/cases/keyboard/domKeyboardLoader.spec.ts @@ -1,8 +1,8 @@ import { assert } from 'chai'; import { DOMKeyboardLoader } from 'keyman/engine/keyboard/dom-keyboard-loader'; -import { extendString, KeyboardHarness, Keyboard, MinimalKeymanGlobal, Mock, DeviceSpec, KeyboardKeymanGlobal } from 'keyman/engine/keyboard'; -import { KeyboardInterface } from 'keyman/engine/js-processor'; +import { extendString, KeyboardHarness, Keyboard, MinimalKeymanGlobal, DeviceSpec, KeyboardKeymanGlobal } from 'keyman/engine/keyboard'; +import { KeyboardInterface, Mock } from 'keyman/engine/js-processor'; declare let window: typeof globalThis; // KeymanEngine from the web/ folder... when available. diff --git a/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js b/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js index 39ab4aea59d..dbc24cad4ff 100644 --- a/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js +++ b/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js @@ -4,8 +4,8 @@ import sinon from 'sinon'; import { LanguageProcessor, TranscriptionCache } from 'keyman/engine/main'; import { PredictionContext } from 'keyman/engine/interfaces'; import { Worker as LMWorker } from "@keymanapp/lexical-model-layer/node"; -import { DeviceSpec, Mock } from 'keyman/engine/keyboard'; -import { KeyboardProcessor } from 'keyman/engine/js-processor'; +import { DeviceSpec } from 'keyman/engine/keyboard'; +import { KeyboardProcessor, Mock } from 'keyman/engine/js-processor'; function compileDummyModel(suggestionSets) { return ` diff --git a/web/src/test/auto/headless/engine/js-processor/engine/context.js b/web/src/test/auto/headless/engine/js-processor/engine/context.js index 3b318607a0d..a355ead2650 100644 --- a/web/src/test/auto/headless/engine/js-processor/engine/context.js +++ b/web/src/test/auto/headless/engine/js-processor/engine/context.js @@ -3,8 +3,8 @@ import { assert } from 'chai'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; -import { KeyboardInterface, KeyboardProcessor } from 'keyman/engine/js-processor'; +import { MinimalKeymanGlobal } from 'keyman/engine/keyboard'; +import { KeyboardInterface, KeyboardProcessor, Mock } from 'keyman/engine/js-processor'; import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; import { NodeProctor, RecordedKeystrokeSequence } from '@keymanapp/recorder-core'; diff --git a/web/src/test/auto/headless/engine/js-processor/engine/notany_context.js b/web/src/test/auto/headless/engine/js-processor/engine/notany_context.js index 1fc2ec01297..ecc7dd92d0d 100644 --- a/web/src/test/auto/headless/engine/js-processor/engine/notany_context.js +++ b/web/src/test/auto/headless/engine/js-processor/engine/notany_context.js @@ -3,8 +3,8 @@ import { assert } from 'chai'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; -import { KeyboardInterface } from 'keyman/engine/js-processor'; +import { MinimalKeymanGlobal } from 'keyman/engine/keyboard'; +import { KeyboardInterface, Mock } from 'keyman/engine/js-processor'; import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; import { NodeProctor, RecordedKeystrokeSequence } from '@keymanapp/recorder-core'; import { extendString } from '@keymanapp/web-utils'; diff --git a/web/src/test/auto/headless/engine/js-processor/kbdInterface.tests.js b/web/src/test/auto/headless/engine/js-processor/kbdInterface.tests.js index 03203a840f4..0d084964425 100644 --- a/web/src/test/auto/headless/engine/js-processor/kbdInterface.tests.js +++ b/web/src/test/auto/headless/engine/js-processor/kbdInterface.tests.js @@ -3,8 +3,8 @@ import { assert } from 'chai'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; -import { KeyboardInterface } from 'keyman/engine/js-processor'; +import { MinimalKeymanGlobal } from 'keyman/engine/keyboard'; +import { KeyboardInterface, Mock } from 'keyman/engine/js-processor'; import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; describe('Headless keyboard loading', function () { diff --git a/web/src/test/auto/headless/engine/js-processor/mocks.js b/web/src/test/auto/headless/engine/js-processor/mocks.js index b02f259886f..bad81bfcca4 100644 --- a/web/src/test/auto/headless/engine/js-processor/mocks.js +++ b/web/src/test/auto/headless/engine/js-processor/mocks.js @@ -1,5 +1,5 @@ import { assert } from 'chai'; -import { Mock } from 'keyman/engine/keyboard'; +import { Mock } from 'keyman/engine/js-processor'; describe('Mocks', function() { describe('app|les', () => { diff --git a/web/src/test/auto/headless/engine/js-processor/non-positional-rules.js b/web/src/test/auto/headless/engine/js-processor/non-positional-rules.js index 2ab62a4840c..a65cec6708d 100644 --- a/web/src/test/auto/headless/engine/js-processor/non-positional-rules.js +++ b/web/src/test/auto/headless/engine/js-processor/non-positional-rules.js @@ -4,8 +4,8 @@ import { ModifierKeyConstants } from '@keymanapp/common-types'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { Codes, KeyEvent, MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; -import { KeyboardInterface } from 'keyman/engine/js-processor'; +import { Codes, KeyEvent, MinimalKeymanGlobal } from 'keyman/engine/keyboard'; +import { KeyboardInterface, Mock } from 'keyman/engine/js-processor'; import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; // Compare and contrast the unit tests here with those for app/browser key-event unit testing diff --git a/web/src/test/auto/headless/engine/js-processor/specialized-backspace.js b/web/src/test/auto/headless/engine/js-processor/specialized-backspace.js index 967701c63a1..7e35817f07f 100644 --- a/web/src/test/auto/headless/engine/js-processor/specialized-backspace.js +++ b/web/src/test/auto/headless/engine/js-processor/specialized-backspace.js @@ -4,8 +4,8 @@ import fs from 'fs'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { Codes, KeyEvent, MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; -import { KeyboardInterface, KeyboardProcessor } from 'keyman/engine/js-processor'; +import { Codes, KeyEvent, MinimalKeymanGlobal } from 'keyman/engine/keyboard'; +import { KeyboardInterface, KeyboardProcessor, Mock } from 'keyman/engine/js-processor'; import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; import { ModifierKeyConstants } from '@keymanapp/common-types'; diff --git a/web/src/test/auto/headless/engine/js-processor/transcriptions.js b/web/src/test/auto/headless/engine/js-processor/transcriptions.js index 569b36d3cd6..45c09b3b80c 100644 --- a/web/src/test/auto/headless/engine/js-processor/transcriptions.js +++ b/web/src/test/auto/headless/engine/js-processor/transcriptions.js @@ -1,6 +1,6 @@ import { assert } from 'chai'; -import { Mock, findCommonSubstringEndIndex } from 'keyman/engine/keyboard'; +import { Mock, findCommonSubstringEndIndex } from 'keyman/engine/js-processor'; import { extendString } from '@keymanapp/web-utils'; extendString(); // Ensure KMW's string-extension functionality is available. diff --git a/web/src/test/auto/headless/engine/keyboard/keyboard-loading.js b/web/src/test/auto/headless/engine/keyboard/keyboard-loading.js index 1dc2baad9bf..0dd89a36148 100644 --- a/web/src/test/auto/headless/engine/keyboard/keyboard-loading.js +++ b/web/src/test/auto/headless/engine/keyboard/keyboard-loading.js @@ -3,8 +3,8 @@ import { assert } from 'chai'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); -import { KeyboardHarness, MinimalKeymanGlobal, Mock } from 'keyman/engine/keyboard'; -import { KeyboardInterface } from 'keyman/engine/js-processor'; +import { KeyboardHarness, MinimalKeymanGlobal } from 'keyman/engine/keyboard'; +import { KeyboardInterface, Mock } from 'keyman/engine/js-processor'; import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; describe('Headless keyboard loading', function() { diff --git a/web/src/tools/testing/recorder-core/src/index.ts b/web/src/tools/testing/recorder-core/src/index.ts index caa0262f6b9..2a739710232 100644 --- a/web/src/tools/testing/recorder-core/src/index.ts +++ b/web/src/tools/testing/recorder-core/src/index.ts @@ -1,5 +1,5 @@ -import { type OutputTarget } from "keyman/engine/keyboard"; -import { KeyDistribution, KeyEvent, Mock } from "keyman/engine/keyboard"; +import { Mock, type OutputTarget } from "keyman/engine/js-processor"; +import { KeyDistribution, KeyEvent } from "keyman/engine/keyboard"; import Proctor from "./proctor.js"; diff --git a/web/src/tools/testing/recorder-core/src/nodeProctor.ts b/web/src/tools/testing/recorder-core/src/nodeProctor.ts index e9a08530c8f..204ef219394 100644 --- a/web/src/tools/testing/recorder-core/src/nodeProctor.ts +++ b/web/src/tools/testing/recorder-core/src/nodeProctor.ts @@ -8,7 +8,8 @@ import { RecordedSyntheticKeystroke } from "./index.js"; -import { KeyEvent, KeyEventSpec, Mock, type OutputTarget, KeyboardHarness } from "keyman/engine/keyboard"; +import { KeyEvent, KeyEventSpec, KeyboardHarness } from "keyman/engine/keyboard"; +import { Mock, type OutputTarget } from "keyman/engine/js-processor"; import { DeviceSpec } from "@keymanapp/web-utils"; import { KeyboardInterface, KeyboardProcessor } from 'keyman/engine/js-processor'; diff --git a/web/src/tools/testing/recorder-core/src/proctor.ts b/web/src/tools/testing/recorder-core/src/proctor.ts index 0242b911a1c..ec4f584b048 100644 --- a/web/src/tools/testing/recorder-core/src/proctor.ts +++ b/web/src/tools/testing/recorder-core/src/proctor.ts @@ -1,5 +1,5 @@ import { type DeviceSpec } from "@keymanapp/web-utils"; -import { type OutputTarget } from "keyman/engine/keyboard"; +import { type OutputTarget } from "keyman/engine/js-processor"; import type { KeyboardTest, TestSet, TestSequence } from "./index.js"; diff --git a/web/src/tools/testing/recorder/browserProctor.ts b/web/src/tools/testing/recorder/browserProctor.ts index 73e5a80ea7f..a48e5572cbe 100644 --- a/web/src/tools/testing/recorder/browserProctor.ts +++ b/web/src/tools/testing/recorder/browserProctor.ts @@ -4,7 +4,7 @@ import { type DeviceSpec } from "@keymanapp/web-utils"; -import { type OutputTarget } from "keyman/engine/keyboard"; +import { type OutputTarget } from "keyman/engine/js-processor"; import { type KeymanEngine } from 'keyman/app/browser'; From 4509805f58803c98142e2b4f1be16eb68be47dee Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Thu, 15 Aug 2024 09:04:35 +0700 Subject: [PATCH 23/65] fix(web): restore flick functionality --- .../osk/src/input/gestures/specsForLayout.ts | 115 ++++++++++-------- web/src/engine/osk/src/visualKeyboard.ts | 7 +- 2 files changed, 67 insertions(+), 55 deletions(-) diff --git a/web/src/engine/osk/src/input/gestures/specsForLayout.ts b/web/src/engine/osk/src/input/gestures/specsForLayout.ts index 34d5576e236..649c5537d08 100644 --- a/web/src/engine/osk/src/input/gestures/specsForLayout.ts +++ b/web/src/engine/osk/src/input/gestures/specsForLayout.ts @@ -20,20 +20,8 @@ import { calcLockedDistance, lockedAngleForDir, MAX_TOLERANCE_ANGLE_SKEW, type O import specs = gestures.specs; -export interface GestureParams { +export interface GestureParams { readonly longpress: { - /** - * Allows enabling or disabling the longpress up-flick shortcut for - * keyboards that do not include any defined flick gestures. - * - * Will be ignored (in favor of `false`) for keyboards that do have defined - * flicks. - * - * Note: this is automatically overwritten during keyboard initialization - * to match the keyboard's properties. - */ - permitsFlick: (item?: Item) => boolean, - /** * The minimum _net_ distance traveled before a longpress flick-shortcut will cancel any * conflicting flick models. @@ -98,19 +86,31 @@ export interface GestureParams { * Is currently also used as the max radius for valid flick-reset recentering targets. */ dirLockDist: number + } +} + +export interface FullGestureParams extends GestureParams { + readonly longpress: GestureParams["longpress"] & { + /** + * Allows enabling or disabling the longpress up-flick shortcut for + * keyboards that do not include any defined flick gestures. + * + * Will be ignored (in favor of `false`) for keyboards that do have defined + * flicks. + * + * Note: this is automatically overwritten during keyboard initialization + * to match the keyboard's properties. + */ + permitsFlick: (item?: Item) => boolean }, /** * Indicates whether roaming-touch oriented behaviors should be enabled. - * - * Note that run-time adjustments to this property after initialization will - * not take affect, unlike the other properties of the overall parameter object. */ roamingEnabled?: boolean; } export const DEFAULT_GESTURE_PARAMS: GestureParams = { longpress: { - permitsFlick: () => true, // Note: actual runtime value is determined at runtime based upon row height. // See `VisualKeyboard.refreshLayout`, CTRL-F "Step 3". flickDistStart: 8, @@ -206,17 +206,19 @@ let dummy: ActiveLayout; let dummy2: LayoutGestureSupportFlags = dummy; /** - * Defines the set of gestures appropriate for use with the specified Keyman keyboard. + * Defines the set of gestures appropriate for use with the specified Keyman + * keyboard. * @param layerGroup The active keyboard's layer group - * @param params A set of tweakable gesture parameters. It will be closure-captured - * and referred to by reference; changes to its values will take - * immediate effect during gesture processing. + * @param params A set of tweakable gesture parameters. It will be + * closure-captured and referred to by reference; changes to + * its values will take immediate effect during gesture + * processing. * - * If params.roamingEnabled is unset, it will be initialized by this + * `params.roamingEnabled` will be initialized by this * method based upon layout properties. * @returns */ -export function gestureSetForLayout(flags: LayoutGestureSupportFlags, params: GestureParams): GestureModelDefs { +export function gestureSetForLayout(flags: LayoutGestureSupportFlags, paramObj: GestureParams): GestureModelDefs { // To be used among the `allowsInitialState` contact-model specifications as needed. const gestureKeyFilter = (key: KeyElement, gestureId: string) => { if(!key) { @@ -248,18 +250,33 @@ export function gestureSetForLayout(flags: LayoutGestureSupportFlags, params: Ge } }; - const doRoaming = params.roamingEnabled ||= !flags.hasFlicks; + const params = paramObj as FullGestureParams; + + // Override any prior entries for keyboard-specific configuration. + params.longpress.permitsFlick = (key) => { + const flickSpec = key?.key.spec.flick; + return !flickSpec || !(flickSpec.n || flickSpec.nw || flickSpec.ne); + }; + const doRoaming = params.roamingEnabled = !flags.hasFlicks; const _initialTapModel: GestureModel = deepCopy(!doRoaming ? initialTapModel(params) : initialTapModelWithReset(params)); const _simpleTapModel: GestureModel = deepCopy(!doRoaming ? simpleTapModel(params) : simpleTapModelWithReset(params)); // Ensure all deep-copy operations for longpress modeling occur before the property-redefining block. const _longpressModel: GestureModel = withKeySpecFiltering(deepCopy(longpressModel(params, true, doRoaming)), 0); + const _multitapStartModel: GestureModel = withKeySpecFiltering(multitapStartModel(params), 0); + const _modipressMultitapStartModel: GestureModel = withKeySpecFiltering(modipressMultitapStartModel(params), 0); // `deepCopy` does not preserve property definitions, instead raw-copying its value. // We need to re-instate the longpress delay property here. Object.defineProperty(_longpressModel.contacts[0].model.timer, 'duration', { get: () => params.longpress.waitLength }); + Object.defineProperty(_multitapStartModel.sustainTimer, 'duration', { + get: () => params.multitap.waitLength + }); + Object.defineProperty(_modipressMultitapStartModel.sustainTimer, 'duration', { + get: () => params.multitap.waitLength + }); // #region Functions for implementing and/or extending path initial-state checks function withKeySpecFiltering(model: GestureModel, contactIndices: number | number[]) { @@ -293,7 +310,7 @@ export function gestureSetForLayout(flags: LayoutGestureSupportFlags, params: Ge const _modipressStartModel = modipressStartModel(); const gestureModels: GestureModel[] = [ _longpressModel, - withKeySpecFiltering(multitapStartModel(params), 0), + _multitapStartModel, multitapEndModel(params), _initialTapModel, _simpleTapModel, @@ -304,7 +321,7 @@ export function gestureSetForLayout(flags: LayoutGestureSupportFlags, params: Ge modipressHoldModel(params), modipressEndModel(), modipressMultitapTransitionModel(), - withKeySpecFiltering(modipressMultitapStartModel(params), 0), + _modipressMultitapStartModel, modipressMultitapEndModel(params), modipressMultitapLockModel() ]; @@ -367,7 +384,7 @@ export function instantContactResolutionModel(): ContactModel { }; } -export function flickStartContactModel(params: GestureParams): gestures.specs.ContactModel { +export function flickStartContactModel(params: FullGestureParams): gestures.specs.ContactModel { const flickParams = params.flick; return { @@ -426,7 +443,7 @@ function determineLockFromStats(pathStats: CumulativePathStats, base } } -export function flickMidContactModel(params: GestureParams): gestures.specs.ContactModel { +export function flickMidContactModel(params: FullGestureParams): gestures.specs.ContactModel { return { itemPriority: 1, pathModel: { @@ -461,7 +478,7 @@ export function flickMidContactModel(params: GestureParams): gestures.specs.Cont } -export function flickEndContactModel(params: GestureParams): ContactModel { +export function flickEndContactModel(params: FullGestureParams): ContactModel { return { itemPriority: 1, pathModel: { @@ -485,7 +502,7 @@ export function flickEndContactModel(params: GestureParams): ContactModel { } } -export function longpressContactModel(params: GestureParams, enabledFlicks: boolean, resetForRoaming: boolean): ContactModel { +export function longpressContactModel(params: FullGestureParams, enabledFlicks: boolean, resetForRoaming: boolean): ContactModel { const spec = params.longpress; return { @@ -581,7 +598,7 @@ export function modipressContactEndModel(): ContactModel { }; } -export function simpleTapContactModel(params: GestureParams, isNotInitial?: boolean): ContactModel { +export function simpleTapContactModel(params: FullGestureParams, isNotInitial?: boolean): ContactModel { // Snapshot at model construction; do not update if changed. const roamingEnabled = params?.roamingEnabled ?? true; // ?? true - used by the banner. @@ -650,7 +667,7 @@ export function specialKeyStartModel(): GestureModel { }; } -export function specialKeyEndModel(params: GestureParams): GestureModel { +export function specialKeyEndModel(params: FullGestureParams): GestureModel { return { id: 'special-key-end', resolutionPriority: 0, @@ -682,7 +699,7 @@ export function specialKeyEndModel(params: GestureParams): GestureModel { * - the common gesture configuration permits the shortcut where supported * @param allowRoaming Indicates whether "roaming touch" mode should be supported. */ -export function longpressModel(params: GestureParams, allowShortcut: boolean, allowRoaming: boolean): GestureModel { +export function longpressModel(params: FullGestureParams, allowShortcut: boolean, allowRoaming: boolean): GestureModel { const base: GestureModel = { id: 'longpress', // Needs to beat flick-start priority. @@ -732,7 +749,7 @@ export function longpressModel(params: GestureParams, allowShortcut: boolean, al /** * For use for transitioning out of roaming-touch. */ -export function longpressModelAfterRoaming(params: GestureParams): GestureModel { +export function longpressModelAfterRoaming(params: FullGestureParams): GestureModel { // The longpress-shortcut is always disabled for keys reached by roaming (param 2) // Only used when roaming is permitted; continued roaming should be allowed. (param 3) const base = longpressModel(params, false, true); @@ -782,7 +799,7 @@ export function longpressRoamRestoration(): GestureModel { } } -export function flickStartModel(params: GestureParams): GestureModel { +export function flickStartModel(params: FullGestureParams): GestureModel { return { id: 'flick-start', resolutionPriority: 3, @@ -799,7 +816,7 @@ export function flickStartModel(params: GestureParams): GestureModel { } } -export function flickRestartModel(params: GestureParams): GestureModel { +export function flickRestartModel(params: FullGestureParams): GestureModel { const base = flickStartModel(params); return { ...base, @@ -859,7 +876,7 @@ export function flickRestartModel(params: GestureParams): GestureModel { +export function flickMidModel(params: FullGestureParams): GestureModel { return { id: 'flick-mid', resolutionPriority: 0, @@ -889,7 +906,7 @@ export function flickMidModel(params: GestureParams): GestureModel { } // Clears existing flick-scrolling & primes the flick-reset recentering mechanism. -export function flickResetModel(params: GestureParams): GestureModel { +export function flickResetModel(params: FullGestureParams): GestureModel { return { id: 'flick-reset', resolutionPriority: 1, @@ -909,7 +926,7 @@ export function flickResetModel(params: GestureParams): GestureModel { }; } -export function flickResetCenteringModel(params: GestureParams): GestureModel { +export function flickResetCenteringModel(params: FullGestureParams): GestureModel { return { id: 'flick-reset-centering', resolutionPriority: 1, @@ -963,7 +980,7 @@ export function flickResetEndModel(): GestureModel { }; }; -export function flickEndModel(params: GestureParams): GestureModel { +export function flickEndModel(params: FullGestureParams): GestureModel { return { id: 'flick-end', resolutionPriority: 0, @@ -990,7 +1007,7 @@ export function flickEndModel(params: GestureParams): GestureModel { } } -export function multitapStartModel(params: GestureParams): GestureModel { +export function multitapStartModel(params: FullGestureParams): GestureModel { return { id: 'multitap-start', resolutionPriority: 2, @@ -1019,7 +1036,7 @@ export function multitapStartModel(params: GestureParams): GestureModel { } } -export function multitapEndModel(params: GestureParams): GestureModel { +export function multitapEndModel(params: FullGestureParams): GestureModel { return { id: 'multitap-end', resolutionPriority: 2, @@ -1053,7 +1070,7 @@ export function multitapEndModel(params: GestureParams): GestureModel { } } -export function initialTapModel(params: GestureParams): GestureModel { +export function initialTapModel(params: FullGestureParams): GestureModel { return { id: 'initial-tap', resolutionPriority: 1, @@ -1089,7 +1106,7 @@ export function initialTapModel(params: GestureParams): GestureModel { } } -export function simpleTapModel(params: GestureParams): GestureModel { +export function simpleTapModel(params: FullGestureParams): GestureModel { return { id: 'simple-tap', resolutionPriority: 1, @@ -1113,7 +1130,7 @@ export function simpleTapModel(params: GestureParams): GestureModel { }; } -export function initialTapModelWithReset(params: GestureParams): GestureModel { +export function initialTapModelWithReset(params: FullGestureParams): GestureModel { const base = initialTapModel(params); return { ...base, @@ -1127,7 +1144,7 @@ export function initialTapModelWithReset(params: GestureParams): GestureModel { +export function simpleTapModelWithReset(params: FullGestureParams): GestureModel { const simpleModel = simpleTapModel(params); return { ...simpleModel, @@ -1189,7 +1206,7 @@ export function modipressStartModel(): GestureModel { } } -export function modipressHoldModel(params: GestureParams): GestureModel { +export function modipressHoldModel(params: FullGestureParams): GestureModel { return { id: 'modipress-hold', resolutionPriority: 5, @@ -1281,7 +1298,7 @@ export function modipressEndModel(): GestureModel { } } -export function modipressMultitapStartModel(params: GestureParams): GestureModel { +export function modipressMultitapStartModel(params: FullGestureParams): GestureModel { return { id: 'modipress-multitap-start', resolutionPriority: 6, @@ -1316,7 +1333,7 @@ export function modipressMultitapStartModel(params: GestureParams): GestureModel } } -export function modipressMultitapEndModel(params: GestureParams): GestureModel { +export function modipressMultitapEndModel(params: FullGestureParams): GestureModel { return { id: 'modipress-multitap-end', resolutionPriority: 5, diff --git a/web/src/engine/osk/src/visualKeyboard.ts b/web/src/engine/osk/src/visualKeyboard.ts index a8152a0db0a..68f0766b90c 100644 --- a/web/src/engine/osk/src/visualKeyboard.ts +++ b/web/src/engine/osk/src/visualKeyboard.ts @@ -151,7 +151,7 @@ export default class VisualKeyboard extends EventEmitter implements Ke /** * Tweakable gesture parameters referenced by supported gestures and the gesture engine. */ - get gestureParams(): GestureParams { + get gestureParams(): GestureParams { return this.config.gestureParams; }; @@ -423,11 +423,6 @@ export default class VisualKeyboard extends EventEmitter implements Ke historyLength: DEBUG_HISTORY_COUNT }; - this.gestureParams.longpress.permitsFlick = (key) => { - const flickSpec = key?.key.spec.flick; - return !flickSpec || !(flickSpec.n || flickSpec.nw || flickSpec.ne); - }; - const recognizer = new GestureRecognizer(gestureSetForLayout(this.kbdLayout, this.gestureParams), config); recognizer.stateToken = this.layerId; From f9e7390991d50df2d973959108a3db63c51e6062 Mon Sep 17 00:00:00 2001 From: rc-swag <58423624+rc-swag@users.noreply.github.com> Date: Thu, 15 Aug 2024 12:48:19 +1000 Subject: [PATCH 24/65] fix(windows): add translatable=false flag --- windows/src/desktop/kmshell/xml/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/windows/src/desktop/kmshell/xml/strings.xml b/windows/src/desktop/kmshell/xml/strings.xml index 4cef9daa9ba..2a9ede67453 100644 --- a/windows/src/desktop/kmshell/xml/strings.xml +++ b/windows/src/desktop/kmshell/xml/strings.xml @@ -10,7 +10,7 @@ - Keyman + Keyman @@ -860,7 +860,7 @@ keyboard that you use in Windows. Keyman keyboards will adapt automatically to - Keyman + Keyman @@ -1026,7 +1026,7 @@ keyboard that you use in Windows. Keyman keyboards will adapt automatically to - Keyman + Keyman From 2938ee110b7a0be8ee7dd5bd6fcc11e662e30afa Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Thu, 15 Aug 2024 10:12:27 +0700 Subject: [PATCH 25/65] refactor(web): remove engine/interfaces dependency on engine/js-processor --- package-lock.json | 24 ++++++------ web/README.md | 17 ++++----- web/build.sh | 3 ++ .../prediction/languageProcessor.interface.ts | 2 +- .../src/prediction/predictionContext.ts | 38 +++---------------- web/src/engine/interfaces/tsconfig.json | 1 - .../engine/js-processor/src/outputTarget.ts | 3 +- web/src/engine/keyboard/src/index.ts | 1 + .../main/src/headless/languageProcessor.ts | 1 + web/src/engine/main/src/keymanEngine.ts | 23 ++++++++++- .../prediction/predictionContext.spec.js | 32 ++++++---------- 11 files changed, 67 insertions(+), 78 deletions(-) diff --git a/package-lock.json b/package-lock.json index ae0082784f2..5a3c53081d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -228,18 +228,6 @@ "typescript": "^5.4.5" } }, - "web/src/tools/testing/recorder-core": { - "name": "@keymanapp/recorder-core", - "license": "MIT", - "dependencies": { - "@keymanapp/keyman-version": "*", - "@keymanapp/models-types": "*", - "@keymanapp/web-utils": "*" - }, - "devDependencies": { - "typescript": "^5.4.5" - } - }, "common/web/sentry-manager": { "name": "@keymanapp/web-sentry-manager", "license": "MIT", @@ -14544,6 +14532,18 @@ "jsdom": "^23.0.1", "mocha": "^10.0.0" } + }, + "web/src/tools/testing/recorder-core": { + "name": "@keymanapp/recorder-core", + "license": "MIT", + "dependencies": { + "@keymanapp/keyman-version": "*", + "@keymanapp/models-types": "*", + "@keymanapp/web-utils": "*" + }, + "devDependencies": { + "typescript": "^5.4.5" + } } } } diff --git a/web/README.md b/web/README.md index 7cd9e02f002..b5f0c7c4c4c 100644 --- a/web/README.md +++ b/web/README.md @@ -81,11 +81,11 @@ title: Dependency Graph %%{init: {"flowchart": {"htmlLabels": false}} }%% graph TD; OSK["/web/src/engine/osk"]; - KP["/web/src/engine/keyboard"]; + KeyboardSpec["/web/src/engine/keyboard"]; JSProc["/web/src/engine/js-processor"]; - OSK-->KP; + OSK-->KeyboardSpec; WebUtils["@keymanapp/web-utils
(/common/web/utils)"]; - KP---->WebUtils; + KeyboardSpec---->WebUtils; Wordbreakers["@keymanapp/models-wordbreakers
(/common/models/wordbreakers)"]; Models["@keymanapp/models-templates
(/common/models/templates)"]; Models-->WebUtils; @@ -107,15 +107,15 @@ graph TD; subgraph Headless["`**Headless** Fully headless components`"] direction LR - KP; - JSProc-->KP; + KeyboardSpec; + JSProc-->KeyboardSpec; WebUtils; PredText; Gestures; end subgraph ClassicWeb["`**ClassicWeb** - Previously unmodularized components`"] + Intermediate-level engine modules`"] Device["/web/src/engine/device-detect"]; Device----->WebUtils; Elements["/web/src/engine/element-wrappers"]; @@ -124,12 +124,11 @@ graph TD; KeyboardCache-->Interfaces; DomUtils["/web/src/engine/dom-utils"]; DomUtils-->WebUtils; - DomUtils-->KP; + DomUtils-->KeyboardSpec; OSK-->DomUtils; OSK-->Gestures; Interfaces["/web/src/engine/interfaces"]; - Interfaces-->KP; - Interfaces-->JSProc; + Interfaces-->KeyboardSpec; OSK-->Interfaces; CommonEngine["/web/src/engine/main"]; CommonEngine-->Device; diff --git a/web/build.sh b/web/build.sh index c3e17e9d433..50471db85f0 100755 --- a/web/build.sh +++ b/web/build.sh @@ -141,6 +141,9 @@ coverage_action() { builder_run_child_actions build:engine/device-detect builder_run_child_actions build:engine/dom-utils + +builder_run_child_actions build:engine/keyboard +builder_run_child_actions build:engine/js-processor builder_run_child_actions build:engine/element-wrappers builder_run_child_actions build:engine/events builder_run_child_actions build:engine/interfaces diff --git a/web/src/engine/interfaces/src/prediction/languageProcessor.interface.ts b/web/src/engine/interfaces/src/prediction/languageProcessor.interface.ts index df5ebae8968..84e78519879 100644 --- a/web/src/engine/interfaces/src/prediction/languageProcessor.interface.ts +++ b/web/src/engine/interfaces/src/prediction/languageProcessor.interface.ts @@ -1,7 +1,7 @@ /// import { EventEmitter } from "eventemitter3"; -import { OutputTarget } from "keyman/engine/js-processor"; +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 221875e62cb..cd856153b23 100644 --- a/web/src/engine/interfaces/src/prediction/predictionContext.ts +++ b/web/src/engine/interfaces/src/prediction/predictionContext.ts @@ -1,6 +1,6 @@ import { EventEmitter } from "eventemitter3"; import { type LanguageProcessorSpec , ReadySuggestions, type InvalidateSourceEnum, StateChangeHandler } from './languageProcessor.interface.js'; -import { type KeyboardProcessor, type OutputTarget } from 'keyman/engine/js-processor'; +import { type OutputTarget } from "keyman/engine/keyboard"; interface PredictionContextEventMap { update: (suggestions: Suggestion[]) => void; @@ -32,7 +32,7 @@ export default class PredictionContext extends EventEmitter string; /** * Represents the active context used when requesting and applying predictive-text operations. @@ -59,27 +59,18 @@ export default class PredictionContext extends EventEmitter Promise; private readonly suggestionReverter: (reversion: Reversion) => void; - /** - * Handler for post-processing once a suggestion has been applied: calls - * into the active keyboard's `begin postKeystroke` entry point. - * - * Called after the suggestion is applied but _before_ new predictions are - * requested based on the resulting context. - */ - private readonly postApplicationHandler: () => void; - - public constructor(langProcessor: LanguageProcessorSpec, kbdProcessor: KeyboardProcessor) { + public constructor(langProcessor: LanguageProcessorSpec, getLayerId: () => string) { super(); this.langProcessor = langProcessor; - this.kbdProcessor = kbdProcessor; + this.getLayerId = getLayerId; const validSuggestionState: () => boolean = () => this.currentTarget && langProcessor.state == 'configured'; this.suggestionApplier = (suggestion) => { if(validSuggestionState()) { - return langProcessor.applySuggestion(suggestion, this.currentTarget, () => kbdProcessor.layerId); + return langProcessor.applySuggestion(suggestion, this.currentTarget, getLayerId); } else { return null; } @@ -94,19 +85,6 @@ export default class PredictionContext extends EventEmitter { - // Tell the keyboard that the current layer has not changed - kbdProcessor.newLayerStore.set(''); - kbdProcessor.oldLayerStore.set(''); - // Call the keyboard's entry point. - kbdProcessor.processPostKeystroke(kbdProcessor.contextDevice, this.currentTarget) - // If we have a RuleBehavior as a result, run it on the target. This should - // only change system store and variable store values. - ?.finalize(kbdProcessor, this.currentTarget, true); - }; - this.connect(); } @@ -116,8 +94,6 @@ export default class PredictionContext extends EventEmitter; -export default abstract class OutputTarget { +export default abstract class OutputTarget implements OutputTargetInterface { private _dks: DeadkeyTracker; constructor() { diff --git a/web/src/engine/keyboard/src/index.ts b/web/src/engine/keyboard/src/index.ts index f5a4edea71d..28b6331c219 100644 --- a/web/src/engine/keyboard/src/index.ts +++ b/web/src/engine/keyboard/src/index.ts @@ -31,6 +31,7 @@ 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"; diff --git a/web/src/engine/main/src/headless/languageProcessor.ts b/web/src/engine/main/src/headless/languageProcessor.ts index c1c1721484b..cd39afc672b 100644 --- a/web/src/engine/main/src/headless/languageProcessor.ts +++ b/web/src/engine/main/src/headless/languageProcessor.ts @@ -336,6 +336,7 @@ export class LanguageProcessor extends EventEmitter { public shutdown() { this.lmEngine.shutdown(); + this.removeAllListeners(); } public get isActive(): boolean { diff --git a/web/src/engine/main/src/keymanEngine.ts b/web/src/engine/main/src/keymanEngine.ts index b91920e70d3..cb4c6305938 100644 --- a/web/src/engine/main/src/keymanEngine.ts +++ b/web/src/engine/main/src/keymanEngine.ts @@ -1,5 +1,5 @@ import { type KeyEvent, type Keyboard, KeyboardKeymanGlobal } from "keyman/engine/keyboard"; -import { ProcessorInitOptions, RuleBehavior } from 'keyman/engine/js-processor'; +import { OutputTarget, ProcessorInitOptions, RuleBehavior } from 'keyman/engine/js-processor'; import { DOMKeyboardLoader as KeyboardLoader } from "keyman/engine/keyboard/dom-keyboard-loader"; import { InputProcessor } from './headless/inputProcessor.js'; import { OSKView } from "keyman/engine/osk"; @@ -241,6 +241,8 @@ export default class KeymanEngine< this.modelCache = new ModelCache(); const kbdCache = this.keyboardRequisitioner.cache; + const keyboardProcessor = this.core.keyboardProcessor; + const predictionContext = new PredictionContext(this.core.languageProcessor, () => keyboardProcessor.layerId); this.contextManager.configure({ resetContext: (target) => { // Could reset the target's deadkeys here, but it's really more of a 'core' task. @@ -253,10 +255,27 @@ export default class KeymanEngine< this.core.resetContext(target); } }, - predictionContext: new PredictionContext(this.core.languageProcessor, this.core.keyboardProcessor), + predictionContext: predictionContext, keyboardCache: this.keyboardRequisitioner.cache }); + /* + * Handler for post-processing once a suggestion has been applied. + * + * This is called after the suggestion is applied but _before_ new + * predictions are requested based on the resulting context. + */ + this.core.languageProcessor.on('suggestionapplied', () => { + // Tell the keyboard that the current layer has not changed + keyboardProcessor.newLayerStore.set(''); + keyboardProcessor.oldLayerStore.set(''); + // Call the keyboard's entry point. + keyboardProcessor.processPostKeystroke(keyboardProcessor.contextDevice, predictionContext.currentTarget as OutputTarget) + // If we have a RuleBehavior as a result, run it on the target. This should + // only change system store and variable store values. + ?.finalize(keyboardProcessor, predictionContext.currentTarget as OutputTarget, true); + }); + // #region Event handler wiring this.config.on('spacebartext', () => { // On change of spacebar-text mode, we currently need a layout refresh to update the diff --git a/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js b/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js index dbc24cad4ff..fe66d0904d7 100644 --- a/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js +++ b/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js @@ -5,7 +5,7 @@ import { LanguageProcessor, TranscriptionCache } from 'keyman/engine/main'; import { PredictionContext } from 'keyman/engine/interfaces'; import { Worker as LMWorker } from "@keymanapp/lexical-model-layer/node"; import { DeviceSpec } from 'keyman/engine/keyboard'; -import { KeyboardProcessor, Mock } from 'keyman/engine/js-processor'; +import { Mock } from 'keyman/engine/js-processor'; function compileDummyModel(suggestionSets) { return ` @@ -15,14 +15,6 @@ LMLayerWorker.loadModel(new models.DummyModel({ `; } -// Common spec used for each test's setup. It's actually irrelevant for the tests, -// but KeyboardProcessor needs an instance. -const deviceSpec = new DeviceSpec( - DeviceSpec.Browser.Chrome, - DeviceSpec.FormFactor.Desktop, - DeviceSpec.OperatingSystem.Windows -); - const appleDummySuggestionSets = [[ // Set 1: { @@ -67,6 +59,10 @@ const appleDummyModel = { code: compileDummyModel(appleDummySuggestionSets) }; +function dummiedGetLayer() { + return 'default'; +} + describe("PredictionContext", () => { let worker; @@ -82,8 +78,7 @@ describe("PredictionContext", () => { const langProcessor = new LanguageProcessor(worker, new TranscriptionCache()); await langProcessor.loadModel(appleDummyModel); // await: must fully 'configure', load script into worker. - const kbdProcessor = new KeyboardProcessor(deviceSpec); - const predictiveContext = new PredictionContext(langProcessor, kbdProcessor); + const predictiveContext = new PredictionContext(langProcessor, dummiedGetLayer); let updateFake = sinon.fake(); predictiveContext.on('update', updateFake); @@ -108,7 +103,7 @@ describe("PredictionContext", () => { mock.insertTextBeforeCaret('e'); // appl| + e = apple let transcription = mock.buildTranscriptionFrom(initialMock, null, true); - await langProcessor.predict(transcription, kbdProcessor.layerId); + await langProcessor.predict(transcription, dummiedGetLayer()); // First predict call results: our second set of dummy suggestions, the first of which includes // a 'keep' of the original text. @@ -123,8 +118,7 @@ describe("PredictionContext", () => { const langProcessor = new LanguageProcessor(worker, new TranscriptionCache()); await langProcessor.loadModel(appleDummyModel); // await: must fully 'configure', load script into worker. - const kbdProcessor = new KeyboardProcessor(deviceSpec); - const predictiveContext = new PredictionContext(langProcessor, kbdProcessor); + const predictiveContext = new PredictionContext(langProcessor, dummiedGetLayer); let mock = new Mock("appl", 4); // "appl|", with '|' as the caret position. const initialSuggestions = await predictiveContext.setCurrentTarget(mock); @@ -149,8 +143,7 @@ describe("PredictionContext", () => { const langProcessor = new LanguageProcessor(worker, new TranscriptionCache()); await langProcessor.loadModel(appleDummyModel); // await: must fully 'configure', load script into worker. - const kbdProcessor = new KeyboardProcessor(deviceSpec); - const predictiveContext = new PredictionContext(langProcessor, kbdProcessor); + const predictiveContext = new PredictionContext(langProcessor, dummiedGetLayer); let textState = new Mock("appl", 4); // "appl|", with '|' as the caret position. @@ -164,7 +157,7 @@ describe("PredictionContext", () => { let previousTextState = Mock.from(textState); textState.insertTextBeforeCaret('e'); // appl| + e = apple let transcription = textState.buildTranscriptionFrom(previousTextState, null, true); - await langProcessor.predict(transcription, kbdProcessor.layerId); + await langProcessor.predict(transcription, dummiedGetLayer()); // Verify setup. assert.equal(updateFake.callCount, 1); @@ -217,8 +210,7 @@ describe("PredictionContext", () => { const langProcessor = new LanguageProcessor(worker, new TranscriptionCache()); await langProcessor.loadModel(appleDummyModel); // await: must fully 'configure', load script into worker. - const kbdProcessor = new KeyboardProcessor(deviceSpec); - const predictiveContext = new PredictionContext(langProcessor, kbdProcessor); + const predictiveContext = new PredictionContext(langProcessor, dummiedGetLayer); let textState = new Mock("appl", 4); // "appl|", with '|' as the caret position. @@ -233,7 +225,7 @@ describe("PredictionContext", () => { let suggestionCaptureFake = sinon.fake(); predictiveContext.once('update', suggestionCaptureFake); - await langProcessor.predict(transcription, kbdProcessor.layerId); + await langProcessor.predict(transcription, dummiedGetLayer()); // We need to capture the suggestion we wish to apply. We could hardcode a forced // value, but that might become brittle in the long-term. From 8af17659a0d97b7ad6236d6c7d9ff8ea94a63102 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Thu, 15 Aug 2024 10:30:33 +0700 Subject: [PATCH 26/65] docs(web): doc tweak --- web/src/engine/osk/src/input/gestures/specsForLayout.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/engine/osk/src/input/gestures/specsForLayout.ts b/web/src/engine/osk/src/input/gestures/specsForLayout.ts index 649c5537d08..541e07a5c03 100644 --- a/web/src/engine/osk/src/input/gestures/specsForLayout.ts +++ b/web/src/engine/osk/src/input/gestures/specsForLayout.ts @@ -209,7 +209,7 @@ let dummy2: LayoutGestureSupportFlags = dummy; * Defines the set of gestures appropriate for use with the specified Keyman * keyboard. * @param layerGroup The active keyboard's layer group - * @param params A set of tweakable gesture parameters. It will be + * @param paramObj A set of tweakable gesture parameters. It will be * closure-captured and referred to by reference; changes to * its values will take immediate effect during gesture * processing. From 88145326dc4036040970f442ff31024b217290bb Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Thu, 15 Aug 2024 10:31:36 +0700 Subject: [PATCH 27/65] docs(web): drops doc-reference to hidden field --- web/src/engine/osk/src/input/gestures/specsForLayout.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/web/src/engine/osk/src/input/gestures/specsForLayout.ts b/web/src/engine/osk/src/input/gestures/specsForLayout.ts index 541e07a5c03..7faf1a7fc17 100644 --- a/web/src/engine/osk/src/input/gestures/specsForLayout.ts +++ b/web/src/engine/osk/src/input/gestures/specsForLayout.ts @@ -213,9 +213,6 @@ let dummy2: LayoutGestureSupportFlags = dummy; * closure-captured and referred to by reference; changes to * its values will take immediate effect during gesture * processing. - * - * `params.roamingEnabled` will be initialized by this - * method based upon layout properties. * @returns */ export function gestureSetForLayout(flags: LayoutGestureSupportFlags, paramObj: GestureParams): GestureModelDefs { From de0b2b54664f33727fe1fffb55fb364d18010e5c Mon Sep 17 00:00:00 2001 From: rc-swag <58423624+rc-swag@users.noreply.github.com> Date: Thu, 15 Aug 2024 13:32:50 +1000 Subject: [PATCH 28/65] fix(windows): remove incorrect translatable false tag --- windows/src/desktop/kmshell/xml/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windows/src/desktop/kmshell/xml/strings.xml b/windows/src/desktop/kmshell/xml/strings.xml index 2a9ede67453..774a4d5e425 100644 --- a/windows/src/desktop/kmshell/xml/strings.xml +++ b/windows/src/desktop/kmshell/xml/strings.xml @@ -10,7 +10,7 @@ - Keyman + Keyman From 9c9d10d23e456c5c7b725be067e9ab65f6701b9e Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 15 Aug 2024 10:35:04 +0700 Subject: [PATCH 29/65] refactor(android): Split setLongpressDelay and applyLongpressDelay --- .../com/keyman/android/SystemKeyboard.java | 6 +-- .../kmapro/AdjustLongpressDelayActivity.java | 11 ++--- .../com/tavultesoft/kmapro/MainActivity.java | 4 +- .../java/com/keyman/engine/KMManager.java | 41 +++++++++++++------ 4 files changed, 36 insertions(+), 26 deletions(-) diff --git a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java index eb44e0a3fa4..dea132c0fd3 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java +++ b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java @@ -80,8 +80,6 @@ public void onCreate() { // Set the system keyboard HTML banner BannerController.setHTMLBanner(this, KeyboardType.KEYBOARD_TYPE_SYSTEM); - int longpressDelay = KMManager.getLongpressDelay(this); - KMManager.setLongpressDelay(longpressDelay); boolean mayHaveHapticFeedback = prefs.getBoolean(KeymanSettingsActivity.hapticFeedbackKey, false); KMManager.setHapticFeedback(mayHaveHapticFeedback); @@ -248,8 +246,8 @@ public void onKeyboardLoaded(KeyboardType keyboardType) { exText = null; } // Initialize the longpress delay - int longpressDelay = KMManager.getLongpressDelay(this); - KMManager.setLongpressDelay(longpressDelay); + int longpressDelay = KMManager.getLongpressDelay(); + KMManager.applyLongpressDelay(longpressDelay); } @Override diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java index 214fd370145..55a663965c5 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java @@ -25,7 +25,6 @@ public class AdjustLongpressDelayActivity extends BaseActivity { private static final String TAG = "AdjustLongpressDelay"; public static final String adjustLongpressDelayKey = "AdjustLongpressDelay"; - private static SharedPreferences.Editor editor = null; // Keeps track of the adjusted longpress delay time for saving. // Internally use milliseconds, but GUI displays seconds @@ -77,9 +76,7 @@ protected void onCreate(Bundle savedInstanceState) { adjustLongpressDelayActivityTitle.setTextColor(ContextCompat.getColor(this, R.color.ms_white)); adjustLongpressDelayActivityTitle.setText(titleStr); - SharedPreferences prefs = context.getSharedPreferences(context.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); - editor = prefs.edit(); - currentDelayTime = KMManager.getLongpressDelay(this); + currentDelayTime = KMManager.getLongpressDelay(); TextView adjustLongpressDelayText = (TextView) findViewById(R.id.delayTimeText); String longpressDelayText = String.format(getString(R.string.longpress_delay_time), (float)(currentDelayTime/1000.0)); @@ -106,8 +103,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { String longpressDelayText = String.format(getString(R.string.longpress_delay_time), (float)(currentDelayTime/1000.0)); adjustLongpressDelayText.setText(longpressDelayText); - editor.putInt(KMManager.KMKey_LongpressDelay, currentDelayTime); - editor.commit(); + KMManager.setLongpressDelay(currentDelayTime); } }); @@ -134,7 +130,8 @@ public void onClick(View v) { @Override public void onBackPressed() { - // Apply the adjusted longpress delay on exit + // setLongpressDelay stores the longpress delay as a preference + // and then updates KeymanWeb with the longpress delay KMManager.setLongpressDelay(currentDelayTime); super.onBackPressed(); diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java index b337d2315d9..fe3dc9b6c8a 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java @@ -752,8 +752,8 @@ private void checkSendCrashReport() { private void checkLongpressDelay() { // Initialize the longpress delay - int longpressDelay = KMManager.getLongpressDelay(this); - KMManager.setLongpressDelay(longpressDelay); + int longpressDelay = KMManager.getLongpressDelay(); + KMManager.applyLongpressDelay(longpressDelay); } private void checkHapticFeedback() { diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java index d4fe9c404c4..348e3136dd3 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java @@ -295,8 +295,8 @@ public String toString() { public static final String KMDefault_DictionaryVersion = "0.1.4"; public static final String KMDefault_DictionaryKMP = KMDefault_DictionaryPackageID + FileUtils.MODELPACKAGE; - // Default KeymanWeb long-press delay - public static final int KMDefault_LongpressDelay = 500; // ms + // Default KeymanWeb longpress delay in milliseconds + public static final int KMDefault_LongpressDelay = 500; // Keyman files protected static final String KMFilename_KeyboardHtml = "keyboard.html"; @@ -2016,23 +2016,23 @@ public static int getOrientation(Context context) { } /** - * Get the long-press delay (in milliseconds) - * @param context - * @return int - long-press delay in milliseconds + * Get the longpress delay (in milliseconds) from stored preference. Defaults to 500ms + * @return int - longpress delay in milliseconds */ - public static int getLongpressDelay(Context context) { - SharedPreferences prefs = context.getSharedPreferences(context.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); + public static int getLongpressDelay() { + SharedPreferences prefs = appContext.getSharedPreferences( + appContext.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); - return prefs.getInt( - KMKey_LongpressDelay, - KMDefault_LongpressDelay); + return prefs.getInt(KMKey_LongpressDelay, KMDefault_LongpressDelay); } /** - * Update KeymanWeb with the long-press delay (in milliseconds) - * @param longpressDelay - int long-press delay in milliseconds + * Set the number of milliseconds to trigger a longpress gesture. + * + * This method requires a keyboard to be loaded for the value to take effect. + * @param longpressDelay - int longpress delay in milliseconds */ - public static void setLongpressDelay(int longpressDelay) { + public static void applyLongpressDelay(int longpressDelay) { if (isKeyboardLoaded(KeyboardType.KEYBOARD_TYPE_INAPP)) { InAppKeyboard.loadJavascript(KMString.format("setLongpressDelay(%d)", longpressDelay)); } @@ -2042,6 +2042,21 @@ public static void setLongpressDelay(int longpressDelay) { } } + /** + * Store the long-press delay (in milliseconds) as a preference. + * Then update KeymanWeb with the longpress delay + * @param longpressDelay - int longpress delay in milliseconds + */ + public static void setLongpressDelay(int longpressDelay) { + SharedPreferences prefs = appContext.getSharedPreferences( + appContext.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); + editor.putInt(KMKey_LongpressDelay, longpressDelay); + editor.commit(); + + applyLongpressDelay(longpressDelay); + } + public static int getBannerHeight(Context context) { int bannerHeight = 0; if (InAppKeyboard != null && InAppKeyboard.getBanner() != BannerType.BLANK) { From 686cfe04b13e1f0c7de5c9b25ed0c2ade75f2fa5 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 15 Aug 2024 15:00:00 +0700 Subject: [PATCH 30/65] fix(android): Advance cursor on newline --- .../src/main/java/com/keyman/engine/KMKeyboardJSHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java index 3a995560c6f..d403a29235b 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardJSHandler.java @@ -189,8 +189,8 @@ public void run() { // Messaging apps case NEWLINE : - // Send newline without advancing cursor - ic.commitText("\n", 0); + // Send newline and advance cursor + ic.commitText("\n", 1); break; // Default ENTER action From c4340542f77648d7072ab2d43d83990456439b34 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Thu, 15 Aug 2024 15:54:15 +0700 Subject: [PATCH 31/65] fix(web): patch up newly-merged-in automated test --- .../engine/interfaces/prediction/predictionContext.spec.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js b/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js index dc91c512136..4217aeb69b6 100644 --- a/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js +++ b/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js @@ -118,8 +118,7 @@ describe("PredictionContext", () => { const langProcessor = new LanguageProcessor(worker, new TranscriptionCache()); await langProcessor.loadModel(appleDummyModel); // await: must fully 'configure', load script into worker. - const kbdProcessor = new KeyboardProcessor(deviceSpec); - const predictiveContext = new PredictionContext(langProcessor, kbdProcessor); + const predictiveContext = new PredictionContext(langProcessor, dummiedGetLayer); let updateFake = sinon.fake(); predictiveContext.on('update', updateFake); @@ -146,13 +145,13 @@ describe("PredictionContext", () => { // Mocking: corresponds to the second set of mocked predictions - round 2 of // 'apple', 'apply', 'apples'. - const skippedPromise = langProcessor.predict(baseTranscription, kbdProcessor.layerId); + const skippedPromise = langProcessor.predict(baseTranscription, dummiedGetLayer()); mock.insertTextBeforeCaret('e'); // appl| + e = apple const finalTranscription = mock.buildTranscriptionFrom(initialMock, null, true); // Mocking: corresponds to the third set of mocked predictions - 'applied'. - const expectedPromise = langProcessor.predict(finalTranscription, kbdProcessor.layerId); + const expectedPromise = langProcessor.predict(finalTranscription, dummiedGetLayer()); await Promise.all([skippedPromise, expectedPromise]); const expected = await expectedPromise; From 170ac4bb6bdbc62231e20a928ef63baa96a20aca Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 8 Aug 2024 18:09:38 +0200 Subject: [PATCH 32/65] =?UTF-8?q?refactor(web):=20rename=20`package-cache`?= =?UTF-8?q?=20=E2=86=92=20`keyboard-storage`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move `web/src/engine/package-cache/` → `web/src/engine/keyboard-storage/`. Fixes: #12132 --- web/README.md | 6 ++-- web/build.sh | 8 ++--- web/package.json | 30 +++++++++---------- web/src/app/browser/src/contextManager.ts | 2 +- web/src/app/browser/src/keymanEngine.ts | 2 +- web/src/app/browser/src/languageMenu.ts | 2 +- web/src/app/webview/src/contextManager.ts | 2 +- web/src/app/webview/src/keymanEngine.ts | 2 +- .../.c8rc.json | 0 .../README.md | 0 .../build.sh | 2 +- .../src/cloud/index.ts | 0 .../src/cloud/queryEngine.ts | 0 .../src/cloud/requesterInterface.ts | 0 .../src/domCloudRequester.ts | 0 .../src/index.ts | 0 .../src/keyboardRequisitioner.ts | 0 .../src/keyboardStub.ts | 0 .../src/modelCache.ts | 0 .../src/nodeCloudRequester.ts | 0 .../src/stubAndKeyboardCache.ts | 0 .../tsconfig.json | 4 +-- web/src/engine/main/build.sh | 2 +- web/src/engine/main/src/contextManagerBase.ts | 2 +- .../engine/main/src/engineConfiguration.ts | 2 +- web/src/engine/main/src/keyboardInterface.ts | 2 +- web/src/engine/main/src/keymanEngine.ts | 4 +-- web/src/engine/main/tsconfig.json | 2 +- .../dom/cases/browser/contextManager.spec.ts | 2 +- .../cloudQueries.spec.ts | 4 +-- .../domCloudRequester.spec.ts | 2 +- .../keyboardRequisitioner.spec.ts | 6 ++-- web/src/test/auto/dom/kbdLoader.ts | 2 +- .../test/auto/dom/web-test-runner.config.mjs | 4 +-- .../cloudQueries.js | 4 +-- .../keyboardRequisitioner.js | 6 ++-- .../keyboardStub.js | 4 +-- .../nodeCloudRequester.js | 2 +- .../stubAndKeyboardCache.js | 2 +- .../test/auto/integrated/cases/engine.spec.ts | 2 +- web/src/test/auto/integrated/test_utils.ts | 2 +- 41 files changed, 58 insertions(+), 58 deletions(-) rename web/src/engine/{package-cache => keyboard-storage}/.c8rc.json (100%) rename web/src/engine/{package-cache => keyboard-storage}/README.md (100%) rename web/src/engine/{package-cache => keyboard-storage}/build.sh (97%) rename web/src/engine/{package-cache => keyboard-storage}/src/cloud/index.ts (100%) rename web/src/engine/{package-cache => keyboard-storage}/src/cloud/queryEngine.ts (100%) rename web/src/engine/{package-cache => keyboard-storage}/src/cloud/requesterInterface.ts (100%) rename web/src/engine/{package-cache => keyboard-storage}/src/domCloudRequester.ts (100%) rename web/src/engine/{package-cache => keyboard-storage}/src/index.ts (100%) rename web/src/engine/{package-cache => keyboard-storage}/src/keyboardRequisitioner.ts (100%) rename web/src/engine/{package-cache => keyboard-storage}/src/keyboardStub.ts (100%) rename web/src/engine/{package-cache => keyboard-storage}/src/modelCache.ts (100%) rename web/src/engine/{package-cache => keyboard-storage}/src/nodeCloudRequester.ts (100%) rename web/src/engine/{package-cache => keyboard-storage}/src/stubAndKeyboardCache.ts (100%) rename web/src/engine/{package-cache => keyboard-storage}/tsconfig.json (57%) rename web/src/test/auto/dom/cases/{packages => keyboard-storage}/cloudQueries.spec.ts (98%) rename web/src/test/auto/dom/cases/{packages => keyboard-storage}/domCloudRequester.spec.ts (97%) rename web/src/test/auto/dom/cases/{packages => keyboard-storage}/keyboardRequisitioner.spec.ts (95%) rename web/src/test/auto/headless/engine/{package-cache => keyboard-storage}/cloudQueries.js (98%) rename web/src/test/auto/headless/engine/{package-cache => keyboard-storage}/keyboardRequisitioner.js (98%) rename web/src/test/auto/headless/engine/{package-cache => keyboard-storage}/keyboardStub.js (96%) rename web/src/test/auto/headless/engine/{package-cache => keyboard-storage}/nodeCloudRequester.js (97%) rename web/src/test/auto/headless/engine/{package-cache => keyboard-storage}/stubAndKeyboardCache.js (99%) diff --git a/web/README.md b/web/README.md index 7cd9e02f002..4f35643e1a9 100644 --- a/web/README.md +++ b/web/README.md @@ -120,8 +120,8 @@ graph TD; Device----->WebUtils; Elements["/web/src/engine/element-wrappers"]; Elements-->JSProc; - KeyboardCache["/web/src/engine/package-cache"]; - KeyboardCache-->Interfaces; + KeyboardStorage["/web/src/engine/keyboard-storage"]; + KeyboardStorage-->Interfaces; DomUtils["/web/src/engine/dom-utils"]; DomUtils-->WebUtils; DomUtils-->KP; @@ -133,7 +133,7 @@ graph TD; OSK-->Interfaces; CommonEngine["/web/src/engine/main"]; CommonEngine-->Device; - CommonEngine-->KeyboardCache; + CommonEngine-->KeyboardStorage; CommonEngine-->OSK; Attachment["/web/src/engine/attachment"]; Attachment-->DomUtils; diff --git a/web/build.sh b/web/build.sh index c3e17e9d433..4705bc55de9 100755 --- a/web/build.sh +++ b/web/build.sh @@ -29,9 +29,9 @@ builder_describe "Builds engine modules for Keyman Engine for Web (KMW)." \ ":engine/element-wrappers Subset used to integrate with website elements" \ ":engine/js-processor Build JS processor for KMW" \ ":engine/keyboard Builds KMW's keyboard-loading and caching code" \ + ":engine/keyboard-storage Subset used to collate keyboards and request them from the cloud" \ ":engine/main Builds all common code used by KMW's app/-level targets" \ ":engine/osk Builds the Web OSK module" \ - ":engine/package-cache Subset used to collate keyboards and request them from the cloud" \ ":engine/interfaces Subset used to configure KMW" \ ":samples Builds all needed resources for the KMW sample-page set" \ ":tools Builds engine-related development resources" \ @@ -61,9 +61,9 @@ builder_describe_outputs \ build:engine/element-wrappers "/web/build/engine/element-wrappers/lib/index.mjs" \ build:engine/js-processor "/web/build/engine/js-processor/lib/index.mjs" \ build:engine/keyboard "/web/build/engine/keyboard/lib/index.mjs" \ + build:engine/keyboard-storage "/web/build/engine/keyboard-storage/lib/index.mjs" \ build:engine/main "/web/build/engine/main/lib/index.mjs" \ build:engine/osk "/web/build/engine/osk/lib/index.mjs" \ - build:engine/package-cache "/web/build/engine/package-cache/lib/index.mjs" \ build:engine/interfaces "/web/build/engine/interfaces/lib/index.mjs" \ build:samples "/web/src/samples/simplest/keymanweb.js" \ build:tools "/web/build/tools/building/sourcemap-root/index.js" \ @@ -152,9 +152,9 @@ builder_run_child_actions build:engine/osk builder_run_child_actions build:engine/attachment # Uses engine/interfaces (due to resource-path config interface) -builder_run_child_actions build:engine/package-cache +builder_run_child_actions build:engine/keyboard-storage -# Uses engine/interfaces, engine/device-detect, engine/package-cache, & engine/osk +# Uses engine/interfaces, engine/device-detect, engine/keyboard-storage, & engine/osk builder_run_child_actions build:engine/main # Uses all but engine/element-wrappers and engine/attachment diff --git a/web/package.json b/web/package.json index b5727dd0095..96a11c0cd3e 100644 --- a/web/package.json +++ b/web/package.json @@ -57,21 +57,21 @@ "types": "./build/engine/keyboard/obj/keyboards/loaders/dom-keyboard-loader.d.ts", "import": "./build/engine/keyboard/obj/keyboards/loaders/dom-keyboard-loader.js" }, - "./engine/package-cache": { - "es6-bundling": "./src/engine/package-cache/src/index.ts", - "types": "./build/engine/package-cache/obj/index.d.ts", - "import": "./build/engine/package-cache/obj/index.js", - "require": "./build/engine/package-cache/obj/index.js" - }, - "./engine/package-cache/dom-requester": { - "es6-bundling": "./src/engine/package-cache/src/domCloudRequester.ts", - "types": "./build/engine/package-cache/obj/domCloudRequester.d.ts", - "import": "./build/engine/package-cache/obj/domCloudRequester.js" - }, - "./engine/package-cache/node-requester": { - "es6-bundling": "./src/engine/package-cache/src/nodeCloudRequester.ts", - "types": "./build/engine/package-cache/obj/nodeCloudRequester.d.ts", - "import": "./build/engine/package-cache/obj/nodeCloudRequester.js" + "./engine/keyboard-storage": { + "es6-bundling": "./src/engine/keyboard-storage/src/index.ts", + "types": "./build/engine/keyboard-storage/obj/index.d.ts", + "import": "./build/engine/keyboard-storage/obj/index.js", + "require": "./build/engine/keyboard-storage/obj/index.js" + }, + "./engine/keyboard-storage/dom-requester": { + "es6-bundling": "./src/engine/keyboard-storage/src/domCloudRequester.ts", + "types": "./build/engine/keyboard-storage/obj/domCloudRequester.d.ts", + "import": "./build/engine/keyboard-storage/obj/domCloudRequester.js" + }, + "./engine/keyboard-storage/node-requester": { + "es6-bundling": "./src/engine/keyboard-storage/src/nodeCloudRequester.ts", + "types": "./build/engine/keyboard-storage/obj/nodeCloudRequester.d.ts", + "import": "./build/engine/keyboard-storage/obj/nodeCloudRequester.js" }, "./engine/main": { "es6-bundling": "./src/engine/main/src/index.ts", diff --git a/web/src/app/browser/src/contextManager.ts b/web/src/app/browser/src/contextManager.ts index f17a17a5299..1fbc9052033 100644 --- a/web/src/app/browser/src/contextManager.ts +++ b/web/src/app/browser/src/contextManager.ts @@ -1,5 +1,5 @@ import { type Keyboard, KeyboardScriptError } from 'keyman/engine/keyboard'; -import { type KeyboardStub } from 'keyman/engine/package-cache'; +import { type KeyboardStub } from 'keyman/engine/keyboard-storage'; import { CookieSerializer } from 'keyman/engine/dom-utils'; import { eventOutputTarget, outputTargetForElement, PageContextAttachment } from 'keyman/engine/attachment'; import { DomEventTracker, LegacyEventEmitter } from 'keyman/engine/events'; diff --git a/web/src/app/browser/src/keymanEngine.ts b/web/src/app/browser/src/keymanEngine.ts index dc912f257be..324394bae22 100644 --- a/web/src/app/browser/src/keymanEngine.ts +++ b/web/src/app/browser/src/keymanEngine.ts @@ -6,7 +6,7 @@ import { TwoStateActivator, VisualKeyboard } from 'keyman/engine/osk'; -import { ErrorStub, KeyboardStub, CloudQueryResult, toPrefixedKeyboardId as prefixed } from 'keyman/engine/package-cache'; +import { ErrorStub, KeyboardStub, CloudQueryResult, toPrefixedKeyboardId as prefixed } from 'keyman/engine/keyboard-storage'; import { DeviceSpec, Keyboard, KeyboardObject } from "keyman/engine/keyboard"; import * as views from './viewsAnchorpoint.js'; diff --git a/web/src/app/browser/src/languageMenu.ts b/web/src/app/browser/src/languageMenu.ts index eb9361ccba3..d3144de6e5f 100644 --- a/web/src/app/browser/src/languageMenu.ts +++ b/web/src/app/browser/src/languageMenu.ts @@ -1,6 +1,6 @@ // Manages the language selection UI for touch-form factors, which is triggered by an OSK key. import { getAbsoluteX, landscapeView } from "keyman/engine/dom-utils"; -import { KeyboardStub } from "keyman/engine/package-cache"; +import { KeyboardStub } from "keyman/engine/keyboard-storage"; import KeymanEngine from "./keymanEngine.js"; import * as util from "./utils/index.js"; diff --git a/web/src/app/webview/src/contextManager.ts b/web/src/app/webview/src/contextManager.ts index 2b242de39c6..b0b90b4d96c 100644 --- a/web/src/app/webview/src/contextManager.ts +++ b/web/src/app/webview/src/contextManager.ts @@ -1,6 +1,6 @@ import { type Keyboard } from 'keyman/engine/keyboard'; import { Mock, OutputTarget, Transcription, findCommonSubstringEndIndex, isEmptyTransform, TextTransform } from 'keyman/engine/js-processor'; -import { KeyboardStub } from 'keyman/engine/package-cache'; +import { KeyboardStub } from 'keyman/engine/keyboard-storage'; import { ContextManagerBase } from 'keyman/engine/main'; import { WebviewConfiguration } from './configuration.js'; diff --git a/web/src/app/webview/src/keymanEngine.ts b/web/src/app/webview/src/keymanEngine.ts index ca0c39fd438..d390a6ce1b2 100644 --- a/web/src/app/webview/src/keymanEngine.ts +++ b/web/src/app/webview/src/keymanEngine.ts @@ -3,7 +3,7 @@ import { RuleBehavior } from 'keyman/engine/js-processor'; import { KeymanEngine as KeymanEngineBase, KeyboardInterface } from 'keyman/engine/main'; import { AnchoredOSKView, ViewConfiguration, StaticActivator } from 'keyman/engine/osk'; import { getAbsoluteX, getAbsoluteY } from 'keyman/engine/dom-utils'; -import { toPrefixedKeyboardId, toUnprefixedKeyboardId } from 'keyman/engine/package-cache'; +import { toPrefixedKeyboardId, toUnprefixedKeyboardId } from 'keyman/engine/keyboard-storage'; import { WebviewConfiguration, WebviewInitOptionDefaults, WebviewInitOptionSpec } from './configuration.js'; import ContextManager, { ContextHost } from './contextManager.js'; diff --git a/web/src/engine/package-cache/.c8rc.json b/web/src/engine/keyboard-storage/.c8rc.json similarity index 100% rename from web/src/engine/package-cache/.c8rc.json rename to web/src/engine/keyboard-storage/.c8rc.json diff --git a/web/src/engine/package-cache/README.md b/web/src/engine/keyboard-storage/README.md similarity index 100% rename from web/src/engine/package-cache/README.md rename to web/src/engine/keyboard-storage/README.md diff --git a/web/src/engine/package-cache/build.sh b/web/src/engine/keyboard-storage/build.sh similarity index 97% rename from web/src/engine/package-cache/build.sh rename to web/src/engine/keyboard-storage/build.sh index b413dd5be8c..33873355ff1 100755 --- a/web/src/engine/package-cache/build.sh +++ b/web/src/engine/keyboard-storage/build.sh @@ -6,7 +6,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" . "${THIS_SCRIPT%/*}/../../../../resources/build/builder.inc.sh" ## END STANDARD BUILD SCRIPT INCLUDE -SUBPROJECT_NAME=engine/package-cache +SUBPROJECT_NAME=engine/keyboard-storage . "$KEYMAN_ROOT/web/common.inc.sh" . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" diff --git a/web/src/engine/package-cache/src/cloud/index.ts b/web/src/engine/keyboard-storage/src/cloud/index.ts similarity index 100% rename from web/src/engine/package-cache/src/cloud/index.ts rename to web/src/engine/keyboard-storage/src/cloud/index.ts diff --git a/web/src/engine/package-cache/src/cloud/queryEngine.ts b/web/src/engine/keyboard-storage/src/cloud/queryEngine.ts similarity index 100% rename from web/src/engine/package-cache/src/cloud/queryEngine.ts rename to web/src/engine/keyboard-storage/src/cloud/queryEngine.ts diff --git a/web/src/engine/package-cache/src/cloud/requesterInterface.ts b/web/src/engine/keyboard-storage/src/cloud/requesterInterface.ts similarity index 100% rename from web/src/engine/package-cache/src/cloud/requesterInterface.ts rename to web/src/engine/keyboard-storage/src/cloud/requesterInterface.ts diff --git a/web/src/engine/package-cache/src/domCloudRequester.ts b/web/src/engine/keyboard-storage/src/domCloudRequester.ts similarity index 100% rename from web/src/engine/package-cache/src/domCloudRequester.ts rename to web/src/engine/keyboard-storage/src/domCloudRequester.ts diff --git a/web/src/engine/package-cache/src/index.ts b/web/src/engine/keyboard-storage/src/index.ts similarity index 100% rename from web/src/engine/package-cache/src/index.ts rename to web/src/engine/keyboard-storage/src/index.ts diff --git a/web/src/engine/package-cache/src/keyboardRequisitioner.ts b/web/src/engine/keyboard-storage/src/keyboardRequisitioner.ts similarity index 100% rename from web/src/engine/package-cache/src/keyboardRequisitioner.ts rename to web/src/engine/keyboard-storage/src/keyboardRequisitioner.ts diff --git a/web/src/engine/package-cache/src/keyboardStub.ts b/web/src/engine/keyboard-storage/src/keyboardStub.ts similarity index 100% rename from web/src/engine/package-cache/src/keyboardStub.ts rename to web/src/engine/keyboard-storage/src/keyboardStub.ts diff --git a/web/src/engine/package-cache/src/modelCache.ts b/web/src/engine/keyboard-storage/src/modelCache.ts similarity index 100% rename from web/src/engine/package-cache/src/modelCache.ts rename to web/src/engine/keyboard-storage/src/modelCache.ts diff --git a/web/src/engine/package-cache/src/nodeCloudRequester.ts b/web/src/engine/keyboard-storage/src/nodeCloudRequester.ts similarity index 100% rename from web/src/engine/package-cache/src/nodeCloudRequester.ts rename to web/src/engine/keyboard-storage/src/nodeCloudRequester.ts diff --git a/web/src/engine/package-cache/src/stubAndKeyboardCache.ts b/web/src/engine/keyboard-storage/src/stubAndKeyboardCache.ts similarity index 100% rename from web/src/engine/package-cache/src/stubAndKeyboardCache.ts rename to web/src/engine/keyboard-storage/src/stubAndKeyboardCache.ts diff --git a/web/src/engine/package-cache/tsconfig.json b/web/src/engine/keyboard-storage/tsconfig.json similarity index 57% rename from web/src/engine/package-cache/tsconfig.json rename to web/src/engine/keyboard-storage/tsconfig.json index 7a2ab5f235d..f093be2cbc6 100644 --- a/web/src/engine/package-cache/tsconfig.json +++ b/web/src/engine/keyboard-storage/tsconfig.json @@ -3,8 +3,8 @@ "compilerOptions": { "baseUrl": "./", - "outDir": "../../../build/engine/package-cache/obj/", - "tsBuildInfoFile": "../../../build/engine/package-cache/obj/tsconfig.tsbuildinfo", + "outDir": "../../../build/engine/keyboard-storage/obj/", + "tsBuildInfoFile": "../../../build/engine/keyboard-storage/obj/tsconfig.tsbuildinfo", "rootDir": "./src" }, diff --git a/web/src/engine/main/build.sh b/web/src/engine/main/build.sh index 15eaf770f2e..737ca9a5bd4 100755 --- a/web/src/engine/main/build.sh +++ b/web/src/engine/main/build.sh @@ -19,7 +19,7 @@ builder_describe "Builds the Keyman Engine for Web's common top-level base class "@/web/src/engine/interfaces build" \ "@/web/src/engine/device-detect build" \ "@/web/src/engine/js-processor build" \ - "@/web/src/engine/package-cache build" \ + "@/web/src/engine/keyboard-storage build" \ "@/web/src/engine/osk build" \ "@/developer/src/kmc-model test" \ "clean" \ diff --git a/web/src/engine/main/src/contextManagerBase.ts b/web/src/engine/main/src/contextManagerBase.ts index 5c774aa72d0..17fed71bd2e 100644 --- a/web/src/engine/main/src/contextManagerBase.ts +++ b/web/src/engine/main/src/contextManagerBase.ts @@ -1,7 +1,7 @@ import { EventEmitter } from 'eventemitter3'; import { ManagedPromise, type Keyboard } from 'keyman/engine/keyboard'; import { type KeyboardInterface, type OutputTarget } from 'keyman/engine/js-processor'; -import { StubAndKeyboardCache, type KeyboardStub } from 'keyman/engine/package-cache'; +import { StubAndKeyboardCache, type KeyboardStub } from 'keyman/engine/keyboard-storage'; import { PredictionContext } from 'keyman/engine/interfaces'; import { EngineConfiguration } from './engineConfiguration.js'; diff --git a/web/src/engine/main/src/engineConfiguration.ts b/web/src/engine/main/src/engineConfiguration.ts index 050a7be11e5..aac559acabd 100644 --- a/web/src/engine/main/src/engineConfiguration.ts +++ b/web/src/engine/main/src/engineConfiguration.ts @@ -4,7 +4,7 @@ import { DeviceSpec, KeyboardProperties, ManagedPromise, physicalKeyDeviceAlias, import { OutputTarget, RuleBehavior } from 'keyman/engine/js-processor'; import { PathConfiguration, PathOptionDefaults, PathOptionSpec } from "keyman/engine/interfaces"; import { Device } from "keyman/engine/device-detect"; -import { KeyboardStub } from "keyman/engine/package-cache"; +import { KeyboardStub } from "keyman/engine/keyboard-storage"; interface EventMap { 'spacebartext': (mode: SpacebarText) => void; diff --git a/web/src/engine/main/src/keyboardInterface.ts b/web/src/engine/main/src/keyboardInterface.ts index 9d922477b20..10194785948 100644 --- a/web/src/engine/main/src/keyboardInterface.ts +++ b/web/src/engine/main/src/keyboardInterface.ts @@ -1,6 +1,6 @@ import { KeyboardObject } from "keyman/engine/keyboard"; import { KeyboardInterface as KeyboardInterfaceBase } from 'keyman/engine/js-processor'; -import { KeyboardStub, RawKeyboardStub, toUnprefixedKeyboardId as unprefixed } from 'keyman/engine/package-cache'; +import { KeyboardStub, RawKeyboardStub, toUnprefixedKeyboardId as unprefixed } from 'keyman/engine/keyboard-storage'; import { ContextManagerBase } from './contextManagerBase.js'; import { VariableStoreCookieSerializer } from "./variableStoreCookieSerializer.js"; diff --git a/web/src/engine/main/src/keymanEngine.ts b/web/src/engine/main/src/keymanEngine.ts index b91920e70d3..30160e683c8 100644 --- a/web/src/engine/main/src/keymanEngine.ts +++ b/web/src/engine/main/src/keymanEngine.ts @@ -3,7 +3,7 @@ import { ProcessorInitOptions, RuleBehavior } from 'keyman/engine/js-processor'; import { DOMKeyboardLoader as KeyboardLoader } from "keyman/engine/keyboard/dom-keyboard-loader"; import { InputProcessor } from './headless/inputProcessor.js'; import { OSKView } from "keyman/engine/osk"; -import { KeyboardRequisitioner, ModelCache, toUnprefixedKeyboardId as unprefixed } from "keyman/engine/package-cache"; +import { KeyboardRequisitioner, ModelCache, toUnprefixedKeyboardId as unprefixed } from "keyman/engine/keyboard-storage"; import { ModelSpec, PredictionContext } from "keyman/engine/interfaces"; import { EngineConfiguration, InitOptionSpec } from "./engineConfiguration.js"; @@ -12,7 +12,7 @@ import { ContextManagerBase } from "./contextManagerBase.js"; import HardKeyboardBase from "./hardKeyboard.js"; import { LegacyAPIEvents } from "./legacyAPIEvents.js"; import { EventNames, EventListener, LegacyEventEmitter } from "keyman/engine/events"; -import DOMCloudRequester from "keyman/engine/package-cache/dom-requester"; +import DOMCloudRequester from "keyman/engine/keyboard-storage/dom-requester"; import KEYMAN_VERSION from "@keymanapp/keyman-version"; // From https://stackoverflow.com/a/69328045 diff --git a/web/src/engine/main/tsconfig.json b/web/src/engine/main/tsconfig.json index e3b2b0616cc..d2e0580161c 100644 --- a/web/src/engine/main/tsconfig.json +++ b/web/src/engine/main/tsconfig.json @@ -13,7 +13,7 @@ "references": [ { "path": "../device-detect" }, { "path": "../osk" }, - { "path": "../package-cache" }, + { "path": "../keyboard-storage" }, { "path": "../interfaces" }, { "path": "../js-processor" } ] diff --git a/web/src/test/auto/dom/cases/browser/contextManager.spec.ts b/web/src/test/auto/dom/cases/browser/contextManager.spec.ts index 291c299b2b0..eabf6eefdd8 100644 --- a/web/src/test/auto/dom/cases/browser/contextManager.spec.ts +++ b/web/src/test/auto/dom/cases/browser/contextManager.spec.ts @@ -3,7 +3,7 @@ import { outputTargetForElement } from 'keyman/engine/attachment'; import { LegacyEventEmitter } from 'keyman/engine/events'; -import { StubAndKeyboardCache, toPrefixedKeyboardId as prefixed } from 'keyman/engine/package-cache'; +import { StubAndKeyboardCache, toPrefixedKeyboardId as prefixed } from 'keyman/engine/keyboard-storage'; import { KeyboardHarness, MinimalKeymanGlobal } from 'keyman/engine/keyboard'; import { DOMKeyboardLoader } from 'keyman/engine/keyboard/dom-keyboard-loader'; diff --git a/web/src/test/auto/dom/cases/packages/cloudQueries.spec.ts b/web/src/test/auto/dom/cases/keyboard-storage/cloudQueries.spec.ts similarity index 98% rename from web/src/test/auto/dom/cases/packages/cloudQueries.spec.ts rename to web/src/test/auto/dom/cases/keyboard-storage/cloudQueries.spec.ts index 9a2fe93c45a..4af873b23cd 100644 --- a/web/src/test/auto/dom/cases/packages/cloudQueries.spec.ts +++ b/web/src/test/auto/dom/cases/keyboard-storage/cloudQueries.spec.ts @@ -1,9 +1,9 @@ import { assert } from 'chai'; import sinon from 'sinon'; -import { CloudQueryEngine, type KeyboardStub } from 'keyman/engine/package-cache'; +import { CloudQueryEngine, type KeyboardStub } from 'keyman/engine/keyboard-storage'; import { PathConfiguration } from 'keyman/engine/interfaces'; -import DOMCloudRequester from 'keyman/engine/package-cache/dom-requester'; +import DOMCloudRequester from 'keyman/engine/keyboard-storage/dom-requester'; import { ManagedPromise } from '@keymanapp/web-utils'; const pathConfig = new PathConfiguration({ diff --git a/web/src/test/auto/dom/cases/packages/domCloudRequester.spec.ts b/web/src/test/auto/dom/cases/keyboard-storage/domCloudRequester.spec.ts similarity index 97% rename from web/src/test/auto/dom/cases/packages/domCloudRequester.spec.ts rename to web/src/test/auto/dom/cases/keyboard-storage/domCloudRequester.spec.ts index 840acf9d991..7101bfd9f7e 100644 --- a/web/src/test/auto/dom/cases/packages/domCloudRequester.spec.ts +++ b/web/src/test/auto/dom/cases/keyboard-storage/domCloudRequester.spec.ts @@ -1,7 +1,7 @@ import { assert } from 'chai'; import sinon from 'sinon'; -import DOMCloudRequester from 'keyman/engine/package-cache/dom-requester'; +import DOMCloudRequester from 'keyman/engine/keyboard-storage/dom-requester'; describe("Mocked cloud query results ('canary' testing)", () => { function performMockedRequest(mockedResultsPath: string) { diff --git a/web/src/test/auto/dom/cases/packages/keyboardRequisitioner.spec.ts b/web/src/test/auto/dom/cases/keyboard-storage/keyboardRequisitioner.spec.ts similarity index 95% rename from web/src/test/auto/dom/cases/packages/keyboardRequisitioner.spec.ts rename to web/src/test/auto/dom/cases/keyboard-storage/keyboardRequisitioner.spec.ts index 7ad8356a322..bada557bf89 100644 --- a/web/src/test/auto/dom/cases/packages/keyboardRequisitioner.spec.ts +++ b/web/src/test/auto/dom/cases/keyboard-storage/keyboardRequisitioner.spec.ts @@ -4,8 +4,8 @@ import sinon from 'sinon'; import { KeyboardHarness, MinimalKeymanGlobal } from 'keyman/engine/keyboard'; import { DOMKeyboardLoader } from 'keyman/engine/keyboard/dom-keyboard-loader'; import { PathConfiguration } from 'keyman/engine/interfaces'; -import { CloudQueryEngine, KeyboardRequisitioner, type KeyboardStub } from 'keyman/engine/package-cache'; -import DOMCloudRequester from 'keyman/engine/package-cache/dom-requester'; +import { CloudQueryEngine, KeyboardRequisitioner, type KeyboardStub } from 'keyman/engine/keyboard-storage'; +import DOMCloudRequester from 'keyman/engine/keyboard-storage/dom-requester'; const pathConfig = new PathConfiguration({ root: '', @@ -14,7 +14,7 @@ const pathConfig = new PathConfiguration({ fonts: '', // The primary / top-level module here is the keyboard-cache bundle. // So, we set up our path config based upon that module for verification purposes. -}, 'http://localhost:9876/@keymanapp/keyman/build/engine/package-cache/lib'); // TODO: set up the current path like actual KMW does it. +}, 'http://localhost:9876/@keymanapp/keyman/build/engine/keyboard-storage/lib'); // TODO: set up the current path like actual KMW does it. /** * Performs mocking setup to facilitate unit testing for the `CloudQueryEngine` class. diff --git a/web/src/test/auto/dom/kbdLoader.ts b/web/src/test/auto/dom/kbdLoader.ts index 8b5c081c758..b0d092c12d5 100644 --- a/web/src/test/auto/dom/kbdLoader.ts +++ b/web/src/test/auto/dom/kbdLoader.ts @@ -9,7 +9,7 @@ import { } from 'keyman/engine/keyboard'; import { KeyboardInterface } from 'keyman/engine/js-processor'; -import { KeyboardStub } from 'keyman/engine/package-cache'; +import { KeyboardStub } from 'keyman/engine/keyboard-storage'; const loader = new DOMKeyboardLoader(new KeyboardInterface(window, MinimalKeymanGlobal)); diff --git a/web/src/test/auto/dom/web-test-runner.config.mjs b/web/src/test/auto/dom/web-test-runner.config.mjs index 1cd8ed0ca29..62edfc7dbf9 100644 --- a/web/src/test/auto/dom/web-test-runner.config.mjs +++ b/web/src/test/auto/dom/web-test-runner.config.mjs @@ -56,9 +56,9 @@ export default { files: ['build/test/dom/cases/osk/**/*.spec.mjs'] }, { - name: 'engine/package-cache', + name: 'engine/keyboard-storage', // Relative, from the containing package.json - files: ['build/test/dom/cases/packages/**/*.spec.mjs'] + files: ['build/test/dom/cases/keyboard-storage/**/*.spec.mjs'] } ], middleware: [ diff --git a/web/src/test/auto/headless/engine/package-cache/cloudQueries.js b/web/src/test/auto/headless/engine/keyboard-storage/cloudQueries.js similarity index 98% rename from web/src/test/auto/headless/engine/package-cache/cloudQueries.js rename to web/src/test/auto/headless/engine/keyboard-storage/cloudQueries.js index 4f379ea5636..eb078c17681 100644 --- a/web/src/test/auto/headless/engine/package-cache/cloudQueries.js +++ b/web/src/test/auto/headless/engine/keyboard-storage/cloudQueries.js @@ -2,9 +2,9 @@ import { assert } from 'chai'; import sinon from 'sinon'; import { ManagedPromise } from '@keymanapp/web-utils'; -import { CloudQueryEngine, StubAndKeyboardCache, toPrefixedKeyboardId as prefixed } from 'keyman/engine/package-cache'; +import { CloudQueryEngine, StubAndKeyboardCache, toPrefixedKeyboardId as prefixed } from 'keyman/engine/keyboard-storage'; import { PathConfiguration } from 'keyman/engine/interfaces'; -import NodeCloudRequester from 'keyman/engine/package-cache/node-requester'; +import NodeCloudRequester from 'keyman/engine/keyboard-storage/node-requester'; import path from 'path'; import { fileURLToPath } from 'url'; diff --git a/web/src/test/auto/headless/engine/package-cache/keyboardRequisitioner.js b/web/src/test/auto/headless/engine/keyboard-storage/keyboardRequisitioner.js similarity index 98% rename from web/src/test/auto/headless/engine/package-cache/keyboardRequisitioner.js rename to web/src/test/auto/headless/engine/keyboard-storage/keyboardRequisitioner.js index 2ca0578790e..b158f4ef9a2 100644 --- a/web/src/test/auto/headless/engine/package-cache/keyboardRequisitioner.js +++ b/web/src/test/auto/headless/engine/keyboard-storage/keyboardRequisitioner.js @@ -7,9 +7,9 @@ import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader' import { KeyboardRequisitioner, toPrefixedKeyboardId as prefixed -} from 'keyman/engine/package-cache'; +} from 'keyman/engine/keyboard-storage'; import { PathConfiguration } from 'keyman/engine/interfaces'; -import NodeCloudRequester from 'keyman/engine/package-cache/node-requester'; +import NodeCloudRequester from 'keyman/engine/keyboard-storage/node-requester'; import path from 'path'; import { fileURLToPath } from 'url'; @@ -33,7 +33,7 @@ const pathConfig = new PathConfiguration({ // Keyboard paths in fixtures are relative to the repository root. keyboards: `file:///${resolvedResourcePackage}/../../..`, // the one part NEEDED for unit tests below. fonts: '', -}, `file:///${path.dirname(require.resolve('keyman/engine/package-cache'))}`); +}, `file:///${path.dirname(require.resolve('keyman/engine/keyboard-storage'))}`); /** * Performs mocking setup to facilitate unit testing for the `CloudQueryEngine` class. diff --git a/web/src/test/auto/headless/engine/package-cache/keyboardStub.js b/web/src/test/auto/headless/engine/keyboard-storage/keyboardStub.js similarity index 96% rename from web/src/test/auto/headless/engine/package-cache/keyboardStub.js rename to web/src/test/auto/headless/engine/keyboard-storage/keyboardStub.js index 6b81e187a46..af7d6b6a57b 100644 --- a/web/src/test/auto/headless/engine/package-cache/keyboardStub.js +++ b/web/src/test/auto/headless/engine/keyboard-storage/keyboardStub.js @@ -1,8 +1,8 @@ import { assert } from 'chai'; import sinon from 'sinon'; -import { KeyboardStub } from 'keyman/engine/package-cache'; -import NodeCloudRequester from 'keyman/engine/package-cache/node-requester'; +import { KeyboardStub } from 'keyman/engine/keyboard-storage'; +import NodeCloudRequester from 'keyman/engine/keyboard-storage/node-requester'; import path from 'path'; import { fileURLToPath } from 'url'; diff --git a/web/src/test/auto/headless/engine/package-cache/nodeCloudRequester.js b/web/src/test/auto/headless/engine/keyboard-storage/nodeCloudRequester.js similarity index 97% rename from web/src/test/auto/headless/engine/package-cache/nodeCloudRequester.js rename to web/src/test/auto/headless/engine/keyboard-storage/nodeCloudRequester.js index 708781932c2..07ac9e98fb6 100644 --- a/web/src/test/auto/headless/engine/package-cache/nodeCloudRequester.js +++ b/web/src/test/auto/headless/engine/keyboard-storage/nodeCloudRequester.js @@ -1,7 +1,7 @@ import { assert } from 'chai'; import sinon from 'sinon'; -import NodeCloudRequester from 'keyman/engine/package-cache/node-requester'; +import NodeCloudRequester from 'keyman/engine/keyboard-storage/node-requester'; import path from 'path'; import { fileURLToPath } from 'url'; diff --git a/web/src/test/auto/headless/engine/package-cache/stubAndKeyboardCache.js b/web/src/test/auto/headless/engine/keyboard-storage/stubAndKeyboardCache.js similarity index 99% rename from web/src/test/auto/headless/engine/package-cache/stubAndKeyboardCache.js rename to web/src/test/auto/headless/engine/keyboard-storage/stubAndKeyboardCache.js index f49bb1238f6..7260b9982e7 100644 --- a/web/src/test/auto/headless/engine/package-cache/stubAndKeyboardCache.js +++ b/web/src/test/auto/headless/engine/keyboard-storage/stubAndKeyboardCache.js @@ -2,7 +2,7 @@ import { assert } from 'chai'; import sinon from 'sinon'; import fs from 'fs'; -import { KeyboardStub, StubAndKeyboardCache } from 'keyman/engine/package-cache'; +import { KeyboardStub, StubAndKeyboardCache } from 'keyman/engine/keyboard-storage'; import { NodeKeyboardLoader } from 'keyman/engine/keyboard/node-keyboard-loader'; import { KeyboardHarness, MinimalKeymanGlobal } from 'keyman/engine/keyboard'; diff --git a/web/src/test/auto/integrated/cases/engine.spec.ts b/web/src/test/auto/integrated/cases/engine.spec.ts index 1ef78358a2e..a7e624cbf44 100644 --- a/web/src/test/auto/integrated/cases/engine.spec.ts +++ b/web/src/test/auto/integrated/cases/engine.spec.ts @@ -9,7 +9,7 @@ import { import * as KMWRecorder from '#recorder'; import { type KeymanEngine, type KeyboardInterface } from 'keyman/app/browser'; -import { type KeyboardStub } from 'keyman/engine/package-cache'; +import { type KeyboardStub } from 'keyman/engine/keyboard-storage'; import { type OSKInputEventSpec } from '#recorder'; type WindowKey = keyof typeof window; diff --git a/web/src/test/auto/integrated/test_utils.ts b/web/src/test/auto/integrated/test_utils.ts index e3c49ef0ee2..6e04885b1a5 100644 --- a/web/src/test/auto/integrated/test_utils.ts +++ b/web/src/test/auto/integrated/test_utils.ts @@ -3,7 +3,7 @@ import Device from 'keyman/engine/device-detect'; import * as KMWRecorder from '#recorder'; import { type BrowserInitOptionSpec, type KeymanEngine } from 'keyman/app/browser'; -import { ErrorStub, type KeyboardAPISpec, type KeyboardStub } from 'keyman/engine/package-cache'; +import { ErrorStub, type KeyboardAPISpec, type KeyboardStub } from 'keyman/engine/keyboard-storage'; type WindowKey = keyof typeof window; const keyman_window = 'keyman' as WindowKey; From b9aa9ccd8ca320207c5a3864933ff3ef960c1570 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Fri, 9 Aug 2024 11:31:51 +0200 Subject: [PATCH 33/65] =?UTF-8?q?refactor(web):=20move=20`predictive-text`?= =?UTF-8?q?=20=E2=86=92=20`worker-main`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This moves `common/predictive-text/` → `web/src/engine/predictive-text/worker-main/`. This also moves `common/test/predictive-text/` → `web/src/test/manual/predictive-text/`. Note though that this testing tool is still broken. Fixes: #12134 --- common/predictive-text/.build-builder | 1 - common/predictive-text/src/tsconfig.json | 23 ---------- docs/CODEOWNERS | 42 +++++++++--------- linux/scripts/dist.sh | 37 ++++++++++----- package-lock.json | 8 ++-- package.json | 4 +- tsconfig.json | 2 +- web/README.md | 2 +- web/build.sh | 6 ++- web/src/engine/main/build.sh | 2 +- .../predictive-text/worker-main}/.gitignore | 0 .../predictive-text/worker-main}/README.md | 0 .../predictive-text/worker-main}/build.sh | 8 ++-- .../worker-main}/docs/build.sh | 0 .../worker-main}/docs/lmlayer-states.dot | 0 .../worker-main}/docs/lmlayer-states.png | Bin .../docs/predictive-text-sequence.png | Bin .../docs/worker-communication-protocol.md | 0 .../predictive-text/worker-main}/package.json | 0 .../predictive-text/worker-main}/src/index.ts | 0 .../worker-main}/src/lmlayer.ts | 0 .../worker-main}/src/node/index.ts | 0 .../worker-main}/src/node/mappedWorker.ts | 0 .../src/node/sourcemappedWorker.ts | 0 .../worker-main}/src/node/tsconfig.json | 2 +- .../worker-main}/src/node/worker.ts | 0 .../worker-main}/src/promise-store.ts | 0 .../worker-main/src/tsconfig.json | 23 ++++++++++ .../worker-main}/src/unwrap.ts | 0 .../worker-main}/src/web/index.ts | 0 .../src/web/sourcemappedWorker.ts | 0 .../worker-main}/src/web/tsconfig.json | 2 +- .../worker-main}/src/web/worker.ts | 0 .../worker-main}/src/worker-interface.d.ts | 0 .../worker-main}/tsconfig.all.json | 12 ++--- .../unit_tests/headless/promise-store.js | 0 .../unit_tests/headless/top-level-lmlayer.js | 0 .../headless/worker-dummy-integration.js | 0 .../headless/worker-trie-integration.js | 0 .../cases/top-level-lmlayer.spec.ts | 0 .../cases/worker-dummy-integration.spec.ts | 0 .../cases/worker-trie-integration.spec.ts | 0 .../unit_tests/in_browser/helpers.mjs | 0 .../in_browser/web-test-runner.CI.config.mjs | 0 .../in_browser/web-test-runner.config.mjs | 2 +- .../worker-main}/unit_tests/test.sh | 2 +- .../test/manual}/predictive-text/.gitignore | 0 .../test/manual}/predictive-text/README.md | 5 +-- .../src/test/manual}/predictive-text/index.js | 4 +- .../test/manual}/predictive-text/package.json | 0 50 files changed, 101 insertions(+), 86 deletions(-) delete mode 100644 common/predictive-text/.build-builder delete mode 100644 common/predictive-text/src/tsconfig.json rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/.gitignore (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/README.md (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/build.sh (84%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/docs/build.sh (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/docs/lmlayer-states.dot (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/docs/lmlayer-states.png (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/docs/predictive-text-sequence.png (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/docs/worker-communication-protocol.md (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/package.json (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/src/index.ts (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/src/lmlayer.ts (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/src/node/index.ts (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/src/node/mappedWorker.ts (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/src/node/sourcemappedWorker.ts (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/src/node/tsconfig.json (89%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/src/node/worker.ts (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/src/promise-store.ts (100%) create mode 100644 web/src/engine/predictive-text/worker-main/src/tsconfig.json rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/src/unwrap.ts (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/src/web/index.ts (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/src/web/sourcemappedWorker.ts (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/src/web/tsconfig.json (83%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/src/web/worker.ts (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/src/worker-interface.d.ts (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/tsconfig.all.json (63%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/unit_tests/headless/promise-store.js (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/unit_tests/headless/top-level-lmlayer.js (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/unit_tests/headless/worker-dummy-integration.js (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/unit_tests/headless/worker-trie-integration.js (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/unit_tests/in_browser/cases/top-level-lmlayer.spec.ts (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/unit_tests/in_browser/cases/worker-dummy-integration.spec.ts (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/unit_tests/in_browser/cases/worker-trie-integration.spec.ts (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/unit_tests/in_browser/helpers.mjs (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/unit_tests/in_browser/web-test-runner.CI.config.mjs (100%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/unit_tests/in_browser/web-test-runner.config.mjs (96%) rename {common/predictive-text => web/src/engine/predictive-text/worker-main}/unit_tests/test.sh (98%) rename {common/test => web/src/test/manual}/predictive-text/.gitignore (100%) rename {common/test => web/src/test/manual}/predictive-text/README.md (96%) rename {common/test => web/src/test/manual}/predictive-text/index.js (99%) rename {common/test => web/src/test/manual}/predictive-text/package.json (100%) diff --git a/common/predictive-text/.build-builder b/common/predictive-text/.build-builder deleted file mode 100644 index 4e15741a629..00000000000 --- a/common/predictive-text/.build-builder +++ /dev/null @@ -1 +0,0 @@ -The presence of this file tells CI to use the new builder_ style parameters for build.sh and unit_tests/test.sh. \ No newline at end of file diff --git a/common/predictive-text/src/tsconfig.json b/common/predictive-text/src/tsconfig.json deleted file mode 100644 index 675bf7cd537..00000000000 --- a/common/predictive-text/src/tsconfig.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "extends": "../../web/tsconfig.kmw-main-base.json", - - "compilerOptions": { - "baseUrl": "./", - "outDir": "../build/obj", - "tsBuildInfoFile": "../build/obj/tsconfig.tsbuildinfo", - "rootDir": "./" - }, - "references": [ - { "path": "../../web/utils" }, - { "path": "../../models/types"}, - { "path": "../../models/wordbreakers"}, - { "path": "../../web/lm-message-types"}, - { "path": "../../models/templates"} - ], - "include" : [ "./*.ts" ], - "exclude" : [ - "node", - "web", - "index.ts" // It's handled by the final layer. - ] -} diff --git a/docs/CODEOWNERS b/docs/CODEOWNERS index 7902ce7a682..75530e6bde1 100644 --- a/docs/CODEOWNERS +++ b/docs/CODEOWNERS @@ -3,30 +3,30 @@ # # @darcywong00 @mcdurdin @ermshiperete @rc-swag @SabineSIL @sgschantz -/android/ @darcywong00 @sgschantz +/android/ @darcywong00 @sgschantz -/common/ @mcdurdin @rc-swag -/core/ @mcdurdin @rc-swag -/common/lexical-model-types/ @jahorton @mcdurdin -/common/models/ @jahorton @mcdurdin -/common/predictive-text/ @jahorton @mcdurdin -/common/schemas/ @mcdurdin @jahorton -/common/test/ @mcdurdin @ermshiperete -/common/web/ @jahorton @mcdurdin +/common/ @mcdurdin @rc-swag +/core/ @mcdurdin @rc-swag +/common/lexical-model-types/ @jahorton @mcdurdin +/common/models/ @jahorton @mcdurdin +/common/schemas/ @mcdurdin @jahorton +/common/test/ @mcdurdin @ermshiperete +/common/web/ @jahorton @mcdurdin -/developer/ @mcdurdin @darcywong00 -/docs/ @mcdurdin @jahorton -/ios/ @sgschantz @jahorton -/linux/ @ermshiperete @darcywong00 -/mac/ @sgschantz @SabineSIL +/developer/ @mcdurdin @darcywong00 +/docs/ @mcdurdin @jahorton +/ios/ @sgschantz @jahorton +/linux/ @ermshiperete @darcywong00 +/mac/ @sgschantz @SabineSIL -/oem/firstvoices/android/ @darcywong00 @sgschantz -/oem/firstvoices/common/ @mcdurdin @rc-swag -/oem/firstvoices/ios/ @sgschantz @jahorton -/oem/firstvoices/windows/ @rc-swag @ermshiperete -/resources/ @mcdurdin @jahorton +/oem/firstvoices/android/ @darcywong00 @sgschantz +/oem/firstvoices/common/ @mcdurdin @rc-swag +/oem/firstvoices/ios/ @sgschantz @jahorton +/oem/firstvoices/windows/ @rc-swag @ermshiperete +/resources/ @mcdurdin @jahorton # Web is currently shared between Eberhard and Joshua: -/web/ @ermshiperete @jahorton +/web/ @ermshiperete @jahorton +/web/src/engine/predictive-text/ @jahorton @mcdurdin -/windows/ @rc-swag @ermshiperete +/windows/ @rc-swag @ermshiperete diff --git a/linux/scripts/dist.sh b/linux/scripts/dist.sh index 0038034d421..6ef0be7d8bb 100755 --- a/linux/scripts/dist.sh +++ b/linux/scripts/dist.sh @@ -30,28 +30,37 @@ cp -a debian ../ cd .. echo "3.0 (native)" > debian/source/format dch keyman --newversion "${VERSION}" --force-bad-version --nomultimaint -dpkg-source --tar-ignore=*~ --tar-ignore=.git --tar-ignore=.gitattributes \ - --tar-ignore=.gitignore --tar-ignore=experiments --tar-ignore=debian \ - --tar-ignore=.github --tar-ignore=.vscode --tar-ignore=android \ +dpkg-source --tar-ignore=*~ \ + --tar-ignore=.git \ + --tar-ignore=.gitattributes \ + --tar-ignore=.gitignore \ + --tar-ignore=experiments \ + --tar-ignore=debian \ + --tar-ignore=.github \ + --tar-ignore=.vscode \ + --tar-ignore=android \ --tar-ignore=.devcontainer \ --tar-ignore=artifacts \ \ --tar-ignore=common/models \ - --tar-ignore=common/predictive-text \ --tar-ignore=common/resources \ --tar-ignore=common/schemas \ --tar-ignore=common/test/keyboards/build.* \ - --tar-ignore=common/test/predictive-text \ --tar-ignore=common/test/resources \ --tar-ignore=common/web \ --tar-ignore=common/windows \ \ --tar-ignore=core/build \ - --tar-ignore=developer --tar-ignore=docs --tar-ignore=ios \ + --tar-ignore=developer \ + --tar-ignore=docs \ + --tar-ignore=ios \ --tar-ignore=linux/keyman-config/keyman_config/version.py \ - --tar-ignore=linux/keyman-config/buildtools/build-langtags.py --tar-ignore=__pycache__ \ + --tar-ignore=linux/keyman-config/buildtools/build-langtags.py \ + --tar-ignore=__pycache__ \ --tar-ignore=linux/help \ - --tar-ignore=mac --tar-ignore=node_modules --tar-ignore=oem \ + --tar-ignore=mac \ + --tar-ignore=node_modules \ + --tar-ignore=oem \ --tar-ignore=linux/build \ --tar-ignore=linux/builddebs \ --tar-ignore=linux/ibus-keyman/build \ @@ -60,11 +69,17 @@ dpkg-source --tar-ignore=*~ --tar-ignore=.git --tar-ignore=.gitattributes \ --tar-ignore=resources/environment.sh \ --tar-ignore=resources/git-hooks \ --tar-ignore=resources/scopes \ - --tar-ignore=resources/build/*.lua --tar-ignore=resources/build/jq* \ + --tar-ignore=resources/build/*.lua \ + --tar-ignore=resources/build/jq* \ --tar-ignore=results \ --tar-ignore=tmp \ - --tar-ignore=web --tar-ignore=windows --tar-ignore=keyman_1* \ - --tar-ignore=dist --tar-ignore=VERSION -Zgzip -b . + --tar-ignore=web \ + --tar-ignore=windows \ + --tar-ignore=keyman_1* \ + --tar-ignore=dist \ + --tar-ignore=VERSION \ + \ + -Zgzip -b . mv ../keyman_"${VERSION}".tar.gz linux/dist/keyman-"${VERSION}".tar.gz echo "3.0 (quilt)" > debian/source/format cd "$BASEDIR" diff --git a/package-lock.json b/package-lock.json index f6ea28257a3..ad53581202a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,9 +25,9 @@ "common/test/resources", "common/tools/*", "common/web/*", - "common/predictive-text", "common/tools/hextobin", - "web" + "web", + "web/src/engine/predictive-text/*" ], "dependencies": { "@keymanapp/common-types": "file:common/web/types", @@ -108,7 +108,7 @@ "typescript": "^5.4.5" } }, - "common/predictive-text": { + "web/src/engine/predictive-text/worker-main": { "name": "@keymanapp/lexical-model-layer", "license": "MIT", "dependencies": { @@ -2892,7 +2892,7 @@ "link": true }, "node_modules/@keymanapp/lexical-model-layer": { - "resolved": "common/predictive-text", + "resolved": "web/src/engine/predictive-text/worker-main", "link": true }, "node_modules/@keymanapp/lm-message-types": { diff --git a/package.json b/package.json index 638f2b2fad1..3f0012db10c 100644 --- a/package.json +++ b/package.json @@ -50,9 +50,9 @@ "common/test/resources", "common/tools/*", "common/web/*", - "common/predictive-text", "common/tools/hextobin", - "web" + "web", + "web/src/engine/predictive-text/*" ], "dependencies": { "@keymanapp/common-types": "file:common/web/types", diff --git a/tsconfig.json b/tsconfig.json index 8e6596a2312..42b3fd1a993 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,6 @@ { "path": "./common/models/templates/tsconfig.json" }, { "path": "./common/models/types/tsconfig.json" }, { "path": "./common/models/wordbreakers/tsconfig.json" }, - { "path": "./common/predictive-text/tsconfig.all.json" }, { "path": "./common/tools/hextobin/" }, { "path": "./common/web/gesture-recognizer/tsconfig.json" }, @@ -43,6 +42,7 @@ { "path": "./resources/build/version/" }, { "path": "./web/src/tsconfig.all.json" }, + { "path": "./web/src/engine/predictive-text/worker-main/tsconfig.all.json" }, // { "path": "./web/tools/recorder/tsconfig.json" }, // { "path": "./web/tools/sourcemap-root/tsconfig.json" }, ] diff --git a/web/README.md b/web/README.md index 4f35643e1a9..1e41497657c 100644 --- a/web/README.md +++ b/web/README.md @@ -92,7 +92,7 @@ graph TD; LMWorker["@keymanapp/lm-worker
(/common/web/lm-worker)"]; LMWorker-->Models; LMWorker-->Wordbreakers; - LMLayer["@keymanapp/lexical-model-layer
(/common/predictive-text)"]; + LMLayer["@keymanapp/lexical-model-layer
(/web/src/engine/predictive-text/worker-main)"]; LMLayer-->LMWorker; Gestures["@keymanapp/gesture-recognizer
(/common/web/gesture-recognizer)"]; Gestures-->WebUtils; diff --git a/web/build.sh b/web/build.sh index 4705bc55de9..f0dd201bc8d 100755 --- a/web/build.sh +++ b/web/build.sh @@ -27,12 +27,13 @@ builder_describe "Builds engine modules for Keyman Engine for Web (KMW)." \ ":engine/dom-utils A common subset of function used for DOM calculations, layout, etc" \ ":engine/events Specialized classes utilized to support KMW API events" \ ":engine/element-wrappers Subset used to integrate with website elements" \ + ":engine/interfaces Subset used to configure KMW" \ ":engine/js-processor Build JS processor for KMW" \ ":engine/keyboard Builds KMW's keyboard-loading and caching code" \ ":engine/keyboard-storage Subset used to collate keyboards and request them from the cloud" \ ":engine/main Builds all common code used by KMW's app/-level targets" \ ":engine/osk Builds the Web OSK module" \ - ":engine/interfaces Subset used to configure KMW" \ + ":engine/predictive-text=src/engine/predictive-text/worker-main Builds KMW's predictive text module" \ ":samples Builds all needed resources for the KMW sample-page set" \ ":tools Builds engine-related development resources" \ ":test-pages=src/test/manual Builds resources needed for the KMW manual testing pages" \ @@ -59,12 +60,13 @@ builder_describe_outputs \ build:engine/dom-utils "/web/build/engine/dom-utils/obj/index.js" \ build:engine/events "/web/build/engine/events/lib/index.mjs" \ build:engine/element-wrappers "/web/build/engine/element-wrappers/lib/index.mjs" \ + build:engine/interfaces "/web/build/engine/interfaces/lib/index.mjs" \ build:engine/js-processor "/web/build/engine/js-processor/lib/index.mjs" \ build:engine/keyboard "/web/build/engine/keyboard/lib/index.mjs" \ build:engine/keyboard-storage "/web/build/engine/keyboard-storage/lib/index.mjs" \ build:engine/main "/web/build/engine/main/lib/index.mjs" \ build:engine/osk "/web/build/engine/osk/lib/index.mjs" \ - build:engine/interfaces "/web/build/engine/interfaces/lib/index.mjs" \ + build:engine/predictive-text "/web/src/engine/predictive-text/worker-main/build/lib/web/index.mjs" \ build:samples "/web/src/samples/simplest/keymanweb.js" \ build:tools "/web/build/tools/building/sourcemap-root/index.js" \ build:test-pages "/web/build/test-resources/sentry-manager.js" diff --git a/web/src/engine/main/build.sh b/web/src/engine/main/build.sh index 737ca9a5bd4..77673626e02 100755 --- a/web/src/engine/main/build.sh +++ b/web/src/engine/main/build.sh @@ -15,12 +15,12 @@ SUBPROJECT_NAME=engine/main builder_describe "Builds the Keyman Engine for Web's common top-level base classes." \ "@/common/web/keyman-version" \ "@/web/src/engine/keyboard" \ - "@/common/predictive-text" \ "@/web/src/engine/interfaces build" \ "@/web/src/engine/device-detect build" \ "@/web/src/engine/js-processor build" \ "@/web/src/engine/keyboard-storage build" \ "@/web/src/engine/osk build" \ + "@/web/src/engine/predictive-text/worker-main" \ "@/developer/src/kmc-model test" \ "clean" \ "configure" \ diff --git a/common/predictive-text/.gitignore b/web/src/engine/predictive-text/worker-main/.gitignore similarity index 100% rename from common/predictive-text/.gitignore rename to web/src/engine/predictive-text/worker-main/.gitignore diff --git a/common/predictive-text/README.md b/web/src/engine/predictive-text/worker-main/README.md similarity index 100% rename from common/predictive-text/README.md rename to web/src/engine/predictive-text/worker-main/README.md diff --git a/common/predictive-text/build.sh b/web/src/engine/predictive-text/worker-main/build.sh similarity index 84% rename from common/predictive-text/build.sh rename to web/src/engine/predictive-text/worker-main/build.sh index b9ab6016914..4120fce53b1 100755 --- a/common/predictive-text/build.sh +++ b/web/src/engine/predictive-text/worker-main/build.sh @@ -8,7 +8,7 @@ ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" -. "${THIS_SCRIPT%/*}/../../resources/build/builder.inc.sh" +. "${THIS_SCRIPT%/*}/../../../../../resources/build/builder.inc.sh" ## END STANDARD BUILD SCRIPT INCLUDE . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" @@ -31,7 +31,7 @@ builder_describe "Builds the lm-layer module" \ builder_describe_outputs \ configure /node_modules \ - build /common/predictive-text/build/lib/web/index.mjs # is built by the final step. + build /web/src/engine/predictive-text/worker-main/build/lib/web/index.mjs # is built by the final step. builder_parse "$@" @@ -48,8 +48,8 @@ function do_build() { tsc -b ./tsconfig.all.json # esbuild-bundled products at this level are not intended to be used for anything but testing. - $BUNDLE_CMD "${KEYMAN_ROOT}/common/predictive-text/build/obj/web/index.js" \ - --out "${KEYMAN_ROOT}/common/predictive-text/build/lib/web/index.mjs" \ + $BUNDLE_CMD "${KEYMAN_ROOT}/web/src/engine/predictive-text/worker-main/build/obj/web/index.js" \ + --out "${KEYMAN_ROOT}/web/src/engine/predictive-text/worker-main/build/lib/web/index.mjs" \ --format esm } diff --git a/common/predictive-text/docs/build.sh b/web/src/engine/predictive-text/worker-main/docs/build.sh similarity index 100% rename from common/predictive-text/docs/build.sh rename to web/src/engine/predictive-text/worker-main/docs/build.sh diff --git a/common/predictive-text/docs/lmlayer-states.dot b/web/src/engine/predictive-text/worker-main/docs/lmlayer-states.dot similarity index 100% rename from common/predictive-text/docs/lmlayer-states.dot rename to web/src/engine/predictive-text/worker-main/docs/lmlayer-states.dot diff --git a/common/predictive-text/docs/lmlayer-states.png b/web/src/engine/predictive-text/worker-main/docs/lmlayer-states.png similarity index 100% rename from common/predictive-text/docs/lmlayer-states.png rename to web/src/engine/predictive-text/worker-main/docs/lmlayer-states.png diff --git a/common/predictive-text/docs/predictive-text-sequence.png b/web/src/engine/predictive-text/worker-main/docs/predictive-text-sequence.png similarity index 100% rename from common/predictive-text/docs/predictive-text-sequence.png rename to web/src/engine/predictive-text/worker-main/docs/predictive-text-sequence.png diff --git a/common/predictive-text/docs/worker-communication-protocol.md b/web/src/engine/predictive-text/worker-main/docs/worker-communication-protocol.md similarity index 100% rename from common/predictive-text/docs/worker-communication-protocol.md rename to web/src/engine/predictive-text/worker-main/docs/worker-communication-protocol.md diff --git a/common/predictive-text/package.json b/web/src/engine/predictive-text/worker-main/package.json similarity index 100% rename from common/predictive-text/package.json rename to web/src/engine/predictive-text/worker-main/package.json diff --git a/common/predictive-text/src/index.ts b/web/src/engine/predictive-text/worker-main/src/index.ts similarity index 100% rename from common/predictive-text/src/index.ts rename to web/src/engine/predictive-text/worker-main/src/index.ts diff --git a/common/predictive-text/src/lmlayer.ts b/web/src/engine/predictive-text/worker-main/src/lmlayer.ts similarity index 100% rename from common/predictive-text/src/lmlayer.ts rename to web/src/engine/predictive-text/worker-main/src/lmlayer.ts diff --git a/common/predictive-text/src/node/index.ts b/web/src/engine/predictive-text/worker-main/src/node/index.ts similarity index 100% rename from common/predictive-text/src/node/index.ts rename to web/src/engine/predictive-text/worker-main/src/node/index.ts diff --git a/common/predictive-text/src/node/mappedWorker.ts b/web/src/engine/predictive-text/worker-main/src/node/mappedWorker.ts similarity index 100% rename from common/predictive-text/src/node/mappedWorker.ts rename to web/src/engine/predictive-text/worker-main/src/node/mappedWorker.ts diff --git a/common/predictive-text/src/node/sourcemappedWorker.ts b/web/src/engine/predictive-text/worker-main/src/node/sourcemappedWorker.ts similarity index 100% rename from common/predictive-text/src/node/sourcemappedWorker.ts rename to web/src/engine/predictive-text/worker-main/src/node/sourcemappedWorker.ts diff --git a/common/predictive-text/src/node/tsconfig.json b/web/src/engine/predictive-text/worker-main/src/node/tsconfig.json similarity index 89% rename from common/predictive-text/src/node/tsconfig.json rename to web/src/engine/predictive-text/worker-main/src/node/tsconfig.json index f95364c4175..a1ab0f2f7cd 100644 --- a/common/predictive-text/src/node/tsconfig.json +++ b/web/src/engine/predictive-text/worker-main/src/node/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../../web/tsconfig.kmw-main-base.json", + "extends": "../../../../../../tsconfig.base.json", "compilerOptions": { // The Worker class needs access to the `new` keyword, else Node will throw an // error when constructing the Worker for unit tests. ES6 is sufficient. diff --git a/common/predictive-text/src/node/worker.ts b/web/src/engine/predictive-text/worker-main/src/node/worker.ts similarity index 100% rename from common/predictive-text/src/node/worker.ts rename to web/src/engine/predictive-text/worker-main/src/node/worker.ts diff --git a/common/predictive-text/src/promise-store.ts b/web/src/engine/predictive-text/worker-main/src/promise-store.ts similarity index 100% rename from common/predictive-text/src/promise-store.ts rename to web/src/engine/predictive-text/worker-main/src/promise-store.ts diff --git a/web/src/engine/predictive-text/worker-main/src/tsconfig.json b/web/src/engine/predictive-text/worker-main/src/tsconfig.json new file mode 100644 index 00000000000..b7cd725cf93 --- /dev/null +++ b/web/src/engine/predictive-text/worker-main/src/tsconfig.json @@ -0,0 +1,23 @@ +{ + "extends": "../../../../../tsconfig.base.json", + + "compilerOptions": { + "baseUrl": "./", + "outDir": "../build/obj", + "tsBuildInfoFile": "../build/obj/tsconfig.tsbuildinfo", + "rootDir": "./" + }, + "references": [ + { "path": "../../../../../../common/web/utils" }, + { "path": "../../../../../../common/models/types"}, + { "path": "../../../../../../common/models/wordbreakers"}, + { "path": "../../../../../../common/web/lm-message-types"}, + { "path": "../../../../../../common/models/templates"} + ], + "include" : [ "./*.ts" ], + "exclude" : [ + "node", + "web", + "index.ts" // It's handled by the final layer. + ] +} diff --git a/common/predictive-text/src/unwrap.ts b/web/src/engine/predictive-text/worker-main/src/unwrap.ts similarity index 100% rename from common/predictive-text/src/unwrap.ts rename to web/src/engine/predictive-text/worker-main/src/unwrap.ts diff --git a/common/predictive-text/src/web/index.ts b/web/src/engine/predictive-text/worker-main/src/web/index.ts similarity index 100% rename from common/predictive-text/src/web/index.ts rename to web/src/engine/predictive-text/worker-main/src/web/index.ts diff --git a/common/predictive-text/src/web/sourcemappedWorker.ts b/web/src/engine/predictive-text/worker-main/src/web/sourcemappedWorker.ts similarity index 100% rename from common/predictive-text/src/web/sourcemappedWorker.ts rename to web/src/engine/predictive-text/worker-main/src/web/sourcemappedWorker.ts diff --git a/common/predictive-text/src/web/tsconfig.json b/web/src/engine/predictive-text/worker-main/src/web/tsconfig.json similarity index 83% rename from common/predictive-text/src/web/tsconfig.json rename to web/src/engine/predictive-text/worker-main/src/web/tsconfig.json index c16936db12d..769c97d589d 100644 --- a/common/predictive-text/src/web/tsconfig.json +++ b/web/src/engine/predictive-text/worker-main/src/web/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../../web/tsconfig.kmw-main-base.json", + "extends": "../../../../../../tsconfig.base.json", "compilerOptions": { "lib": ["es6", "DOM"], "baseUrl": "../", diff --git a/common/predictive-text/src/web/worker.ts b/web/src/engine/predictive-text/worker-main/src/web/worker.ts similarity index 100% rename from common/predictive-text/src/web/worker.ts rename to web/src/engine/predictive-text/worker-main/src/web/worker.ts diff --git a/common/predictive-text/src/worker-interface.d.ts b/web/src/engine/predictive-text/worker-main/src/worker-interface.d.ts similarity index 100% rename from common/predictive-text/src/worker-interface.d.ts rename to web/src/engine/predictive-text/worker-main/src/worker-interface.d.ts diff --git a/common/predictive-text/tsconfig.all.json b/web/src/engine/predictive-text/worker-main/tsconfig.all.json similarity index 63% rename from common/predictive-text/tsconfig.all.json rename to web/src/engine/predictive-text/worker-main/tsconfig.all.json index f47b208edaf..6307444b963 100644 --- a/common/predictive-text/tsconfig.all.json +++ b/web/src/engine/predictive-text/worker-main/tsconfig.all.json @@ -3,7 +3,7 @@ // require separate sub-tsconfigs, both of which require common references. The multi-config // setup in this project and its subfolders ensure all modules can compile cleanly and in the // necessary compilation order. - "extends": "../web/tsconfig.kmw-main-base.json", + "extends": "../../../../tsconfig.base.json", "compilerOptions": { "baseUrl": "./", @@ -13,11 +13,11 @@ }, "files": [], "references": [ - { "path": "../web/utils" }, - { "path": "../models/types"}, - { "path": "../models/wordbreakers"}, - { "path": "../web/lm-message-types"}, - { "path": "../models/templates"}, + { "path": "../../../../../common/web/utils" }, + { "path": "../../../../../common/models/types"}, + { "path": "../../../../../common/models/wordbreakers"}, + { "path": "../../../../../common/web/lm-message-types"}, + { "path": "../../../../../common/models/templates"}, { "path": "src/node" }, { "path": "src/web" } ], diff --git a/common/predictive-text/unit_tests/headless/promise-store.js b/web/src/engine/predictive-text/worker-main/unit_tests/headless/promise-store.js similarity index 100% rename from common/predictive-text/unit_tests/headless/promise-store.js rename to web/src/engine/predictive-text/worker-main/unit_tests/headless/promise-store.js diff --git a/common/predictive-text/unit_tests/headless/top-level-lmlayer.js b/web/src/engine/predictive-text/worker-main/unit_tests/headless/top-level-lmlayer.js similarity index 100% rename from common/predictive-text/unit_tests/headless/top-level-lmlayer.js rename to web/src/engine/predictive-text/worker-main/unit_tests/headless/top-level-lmlayer.js diff --git a/common/predictive-text/unit_tests/headless/worker-dummy-integration.js b/web/src/engine/predictive-text/worker-main/unit_tests/headless/worker-dummy-integration.js similarity index 100% rename from common/predictive-text/unit_tests/headless/worker-dummy-integration.js rename to web/src/engine/predictive-text/worker-main/unit_tests/headless/worker-dummy-integration.js diff --git a/common/predictive-text/unit_tests/headless/worker-trie-integration.js b/web/src/engine/predictive-text/worker-main/unit_tests/headless/worker-trie-integration.js similarity index 100% rename from common/predictive-text/unit_tests/headless/worker-trie-integration.js rename to web/src/engine/predictive-text/worker-main/unit_tests/headless/worker-trie-integration.js diff --git a/common/predictive-text/unit_tests/in_browser/cases/top-level-lmlayer.spec.ts b/web/src/engine/predictive-text/worker-main/unit_tests/in_browser/cases/top-level-lmlayer.spec.ts similarity index 100% rename from common/predictive-text/unit_tests/in_browser/cases/top-level-lmlayer.spec.ts rename to web/src/engine/predictive-text/worker-main/unit_tests/in_browser/cases/top-level-lmlayer.spec.ts diff --git a/common/predictive-text/unit_tests/in_browser/cases/worker-dummy-integration.spec.ts b/web/src/engine/predictive-text/worker-main/unit_tests/in_browser/cases/worker-dummy-integration.spec.ts similarity index 100% rename from common/predictive-text/unit_tests/in_browser/cases/worker-dummy-integration.spec.ts rename to web/src/engine/predictive-text/worker-main/unit_tests/in_browser/cases/worker-dummy-integration.spec.ts diff --git a/common/predictive-text/unit_tests/in_browser/cases/worker-trie-integration.spec.ts b/web/src/engine/predictive-text/worker-main/unit_tests/in_browser/cases/worker-trie-integration.spec.ts similarity index 100% rename from common/predictive-text/unit_tests/in_browser/cases/worker-trie-integration.spec.ts rename to web/src/engine/predictive-text/worker-main/unit_tests/in_browser/cases/worker-trie-integration.spec.ts diff --git a/common/predictive-text/unit_tests/in_browser/helpers.mjs b/web/src/engine/predictive-text/worker-main/unit_tests/in_browser/helpers.mjs similarity index 100% rename from common/predictive-text/unit_tests/in_browser/helpers.mjs rename to web/src/engine/predictive-text/worker-main/unit_tests/in_browser/helpers.mjs diff --git a/common/predictive-text/unit_tests/in_browser/web-test-runner.CI.config.mjs b/web/src/engine/predictive-text/worker-main/unit_tests/in_browser/web-test-runner.CI.config.mjs similarity index 100% rename from common/predictive-text/unit_tests/in_browser/web-test-runner.CI.config.mjs rename to web/src/engine/predictive-text/worker-main/unit_tests/in_browser/web-test-runner.CI.config.mjs diff --git a/common/predictive-text/unit_tests/in_browser/web-test-runner.config.mjs b/web/src/engine/predictive-text/worker-main/unit_tests/in_browser/web-test-runner.config.mjs similarity index 96% rename from common/predictive-text/unit_tests/in_browser/web-test-runner.config.mjs rename to web/src/engine/predictive-text/worker-main/unit_tests/in_browser/web-test-runner.config.mjs index 523cd254577..6f9df64ddbf 100644 --- a/common/predictive-text/unit_tests/in_browser/web-test-runner.config.mjs +++ b/web/src/engine/predictive-text/worker-main/unit_tests/in_browser/web-test-runner.config.mjs @@ -7,7 +7,7 @@ import { dirname, resolve } from 'path'; import { sessionStabilityReporter } from '@keymanapp/common-test-resources/test-runner-stability-reporter.mjs'; const dir = dirname(fileURLToPath(import.meta.url)); -const KEYMAN_ROOT = resolve(dir, '../../../../'); +const KEYMAN_ROOT = resolve(dir, '../../../../../../../'); /** @type {import('@web/test-runner').TestRunnerConfig} */ export default { diff --git a/common/predictive-text/unit_tests/test.sh b/web/src/engine/predictive-text/worker-main/unit_tests/test.sh similarity index 98% rename from common/predictive-text/unit_tests/test.sh rename to web/src/engine/predictive-text/worker-main/unit_tests/test.sh index 3eb87bae569..007bf363576 100755 --- a/common/predictive-text/unit_tests/test.sh +++ b/web/src/engine/predictive-text/worker-main/unit_tests/test.sh @@ -3,7 +3,7 @@ ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" -. "${THIS_SCRIPT%/*}/../../../resources/build/build-utils.sh" +. "${THIS_SCRIPT%/*}/../../../../../../resources/build/build-utils.sh" ## END STANDARD BUILD SCRIPT INCLUDE . "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh" diff --git a/common/test/predictive-text/.gitignore b/web/src/test/manual/predictive-text/.gitignore similarity index 100% rename from common/test/predictive-text/.gitignore rename to web/src/test/manual/predictive-text/.gitignore diff --git a/common/test/predictive-text/README.md b/web/src/test/manual/predictive-text/README.md similarity index 96% rename from common/test/predictive-text/README.md rename to web/src/test/manual/predictive-text/README.md index ddf89bb8be5..0ab038ca11a 100644 --- a/common/test/predictive-text/README.md +++ b/web/src/test/manual/predictive-text/README.md @@ -9,10 +9,9 @@ Install **NOTE**: Requires Node >= 10.0 First, ensure that Keyman web and the LMLayer are built. You can run the -build script in `/web/source` to do this for you: +build script in `/web` to do this for you: - cd ../../../web/source - ./build.sh + ../../../../web/build.sh Then, you can install locally with `npm`: diff --git a/common/test/predictive-text/index.js b/web/src/test/manual/predictive-text/index.js similarity index 99% rename from common/test/predictive-text/index.js rename to web/src/test/manual/predictive-text/index.js index 934dcf67a6c..605ed2939ce 100755 --- a/common/test/predictive-text/index.js +++ b/web/src/test/manual/predictive-text/index.js @@ -13,7 +13,7 @@ const {EventIterator} = require('event-iterator'); const program = require('commander'); // Load the most recent LMLayer code locally. -const LMLayer = require('../../predictive-text'); +const LMLayer = require('../../../engine/predictive-text/worker-main'); ///////////////////////////////// Constants ///////////////////////////////// @@ -331,7 +331,7 @@ async function asyncRepl(modelFile) { function createAsyncWorker() { // XXX: import the LMLayerWorker directly -- I know where it is built. - const LMLayerWorker = require('../../predictive-text/build/intermediate'); + const LMLayerWorker = require('../../../engine/predictive-text/build/intermediate'); const vm = require('vm'); let worker = { diff --git a/common/test/predictive-text/package.json b/web/src/test/manual/predictive-text/package.json similarity index 100% rename from common/test/predictive-text/package.json rename to web/src/test/manual/predictive-text/package.json From 55ed18bc875db8a7dbc057aa0b697bc32346b491 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Thu, 15 Aug 2024 14:03:17 -0400 Subject: [PATCH 34/65] auto: increment master version to 18.0.91 --- HISTORY.md | 8 ++++++++ VERSION.md | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 185c9d7626f..f9117038345 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,13 @@ # Keyman Version History +## 18.0.90 alpha 2024-08-15 + +* refactor(web): move parts of `keyboard-processor` → `js-processor` (#12111) +* fix(web): allow `lm-worker` to build on Linux (#12181) +* refactor(web): move remaining parts of `keyboard-processor` → `keyboard` (#12131) +* docs: update .kmx documentation around bitmaps, modifier state (#12183) +* refactor(web): rename `package-cache` → `keyboard-storage` (#12135) + ## 18.0.89 alpha 2024-08-14 * feat(web): test skipped prediction round handling (#12169) diff --git a/VERSION.md b/VERSION.md index 49d69062262..8f233fffc08 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -18.0.90 \ No newline at end of file +18.0.91 \ No newline at end of file From c3e3cbaaee37fcfebc0370250149f50882fa0dd7 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Fri, 16 Aug 2024 10:07:49 +0700 Subject: [PATCH 35/65] fix(web): fix malformed reversion display strings Fixes: #12199 --- common/web/lm-worker/src/main/model-compositor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/web/lm-worker/src/main/model-compositor.ts b/common/web/lm-worker/src/main/model-compositor.ts index 39a6add834a..c6b8367b782 100644 --- a/common/web/lm-worker/src/main/model-compositor.ts +++ b/common/web/lm-worker/src/main/model-compositor.ts @@ -225,7 +225,7 @@ export class ModelCompositor { // Handles display string for reversions triggered by accepting a suggestion mid-token. const preCaretToken = postContextTokenization.left[postContextTokenization.left.length - 1]; revertedPrefix = (preCaretToken && !preCaretToken.isWhitespace) ? preCaretToken.text : ''; - revertedPrefix += postContextTokenization.caretSplitsToken ? postContextTokenization.right[0] : ''; + revertedPrefix += postContextTokenization.caretSplitsToken ? postContextTokenization.right[0].text : ''; } else { revertedPrefix = this.wordbreak(postContext); } From e52937f907c60097dc1eb2d51ffbb0b39a5e85b5 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Fri, 16 Aug 2024 06:58:05 +0200 Subject: [PATCH 36/65] Apply suggestions from code review Co-authored-by: Joshua Horton --- web/src/engine/predictive-text/worker-main/src/tsconfig.json | 4 +--- web/src/engine/predictive-text/worker-main/tsconfig.all.json | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/web/src/engine/predictive-text/worker-main/src/tsconfig.json b/web/src/engine/predictive-text/worker-main/src/tsconfig.json index b7cd725cf93..9c7a1f47ee8 100644 --- a/web/src/engine/predictive-text/worker-main/src/tsconfig.json +++ b/web/src/engine/predictive-text/worker-main/src/tsconfig.json @@ -10,9 +10,7 @@ "references": [ { "path": "../../../../../../common/web/utils" }, { "path": "../../../../../../common/models/types"}, - { "path": "../../../../../../common/models/wordbreakers"}, - { "path": "../../../../../../common/web/lm-message-types"}, - { "path": "../../../../../../common/models/templates"} + { "path": "../../../../../../common/web/lm-message-types"} ], "include" : [ "./*.ts" ], "exclude" : [ diff --git a/web/src/engine/predictive-text/worker-main/tsconfig.all.json b/web/src/engine/predictive-text/worker-main/tsconfig.all.json index 6307444b963..f86c0815422 100644 --- a/web/src/engine/predictive-text/worker-main/tsconfig.all.json +++ b/web/src/engine/predictive-text/worker-main/tsconfig.all.json @@ -15,9 +15,7 @@ "references": [ { "path": "../../../../../common/web/utils" }, { "path": "../../../../../common/models/types"}, - { "path": "../../../../../common/models/wordbreakers"}, { "path": "../../../../../common/web/lm-message-types"}, - { "path": "../../../../../common/models/templates"}, { "path": "src/node" }, { "path": "src/web" } ], From 50d0107f38aad117939f7a225186557331816119 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 16 Aug 2024 08:04:18 +0200 Subject: [PATCH 37/65] fix(developer): enforce presence of kps Info.Description field in info compilers The Description field should be required for published keyboards and models, so this change means kmc-keyboard-info and kmc-model-info will report an error if it is missing. Relates-to: keymanapp/keyboards#3037 Relates-to: keymanapp/lexical-models#262 Fixes: #12202 --- .../src/keyboard-info-compiler-messages.ts | 10 ++++++++-- .../kmc-keyboard-info/src/keyboard-info-compiler.ts | 3 +++ .../kmc-model-info/src/model-info-compiler-messages.ts | 5 +++++ .../src/kmc-model-info/src/model-info-compiler.ts | 3 +++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/developer/src/kmc-keyboard-info/src/keyboard-info-compiler-messages.ts b/developer/src/kmc-keyboard-info/src/keyboard-info-compiler-messages.ts index 285e272da5b..bf5d989718b 100644 --- a/developer/src/kmc-keyboard-info/src/keyboard-info-compiler-messages.ts +++ b/developer/src/kmc-keyboard-info/src/keyboard-info-compiler-messages.ts @@ -52,8 +52,14 @@ export class KeyboardInfoCompilerMessages { static Error_FontFileCannotBeRead = (o:{filename: string}) => m(this.ERROR_FontFileCannotBeRead, `Font ${def(o.filename)} could not be parsed to extract a font family.`); -static ERROR_FontFileMetaDataIsInvalid = SevError | 0x000F; -static Error_FontFileMetaDataIsInvalid = (o:{filename: string,message:string}) => m(this.ERROR_FontFileMetaDataIsInvalid, + static ERROR_FontFileMetaDataIsInvalid = SevError | 0x000F; + static Error_FontFileMetaDataIsInvalid = (o:{filename: string,message:string}) => m( + this.ERROR_FontFileMetaDataIsInvalid, `Font ${def(o.filename)} meta data invalid: ${def(o.message)}.`); + + static ERROR_DescriptionIsMissing = SevError | 0x0010; + static Error_DescriptionIsMissing = (o:{filename:string}) => m( + this.ERROR_DescriptionIsMissing, + `The Info.Description field in the package ${def(o.filename)} is required, but is missing or empty.`); } diff --git a/developer/src/kmc-keyboard-info/src/keyboard-info-compiler.ts b/developer/src/kmc-keyboard-info/src/keyboard-info-compiler.ts index 74699556988..8e89bb81646 100644 --- a/developer/src/kmc-keyboard-info/src/keyboard-info-compiler.ts +++ b/developer/src/kmc-keyboard-info/src/keyboard-info-compiler.ts @@ -251,6 +251,9 @@ export class KeyboardInfoCompiler implements KeymanCompiler { if(kmpJsonData.info.description?.description) { keyboard_info.description = kmpJsonData.info.description.description.trim(); + } else { + this.callbacks.reportMessage(KeyboardInfoCompilerMessages.Error_DescriptionIsMissing({filename:sources.kpsFilename})); + return null; } // extract the language identifiers from the language metadata arrays for diff --git a/developer/src/kmc-model-info/src/model-info-compiler-messages.ts b/developer/src/kmc-model-info/src/model-info-compiler-messages.ts index e033d6c021c..cbf6b57eb90 100644 --- a/developer/src/kmc-model-info/src/model-info-compiler-messages.ts +++ b/developer/src/kmc-model-info/src/model-info-compiler-messages.ts @@ -44,5 +44,10 @@ export class ModelInfoCompilerMessages { static ERROR_NoLicenseFound = SevError | 0x0009; static Error_NoLicenseFound = () => m(this.ERROR_NoLicenseFound, `No license for the model was found. MIT license is required for publication to Keyman lexical-models repository.`); + + static ERROR_DescriptionIsMissing = SevError | 0x000A; + static Error_DescriptionIsMissing = (o:{filename:string}) => m( + this.ERROR_DescriptionIsMissing, + `The Info.Description field in the package ${def(o.filename)} is required, but is missing or empty.`); } diff --git a/developer/src/kmc-model-info/src/model-info-compiler.ts b/developer/src/kmc-model-info/src/model-info-compiler.ts index d4f3d10d435..a5fb62cbcda 100644 --- a/developer/src/kmc-model-info/src/model-info-compiler.ts +++ b/developer/src/kmc-model-info/src/model-info-compiler.ts @@ -204,6 +204,9 @@ export class ModelInfoCompiler implements KeymanCompiler { if(sources.kmpJsonData.info.description?.description) { model_info.description = sources.kmpJsonData.info.description.description.trim(); + } else { + this.callbacks.reportMessage(ModelInfoCompilerMessages.Error_DescriptionIsMissing({filename:sources.kpsFilename})); + return null; } // isRTL -- this is a little bit of a heuristic from a compiled .js From ba96d26858a257b8fe22b7a2c5b3e3e8591db0cc Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 16 Aug 2024 08:24:37 +0200 Subject: [PATCH 38/65] fix(developer): enforce presence of Version field when FollowKeyboardVersion is not set, in package compiler Fixes: #12193 --- .../src/compiler/package-compiler-messages.ts | 6 ++++ .../src/compiler/package-version-validator.ts | 5 +++ .../absolute_path/source/absolute_path.kps | 1 + .../error_package_file_has_empty_version.kps | 32 +++++++++++++++++++ .../src/kmc-package/test/test-messages.ts | 4 +++ .../kmc-package/test/test-package-compiler.ts | 2 ++ 6 files changed, 50 insertions(+) create mode 100644 developer/src/kmc-package/test/fixtures/invalid/error_package_file_has_empty_version.kps diff --git a/developer/src/kmc-package/src/compiler/package-compiler-messages.ts b/developer/src/kmc-package/src/compiler/package-compiler-messages.ts index 154cb2143e7..00d8a380b5e 100644 --- a/developer/src/kmc-package/src/compiler/package-compiler-messages.ts +++ b/developer/src/kmc-package/src/compiler/package-compiler-messages.ts @@ -138,5 +138,11 @@ export class PackageCompilerMessages { static ERROR_InvalidAuthorEmail = SevError | 0x0020; static Error_InvalidAuthorEmail = (o:{email:string}) => m(this.ERROR_InvalidAuthorEmail, `Invalid author email: ${def(o.email)}`); + + static ERROR_PackageFileHasEmptyVersion = SevError | 0x0021; + static Error_PackageFileHasEmptyVersion = () => m( + this.ERROR_PackageFileHasEmptyVersion, + `Package version is not following keyboard version, but the package version field is blank.` + ); } diff --git a/developer/src/kmc-package/src/compiler/package-version-validator.ts b/developer/src/kmc-package/src/compiler/package-version-validator.ts index 1aad375d400..b20e086aec7 100644 --- a/developer/src/kmc-package/src/compiler/package-version-validator.ts +++ b/developer/src/kmc-package/src/compiler/package-version-validator.ts @@ -42,6 +42,11 @@ export class PackageVersionValidator { if(!this.checkFollowKeyboardVersion(kmp)) { return false; } + } else { + if(!kmp.info.version) { + this.callbacks.reportMessage(PackageCompilerMessages.Error_PackageFileHasEmptyVersion()); + return false; + } } if(!kmp.keyboards) { diff --git a/developer/src/kmc-package/test/fixtures/absolute_path/source/absolute_path.kps b/developer/src/kmc-package/test/fixtures/absolute_path/source/absolute_path.kps index e7c4a8b8512..b5a74c06ee1 100644 --- a/developer/src/kmc-package/test/fixtures/absolute_path/source/absolute_path.kps +++ b/developer/src/kmc-package/test/fixtures/absolute_path/source/absolute_path.kps @@ -17,6 +17,7 @@ Absolute Path + 1.0 diff --git a/developer/src/kmc-package/test/fixtures/invalid/error_package_file_has_empty_version.kps b/developer/src/kmc-package/test/fixtures/invalid/error_package_file_has_empty_version.kps new file mode 100644 index 00000000000..386b4e2e03e --- /dev/null +++ b/developer/src/kmc-package/test/fixtures/invalid/error_package_file_has_empty_version.kps @@ -0,0 +1,32 @@ + + + + 15.0.266.0 + 7.0 + + + + Invalid Email Address + © 2019 National Research Council Canada + Eddie Antonio Santos + + + + + basic.kmx + Keyboard Basic + 0 + .kmx + + + + + Basic + basic + 1.0 + + Central Khmer (Khmer, Cambodia) + + + + diff --git a/developer/src/kmc-package/test/test-messages.ts b/developer/src/kmc-package/test/test-messages.ts index e8fdfa842a5..2d8df44eb50 100644 --- a/developer/src/kmc-package/test/test-messages.ts +++ b/developer/src/kmc-package/test/test-messages.ts @@ -236,4 +236,8 @@ describe('PackageCompilerMessages', function () { PackageCompilerMessages.ERROR_InvalidAuthorEmail); }); + it('should generate ERROR_PackageFileHasEmptyVersion if FollowKeyboardVersion is not present and Version is empty', async function() { + await testForMessage(this, ['invalid', 'error_package_file_has_empty_version.kps'], + PackageCompilerMessages.ERROR_PackageFileHasEmptyVersion); + }); }); diff --git a/developer/src/kmc-package/test/test-package-compiler.ts b/developer/src/kmc-package/test/test-package-compiler.ts index 3f0e8d28fd2..7952e2145a2 100644 --- a/developer/src/kmc-package/test/test-package-compiler.ts +++ b/developer/src/kmc-package/test/test-package-compiler.ts @@ -209,6 +209,8 @@ describe('KmpCompiler', function () { kmpJson = kmpCompiler.transformKpsToKmpObject(kpsPath); }); + assert.isNotNull(kmpJson); + await assert.isNull(kmpCompiler.buildKmpFile(kpsPath, kmpJson)); if(debug) callbacks.printMessages(); From 78857d96c9cb5c521d0bb912db99e2d636343dca Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Fri, 9 Aug 2024 17:23:55 +0200 Subject: [PATCH 39/65] =?UTF-8?q?refactor(web):=20move=20`lm-message-types?= =?UTF-8?q?`=20=E2=86=92=20`predictive-text/types`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moves `common/web/lm-message-types/` → `web/src/engine/predictive-text/types/` Fixes: #12147 --- common/web/build.sh | 1 - common/web/lm-message-types/tsconfig.json | 12 ---------- common/web/lm-worker/tsconfig.json | 2 +- package-lock.json | 4 ++-- tsconfig.base.json | 2 +- tsconfig.json | 2 +- .../predictive-text/types}/message.d.ts | 0 .../predictive-text/types}/package.json | 0 .../predictive-text/types/tsconfig.json | 11 +++++++++ .../worker-main/src/tsconfig.json | 2 +- .../worker-main/tsconfig.all.json | 2 +- .../predictive-text/{index.js => index.mjs} | 23 ++++++++----------- .../tools/testing/recorder-core/tsconfig.json | 2 +- web/src/tools/testing/recorder/tsconfig.json | 4 ++-- 14 files changed, 31 insertions(+), 36 deletions(-) delete mode 100644 common/web/lm-message-types/tsconfig.json rename {common/web/lm-message-types => web/src/engine/predictive-text/types}/message.d.ts (100%) rename {common/web/lm-message-types => web/src/engine/predictive-text/types}/package.json (100%) create mode 100644 web/src/engine/predictive-text/types/tsconfig.json rename web/src/test/manual/predictive-text/{index.js => index.mjs} (96%) diff --git a/common/web/build.sh b/common/web/build.sh index 554b1e8ebb3..fbc015613fd 100755 --- a/common/web/build.sh +++ b/common/web/build.sh @@ -10,7 +10,6 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" # # TODO: future modules may include -# :lm-message-types \ # :sentry-manager \ # diff --git a/common/web/lm-message-types/tsconfig.json b/common/web/lm-message-types/tsconfig.json deleted file mode 100644 index 559b764980e..00000000000 --- a/common/web/lm-message-types/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "../../../tsconfig.base.json", - "compilerOptions": { - "declaration": true, - "outDir": "build/", - "sourceMap": true, - "lib": ["es6"], - "target": "es6" - }, - "include": ["./*.ts"], - "exclude": ["test.ts"] -} diff --git a/common/web/lm-worker/tsconfig.json b/common/web/lm-worker/tsconfig.json index f439e969409..95b403c768b 100644 --- a/common/web/lm-worker/tsconfig.json +++ b/common/web/lm-worker/tsconfig.json @@ -13,7 +13,7 @@ "references": [ // types { "path": "../../models/types" }, - { "path": "../lm-message-types" }, + { "path": "../../../web/src/engine/predictive-text/types" }, // modules { "path": "../keyman-version" }, { "path": "../utils" }, diff --git a/package-lock.json b/package-lock.json index ad53581202a..99a3d2f934b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -198,7 +198,7 @@ "typescript": "^5.4.5" } }, - "common/web/lm-message-types": { + "web/src/engine/predictive-text/types": { "name": "@keymanapp/lm-message-types", "license": "MIT", "devDependencies": { @@ -2896,7 +2896,7 @@ "link": true }, "node_modules/@keymanapp/lm-message-types": { - "resolved": "common/web/lm-message-types", + "resolved": "web/src/engine/predictive-text/types", "link": true }, "node_modules/@keymanapp/lm-worker": { diff --git a/tsconfig.base.json b/tsconfig.base.json index c4e0599eef6..7f69376372d 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -31,7 +31,7 @@ "@keymanapp/models-templates": ["./common/models/templates"], "@keymanapp/models-wordbreakers": ["./common/models/wordbreakers"], "@keymanapp/web-utils": ["./common/web/utils"], - "@keymanapp/lm-message-types": ["./common/web/lm-message-types"], + "@keymanapp/lm-message-types": ["./web/src/engine/predictive-text/types"], "@keymanapp/keyman-version": ["./common/web/keyman-version"], "@keymanapp/ldml-keyboard-constants": [ "./core/include/ldml" ], } diff --git a/tsconfig.json b/tsconfig.json index 42b3fd1a993..252fd738dc3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,6 @@ { "path": "./common/web/gesture-recognizer/tsconfig.json" }, { "path": "./common/web/gesture-recognizer/src/tools/unit-test-resources/tsconfig.json" }, { "path": "./common/web/keyman-version" }, - { "path": "./common/web/lm-message-types/" }, { "path": "./common/web/lm-worker/" }, { "path": "./common/web/recorder/tsconfig.json" }, { "path": "./common/web/sentry-manager/src/tsconfig.json" }, @@ -42,6 +41,7 @@ { "path": "./resources/build/version/" }, { "path": "./web/src/tsconfig.all.json" }, + { "path": "./web/src/engine/predictive-text/types/" }, { "path": "./web/src/engine/predictive-text/worker-main/tsconfig.all.json" }, // { "path": "./web/tools/recorder/tsconfig.json" }, // { "path": "./web/tools/sourcemap-root/tsconfig.json" }, diff --git a/common/web/lm-message-types/message.d.ts b/web/src/engine/predictive-text/types/message.d.ts similarity index 100% rename from common/web/lm-message-types/message.d.ts rename to web/src/engine/predictive-text/types/message.d.ts diff --git a/common/web/lm-message-types/package.json b/web/src/engine/predictive-text/types/package.json similarity index 100% rename from common/web/lm-message-types/package.json rename to web/src/engine/predictive-text/types/package.json diff --git a/web/src/engine/predictive-text/types/tsconfig.json b/web/src/engine/predictive-text/types/tsconfig.json new file mode 100644 index 00000000000..8b87ca26672 --- /dev/null +++ b/web/src/engine/predictive-text/types/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "baseUrl": "./", + "outDir": "build/", + "tsBuildInfoFile": "build/tsconfig.tsbuildinfo", + "rootDir": "./src" + }, + "include": ["./*.ts"], + "exclude": ["test.ts"] +} diff --git a/web/src/engine/predictive-text/worker-main/src/tsconfig.json b/web/src/engine/predictive-text/worker-main/src/tsconfig.json index 9c7a1f47ee8..edf6195b3ab 100644 --- a/web/src/engine/predictive-text/worker-main/src/tsconfig.json +++ b/web/src/engine/predictive-text/worker-main/src/tsconfig.json @@ -10,7 +10,7 @@ "references": [ { "path": "../../../../../../common/web/utils" }, { "path": "../../../../../../common/models/types"}, - { "path": "../../../../../../common/web/lm-message-types"} + { "path": "../../types"} ], "include" : [ "./*.ts" ], "exclude" : [ diff --git a/web/src/engine/predictive-text/worker-main/tsconfig.all.json b/web/src/engine/predictive-text/worker-main/tsconfig.all.json index f86c0815422..722ce0114bd 100644 --- a/web/src/engine/predictive-text/worker-main/tsconfig.all.json +++ b/web/src/engine/predictive-text/worker-main/tsconfig.all.json @@ -15,7 +15,7 @@ "references": [ { "path": "../../../../../common/web/utils" }, { "path": "../../../../../common/models/types"}, - { "path": "../../../../../common/web/lm-message-types"}, + { "path": "../types"}, { "path": "src/node" }, { "path": "src/web" } ], diff --git a/web/src/test/manual/predictive-text/index.js b/web/src/test/manual/predictive-text/index.mjs similarity index 96% rename from web/src/test/manual/predictive-text/index.js rename to web/src/test/manual/predictive-text/index.mjs index 605ed2939ce..33398a69577 100755 --- a/web/src/test/manual/predictive-text/index.js +++ b/web/src/test/manual/predictive-text/index.mjs @@ -5,16 +5,17 @@ * model. */ -const fs = require('fs'); -const path = require('path'); -const readline = require('readline'); +import fs from 'fs'; +import path from 'path'; +import readline from 'readline'; +import vm from 'vm'; -const {EventIterator} = require('event-iterator'); -const program = require('commander'); +import {EventIterator} from 'event-iterator'; +import program from 'commander'; // Load the most recent LMLayer code locally. -const LMLayer = require('../../../engine/predictive-text/worker-main'); - +import { LMLayer } from 'keyman/engine/predictive-text/worker-main'; +import { LMLayerWorker } from '@keymanapp/lm-worker'; ///////////////////////////////// Constants ///////////////////////////////// @@ -22,7 +23,7 @@ const WORKER_DEBUG = false; const EXIT_USAGE = 1; /** "Control sequence introducer" for ANSI escape codes: */ -const CSI = '\033['; +const CSI = '\u001b['; /** * ANSI escape codes to deal with the screen and the cursor. * See https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_sequences @@ -47,8 +48,7 @@ main(); function main() { // Command line options: program - .name(require('./package.json').name) - .version(require('./package.json').version) + .name('lmlayer-cli') .usage('[-i | -p [-p ...]] (-f | )') .description('CLI for trying lexical models.') .arguments('[model-id]') @@ -330,9 +330,6 @@ async function asyncRepl(modelFile) { function createAsyncWorker() { - // XXX: import the LMLayerWorker directly -- I know where it is built. - const LMLayerWorker = require('../../../engine/predictive-text/build/intermediate'); - const vm = require('vm'); let worker = { postMessage(message) { diff --git a/web/src/tools/testing/recorder-core/tsconfig.json b/web/src/tools/testing/recorder-core/tsconfig.json index 920536eeee2..01e14319451 100644 --- a/web/src/tools/testing/recorder-core/tsconfig.json +++ b/web/src/tools/testing/recorder-core/tsconfig.json @@ -16,7 +16,7 @@ "references": [ { "path": "../../../../../common/web/keyman-version" }, { "path": "../../../../../common/web/utils/" }, - { "path": "../../../../../common/web/lm-message-types" }, + { "path": "../../../engine/predictive-text/types" }, { "path": "../../../engine/js-processor" }, { "path": "../../../engine/keyboard" }, ], diff --git a/web/src/tools/testing/recorder/tsconfig.json b/web/src/tools/testing/recorder/tsconfig.json index f5974b5738b..e25a4f60341 100644 --- a/web/src/tools/testing/recorder/tsconfig.json +++ b/web/src/tools/testing/recorder/tsconfig.json @@ -12,8 +12,8 @@ "references": [ { "path": "../../../../../common/web/keyman-version" }, { "path": "../../../../../common/web/utils" }, - { "path": "../../../../../common/web/lm-message-types" }, - { "path": "../../../../../web/src/app/browser" }, + { "path": "../../../engine/predictive-text/types" }, + { "path": "../../../app/browser" }, { "path": "../recorder-core" }, { "path": "../../../engine/keyboard" }, ] From ea62ac23e792b7c16d0377a39de13468724cb7d2 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Fri, 9 Aug 2024 18:18:53 +0200 Subject: [PATCH 40/65] =?UTF-8?q?refactor(web):=20move=20`lm-worker`=20?= =?UTF-8?q?=E2=86=92=20`worker-thread`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move `common/web/lm-worker/` → `web/src/engine/predictive-text/worker-thread/`. Fixes: #12148 --- common/web/lm-worker/tsconfig.json | 26 --------------- package-lock.json | 4 +-- tsconfig.json | 2 +- web/README.md | 2 +- web/src/app/browser/build.sh | 2 +- .../predictive-text/worker-main/build.sh | 2 +- .../worker-main/unit_tests/test.sh | 4 +-- .../predictive-text/worker-thread}/.c8rc.json | 0 .../worker-thread}/build-polyfiller.js | 2 +- .../worker-thread}/build-wrapper.js | 0 .../predictive-text/worker-thread}/build.sh | 10 +++--- .../worker-thread}/package.json | 0 .../main/correction/classical-calculation.ts | 0 .../src/main/correction/context-tracker.ts | 0 .../src/main/correction/distance-modeler.ts | 0 .../src/main/correction/execution-timer.ts | 0 .../src/main/correction/index.ts | 0 .../main/correction/transform-tokenization.ts | 0 .../worker-thread}/src/main/index.ts | 0 .../src/main/model-compositor.ts | 0 .../worker-thread}/src/main/model-helpers.ts | 0 .../src/main/models/dummy-model.ts | 0 .../worker-thread}/src/main/models/index.ts | 0 .../src/main/predict-helpers.ts | 0 .../worker-thread}/src/main/transformUtils.ts | 0 .../src/main/worker-interfaces.ts | 0 .../worker-thread}/src/main/worker-main.ts | 0 .../src/polyfills/array.fill.js | 0 .../src/polyfills/array.findIndex.js | 0 .../src/polyfills/array.from.js | 0 .../src/polyfills/array.includes.js | 0 .../src/polyfills/object.values.js | 0 .../src/polyfills/symbol-es6.min.js | 0 .../src/test/mocha/cases/auto-correct.js | 0 .../src/test/mocha/cases/casing-detection.js | 0 .../cases/early-correction-search-stopping.js | 0 .../edit-distance/classical-calculation.js | 0 .../cases/edit-distance/context-tracker.js | 0 .../cases/edit-distance/distance-modeler.js | 0 .../cases/edit-distance/execution-timer.js | 0 .../mocha/cases/predict-from-corrections.js | 0 .../mocha/cases/suggestion-deduplication.js | 0 .../mocha/cases/suggestion-finalization.js | 0 .../test/mocha/cases/suggestion-similarity.js | 0 .../mocha/cases/transform-tokenization.js | 0 .../src/test/mocha/cases/transform-utils.js | 0 .../mocha/cases/worker-custom-punctuation.js | 0 .../test/mocha/cases/worker-initialization.js | 0 .../mocha/cases/worker-model-compositor.js | 0 .../test/mocha/cases/worker-predict-dummy.js | 0 .../src/test/mocha/cases/worker-predict.js | 0 .../src/test/test-runner/cases/worker.spec.ts | 0 .../test-runner/web-test-runner.CI.config.mjs | 0 .../test-runner/web-test-runner.config.mjs | 0 .../worker-thread/tsconfig.json | 32 +++++++++++++++++++ 55 files changed, 46 insertions(+), 40 deletions(-) delete mode 100644 common/web/lm-worker/tsconfig.json rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/.c8rc.json (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/build-polyfiller.js (98%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/build-wrapper.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/build.sh (87%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/package.json (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/main/correction/classical-calculation.ts (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/main/correction/context-tracker.ts (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/main/correction/distance-modeler.ts (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/main/correction/execution-timer.ts (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/main/correction/index.ts (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/main/correction/transform-tokenization.ts (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/main/index.ts (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/main/model-compositor.ts (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/main/model-helpers.ts (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/main/models/dummy-model.ts (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/main/models/index.ts (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/main/predict-helpers.ts (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/main/transformUtils.ts (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/main/worker-interfaces.ts (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/main/worker-main.ts (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/polyfills/array.fill.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/polyfills/array.findIndex.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/polyfills/array.from.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/polyfills/array.includes.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/polyfills/object.values.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/polyfills/symbol-es6.min.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/mocha/cases/auto-correct.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/mocha/cases/casing-detection.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/mocha/cases/early-correction-search-stopping.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/mocha/cases/edit-distance/classical-calculation.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/mocha/cases/edit-distance/context-tracker.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/mocha/cases/edit-distance/distance-modeler.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/mocha/cases/edit-distance/execution-timer.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/mocha/cases/predict-from-corrections.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/mocha/cases/suggestion-deduplication.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/mocha/cases/suggestion-finalization.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/mocha/cases/suggestion-similarity.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/mocha/cases/transform-tokenization.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/mocha/cases/transform-utils.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/mocha/cases/worker-custom-punctuation.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/mocha/cases/worker-initialization.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/mocha/cases/worker-model-compositor.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/mocha/cases/worker-predict-dummy.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/mocha/cases/worker-predict.js (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/test-runner/cases/worker.spec.ts (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/test-runner/web-test-runner.CI.config.mjs (100%) rename {common/web/lm-worker => web/src/engine/predictive-text/worker-thread}/src/test/test-runner/web-test-runner.config.mjs (100%) create mode 100644 web/src/engine/predictive-text/worker-thread/tsconfig.json diff --git a/common/web/lm-worker/tsconfig.json b/common/web/lm-worker/tsconfig.json deleted file mode 100644 index 95b403c768b..00000000000 --- a/common/web/lm-worker/tsconfig.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "extends": "../../models/tsconfig.kmw-worker-base.json", - - "compilerOptions": { - "baseUrl": "./", - "outDir": "build/obj", - "tsBuildInfoFile": "build/obj/tsconfig.tsbuildinfo", - "rootDir": "./src/main", - - // As this one is the one that directly interfaces with the worker (from the inside) - "lib": ["webworker", "es6"], - }, - "references": [ - // types - { "path": "../../models/types" }, - { "path": "../../../web/src/engine/predictive-text/types" }, - // modules - { "path": "../keyman-version" }, - { "path": "../utils" }, - { "path": "../../models/templates" }, - { "path": "../../models/wordbreakers" }, - ], - "include": [ - "src/main/**/*.ts" - ] -} diff --git a/package-lock.json b/package-lock.json index 99a3d2f934b..8df9c941c25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -205,7 +205,7 @@ "typescript": "^5.4.5" } }, - "common/web/lm-worker": { + "web/src/engine/predictive-text/worker-thread": { "name": "@keymanapp/lm-worker", "license": "MIT", "dependencies": { @@ -2900,7 +2900,7 @@ "link": true }, "node_modules/@keymanapp/lm-worker": { - "resolved": "common/web/lm-worker", + "resolved": "web/src/engine/predictive-text/worker-thread", "link": true }, "node_modules/@keymanapp/models-templates": { diff --git a/tsconfig.json b/tsconfig.json index 252fd738dc3..1a02e20ff15 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,6 @@ { "path": "./common/web/gesture-recognizer/tsconfig.json" }, { "path": "./common/web/gesture-recognizer/src/tools/unit-test-resources/tsconfig.json" }, { "path": "./common/web/keyman-version" }, - { "path": "./common/web/lm-worker/" }, { "path": "./common/web/recorder/tsconfig.json" }, { "path": "./common/web/sentry-manager/src/tsconfig.json" }, { "path": "./common/web/types/" }, @@ -43,6 +42,7 @@ { "path": "./web/src/tsconfig.all.json" }, { "path": "./web/src/engine/predictive-text/types/" }, { "path": "./web/src/engine/predictive-text/worker-main/tsconfig.all.json" }, + { "path": "./web/src/engine/predictive-text/worker-thread" }, // { "path": "./web/tools/recorder/tsconfig.json" }, // { "path": "./web/tools/sourcemap-root/tsconfig.json" }, ] diff --git a/web/README.md b/web/README.md index 1e41497657c..bc2938bae0a 100644 --- a/web/README.md +++ b/web/README.md @@ -89,7 +89,7 @@ graph TD; Wordbreakers["@keymanapp/models-wordbreakers
(/common/models/wordbreakers)"]; Models["@keymanapp/models-templates
(/common/models/templates)"]; Models-->WebUtils; - LMWorker["@keymanapp/lm-worker
(/common/web/lm-worker)"]; + LMWorker["@keymanapp/lm-worker
(/web/src/engine/predictive-text/worker-thread)"]; LMWorker-->Models; LMWorker-->Wordbreakers; LMLayer["@keymanapp/lexical-model-layer
(/web/src/engine/predictive-text/worker-main)"]; diff --git a/web/src/app/browser/build.sh b/web/src/app/browser/build.sh index 049bc056b5e..1d757e264a2 100755 --- a/web/src/app/browser/build.sh +++ b/web/src/app/browser/build.sh @@ -79,7 +79,7 @@ compile_and_copy() { local PROFILE_DEST="$KEYMAN_ROOT/web/build/profiling/" mkdir -p "$PROFILE_DEST" cp "${BUILD_ROOT}/filesize-profile.log" "$PROFILE_DEST/web-engine-filesize.log" - cp "$KEYMAN_ROOT/common/web/lm-worker/build/filesize-profile.log" "$PROFILE_DEST/lm-worker-filesize.log" + cp "$KEYMAN_ROOT/web/src/engine/predictive-text/worker-thread/build/filesize-profile.log" "$PROFILE_DEST/lm-worker-filesize.log" } builder_run_action configure verify_npm_setup diff --git a/web/src/engine/predictive-text/worker-main/build.sh b/web/src/engine/predictive-text/worker-main/build.sh index 4120fce53b1..33e5eaebeb6 100755 --- a/web/src/engine/predictive-text/worker-main/build.sh +++ b/web/src/engine/predictive-text/worker-main/build.sh @@ -22,7 +22,7 @@ BUNDLE_CMD="node $KEYMAN_ROOT/common/web/es-bundling/build/common-bundle.mjs" builder_describe "Builds the lm-layer module" \ "@/common/web/keyman-version" \ "@/common/web/es-bundling" \ - "@/common/web/lm-worker" \ + "@/web/src/engine/predictive-text/worker-thread" \ "clean" \ "configure" \ "build" \ diff --git a/web/src/engine/predictive-text/worker-main/unit_tests/test.sh b/web/src/engine/predictive-text/worker-main/unit_tests/test.sh index 007bf363576..dda8d578640 100755 --- a/web/src/engine/predictive-text/worker-main/unit_tests/test.sh +++ b/web/src/engine/predictive-text/worker-main/unit_tests/test.sh @@ -57,9 +57,9 @@ if builder_start_action test:libraries; then "$KEYMAN_ROOT/common/models/templates/build.sh" test $TEST_OPTS popd - pushd "$KEYMAN_ROOT/common/web/lm-worker" + pushd "$KEYMAN_ROOT/web/src/engine/predictive-text/worker-thread" echo - echo "### Running ${BUILDER_TERM_START}common/web/lm-worker${BUILDER_TERM_END} tests" + echo "### Running ${BUILDER_TERM_START}web/src/engine/predictive-text/worker-thread${BUILDER_TERM_END} tests" ./build.sh test $TEST_OPTS popd diff --git a/common/web/lm-worker/.c8rc.json b/web/src/engine/predictive-text/worker-thread/.c8rc.json similarity index 100% rename from common/web/lm-worker/.c8rc.json rename to web/src/engine/predictive-text/worker-thread/.c8rc.json diff --git a/common/web/lm-worker/build-polyfiller.js b/web/src/engine/predictive-text/worker-thread/build-polyfiller.js similarity index 98% rename from common/web/lm-worker/build-polyfiller.js rename to web/src/engine/predictive-text/worker-thread/build-polyfiller.js index 41cec75ce7d..eab268e9867 100644 --- a/common/web/lm-worker/build-polyfiller.js +++ b/web/src/engine/predictive-text/worker-thread/build-polyfiller.js @@ -166,7 +166,7 @@ let fullWorkerConcatenation = concatScriptsAndSourcemaps(sourceFileSet, destFile // New stage: cleaning the sourcemaps // Sources are being passed into the sourcemap concatenator via our working directory. -let sourceRoot = '@keymanapp/keyman/common/web/lm-worker/'; +let sourceRoot = '@keymanapp/keyman/web/src/engine/predictive-text/worker-thread/'; fullWorkerConcatenation.sourcemapJSON.sourceRoot = sourceRoot; // End "cleaning the sourcemaps" diff --git a/common/web/lm-worker/build-wrapper.js b/web/src/engine/predictive-text/worker-thread/build-wrapper.js similarity index 100% rename from common/web/lm-worker/build-wrapper.js rename to web/src/engine/predictive-text/worker-thread/build-wrapper.js diff --git a/common/web/lm-worker/build.sh b/web/src/engine/predictive-text/worker-thread/build.sh similarity index 87% rename from common/web/lm-worker/build.sh rename to web/src/engine/predictive-text/worker-thread/build.sh index 0343d151c8f..8c6a4ca0012 100755 --- a/common/web/lm-worker/build.sh +++ b/web/src/engine/predictive-text/worker-thread/build.sh @@ -6,7 +6,7 @@ ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" -. "${THIS_SCRIPT%/*}/../../../resources/build/builder.inc.sh" +. "${THIS_SCRIPT%/*}/../../../../../resources/build/builder.inc.sh" ## END STANDARD BUILD SCRIPT INCLUDE . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" @@ -17,7 +17,7 @@ WORKER_OUTPUT_FILENAME=build/lib/worker-main.js INTERMEDIATE=./build/intermediate LIB=./build/lib -bundle_cmd="node ../es-bundling/build/common-bundle.mjs" +bundle_cmd="node ${KEYMAN_ROOT}/common/web/es-bundling/build/common-bundle.mjs" SRCMAP_CLEANER="node $KEYMAN_ROOT/web/build/tools/building/sourcemap-root/index.js" @@ -34,7 +34,7 @@ builder_describe \ builder_describe_outputs \ configure /node_modules \ - build /common/web/lm-worker/$LIB/worker-main.wrapped.min.js + build "/web/src/engine/predictive-text/worker-thread/${LIB}/worker-main.wrapped.min.js" builder_parse "$@" @@ -65,7 +65,7 @@ function do_build() { $bundle_cmd src/main/worker-main.ts \ --out $INTERMEDIATE/worker-main.js \ --target "es6" \ - --sourceRoot '@keymanapp/keyman/common/web/lm-worker/src/main' + --sourceRoot '@keymanapp/keyman/web/src/engine/predictive-text/worker-thread/src/main' $SRCMAP_CLEANER \ $INTERMEDIATE/worker-main.js.map \ @@ -77,7 +77,7 @@ function do_build() { --minify \ --profile build/filesize-profile.log \ --target "es6" \ - --sourceRoot '@keymanapp/keyman/common/web/lm-worker/src/main' + --sourceRoot '@keymanapp/keyman/web/src/engine/predictive-text/worker-thread/src/main' $SRCMAP_CLEANER \ $INTERMEDIATE/worker-main.min.js.map \ diff --git a/common/web/lm-worker/package.json b/web/src/engine/predictive-text/worker-thread/package.json similarity index 100% rename from common/web/lm-worker/package.json rename to web/src/engine/predictive-text/worker-thread/package.json diff --git a/common/web/lm-worker/src/main/correction/classical-calculation.ts b/web/src/engine/predictive-text/worker-thread/src/main/correction/classical-calculation.ts similarity index 100% rename from common/web/lm-worker/src/main/correction/classical-calculation.ts rename to web/src/engine/predictive-text/worker-thread/src/main/correction/classical-calculation.ts diff --git a/common/web/lm-worker/src/main/correction/context-tracker.ts b/web/src/engine/predictive-text/worker-thread/src/main/correction/context-tracker.ts similarity index 100% rename from common/web/lm-worker/src/main/correction/context-tracker.ts rename to web/src/engine/predictive-text/worker-thread/src/main/correction/context-tracker.ts diff --git a/common/web/lm-worker/src/main/correction/distance-modeler.ts b/web/src/engine/predictive-text/worker-thread/src/main/correction/distance-modeler.ts similarity index 100% rename from common/web/lm-worker/src/main/correction/distance-modeler.ts rename to web/src/engine/predictive-text/worker-thread/src/main/correction/distance-modeler.ts diff --git a/common/web/lm-worker/src/main/correction/execution-timer.ts b/web/src/engine/predictive-text/worker-thread/src/main/correction/execution-timer.ts similarity index 100% rename from common/web/lm-worker/src/main/correction/execution-timer.ts rename to web/src/engine/predictive-text/worker-thread/src/main/correction/execution-timer.ts diff --git a/common/web/lm-worker/src/main/correction/index.ts b/web/src/engine/predictive-text/worker-thread/src/main/correction/index.ts similarity index 100% rename from common/web/lm-worker/src/main/correction/index.ts rename to web/src/engine/predictive-text/worker-thread/src/main/correction/index.ts diff --git a/common/web/lm-worker/src/main/correction/transform-tokenization.ts b/web/src/engine/predictive-text/worker-thread/src/main/correction/transform-tokenization.ts similarity index 100% rename from common/web/lm-worker/src/main/correction/transform-tokenization.ts rename to web/src/engine/predictive-text/worker-thread/src/main/correction/transform-tokenization.ts diff --git a/common/web/lm-worker/src/main/index.ts b/web/src/engine/predictive-text/worker-thread/src/main/index.ts similarity index 100% rename from common/web/lm-worker/src/main/index.ts rename to web/src/engine/predictive-text/worker-thread/src/main/index.ts diff --git a/common/web/lm-worker/src/main/model-compositor.ts b/web/src/engine/predictive-text/worker-thread/src/main/model-compositor.ts similarity index 100% rename from common/web/lm-worker/src/main/model-compositor.ts rename to web/src/engine/predictive-text/worker-thread/src/main/model-compositor.ts diff --git a/common/web/lm-worker/src/main/model-helpers.ts b/web/src/engine/predictive-text/worker-thread/src/main/model-helpers.ts similarity index 100% rename from common/web/lm-worker/src/main/model-helpers.ts rename to web/src/engine/predictive-text/worker-thread/src/main/model-helpers.ts diff --git a/common/web/lm-worker/src/main/models/dummy-model.ts b/web/src/engine/predictive-text/worker-thread/src/main/models/dummy-model.ts similarity index 100% rename from common/web/lm-worker/src/main/models/dummy-model.ts rename to web/src/engine/predictive-text/worker-thread/src/main/models/dummy-model.ts diff --git a/common/web/lm-worker/src/main/models/index.ts b/web/src/engine/predictive-text/worker-thread/src/main/models/index.ts similarity index 100% rename from common/web/lm-worker/src/main/models/index.ts rename to web/src/engine/predictive-text/worker-thread/src/main/models/index.ts diff --git a/common/web/lm-worker/src/main/predict-helpers.ts b/web/src/engine/predictive-text/worker-thread/src/main/predict-helpers.ts similarity index 100% rename from common/web/lm-worker/src/main/predict-helpers.ts rename to web/src/engine/predictive-text/worker-thread/src/main/predict-helpers.ts diff --git a/common/web/lm-worker/src/main/transformUtils.ts b/web/src/engine/predictive-text/worker-thread/src/main/transformUtils.ts similarity index 100% rename from common/web/lm-worker/src/main/transformUtils.ts rename to web/src/engine/predictive-text/worker-thread/src/main/transformUtils.ts diff --git a/common/web/lm-worker/src/main/worker-interfaces.ts b/web/src/engine/predictive-text/worker-thread/src/main/worker-interfaces.ts similarity index 100% rename from common/web/lm-worker/src/main/worker-interfaces.ts rename to web/src/engine/predictive-text/worker-thread/src/main/worker-interfaces.ts diff --git a/common/web/lm-worker/src/main/worker-main.ts b/web/src/engine/predictive-text/worker-thread/src/main/worker-main.ts similarity index 100% rename from common/web/lm-worker/src/main/worker-main.ts rename to web/src/engine/predictive-text/worker-thread/src/main/worker-main.ts diff --git a/common/web/lm-worker/src/polyfills/array.fill.js b/web/src/engine/predictive-text/worker-thread/src/polyfills/array.fill.js similarity index 100% rename from common/web/lm-worker/src/polyfills/array.fill.js rename to web/src/engine/predictive-text/worker-thread/src/polyfills/array.fill.js diff --git a/common/web/lm-worker/src/polyfills/array.findIndex.js b/web/src/engine/predictive-text/worker-thread/src/polyfills/array.findIndex.js similarity index 100% rename from common/web/lm-worker/src/polyfills/array.findIndex.js rename to web/src/engine/predictive-text/worker-thread/src/polyfills/array.findIndex.js diff --git a/common/web/lm-worker/src/polyfills/array.from.js b/web/src/engine/predictive-text/worker-thread/src/polyfills/array.from.js similarity index 100% rename from common/web/lm-worker/src/polyfills/array.from.js rename to web/src/engine/predictive-text/worker-thread/src/polyfills/array.from.js diff --git a/common/web/lm-worker/src/polyfills/array.includes.js b/web/src/engine/predictive-text/worker-thread/src/polyfills/array.includes.js similarity index 100% rename from common/web/lm-worker/src/polyfills/array.includes.js rename to web/src/engine/predictive-text/worker-thread/src/polyfills/array.includes.js diff --git a/common/web/lm-worker/src/polyfills/object.values.js b/web/src/engine/predictive-text/worker-thread/src/polyfills/object.values.js similarity index 100% rename from common/web/lm-worker/src/polyfills/object.values.js rename to web/src/engine/predictive-text/worker-thread/src/polyfills/object.values.js diff --git a/common/web/lm-worker/src/polyfills/symbol-es6.min.js b/web/src/engine/predictive-text/worker-thread/src/polyfills/symbol-es6.min.js similarity index 100% rename from common/web/lm-worker/src/polyfills/symbol-es6.min.js rename to web/src/engine/predictive-text/worker-thread/src/polyfills/symbol-es6.min.js diff --git a/common/web/lm-worker/src/test/mocha/cases/auto-correct.js b/web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/auto-correct.js similarity index 100% rename from common/web/lm-worker/src/test/mocha/cases/auto-correct.js rename to web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/auto-correct.js diff --git a/common/web/lm-worker/src/test/mocha/cases/casing-detection.js b/web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/casing-detection.js similarity index 100% rename from common/web/lm-worker/src/test/mocha/cases/casing-detection.js rename to web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/casing-detection.js diff --git a/common/web/lm-worker/src/test/mocha/cases/early-correction-search-stopping.js b/web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/early-correction-search-stopping.js similarity index 100% rename from common/web/lm-worker/src/test/mocha/cases/early-correction-search-stopping.js rename to web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/early-correction-search-stopping.js diff --git a/common/web/lm-worker/src/test/mocha/cases/edit-distance/classical-calculation.js b/web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/edit-distance/classical-calculation.js similarity index 100% rename from common/web/lm-worker/src/test/mocha/cases/edit-distance/classical-calculation.js rename to web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/edit-distance/classical-calculation.js diff --git a/common/web/lm-worker/src/test/mocha/cases/edit-distance/context-tracker.js b/web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/edit-distance/context-tracker.js similarity index 100% rename from common/web/lm-worker/src/test/mocha/cases/edit-distance/context-tracker.js rename to web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/edit-distance/context-tracker.js diff --git a/common/web/lm-worker/src/test/mocha/cases/edit-distance/distance-modeler.js b/web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/edit-distance/distance-modeler.js similarity index 100% rename from common/web/lm-worker/src/test/mocha/cases/edit-distance/distance-modeler.js rename to web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/edit-distance/distance-modeler.js diff --git a/common/web/lm-worker/src/test/mocha/cases/edit-distance/execution-timer.js b/web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/edit-distance/execution-timer.js similarity index 100% rename from common/web/lm-worker/src/test/mocha/cases/edit-distance/execution-timer.js rename to web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/edit-distance/execution-timer.js diff --git a/common/web/lm-worker/src/test/mocha/cases/predict-from-corrections.js b/web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/predict-from-corrections.js similarity index 100% rename from common/web/lm-worker/src/test/mocha/cases/predict-from-corrections.js rename to web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/predict-from-corrections.js diff --git a/common/web/lm-worker/src/test/mocha/cases/suggestion-deduplication.js b/web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/suggestion-deduplication.js similarity index 100% rename from common/web/lm-worker/src/test/mocha/cases/suggestion-deduplication.js rename to web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/suggestion-deduplication.js diff --git a/common/web/lm-worker/src/test/mocha/cases/suggestion-finalization.js b/web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/suggestion-finalization.js similarity index 100% rename from common/web/lm-worker/src/test/mocha/cases/suggestion-finalization.js rename to web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/suggestion-finalization.js diff --git a/common/web/lm-worker/src/test/mocha/cases/suggestion-similarity.js b/web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/suggestion-similarity.js similarity index 100% rename from common/web/lm-worker/src/test/mocha/cases/suggestion-similarity.js rename to web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/suggestion-similarity.js diff --git a/common/web/lm-worker/src/test/mocha/cases/transform-tokenization.js b/web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/transform-tokenization.js similarity index 100% rename from common/web/lm-worker/src/test/mocha/cases/transform-tokenization.js rename to web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/transform-tokenization.js diff --git a/common/web/lm-worker/src/test/mocha/cases/transform-utils.js b/web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/transform-utils.js similarity index 100% rename from common/web/lm-worker/src/test/mocha/cases/transform-utils.js rename to web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/transform-utils.js diff --git a/common/web/lm-worker/src/test/mocha/cases/worker-custom-punctuation.js b/web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/worker-custom-punctuation.js similarity index 100% rename from common/web/lm-worker/src/test/mocha/cases/worker-custom-punctuation.js rename to web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/worker-custom-punctuation.js diff --git a/common/web/lm-worker/src/test/mocha/cases/worker-initialization.js b/web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/worker-initialization.js similarity index 100% rename from common/web/lm-worker/src/test/mocha/cases/worker-initialization.js rename to web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/worker-initialization.js diff --git a/common/web/lm-worker/src/test/mocha/cases/worker-model-compositor.js b/web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/worker-model-compositor.js similarity index 100% rename from common/web/lm-worker/src/test/mocha/cases/worker-model-compositor.js rename to web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/worker-model-compositor.js diff --git a/common/web/lm-worker/src/test/mocha/cases/worker-predict-dummy.js b/web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/worker-predict-dummy.js similarity index 100% rename from common/web/lm-worker/src/test/mocha/cases/worker-predict-dummy.js rename to web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/worker-predict-dummy.js diff --git a/common/web/lm-worker/src/test/mocha/cases/worker-predict.js b/web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/worker-predict.js similarity index 100% rename from common/web/lm-worker/src/test/mocha/cases/worker-predict.js rename to web/src/engine/predictive-text/worker-thread/src/test/mocha/cases/worker-predict.js diff --git a/common/web/lm-worker/src/test/test-runner/cases/worker.spec.ts b/web/src/engine/predictive-text/worker-thread/src/test/test-runner/cases/worker.spec.ts similarity index 100% rename from common/web/lm-worker/src/test/test-runner/cases/worker.spec.ts rename to web/src/engine/predictive-text/worker-thread/src/test/test-runner/cases/worker.spec.ts diff --git a/common/web/lm-worker/src/test/test-runner/web-test-runner.CI.config.mjs b/web/src/engine/predictive-text/worker-thread/src/test/test-runner/web-test-runner.CI.config.mjs similarity index 100% rename from common/web/lm-worker/src/test/test-runner/web-test-runner.CI.config.mjs rename to web/src/engine/predictive-text/worker-thread/src/test/test-runner/web-test-runner.CI.config.mjs diff --git a/common/web/lm-worker/src/test/test-runner/web-test-runner.config.mjs b/web/src/engine/predictive-text/worker-thread/src/test/test-runner/web-test-runner.config.mjs similarity index 100% rename from common/web/lm-worker/src/test/test-runner/web-test-runner.config.mjs rename to web/src/engine/predictive-text/worker-thread/src/test/test-runner/web-test-runner.config.mjs diff --git a/web/src/engine/predictive-text/worker-thread/tsconfig.json b/web/src/engine/predictive-text/worker-thread/tsconfig.json new file mode 100644 index 00000000000..bfc8498730b --- /dev/null +++ b/web/src/engine/predictive-text/worker-thread/tsconfig.json @@ -0,0 +1,32 @@ +{ + "extends": "../../../../tsconfig.base.json", + + "compilerOptions": { + "baseUrl": "./", + "outDir": "build/obj", + "tsBuildInfoFile": "build/obj/tsconfig.tsbuildinfo", + "rootDir": "./src/main", + // To help better support legacy Android devices + "downlevelIteration": true, + // Facilitates & simplifies stitching together the worker sourcemaps during the polyfill-concatenation step. + "inlineSourceMap": true, + // May not be set at the same time as the prior setting. + "sourceMap": false, + + // As this one is the one that directly interfaces with the worker (from the inside) + "lib": ["webworker", "es6"], + }, + "references": [ + // types + { "path": "../../../../../common/models/types" }, + { "path": "../types" }, + // modules + { "path": "../../../../../common/web/keyman-version" }, + { "path": "../../../../../common/web/utils" }, + { "path": "../../../../../common/models/templates" }, + { "path": "../../../../../common/models/wordbreakers" }, + ], + "include": [ + "src/main/**/*.ts" + ] +} From 1cbd061c05b7a64cf3c688a8a0399bcb06ee90b5 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 16 Aug 2024 08:54:27 +0200 Subject: [PATCH 41/65] chore(developer): remove impossible test for missing version --- .../test/test-keyboard-info-compiler.ts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/developer/src/kmc-keyboard-info/test/test-keyboard-info-compiler.ts b/developer/src/kmc-keyboard-info/test/test-keyboard-info-compiler.ts index 9b61b8e93d9..99c244be2dd 100644 --- a/developer/src/kmc-keyboard-info/test/test-keyboard-info-compiler.ts +++ b/developer/src/kmc-keyboard-info/test/test-keyboard-info-compiler.ts @@ -835,17 +835,4 @@ describe('keyboard-info-compiler', function () { const result = await compiler['fontSourceToKeyboardInfoFont'](KHMER_ANGKOR_KPS, kmpJsonData, fonts); assert.deepEqual(result, KHMER_ANGKOR_DISPLAY_FONT_INFO); }); - - it('handles missing info.version in a package file', async function() { - const sources = { - ...KHMER_ANGKOR_SOURCES, - kpsFilename: makePathToFixture('missing-info-version-in-kps-11856', 'khmer_angkor.kps') - }; - const compiler = new KeyboardInfoCompiler(); - assert.isTrue(await compiler.init(callbacks, {sources})); - const kpjFilename = KHMER_ANGKOR_KPJ; - const result = await compiler.run(kpjFilename); - const actual = JSON.parse(new TextDecoder().decode(result.artifacts.keyboard_info.data)); - assert.equal(actual.version, '1.0'); - }); }); From 1550db1eb8f5286dcf51df064393694fdc227a67 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Fri, 16 Aug 2024 14:05:09 -0400 Subject: [PATCH 42/65] auto: increment master version to 18.0.92 --- HISTORY.md | 8 ++++++++ VERSION.md | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index f9117038345..b58c086466b 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,13 @@ # Keyman Version History +## 18.0.91 alpha 2024-08-16 + +* refactor(web): move `predictive-text` → `worker-main` (#12146) +* fix(web): restore flick functionality (#12187) +* refactor(web): move `lm-message-types` → `predictive-text/types` (#12149) +* fix(developer): enforce presence of kps Info.Description field in info compilers (#12204) +* fix(developer): enforce presence of Version field when FollowKeyboardVersion is not set, in package compiler (#12205) + ## 18.0.90 alpha 2024-08-15 * refactor(web): move parts of `keyboard-processor` → `js-processor` (#12111) diff --git a/VERSION.md b/VERSION.md index 8f233fffc08..ce8cfb73ead 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -18.0.91 \ No newline at end of file +18.0.92 \ No newline at end of file From 8cc506ea186cd8bc9364b1b0996122240ea8634e Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Mon, 19 Aug 2024 09:44:19 +0700 Subject: [PATCH 43/65] fix(android): Address review comments * Have KMManager control the longpress delay * Rename applyLongpressDelay to sendOptionsToKeyboard --- .../com/keyman/android/SystemKeyboard.java | 5 +-- .../kmapro/AdjustLongpressDelayActivity.java | 39 ++++++++++--------- .../com/tavultesoft/kmapro/MainActivity.java | 9 +---- .../KMEA/app/src/main/assets/android-host.js | 2 + .../java/com/keyman/engine/KMManager.java | 35 ++++++++--------- 5 files changed, 42 insertions(+), 48 deletions(-) diff --git a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java index dea132c0fd3..df71220cfc2 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java +++ b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java @@ -245,9 +245,8 @@ public void onKeyboardLoaded(KeyboardType keyboardType) { if (exText != null) exText = null; } - // Initialize the longpress delay - int longpressDelay = KMManager.getLongpressDelay(); - KMManager.applyLongpressDelay(longpressDelay); + // Initialize keyboard options + KMManager.sendOptionsToKeyboard(); } @Override diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java index 55a663965c5..e3f2dc3d926 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java @@ -28,21 +28,21 @@ public class AdjustLongpressDelayActivity extends BaseActivity { // Keeps track of the adjusted longpress delay time for saving. // Internally use milliseconds, but GUI displays seconds - private static int currentDelayTime = KMManager.KMDefault_LongpressDelay; // ms + private static int currentDelayTimeMS = KMManager.KMDefault_LongpressDelay; // ms private static int minLongpressTime = 300; // ms private static int maxLongpressTime = 1500; // ms private static int delayTimeIncrement = 200; // ms /** - * Convert currentDelayTime to progress + * Convert currentDelayTimeMS to progress * @return int */ private int delayTimeToProgress() { - return (currentDelayTime / delayTimeIncrement) - 1; + return (currentDelayTimeMS / delayTimeIncrement) - 1; } /** - * Convert progress to currentDelayTime + * Convert progress to currentDelayTimeMS * @param progress * @return int (milliseconds) */ @@ -76,12 +76,12 @@ protected void onCreate(Bundle savedInstanceState) { adjustLongpressDelayActivityTitle.setTextColor(ContextCompat.getColor(this, R.color.ms_white)); adjustLongpressDelayActivityTitle.setText(titleStr); - currentDelayTime = KMManager.getLongpressDelay(); + currentDelayTimeMS = KMManager.getLongpressDelay(); TextView adjustLongpressDelayText = (TextView) findViewById(R.id.delayTimeText); - String longpressDelayText = String.format(getString(R.string.longpress_delay_time), (float)(currentDelayTime/1000.0)); + String longpressDelayTextSeconds = String.format(getString(R.string.longpress_delay_time), (float)(currentDelayTimeMS/1000.0)); adjustLongpressDelayText.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); - adjustLongpressDelayText.setText(longpressDelayText); + adjustLongpressDelayText.setText(longpressDelayTextSeconds); final SeekBar seekBar = (SeekBar) findViewById(R.id.seekBar); seekBar.setProgress(delayTimeToProgress()); @@ -99,19 +99,19 @@ public void onStartTrackingTouch(SeekBar seekBar) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - currentDelayTime = progressToDelayTime(progress); - String longpressDelayText = String.format(getString(R.string.longpress_delay_time), (float)(currentDelayTime/1000.0)); - adjustLongpressDelayText.setText(longpressDelayText); - - KMManager.setLongpressDelay(currentDelayTime); + // Update the text field. + // The keyboard options will be saved and sent to KeymanWeb when exiting the menu + currentDelayTimeMS = progressToDelayTime(progress); + String longpressDelayTextSeconds = String.format(getString(R.string.longpress_delay_time), (float)(currentDelayTimeMS/1000.0)); + adjustLongpressDelayText.setText(longpressDelayTextSeconds); } }); findViewById(R.id.delayTimeDownButton).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if (currentDelayTime > minLongpressTime) { - currentDelayTime -= delayTimeIncrement; + if (currentDelayTimeMS > minLongpressTime) { + currentDelayTimeMS -= delayTimeIncrement; seekBar.setProgress(delayTimeToProgress()); } } @@ -120,8 +120,8 @@ public void onClick(View v) { findViewById(R.id.delayTimeUpButton).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if (currentDelayTime < maxLongpressTime) { - currentDelayTime += delayTimeIncrement; + if (currentDelayTimeMS < maxLongpressTime) { + currentDelayTimeMS += delayTimeIncrement; seekBar.setProgress(delayTimeToProgress()); } } @@ -130,9 +130,10 @@ public void onClick(View v) { @Override public void onBackPressed() { - // setLongpressDelay stores the longpress delay as a preference - // and then updates KeymanWeb with the longpress delay - KMManager.setLongpressDelay(currentDelayTime); + // Store the longpress delay as a reference + // and then update KeymanWeb with the longpress delay + KMManager.setLongpressDelay(currentDelayTimeMS); + KMManager.sendOptionsToKeyboard(); super.onBackPressed(); } diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java index fe3dc9b6c8a..bcc133ea819 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java @@ -472,7 +472,8 @@ public boolean onKeyUp(int keycode, KeyEvent e) { @Override public void onKeyboardLoaded(KeyboardType keyboardType) { - checkLongpressDelay(); + // Initialize keyboard options + KMManager.sendOptionsToKeyboard(); } @Override @@ -750,12 +751,6 @@ private void checkSendCrashReport() { KMManager.setMaySendCrashReport(maySendCrashReport); } - private void checkLongpressDelay() { - // Initialize the longpress delay - int longpressDelay = KMManager.getLongpressDelay(); - KMManager.applyLongpressDelay(longpressDelay); - } - private void checkHapticFeedback() { SharedPreferences prefs = getSharedPreferences(getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); boolean mayHaveHapticFeedback = prefs.getBoolean(KeymanSettingsActivity.hapticFeedbackKey, false); diff --git a/android/KMEA/app/src/main/assets/android-host.js b/android/KMEA/app/src/main/assets/android-host.js index b09dbf8beb8..62d396aae0b 100644 --- a/android/KMEA/app/src/main/assets/android-host.js +++ b/android/KMEA/app/src/main/assets/android-host.js @@ -118,6 +118,8 @@ function setLongpressDelay(delay) { if (keyman.osk) { keyman.osk.gestureParams.longpress.waitLength = delay; console.debug('setLongpressDelay('+delay+')'); + } else { + window.console.log('setLongpressDelay error: keyman.osk undefined'); } } diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java index 348e3136dd3..68e686497f3 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java @@ -2027,24 +2027,7 @@ public static int getLongpressDelay() { } /** - * Set the number of milliseconds to trigger a longpress gesture. - * - * This method requires a keyboard to be loaded for the value to take effect. - * @param longpressDelay - int longpress delay in milliseconds - */ - public static void applyLongpressDelay(int longpressDelay) { - if (isKeyboardLoaded(KeyboardType.KEYBOARD_TYPE_INAPP)) { - InAppKeyboard.loadJavascript(KMString.format("setLongpressDelay(%d)", longpressDelay)); - } - - if (SystemKeyboard != null) { - SystemKeyboard.loadJavascript(KMString.format("setLongpressDelay(%d)", longpressDelay)); - } - } - - /** - * Store the long-press delay (in milliseconds) as a preference. - * Then update KeymanWeb with the longpress delay + * Set the longpress delay (in milliseconds) as a stored preference. * @param longpressDelay - int longpress delay in milliseconds */ public static void setLongpressDelay(int longpressDelay) { @@ -2053,8 +2036,22 @@ public static void setLongpressDelay(int longpressDelay) { SharedPreferences.Editor editor = prefs.edit(); editor.putInt(KMKey_LongpressDelay, longpressDelay); editor.commit(); + } + + /** + * Sends options to the KeymanWeb keyboard. + * 1. number of milliseconds to trigger a longpress gesture. + * This method requires a keyboard to be loaded for the value to take effect. + */ + public static void sendOptionsToKeyboard() { + int longpressDelay = getLongpressDelay(); + if (isKeyboardLoaded(KeyboardType.KEYBOARD_TYPE_INAPP)) { + InAppKeyboard.loadJavascript(KMString.format("setLongpressDelay(%d)", longpressDelay)); + } - applyLongpressDelay(longpressDelay); + if (SystemKeyboard != null) { + SystemKeyboard.loadJavascript(KMString.format("setLongpressDelay(%d)", longpressDelay)); + } } public static int getBannerHeight(Context context) { From 98d5322e51d473b5ce14e294a890a3c4c4284910 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Mon, 19 Aug 2024 12:53:51 +0700 Subject: [PATCH 44/65] fix(web): disable fat-finger data use when mayCorrect = false --- web/src/engine/main/src/keymanEngine.ts | 4 ++++ web/src/engine/osk/src/visualKeyboard.ts | 7 ------- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/web/src/engine/main/src/keymanEngine.ts b/web/src/engine/main/src/keymanEngine.ts index 30160e683c8..c2426560663 100644 --- a/web/src/engine/main/src/keymanEngine.ts +++ b/web/src/engine/main/src/keymanEngine.ts @@ -61,6 +61,10 @@ export default class KeymanEngine< return; } + if(!this.core.languageProcessor.mayCorrect) { + event.keyDistribution = []; + } + if(this.keyEventRefocus) { // Do anything needed to guarantee that the outputTarget stays active (`app/browser`: maintains focus). // (Interaction with the OSK may have de-focused the element providing active context; diff --git a/web/src/engine/osk/src/visualKeyboard.ts b/web/src/engine/osk/src/visualKeyboard.ts index 26b269d7f26..013ad76241e 100644 --- a/web/src/engine/osk/src/visualKeyboard.ts +++ b/web/src/engine/osk/src/visualKeyboard.ts @@ -929,13 +929,6 @@ export default class VisualKeyboard extends EventEmitter implements Ke * @returns */ getSimpleTapCorrectionDistances(input: InputSample, keySpec?: ActiveKey): Map { - // TODO: It'd be nice to optimize by keeping these off when unused, but the wiring - // necessary would get in the way of modularization at the moment. - // let keyman = com.keyman.singleton; - // if (!keyman.core.languageProcessor.mayCorrect) { - // return null; - // } - // Note: if subkeys are active, they will still be displayed at this time. let touchKbdPos = this.getTouchCoordinatesOnKeyboard(input); let layerGroup = this.layerGroup.element; // Always has proper dimensions, unlike kbdDiv itself. From ac0f4f6a83297f6bd2cac53590427a6dc73c8b90 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Mon, 19 Aug 2024 10:08:36 +0200 Subject: [PATCH 45/65] refactor(web): run npm install Addresses code review comments --- package-lock.json | 99 +++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 50 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8df9c941c25..d87ca37496c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -108,25 +108,6 @@ "typescript": "^5.4.5" } }, - "web/src/engine/predictive-text/worker-main": { - "name": "@keymanapp/lexical-model-layer", - "license": "MIT", - "dependencies": { - "@keymanapp/keyman-version": "*", - "@keymanapp/models-templates": "*", - "@keymanapp/models-wordbreakers": "*", - "@keymanapp/web-utils": "*", - "es6-shim": "^0.35.5", - "string.prototype.codepointat": "^0.2.1" - }, - "devDependencies": { - "@keymanapp/models-types": "*", - "@keymanapp/resources-gosh": "*", - "mocha": "^10.0.0", - "mocha-teamcity-reporter": "^4.0.0", - "typescript": "^5.4.5" - } - }, "common/test/resources": { "name": "@keymanapp/common-test-resources", "license": "MIT", @@ -198,36 +179,6 @@ "typescript": "^5.4.5" } }, - "web/src/engine/predictive-text/types": { - "name": "@keymanapp/lm-message-types", - "license": "MIT", - "devDependencies": { - "typescript": "^5.4.5" - } - }, - "web/src/engine/predictive-text/worker-thread": { - "name": "@keymanapp/lm-worker", - "license": "MIT", - "dependencies": { - "@keymanapp/keyman-version": "*", - "@keymanapp/models-templates": "*", - "@keymanapp/models-wordbreakers": "*", - "@keymanapp/web-utils": "*", - "es6-shim": "^0.35.5", - "string.prototype.codepointat": "^0.2.1", - "string.prototype.startswith": "^0.2.0" - }, - "devDependencies": { - "@keymanapp/common-test-resources": "*", - "@keymanapp/models-types": "*", - "@keymanapp/resources-gosh": "*", - "c8": "^7.12.0", - "combine-source-map": "^0.8.0", - "mocha": "^10.0.0", - "mocha-teamcity-reporter": "^4.0.0", - "typescript": "^5.4.5" - } - }, "common/web/sentry-manager": { "name": "@keymanapp/web-sentry-manager", "license": "MIT", @@ -14819,11 +14770,59 @@ "mocha": "^10.0.0" } }, + "web/src/engine/predictive-text/types": { + "name": "@keymanapp/lm-message-types", + "license": "MIT", + "devDependencies": { + "typescript": "^5.4.5" + } + }, + "web/src/engine/predictive-text/worker-main": { + "name": "@keymanapp/lexical-model-layer", + "license": "MIT", + "dependencies": { + "@keymanapp/keyman-version": "*", + "@keymanapp/models-templates": "*", + "@keymanapp/models-wordbreakers": "*", + "@keymanapp/web-utils": "*", + "es6-shim": "^0.35.5", + "string.prototype.codepointat": "^0.2.1" + }, + "devDependencies": { + "@keymanapp/models-types": "*", + "@keymanapp/resources-gosh": "*", + "mocha": "^10.0.0", + "mocha-teamcity-reporter": "^4.0.0", + "typescript": "^5.4.5" + } + }, + "web/src/engine/predictive-text/worker-thread": { + "name": "@keymanapp/lm-worker", + "license": "MIT", + "dependencies": { + "@keymanapp/keyman-version": "*", + "@keymanapp/models-templates": "*", + "@keymanapp/models-wordbreakers": "*", + "@keymanapp/web-utils": "*", + "es6-shim": "^0.35.5", + "string.prototype.codepointat": "^0.2.1", + "string.prototype.startswith": "^0.2.0" + }, + "devDependencies": { + "@keymanapp/common-test-resources": "*", + "@keymanapp/models-types": "*", + "@keymanapp/resources-gosh": "*", + "c8": "^7.12.0", + "combine-source-map": "^0.8.0", + "mocha": "^10.0.0", + "mocha-teamcity-reporter": "^4.0.0", + "typescript": "^5.4.5" + } + }, "web/src/tools/testing/recorder-core": { "name": "@keymanapp/recorder-core", "license": "MIT", "dependencies": { - "@keymanapp/keyboard-processor": "*", "@keymanapp/keyman-version": "*", "@keymanapp/models-types": "*", "@keymanapp/web-utils": "*" From 7c0f51c486c79e89f5f8b5e87f58df2965b804e4 Mon Sep 17 00:00:00 2001 From: "Steven R. Loomis" Date: Mon, 19 Aug 2024 10:22:10 -0500 Subject: [PATCH 46/65] fix(core): set mac build version for meson cli build to 10.13 - add as option to compiler - Match version in #11302 Fixes: #11423 --- core/cross-mac-arm64.build | 6 +++--- core/cross-mac-x86_64.build | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/cross-mac-arm64.build b/core/cross-mac-arm64.build index 720e9f31007..faf3e6e9c15 100644 --- a/core/cross-mac-arm64.build +++ b/core/cross-mac-arm64.build @@ -5,9 +5,9 @@ cpu = 'arm64' endian = 'little' [binaries] -c = ['clang', '-arch', 'arm64'] -objc = ['clang', '-arch', 'arm64'] -cpp = ['clang++', '-arch', 'arm64'] +c = ['clang', '-arch', 'arm64', '-mmacosx-version-min=10.13'] +objc = ['clang', '-arch', 'arm64', '-mmacosx-version-min=10.13'] +cpp = ['clang++', '-arch', 'arm64', '-mmacosx-version-min=10.13'] ar = 'ar' ld = 'ld' strip = 'strip' diff --git a/core/cross-mac-x86_64.build b/core/cross-mac-x86_64.build index 2ab2c62a600..3378fe11a40 100644 --- a/core/cross-mac-x86_64.build +++ b/core/cross-mac-x86_64.build @@ -5,9 +5,9 @@ cpu = 'x86_64' endian = 'little' [binaries] -c = ['clang', '-arch', 'x86_64'] -objc = ['clang', '-arch', 'x86_64'] -cpp = ['clang++', '-arch', 'x86_64'] +c = ['clang', '-arch', 'x86_64', '-mmacosx-version-min=10.13'] +objc = ['clang', '-arch', 'x86_64', '-mmacosx-version-min=10.13'] +cpp = ['clang++', '-arch', 'x86_64', '-mmacosx-version-min=10.13'] ar = 'ar' ld = 'ld' strip = 'strip' From 6e7fcba318bd392e9ac9f54f4edd6e496832f959 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Mon, 19 Aug 2024 14:03:29 -0400 Subject: [PATCH 47/65] auto: increment master version to 18.0.93 --- HISTORY.md | 9 +++++++++ VERSION.md | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index b58c086466b..5d82f22e40a 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,14 @@ # Keyman Version History +## 18.0.92 alpha 2024-08-19 + +* chore(deps-dev): bump @75lb/deep-merge from 1.1.1 to 1.1.2 (#12118) +* chore(deps): bump semver from 7.5.4 to 7.6.0 (#12119) +* fix(windows): "Keyman" is not localized in UI strings (#12162) +* feat(android): Enhance how ENTER key is handled in apps (#12125) +* refactor(web): move `lm-worker` → `worker-thread` (#12150) +* fix(developer): remove redundant check in LdmlKeyboardCompiler.validate() (#11858) + ## 18.0.91 alpha 2024-08-16 * refactor(web): move `predictive-text` → `worker-main` (#12146) diff --git a/VERSION.md b/VERSION.md index ce8cfb73ead..f74f9c87c90 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -18.0.92 \ No newline at end of file +18.0.93 \ No newline at end of file From e303cdf8018482c750c4b51f79450686240c1daf Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Tue, 20 Aug 2024 06:08:31 +0700 Subject: [PATCH 48/65] chore(android): Replace paddingLeft/Right with Start/End --- .../kMAPro/src/main/res/layout/web_browser_bar_layout.xml | 2 -- android/KMEA/app/src/main/res/layout/help_bubble_layout.xml | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/android/KMAPro/kMAPro/src/main/res/layout/web_browser_bar_layout.xml b/android/KMAPro/kMAPro/src/main/res/layout/web_browser_bar_layout.xml index 2e9b059c55f..749412e0676 100644 --- a/android/KMAPro/kMAPro/src/main/res/layout/web_browser_bar_layout.xml +++ b/android/KMAPro/kMAPro/src/main/res/layout/web_browser_bar_layout.xml @@ -15,7 +15,6 @@ android:layout_height="match_parent" android:layout_margin="3dp" android:padding="4dp" - android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_above="@+id/progressBar" android:weightSum="2" @@ -76,7 +75,6 @@ style="@style/Base.Widget.AppCompat.ProgressBar.Horizontal" android:layout_width="match_parent" android:layout_height="@dimen/keyman_bar_height" - android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignParentBottom="true" android:visibility="visible" diff --git a/android/KMEA/app/src/main/res/layout/help_bubble_layout.xml b/android/KMEA/app/src/main/res/layout/help_bubble_layout.xml index 953c74e6924..16e2c3d47a0 100644 --- a/android/KMEA/app/src/main/res/layout/help_bubble_layout.xml +++ b/android/KMEA/app/src/main/res/layout/help_bubble_layout.xml @@ -15,8 +15,8 @@ android:layout_gravity="center" android:gravity="center" android:paddingBottom="10dp" - android:paddingLeft="2dp" - android:paddingRight="2dp" + android:paddingStart="2dp" + android:paddingEnd="2dp" android:text="@string/help_bubble_text" android:textColor="#404040" android:textSize="12sp" /> From c9bc396e91752e9c5636673219c9dd4c560f8eda Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Tue, 20 Aug 2024 08:08:49 +0700 Subject: [PATCH 49/65] fix(android): Auto-mirror back and forward arrows for RTL support --- .../kmapro/KeyboardSettingsActivity.java | 2 +- .../kmapro/LanguageSettingsActivity.java | 6 +++--- .../kmapro/LanguagesSettingsActivity.java | 2 +- .../tavultesoft/kmapro/SelectPackageActivity.java | 2 +- .../src/main/res/drawable/ic_action_back.xml | 4 ---- .../kMAPro/src/main/res/layout/activity_info.xml | 5 +++-- .../src/main/res/layout/activity_web_browser.xml | 4 ++-- .../main/res/layout/preference_icon_layout.xml | 2 +- .../com/keyman/engine/KeyboardInfoActivity.java | 2 +- .../java/com/keyman/engine/ModelInfoActivity.java | 2 +- .../com/keyman/engine/ModelPickerActivity.java | 2 +- .../src/main/res/drawable-hdpi/ic_arrow_back.png | Bin 0 -> 321 bytes .../src/main/res/drawable-mdpi/ic_arrow_back.png | Bin 0 -> 270 bytes .../src/main/res/drawable-xhdpi/ic_arrow_back.png | Bin 0 -> 330 bytes .../main/res/drawable-xxhdpi/ic_arrow_back.png | Bin 0 -> 352 bytes .../main/res/drawable-xxxhdpi/ic_arrow_back.png | Bin 0 -> 413 bytes .../app/src/main/res/drawable/ic_action_back.xml | 5 +++++ .../src/main/res/drawable/ic_action_forward.xml | 3 ++- .../main/res/layout/models_list_row_layout.xml | 2 +- 19 files changed, 23 insertions(+), 20 deletions(-) delete mode 100644 android/KMAPro/kMAPro/src/main/res/drawable/ic_action_back.xml create mode 100644 android/KMEA/app/src/main/res/drawable-hdpi/ic_arrow_back.png create mode 100644 android/KMEA/app/src/main/res/drawable-mdpi/ic_arrow_back.png create mode 100644 android/KMEA/app/src/main/res/drawable-xhdpi/ic_arrow_back.png create mode 100644 android/KMEA/app/src/main/res/drawable-xxhdpi/ic_arrow_back.png create mode 100644 android/KMEA/app/src/main/res/drawable-xxxhdpi/ic_arrow_back.png create mode 100644 android/KMEA/app/src/main/res/drawable/ic_action_back.xml rename android/{KMAPro/kMAPro => KMEA/app}/src/main/res/drawable/ic_action_forward.xml (67%) diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeyboardSettingsActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeyboardSettingsActivity.java index 0989bf0d08b..689548a56ec 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeyboardSettingsActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeyboardSettingsActivity.java @@ -105,7 +105,7 @@ public void onCreate(Bundle savedInstanceState) { hashMap = new HashMap<>(); final String customHelpLink = kbd.getHelpLink(); // Check if app declared FileProvider - icon = String.valueOf(R.drawable.ic_arrow_forward); + icon = String.valueOf(R.drawable.ic_action_forward); // Don't show help link arrow if File Provider unavailable, or custom help doesn't exist if ( (customHelpLink != null && !FileProviderUtils.exists(context)) || (customHelpLink == null && !packageID.equals(KMManager.KMDefault_UndefinedPackageID)) ) { diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguageSettingsActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguageSettingsActivity.java index faa3e0efbf1..75116bad8cc 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguageSettingsActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguageSettingsActivity.java @@ -174,7 +174,7 @@ public void onCreate(Bundle savedInstanceState) { updateActiveLexicalModel(); ImageView imageView = (ImageView) layout.findViewById(R.id.image1); - imageView.setImageResource(R.drawable.ic_arrow_forward); + imageView.setImageResource(R.drawable.ic_action_forward); layout.setEnabled(true); layout.setOnClickListener(new View.OnClickListener() { @Override @@ -198,7 +198,7 @@ public void onClick(View v) { * textView = (TextView) layout.findViewById(R.id.text1); * textView.setText(getString(R.string.manage_dictionary)); * imageView = (ImageView) layout.findViewById(R.id.image1); - * imageView.setImageResource(R.drawable.ic_arrow_forward); + * imageView.setImageResource(R.drawable.ic_action_forward); */ listView.setAdapter(adapter); @@ -346,7 +346,7 @@ public View getView(int position, View convertView, ViewGroup parent) { } holder.text.setText(kbd.getResourceName()); - holder.img.setImageResource(R.drawable.ic_arrow_forward); + holder.img.setImageResource(R.drawable.ic_action_forward); return convertView; } diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguagesSettingsActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguagesSettingsActivity.java index 7b621da4b7a..6e21d04f7bf 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguagesSettingsActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/LanguagesSettingsActivity.java @@ -203,7 +203,7 @@ public View getView(int position, View convertView, ViewGroup parent) { } holder.textLang.setText(data.name); - holder.img.setImageResource(R.drawable.ic_arrow_forward); + holder.img.setImageResource(R.drawable.ic_action_forward); holder.textCount.setText(getContext().getResources().getQuantityString(R.plurals.keyboard_count, data.keyboards.size(), data.keyboards.size())); diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/SelectPackageActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/SelectPackageActivity.java index 46bc68ca1a5..9b053321824 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/SelectPackageActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/SelectPackageActivity.java @@ -81,7 +81,7 @@ public void onCreate(Bundle savedInstanceState) { HashMap hashMap = new HashMap<>(); hashMap.put(titleKey, keyboardName); hashMap.put(subtitleKey, pkgID); - String icon = String.valueOf(R.drawable.ic_arrow_forward); + String icon = String.valueOf(R.drawable.ic_action_forward); hashMap.put(iconKey, icon); list.add(hashMap); } diff --git a/android/KMAPro/kMAPro/src/main/res/drawable/ic_action_back.xml b/android/KMAPro/kMAPro/src/main/res/drawable/ic_action_back.xml deleted file mode 100644 index 165d535d3d0..00000000000 --- a/android/KMAPro/kMAPro/src/main/res/drawable/ic_action_back.xml +++ /dev/null @@ -1,4 +0,0 @@ - - diff --git a/android/KMAPro/kMAPro/src/main/res/layout/activity_info.xml b/android/KMAPro/kMAPro/src/main/res/layout/activity_info.xml index 59de5185356..3b71e871785 100644 --- a/android/KMAPro/kMAPro/src/main/res/layout/activity_info.xml +++ b/android/KMAPro/kMAPro/src/main/res/layout/activity_info.xml @@ -19,11 +19,12 @@ + android:src="@drawable/ic_action_back" /> + android:src="@drawable/ic_action_forward" /> + android:src="@drawable/ic_action_back" /> + android:src="@drawable/ic_action_forward" /> + android:src="@drawable/ic_action_forward" /> diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KeyboardInfoActivity.java b/android/KMEA/app/src/main/java/com/keyman/engine/KeyboardInfoActivity.java index c2daaea3030..1897920b731 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KeyboardInfoActivity.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KeyboardInfoActivity.java @@ -88,7 +88,7 @@ public void onCreate(Bundle savedInstanceState) { hashMap = new HashMap(); final String customHelpLink = kbd.getHelpLink(); // Check if app declared FileProvider - String icon = String.valueOf(R.drawable.ic_arrow_forward); + String icon = String.valueOf(R.drawable.ic_action_forward); // Don't show help link arrow if it's a local help file and File Provider unavailable, // or custom help doesn't exist if ( (customHelpLink != null && ! KMManager.isTestMode() && diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/ModelInfoActivity.java b/android/KMEA/app/src/main/java/com/keyman/engine/ModelInfoActivity.java index ef1b180c52f..ce81927699a 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/ModelInfoActivity.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/ModelInfoActivity.java @@ -81,7 +81,7 @@ public void onCreate(Bundle savedInstanceState) { final String customHelpLink = lm.getHelpLink(); // Check if app declared FileProvider // Currently, model help only available if custom link exists - icon = String.valueOf(R.drawable.ic_arrow_forward); + icon = String.valueOf(R.drawable.ic_action_forward); // Don't show help link arrow if both custom help and File Provider don't exist // TODO: Update this when model help available on help.keyman.com if ( (!customHelpLink.equals("") && !FileProviderUtils.exists(context)) || diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/ModelPickerActivity.java b/android/KMEA/app/src/main/java/com/keyman/engine/ModelPickerActivity.java index 8b74e261a37..4595aae1e70 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/ModelPickerActivity.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/ModelPickerActivity.java @@ -321,7 +321,7 @@ public View getView(int position, View convertView, ViewGroup parent) { // once it has its own backing Dataset instance. // Is this an installed model or not? - holder.imgDetails.setImageResource(R.drawable.ic_arrow_forward); + holder.imgDetails.setImageResource(R.drawable.ic_action_forward); if (KeyboardPickerActivity.containsLexicalModel(context, modelKey)) { holder.imgInstalled.setImageResource(R.drawable.ic_check); } else { diff --git a/android/KMEA/app/src/main/res/drawable-hdpi/ic_arrow_back.png b/android/KMEA/app/src/main/res/drawable-hdpi/ic_arrow_back.png new file mode 100644 index 0000000000000000000000000000000000000000..7922c650163774b332ade994ec590a8605838a89 GIT binary patch literal 321 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8JTOS+@4BLl<6e(pbstUx|flDE4H z!~gdFGy8!&_7YEDSN0biB8;NE6Zt%D0EJ3DT^vI^j=#NR%h#a5)Amr@^kTHPP2=>B z=_d2M)MZKzScoLEU;eOh(()}LMLEYFm(Fnb;WyVOVcDg`S!W_r?lfmI-gtRasEcd8 zr)^-DesD)|d=3BlDB)jWKR3^qwW8jm_u5Lw$y%i={C25bk1SYoecyA5(~P z+$aP(K()j*q9i4;B-JXpC>2OC7#SFu=o(n)8X1Hb7+M(_SeaO88yHv_80`Nak%^)q sH$NpatrDccSl7Tz*U&7)z}O0?$G`}p;l$B1$v_PZp00i_>zopr0L$uYU;qFB literal 0 HcmV?d00001 diff --git a/android/KMEA/app/src/main/res/drawable-mdpi/ic_arrow_back.png b/android/KMEA/app/src/main/res/drawable-mdpi/ic_arrow_back.png new file mode 100644 index 0000000000000000000000000000000000000000..0c1eb7a4174665a072e617f180f97aa265c71146 GIT binary patch literal 270 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1mUKs7M+SzC{oH>NS%G|}ByV>Y zhX3vTXZ8bm>?NMQuIw*3L>R?HSNb>m0)?DBT^vI!PA4Zw>|4;du+ik{f60FaFD5Os zsam3OoPA+KXT;|f4^&#FX>=3_cH9IjGDG3P)NxjKQ#{-xc4lo)Q-1uL( z5@?!giEBhjN@7W>RdP`(kYX@0Ff!3Ku+TL!2r)3UGBUCNS%G|}ByV>Y zhX3vTXZ8bm>?NMQuIw*3L>R?Ijt4i*0t(f6x;TbJ9DX~&o6o^PfR&p&{Zr(QX`+Qj zGbdXxvrBMq6j1Ew^N%}Qwk&IxBS+!1S+~O8e=O_teE)IEwqK1gzjABU{!ZIBz0QAr zT}1s;iPzzcAO5l0>|2z&NPXixCr;HV74=G1HJeozFeofL9O-v)PGwO|Qze&s>gQ_3 zf2TR(l3uzfi7#La^8Cw||X&V?= z85rz{*yMnsAvZrIGp!P&!C2S8OxMsX#K71JsK)@R;l$B1$v_PZp00i_>zopr09|u! A6951J literal 0 HcmV?d00001 diff --git a/android/KMEA/app/src/main/res/drawable-xxhdpi/ic_arrow_back.png b/android/KMEA/app/src/main/res/drawable-xxhdpi/ic_arrow_back.png new file mode 100644 index 0000000000000000000000000000000000000000..831448cb178f6af0841e5ba5b01f9e8748b1991c GIT binary patch literal 352 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhawSkfJR9T^xl_H+M9WCik>lDyqr z82-2SpV<%Ov6p!Iy0X9E5MdP8oNs-u8z?lz)5S3)5l3<^A{=HeInRdKG2^riX9j$LzB%}>)m$CNH| z?t1U%Cg$axpBtH%&-~m1WL+*kW5K(i+H(2=_h+sZZ%_1H$@H#%ciXv%g;PkyV}b&& z!>m0X(PrwCuH|^C?AwgT!g XFoI|}ar8_wPy>UftDnm{r-UW|I~sRl literal 0 HcmV?d00001 diff --git a/android/KMEA/app/src/main/res/drawable-xxxhdpi/ic_arrow_back.png b/android/KMEA/app/src/main/res/drawable-xxxhdpi/ic_arrow_back.png new file mode 100644 index 0000000000000000000000000000000000000000..5794fbcaac0b9ace84d73afca26e8e0cef024f9a GIT binary patch literal 413 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD0wg^q?%xcgSkfJR9T^xl_H+M9WCik>lDyqr z82-2SpV<%Ov6p!Iy0X9E5MdOz&S~0z7$|hn)5S5Q;?~| zWM<3wT+er-cc)?gQGXBHg@58_)OdKmIbNG&re=}Q#EgY#KI><(dUKI*-m4{dT2@=B zn=efHXZ3K=xf8w_uRx)|5dD>9V!`w1%a#{hfIQU_*NBpo#FA92sBK_iWnjSjYneKVhTQy=%(P0724h_VGhIWo5CdZ?pdJGwh=vnK R&m@B^^mO%eS?83{1OP9Qo00$k literal 0 HcmV?d00001 diff --git a/android/KMEA/app/src/main/res/drawable/ic_action_back.xml b/android/KMEA/app/src/main/res/drawable/ic_action_back.xml new file mode 100644 index 00000000000..cae0c5eed49 --- /dev/null +++ b/android/KMEA/app/src/main/res/drawable/ic_action_back.xml @@ -0,0 +1,5 @@ + + diff --git a/android/KMAPro/kMAPro/src/main/res/drawable/ic_action_forward.xml b/android/KMEA/app/src/main/res/drawable/ic_action_forward.xml similarity index 67% rename from android/KMAPro/kMAPro/src/main/res/drawable/ic_action_forward.xml rename to android/KMEA/app/src/main/res/drawable/ic_action_forward.xml index 15efecf5575..2ffd9c4540e 100644 --- a/android/KMAPro/kMAPro/src/main/res/drawable/ic_action_forward.xml +++ b/android/KMEA/app/src/main/res/drawable/ic_action_forward.xml @@ -1,4 +1,5 @@ + android:tint="@android:color/black" + android:autoMirrored="true"/> diff --git a/android/KMEA/app/src/main/res/layout/models_list_row_layout.xml b/android/KMEA/app/src/main/res/layout/models_list_row_layout.xml index ac07621cdd6..a2116bcb4c5 100644 --- a/android/KMEA/app/src/main/res/layout/models_list_row_layout.xml +++ b/android/KMEA/app/src/main/res/layout/models_list_row_layout.xml @@ -44,7 +44,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:color/transparent" - android:src="@drawable/ic_arrow_forward" + android:src="@drawable/ic_action_forward" android:layout_alignParentEnd="true" android:layout_centerVertical="true" android:layout_marginEnd="12dp" From 5f134fe590b7d187f82cfb7348bd847700a0347e Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Tue, 20 Aug 2024 09:34:06 +0700 Subject: [PATCH 50/65] feat(android): Add localization for Arabic --- .../src/main/res/values-ar-rSA/strings.xml | 168 ++++++++++++++++ .../com/keyman/engine/DisplayLanguages.java | 1 + .../src/main/res/values-ar-rSA/strings.xml | 188 ++++++++++++++++++ 3 files changed, 357 insertions(+) create mode 100644 android/KMAPro/kMAPro/src/main/res/values-ar-rSA/strings.xml create mode 100644 android/KMEA/app/src/main/res/values-ar-rSA/strings.xml diff --git a/android/KMAPro/kMAPro/src/main/res/values-ar-rSA/strings.xml b/android/KMAPro/kMAPro/src/main/res/values-ar-rSA/strings.xml new file mode 100644 index 00000000000..6ceb657187b --- /dev/null +++ b/android/KMAPro/kMAPro/src/main/res/values-ar-rSA/strings.xml @@ -0,0 +1,168 @@ + + + + + مشاركة + + متصفح ويب + + حجم النص + + المزيد + + محو النص + + معلومات + + الإعدادات + + تنزيل التحديثات + + إصدار: %1$s + + يتطلب Keyman إصدار 57 من Chrome أو أعلى. + + تحديث Chrome + + ابدأ الكتابة هنا… + + + + حجم النص: %1$d + + تكبير حجم النص + + تصغير حجم النص + + Text size slider + + \nسيتم محو كل النص\n + + إبدأ الآن + + اضف لوحة مفاتيح بلغتك + + تمكين Keyman لوحة المفاتيح الأساسية للنظام + + إعداد Keyman لوحة المفاتيح الإفتراضية + + المزيد من المعلومات + + أظهر \"%1$s\" عند البدء + + لتثبيت حزم لوحات المفاتيح، امنح Keyman الإذن لقراءة التخزين الخارجي. + + تم رفض أذونات التخزين. قد يفشل تثبيت حزمة لوحة المفاتيح + Storage permission request failed. Try Keyman Settings - Install from local file + + الإعدادات + + + اللغات المثبتة (%1$d) + اللغات المثبتة (%1$d) + اللغات المثبتة (%1$d) + اللغات المثبتة (%1$d) + اللغات المثبتة (%1$d) + اللغات المثبتة (%1$d) + + + تثبيت لوحة المفاتيح او القاموس + + لغة العرض + + تعديل ارتفاع لوحة المفاتيح + + نص مفتاح المسافة + + لوحة المفاتيح + + اللغة + + اللغة + لوحة المفاتيح + + فارغ + + أظهر اسم لوحة المفاتيح على مفتاح المسافة + + أظهر اسم اللغة على المسافة + + اللغة ولوحة المفاتيح على المسافة + + لا تظهر نص على المسافة + + الاهتزاز عند الكتابة + + إظهار اللافتة دائماً + + سيتم تنفيذها + + عند إيقاف التشغيل، يظهر فقط عند تفعيل النص التنبؤي + + السماح بإرسال تقارير توقف التشغيل المفاجئ عبر الشبك + + عند التشغيل، سيتم إرسال تقارير التوقف المفاجئ + + عند إيقاف التشغيل، لن يتم إرسال التقارير + + تثبيت من keyman.com + + التثبيت من ملف محلي + + التثبيت من جهاز آخر + + اضف لغات للوحة المفاتيح المثبتة + + (من حزمة لوحة المفاتيح) + + اختر حزمة لوحة مفاتيح + + اختر لغة %1$s + + تمت اضافة %1$s إلى %2$s + + كل اللغات مثبتة مسبقا + + اسحب لوحة المفاتيح لتغيير مدى ارتفاعها + + دور الجهاز لضبط الوضع العمودي والوضع الأفقي + + إعادة ضبط الافتراضيات + + ابحث أو اكتب عنوان URL + + علامات مرجعية + + لا تتوفر أي علامات مرجعية + + أضف علامة مرجعية + + العنوان + + عنوان Url + + فشل في تنزيل حزمة %1$s + + يتم الآن تحميل لوحة مفاتيح حزمة \n%1$s… + + فشل في الإستخراج + + تثبيت لوحة المفاتيح + + تثبيت القاموس + + ليس %1$s ملف حزمة صالحة لبرنامج Keyman.\n%2$s\" + + ليس في حزمة لوحة المفاتيح لوحات مفاتيح مكيّفة لشاشات اللمس + + لا يوجد نصوص تنبؤية للتنزيل + + لا لوحات مفاتيح و نصوص تنبؤية للتنزيل + + ليس لحزمة لوحة المفاتيح لغات ذات صلة لتثبيتها + + غير صالح\ناقص البيانات الوصفية في الحزمة + + تتطلب لوحة المفاتيح إصدارًا أحدث من Keyman + + غير قادر على تشغيل متصفح الويب + diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/DisplayLanguages.java b/android/KMEA/app/src/main/java/com/keyman/engine/DisplayLanguages.java index 6a159523a2e..4783e401b8e 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/DisplayLanguages.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/DisplayLanguages.java @@ -40,6 +40,7 @@ public static final DisplayLanguageType[] getDisplayLanguages(Context context) { DisplayLanguageType[] languages = { new DisplayLanguageType(unspecifiedLocale, context.getString(R.string.default_locale)), new DisplayLanguageType("am-ET", "አማርኛ (Amharic)"), + new DisplayLanguageType("ar-SA", "(Arabic) العربية"), new DisplayLanguageType("az-AZ", "Azərbaycanca (Azəricə)"), new DisplayLanguageType("bwr-NG", "Bura-Pabir"), new DisplayLanguageType("cs-CZ", "čeština (Czech)"), diff --git a/android/KMEA/app/src/main/res/values-ar-rSA/strings.xml b/android/KMEA/app/src/main/res/values-ar-rSA/strings.xml new file mode 100644 index 00000000000..cb2e9f0d512 --- /dev/null +++ b/android/KMEA/app/src/main/res/values-ar-rSA/strings.xml @@ -0,0 +1,188 @@ + + + + + + + لوحة مفاتيح + لوحات مفاتيح + لوحتا مفاتيح + لوحات مفاتيح + لوحة مفاتيح + لوحة مفاتيح + + + + طريقة إداخل أخرى + طريقة إدخال أخرى + طريقتا إدخال أخريتان + طرق إدخال + طريقة إدخال أخرى + طريقة إدخال أخرى + + + إضافة لوحة مفاتيح جديدة + + اللغات المثبتة + + إعدادات %1$s + + إضافة + + عودة + + إلغاء + + إغلاق + + إغلاق Keyman + + الأمام + + طريقة الإدخال التالية + + تحميل + + تثبيت + + لاحقًا + + التالي + + موافق + + تحديث + + لا يوجد اتصال بالإنترنت + + لا يمكن الاتصال بخادم Keyman! + + هل ترغب بإزالة لوحة المفاتيح هذه؟ + + هل ترغب بتحميل آخر إصدار من لوحة المفاتيح هذه؟ + + هل ترغب بتحديث لوحات المفاتيح والقواميس الآن؟ + + تحديثات الموارد + + تتوفر تحديثات موارد + + %1$s (تحديث متوفر) + + تحديثات متوفرة للوحة مفاتيح %1$s: %2$s + + تحديثات متوفرة لقاموس %1$s: %2$s + + إصدار لوحة المفاتيح + + رابط المساعدة + + إزالة تثبيت لوحة المفاتيح + + [new] %1$s + + امسح هذا الرمز لتحميل \nلوحة المفاتيح هذه على جهاز آخر + + أهلًا بك في %1$s + + مكتبة FileProvider مطلوبة لعرض ملفات المساعدة: %1$s + + خطأ كبير في لوحة مفاتيح مع %1$s:%2$s لأجل لغة %3$s. سيتم تحميل لوحة المفاتيح الأساسية. + + خطأ في لوحة مفاتيح %1$s:%2$s لأجل لغة %3$s. + + يجري التحقق من قاموس ذي صلة للتحميل + لا يمكن الاتصال بخادم Keyman للتحقق من تنزيل القاموس المرتبط + + هل ترغب بتحملي آخر إصدار من هذا القاموس؟ + + لا يوجد قاموس لتحميله + + كتالوغ المصدر غير متوفر + + بدء تحديث الكتالوغ في الخلفية + + الكتالوغ لا يزال يتم تحميله، يرجى المحاولة مجددًا بعد قليل! + + البحث عن مصدر + + بدء تحميل لوحة المفاتيح في الخلفية + + يجري بالفعل تحميل لوحة المفاتيح المختارة، يرجى المحاولة مجددًا بعد قليل! + + اكتمل تحميل لوحة المفاتيح! + + بدأ تحميل القاموس في الخلفية + + يجري بالفعل تحميل القاموس، يرجى المحاولة مجددًا بعد قليل! + + اكتمل تحميل القاموس. + + فشل التحميل + + فشل استرجاع الملف المحمل + + فشل الوصول إلى الخادم! + + "جميع الموارد محدّثة!" + + فشل تحديث واحد أو أكثر من المصادر! + + تم تحديث الموارد بنجاح! + + إصدار القاموس + + إزالة تثبيت القاموس + + هل ترغب بإزالة هذا القاموس؟ + + تم حذف القاموس + + تم تثبيت لوحة مفاتيح %1$s + + تم حذف لوحة المفاتيح + + تفعيل التصحيحات + + تفعيل التوقعات + + القاموس + + Dictionaries + Dictionary + Dictionaries + Dictionaries + Dictionaries + Dictionaries + + + البحث عن قاموس متوفر + تحقق من وجود قواميس على الإنترنت + + قاموس: %1$s + + قواميس %1$s + + + تم تثبيت القاموس + + + (%1$d اوحات) + (لوحة مفاتيح %1$d) + (لوحتا مفاتيح %1$d) + (%1$d لوحة مفاتيح) + (%1$d لوحة مفاتيح) + (%1$d لوحة مفاتيح) + + + اللغة الأصلية + + + + حذف + + + اضغط هنا لتغيير لوحة المفاتيح + + غير قادر على تشغيل متصفح الويب + From 92275697c049770f2f3e07577756442e0ce60123 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Tue, 20 Aug 2024 10:52:28 +0700 Subject: [PATCH 51/65] fix(web): improve tokenization output when wordbreaker breaks spec for span .left, .right values in output --- common/models/templates/src/tokenization.ts | 28 ++-- .../templates/test/custom-breakers.def.js | 128 ++++++++++++++++++ .../templates/test/test-tokenization.js | 75 ++++++++++ 3 files changed, 219 insertions(+), 12 deletions(-) create mode 100644 common/models/templates/test/custom-breakers.def.js diff --git a/common/models/templates/src/tokenization.ts b/common/models/templates/src/tokenization.ts index 46290a455d4..2fb07da357b 100644 --- a/common/models/templates/src/tokenization.ts +++ b/common/models/templates/src/tokenization.ts @@ -61,20 +61,21 @@ export function tokenize( let currentIndex = 0; while(leftSpans.length > 0) { const nextSpan = leftSpans[0]; - if(nextSpan.start != currentIndex) { + if(Math.max(nextSpan.start, currentIndex) != currentIndex) { + const nextIndex = Math.max(currentIndex, nextSpan.start); // Implicit whitespace span! tokenization.left.push({ - text: context.left!.substring(currentIndex, nextSpan.start), + text: context.left!.substring(currentIndex, nextIndex), isWhitespace: true }); - currentIndex = nextSpan.start; + currentIndex = nextIndex; } else { leftSpans.shift(); // Explicit non-whitespace span. tokenization.left.push({ text: nextSpan.text }); - currentIndex = nextSpan.end; + currentIndex = Math.max(currentIndex, nextSpan.end); } } @@ -84,11 +85,12 @@ export function tokenize( // Note: the default wordbreaker won't need this code, as it emits a `''` // after final whitespace. if(context.left != null && currentIndex != context.left.length) { + const nextIndex = Math.max(currentIndex, context.left!.length); tokenization.left.push({ - text: context.left.substring(currentIndex, context.left!.length), + text: context.left.substring(currentIndex, nextIndex), isWhitespace: true }); - currentIndex = context.left!.length; + currentIndex = nextIndex; } // New step 2: handle any rejoins needed. @@ -134,13 +136,14 @@ export function tokenize( // `caretSplitsToken` check is additional. while(rightSpans.length > 0) { const nextSpan = rightSpans[0]; - if(nextSpan.start != currentIndex) { + if(Math.max(nextSpan.start, currentIndex) != currentIndex) { + const nextIndex = Math.max(currentIndex, nextSpan.start); // Implicit whitespace span! tokenization.right.push({ - text: context.right!.substring(currentIndex, nextSpan.start), + text: context.right!.substring(currentIndex, nextIndex), isWhitespace: true }); - currentIndex = nextSpan.start; + currentIndex = nextIndex; } else { const leftTail = tokenization.left[leftTokenCount-1]; if(leftTail) { @@ -159,7 +162,7 @@ export function tokenize( tokenization.right.push({ text: nextSpan.text }); - currentIndex = nextSpan.end; + currentIndex = Math.max(currentIndex, nextSpan.end); } // We've always processed the "first right token" after the first iteration. @@ -176,11 +179,12 @@ export function tokenize( // Also note: is pretty much WET with the similar check after the // leftSpan loop. if(context.right && currentIndex != context.right.length) { + const nextIndex = Math.max(currentIndex, context.right!.length); tokenization.right.push({ - text: context.right.substring(currentIndex, context.right!.length), + text: context.right.substring(currentIndex, nextIndex), isWhitespace: true }); - currentIndex = context.right!.length; + currentIndex = nextIndex; } return tokenization; diff --git a/common/models/templates/test/custom-breakers.def.js b/common/models/templates/test/custom-breakers.def.js new file mode 100644 index 00000000000..c907467ce02 --- /dev/null +++ b/common/models/templates/test/custom-breakers.def.js @@ -0,0 +1,128 @@ +/** + * The custom wordbreaker used by the sil.km.gcc model as of + * https://github.com/keymanapp/lexical-models/pull/265. + * @type {WordBreakingFunction} + * */ +export function customWordBreakerProper(str) { + const whitespaceRegex = /\s|\u200b|\n|\r/; + const tokens = str.split(whitespaceRegex); + + for(let i=0; i < tokens.length; i++) { + const token = tokens[i]; + if(token.length == 0) { + tokens.splice(i, 1); + i--; + continue; + } else if(token.length == 1 && whitespaceRegex.test(token)) { + tokens.splice(i, 1); + i--; + continue; + } + + // Certain punctuation marks should be considered a separate token from the word they're next to. + const punctuationMarks = ['«', '»', '$', '#' /* add extras here */]; + const punctSplitIndices = []; + + // Find if and where each mark exists within the token + for(let i = 0; i < punctuationMarks.length; i++) { + const split = token.indexOf(punctuationMarks[i]); + if(split >= 0) { + punctSplitIndices.push(split); + } + } + + // Sort and pick the earliest mark's location. If none exists, use -1. + punctSplitIndices.sort(); + const splitPoint = punctSplitIndices[0] === undefined ? -1 : punctSplitIndices[0]; + + if(splitPoint > -1) { + const left = token.substring(0, splitPoint); // (0, -1) => '' + const punct = token.substring(splitPoint, splitPoint+1); + const right = token.substring(splitPoint+1); // Starting past the end of the string => '' + + if(left) { + tokens.splice(i++, 0, left); + } + tokens.splice(i++, 1, punct); + if(right) { + tokens.splice(i, 0, right); + } + // Ensure that the next iteration puts `i` immediately after the punctuation token... even if + // there was a `right` portion, as it may have extra marks that also need to be spun off. + i--; + } + } + + let latestIndex = 0; + return tokens.map(function(token) { + const start = str.indexOf(token, latestIndex); + latestIndex = start + token.length; + return { + left: start, + start: start, + right: start + token.length, + end: start + token.length, + length: token.length, + text: token + } + }); +} + +/** + * The version of the custom wordbreaker used by the sil.km.gcc model + * before https://github.com/keymanapp/lexical-models/pull/265, which + * triggered #12200. + * @type {WordBreakingFunction} + * */ +export function customWordBreakerFormer (str) { + const tokens = str.split(/\s|\u200b/); + + for(let i=0; i < tokens.length; i++) { + const token = tokens[i]; + if(token.length == 1) { + continue; + } + + // Certain punctuation marks should be considered a separate token from the word they're next to. + const punctuationMarks = ['«', '»', '$', '#' /* add extras here */]; + const punctSplitIndices = []; + + // Find if and where each mark exists within the token + for(let i = 0; i < punctuationMarks.length; i++) { + const split = token.indexOf(punctuationMarks[i]); + if(split >= 0) { + punctSplitIndices.push(split); + } + } + + // Sort and pick the earliest mark's location. If none exists, use -1. + punctSplitIndices.sort(); + const splitPoint = punctSplitIndices[0] === undefined ? -1 : punctSplitIndices[0]; + + if(splitPoint > -1) { + const left = token.substring(0, splitPoint); // (0, -1) => '' + const punct = token.substring(splitPoint, splitPoint+1); + const right = token.substring(splitPoint+1); // Starting past the end of the string => '' + + if(left) { + tokens.splice(i++, 0, left); + } + tokens.splice(i++, 1, punct); + if(right) { + tokens.splice(i, 0, right); + } + // Ensure that the next iteration puts `i` immediately after the punctuation token... even if + // there was a `right` portion, as it may have extra marks that also need to be spun off. + i--; + } + } + return tokens.map(function(token) { + return { + left: str.indexOf(token), + start: str.indexOf(token), + right: str.indexOf(token) + token.length, + end: str.indexOf(token) + token.length, + text: token + } + }); +} \ No newline at end of file diff --git a/common/models/templates/test/test-tokenization.js b/common/models/templates/test/test-tokenization.js index 2a5ec136f69..20b7082dfec 100644 --- a/common/models/templates/test/test-tokenization.js +++ b/common/models/templates/test/test-tokenization.js @@ -5,6 +5,7 @@ import { assert } from 'chai'; import * as models from "@keymanapp/models-templates"; import * as wordBreakers from "@keymanapp/models-wordbreakers"; +import { customWordBreakerFormer, customWordBreakerProper } from './custom-breakers.def.js'; function asProcessedToken(text) { // default wordbreaker emits these at the end of each context half if ending with whitespace. @@ -490,6 +491,80 @@ describe('Tokenization functions', function() { caretSplitsToken: true }); }); + + it('mitigates effects of previously-distributed malformed wordbreaker output', function () { + const text = 'the quick brown fox jumped over the lazy dog '; + /** @type { Context } */ + const context = { + left: text, + right: '', + startOfBuffer: true, + endOfBuffer: true + } + + const tokenized = models.tokenize(customWordBreakerFormer, context); + + // Mitigation aims to prevent the _worst_ side-effects that can result from invalidating the + // underlying assumption of a monotonically-increasing index within the context - + // assigning repeated or blank entries the text that preceded them! + assert.notExists(tokenized.left.find((token) => token.text == text)); + assert.notExists(tokenized.left.find((token) => token.text.startsWith(text.substring(0, 25)))); + + // 'the' appears twice in the context, which should result in two separate 'the' tokens here. + // This was improperly handled when we didn't check that assumption. + assert.equal(tokenized.left.filter((token) => token.text == 'the').length, 2); + + // Does not address multiple blank-token ('') entries that result from intervening spaces; + // that would add too much extra complexity to the method... and it can already be + // handled decently by the predictive-text engine. + }); + + it('properly works with well-formed custom wordbreaker output', function () { + const text = 'the quick brown fox jumped over the lazy dog '; + /** @type { Context } */ + const context = { + left: text, + right: '', + startOfBuffer: true, + endOfBuffer: true + } + + const tokenized = models.tokenize(customWordBreakerProper, context); + + // Easier-to-parse version + assert.deepEqual( + tokenized.left + .filter((entry) => !entry.isWhitespace) + .map((entry) => entry.text), + ['the', 'quick', 'brown', 'fox', 'jumped', 'over', 'the', 'lazy', 'dog'] + ); + + // This time, with whitespaces. + assert.deepEqual( + tokenized.left.map((entry) => entry.text), [ + 'the', + ' ', + 'quick', + ' ', + 'brown', + ' ', + 'fox', + ' ', + 'jumped', + ' ', + 'over', + ' ', + 'the', + ' ', + 'lazy', + ' ', + 'dog', + ' ' + ] + ); + }); + + // }); describe('getLastPreCaretToken', function() { From ec32e21bf4bd6f7d225126e34deaec7ff728e302 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Tue, 20 Aug 2024 11:04:32 +0700 Subject: [PATCH 52/65] feat(web): adds extra assertion to 'mitigation' test --- common/models/templates/test/test-tokenization.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/common/models/templates/test/test-tokenization.js b/common/models/templates/test/test-tokenization.js index 20b7082dfec..d8f27197a27 100644 --- a/common/models/templates/test/test-tokenization.js +++ b/common/models/templates/test/test-tokenization.js @@ -517,6 +517,13 @@ describe('Tokenization functions', function() { // Does not address multiple blank-token ('') entries that result from intervening spaces; // that would add too much extra complexity to the method... and it can already be // handled decently by the predictive-text engine. + assert.deepEqual( + tokenized.left + .filter((entry) => !entry.isWhitespace) + .filter((entry) => entry.text != '') + .map((entry) => entry.text), + ['the', 'quick', 'brown', 'fox', 'jumped', 'over', 'the', 'lazy', 'dog'] + ); }); it('properly works with well-formed custom wordbreaker output', function () { From 93b1881cb8b2c8544f0210d8f9896d5f8bd6d244 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Tue, 20 Aug 2024 13:55:13 +0700 Subject: [PATCH 53/65] fix(android): Auto-mirror increment and decrement arrows --- .../java/com/tavultesoft/kmapro/MainActivity.java | 14 ++++++++++++-- .../src/main/res/drawable/ic_action_decrement.xml | 5 +++++ .../src/main/res/drawable/ic_action_increment.xml | 5 +++++ .../src/main/res/layout/text_size_controller.xml | 4 ++-- 4 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 android/KMAPro/kMAPro/src/main/res/drawable/ic_action_decrement.xml create mode 100644 android/KMAPro/kMAPro/src/main/res/drawable/ic_action_increment.xml diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java index 1e5231f5215..21d1af493ae 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java @@ -646,7 +646,7 @@ private void showTextSizeDialog() { final View textSizeController = inflater.inflate(R.layout.text_size_controller, null); final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(MainActivity.this); dialogBuilder.setIcon(R.drawable.ic_light_action_textsize); - dialogBuilder.setTitle(String.format(getString(R.string.text_size), textSize)); + dialogBuilder.setTitle(getTextSizeString()); dialogBuilder.setView(textSizeController); dialogBuilder.setPositiveButton(getString(R.string.label_ok), new DialogInterface.OnClickListener() { @Override @@ -677,7 +677,7 @@ public void onStartTrackingTouch(SeekBar seekBar) { public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { textSize = progress + minTextSize; textView.setTextSize((float) textSize); - dialog.setTitle(String.format(getString(R.string.text_size), textSize)); + dialog.setTitle(getTextSizeString()); } }); @@ -702,6 +702,16 @@ public void onClick(View v) { }); } + /** + * Combine a localized string for "Text Size" plus Arabic numerals + * @return String + */ + private String getTextSizeString() { + // Instead of formatting the number, will truncate formatting and concat the actual textSize + String label = getString(R.string.text_size).replace("%1$d", ""); + return label + KMString.format(" %d", textSize); + } + private void showClearTextDialog() { AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(MainActivity.this); dialogBuilder.setIcon(R.drawable.ic_light_action_trash); diff --git a/android/KMAPro/kMAPro/src/main/res/drawable/ic_action_decrement.xml b/android/KMAPro/kMAPro/src/main/res/drawable/ic_action_decrement.xml new file mode 100644 index 00000000000..c3085bec5e9 --- /dev/null +++ b/android/KMAPro/kMAPro/src/main/res/drawable/ic_action_decrement.xml @@ -0,0 +1,5 @@ + + diff --git a/android/KMAPro/kMAPro/src/main/res/drawable/ic_action_increment.xml b/android/KMAPro/kMAPro/src/main/res/drawable/ic_action_increment.xml new file mode 100644 index 00000000000..ea188f818f1 --- /dev/null +++ b/android/KMAPro/kMAPro/src/main/res/drawable/ic_action_increment.xml @@ -0,0 +1,5 @@ + + diff --git a/android/KMAPro/kMAPro/src/main/res/layout/text_size_controller.xml b/android/KMAPro/kMAPro/src/main/res/layout/text_size_controller.xml index 2245ef557a3..c250b1bf072 100644 --- a/android/KMAPro/kMAPro/src/main/res/layout/text_size_controller.xml +++ b/android/KMAPro/kMAPro/src/main/res/layout/text_size_controller.xml @@ -15,7 +15,7 @@ android:layout_marginStart="5dp" android:layout_marginEnd="5dp" android:contentDescription="@string/ic_text_size_down" - android:src="@drawable/ic_light_dialog_textsize_down" /> + android:src="@drawable/ic_action_decrement" /> + android:src="@drawable/ic_action_increment" /> From 97697b695ff85eed11047489b08c1f9299f559ca Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Tue, 20 Aug 2024 14:19:14 +0700 Subject: [PATCH 54/65] fix(web): fix documentation-keyboard spacebar-text scaling Fixes: #12231 --- web/src/engine/osk/src/visualKeyboard.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/web/src/engine/osk/src/visualKeyboard.ts b/web/src/engine/osk/src/visualKeyboard.ts index 26b269d7f26..0d529af651e 100644 --- a/web/src/engine/osk/src/visualKeyboard.ts +++ b/web/src/engine/osk/src/visualKeyboard.ts @@ -1246,6 +1246,7 @@ export default class VisualKeyboard extends EventEmitter implements Ke const groupStyle = getComputedStyle(this.layerGroup.element); const isInDOM = computedStyle.height != '' && computedStyle.height != 'auto'; + const isGroupInDOM = groupStyle.height != '' && groupStyle.height != 'auto'; if (computedStyle.border) { this._borderWidth = new ParsedLengthStyle(computedStyle.borderWidth).val; @@ -1258,10 +1259,11 @@ export default class VisualKeyboard extends EventEmitter implements Ke this._computedHeight = this.height; } else if (isInDOM) { this._computedWidth = parseInt(computedStyle.width, 10); - if (!this._computedWidth) { - this._computedWidth = parseInt(groupStyle.width, 10); - } this._computedHeight = parseInt(computedStyle.height, 10); + } else if (isGroupInDOM) { + // May occur for documentation-keyboards, which are detached from their VisualKeyboard base. + this._computedWidth = parseInt(groupStyle.width, 10); + this._computedHeight = parseInt(groupStyle.height, 10); } else { // Cannot perform layout operations! return; @@ -1604,6 +1606,11 @@ export default class VisualKeyboard extends EventEmitter implements Ke // the page. kbdObj.appendStyleSheet(); + // Unset the width + height we used thus far; this method's consumer may choose to rescale + // the returned element. If so, we don't want to use our outdated value by mistake. + delete kbdObj._width; + delete kbdObj._height; + return classWrapper; } From 23e02d2a86812e7807fdad6304db99abf1d773de Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Tue, 20 Aug 2024 14:38:58 +0700 Subject: [PATCH 55/65] change(web): better way to re-establish default sizing --- web/src/engine/osk/src/visualKeyboard.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/web/src/engine/osk/src/visualKeyboard.ts b/web/src/engine/osk/src/visualKeyboard.ts index 0d529af651e..a70c6b68ed4 100644 --- a/web/src/engine/osk/src/visualKeyboard.ts +++ b/web/src/engine/osk/src/visualKeyboard.ts @@ -1608,8 +1608,7 @@ export default class VisualKeyboard extends EventEmitter implements Ke // Unset the width + height we used thus far; this method's consumer may choose to rescale // the returned element. If so, we don't want to use our outdated value by mistake. - delete kbdObj._width; - delete kbdObj._height; + kbdObj.setSize(); return classWrapper; } From 01ae0c0a9ac23df03482223390a1a8f0ceba3d43 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Tue, 20 Aug 2024 14:40:24 +0700 Subject: [PATCH 56/65] chore(web): Revert "change(web): better way to re-establish default sizing" This reverts commit 23e02d2a86812e7807fdad6304db99abf1d773de. --- web/src/engine/osk/src/visualKeyboard.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/src/engine/osk/src/visualKeyboard.ts b/web/src/engine/osk/src/visualKeyboard.ts index a70c6b68ed4..0d529af651e 100644 --- a/web/src/engine/osk/src/visualKeyboard.ts +++ b/web/src/engine/osk/src/visualKeyboard.ts @@ -1608,7 +1608,8 @@ export default class VisualKeyboard extends EventEmitter implements Ke // Unset the width + height we used thus far; this method's consumer may choose to rescale // the returned element. If so, we don't want to use our outdated value by mistake. - kbdObj.setSize(); + delete kbdObj._width; + delete kbdObj._height; return classWrapper; } From ab3722ecfaf2f804a53679315891187bb05feab8 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 20 Aug 2024 15:10:14 +0200 Subject: [PATCH 57/65] fix(core): look for `emcc` instead of `emcc.py` on Linux and Mac `emcc.py` is not marked as executable in emcripten's git repo so the build failed when trying to locate emscripten. However, it turns out that `emcc` is marked as executable, so we use that instead. On Windows however, we still need to use `emcc.py` because otherwise Meson won't detect it as valid compiler. --- core/wasm.build.linux.in | 6 ++--- core/wasm.build.mac.in | 6 ++--- core/wasm.defs.build | 6 ++--- developer/src/kmcmplib/wasm.build.linux.in | 6 ++--- developer/src/kmcmplib/wasm.build.mac.in | 6 ++--- resources/locate_emscripten.inc.sh | 30 +++++++++++++--------- 6 files changed, 33 insertions(+), 27 deletions(-) diff --git a/core/wasm.build.linux.in b/core/wasm.build.linux.in index d449dcf94a0..27cb7ba68fe 100644 --- a/core/wasm.build.linux.in +++ b/core/wasm.build.linux.in @@ -1,4 +1,4 @@ [binaries] -c = ['$EMSCRIPTEN_BASE/emcc.py'] -cpp = ['$EMSCRIPTEN_BASE/em++.py'] -ar = ['$EMSCRIPTEN_BASE/emar.py'] \ No newline at end of file +c = ['$EMSCRIPTEN_BASE/emcc'] +cpp = ['$EMSCRIPTEN_BASE/em++'] +ar = ['$EMSCRIPTEN_BASE/emar'] diff --git a/core/wasm.build.mac.in b/core/wasm.build.mac.in index d449dcf94a0..27cb7ba68fe 100644 --- a/core/wasm.build.mac.in +++ b/core/wasm.build.mac.in @@ -1,4 +1,4 @@ [binaries] -c = ['$EMSCRIPTEN_BASE/emcc.py'] -cpp = ['$EMSCRIPTEN_BASE/em++.py'] -ar = ['$EMSCRIPTEN_BASE/emar.py'] \ No newline at end of file +c = ['$EMSCRIPTEN_BASE/emcc'] +cpp = ['$EMSCRIPTEN_BASE/em++'] +ar = ['$EMSCRIPTEN_BASE/emar'] diff --git a/core/wasm.defs.build b/core/wasm.defs.build index 4a598a1e1c1..f41af337a38 100644 --- a/core/wasm.defs.build +++ b/core/wasm.defs.build @@ -1,7 +1,7 @@ [binaries] -c = ['emcc.py'] -cpp = ['em++.py'] -ar = ['emar.py'] +c = ['emcc'] +cpp = ['em++'] +ar = ['emar'] exe_wrapper = 'node' [properties] diff --git a/developer/src/kmcmplib/wasm.build.linux.in b/developer/src/kmcmplib/wasm.build.linux.in index c5e61a9bda9..27cb7ba68fe 100644 --- a/developer/src/kmcmplib/wasm.build.linux.in +++ b/developer/src/kmcmplib/wasm.build.linux.in @@ -1,4 +1,4 @@ [binaries] -c = ['$EMSCRIPTEN_BASE/emcc.py'] -cpp = ['$EMSCRIPTEN_BASE/em++.py'] -ar = ['$EMSCRIPTEN_BASE/emar.py'] +c = ['$EMSCRIPTEN_BASE/emcc'] +cpp = ['$EMSCRIPTEN_BASE/em++'] +ar = ['$EMSCRIPTEN_BASE/emar'] diff --git a/developer/src/kmcmplib/wasm.build.mac.in b/developer/src/kmcmplib/wasm.build.mac.in index c5e61a9bda9..27cb7ba68fe 100644 --- a/developer/src/kmcmplib/wasm.build.mac.in +++ b/developer/src/kmcmplib/wasm.build.mac.in @@ -1,4 +1,4 @@ [binaries] -c = ['$EMSCRIPTEN_BASE/emcc.py'] -cpp = ['$EMSCRIPTEN_BASE/em++.py'] -ar = ['$EMSCRIPTEN_BASE/emar.py'] +c = ['$EMSCRIPTEN_BASE/emcc'] +cpp = ['$EMSCRIPTEN_BASE/em++'] +ar = ['$EMSCRIPTEN_BASE/emar'] diff --git a/resources/locate_emscripten.inc.sh b/resources/locate_emscripten.inc.sh index be66adfa32f..20923770e2a 100644 --- a/resources/locate_emscripten.inc.sh +++ b/resources/locate_emscripten.inc.sh @@ -2,30 +2,36 @@ # no hashbang for .inc.sh # -# We don't want to rely on emcc.py being on the path, because Emscripten puts far +# We don't want to rely on emcc being on the path, because Emscripten puts far # too many things onto the path (in particular for us, node). # -# The following comment suggests that we don't need emcc.py on the path. +# The following comment suggests that we don't need emcc on the path. # https://github.com/emscripten-core/emscripten/issues/4848#issuecomment-1097357775 # -# So we try and locate emcc.py in common locations ourselves. The search pattern +# So we try and locate emcc in common locations ourselves. The search pattern # is: # # 1. Look for $EMSCRIPTEN_BASE (our primary emscripten variable), which should -# point to the folder that emcc.py is located in -# 2. Look for $EMCC which should point to the emcc.py executable -# 3. Look for emcc.py on the path +# point to the folder that emcc is located in +# 2. Look for $EMCC which should point to the emcc executable +# 3. Look for emcc on the path # locate_emscripten() { + local EMCC_EXECUTABLE + if [[ "${BUILDER_OS}" == "win" ]]; then + EMCC_EXECUTABLE="emcc.py" + else + EMCC_EXECUTABLE="emcc" + fi if [[ -z ${EMSCRIPTEN_BASE+x} ]]; then if [[ -z ${EMCC+x} ]]; then - local EMCC=`which emcc.py` - [[ -z $EMCC ]] && builder_die "locate_emscripten: Could not locate emscripten (emcc.py) on the path or with \$EMCC or \$EMSCRIPTEN_BASE" + local EMCC=$(which ${EMCC_EXECUTABLE}) + [[ -z $EMCC ]] && builder_die "locate_emscripten: Could not locate emscripten (${EMCC_EXECUTABLE}) on the path or with \$EMCC or \$EMSCRIPTEN_BASE" fi - [[ -f $EMCC && ! -x $EMCC ]] && builder_die "locate_emscripten: Variable EMCC ($EMCC) points to emcc.py but it is not executable" - [[ -x $EMCC ]] || builder_die "locate_emscripten: Variable EMCC ($EMCC) does not point to a valid executable emcc.py" + [[ -f $EMCC && ! -x $EMCC ]] && builder_die "locate_emscripten: Variable EMCC ($EMCC) points to ${EMCC_EXECUTABLE} but it is not executable" + [[ -x $EMCC ]] || builder_die "locate_emscripten: Variable EMCC ($EMCC) does not point to a valid executable ${EMCC_EXECUTABLE}" EMSCRIPTEN_BASE="$(dirname "$EMCC")" fi - [[ -f ${EMSCRIPTEN_BASE}/emcc.py && ! -x ${EMSCRIPTEN_BASE}/emcc.py ]] && builder_die "locate_emscripten: Variable EMSCRIPTEN_BASE ($EMSCRIPTEN_BASE) contains emcc.py but it is not executable" - [[ -x ${EMSCRIPTEN_BASE}/emcc.py ]] || builder_die "locate_emscripten: Variable EMSCRIPTEN_BASE ($EMSCRIPTEN_BASE) does not point to emcc.py's folder" + [[ -f ${EMSCRIPTEN_BASE}/${EMCC_EXECUTABLE} && ! -x ${EMSCRIPTEN_BASE}/${EMCC_EXECUTABLE} ]] && builder_die "locate_emscripten: Variable EMSCRIPTEN_BASE ($EMSCRIPTEN_BASE) contains ${EMCC_EXECUTABLE} but it is not executable" + [[ -x ${EMSCRIPTEN_BASE}/${EMCC_EXECUTABLE} ]] || builder_die "locate_emscripten: Variable EMSCRIPTEN_BASE ($EMSCRIPTEN_BASE) does not point to ${EMCC_EXECUTABLE}'s folder" } From 36b2a98e20eb5e27aa525143e5c111b3607fd8f1 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Tue, 20 Aug 2024 21:01:53 +0700 Subject: [PATCH 58/65] Update android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java Co-authored-by: Marc Durdin --- .../tavultesoft/kmapro/AdjustLongpressDelayActivity.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java index 590bbdc2673..e45d2a2fb22 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/AdjustLongpressDelayActivity.java @@ -1,5 +1,7 @@ -/** - * Copyright (C) SIL International. All rights reserved. +/* + * Keyman is copyright (C) SIL International. MIT License. + * + * (Optional description of this file) */ package com.tavultesoft.kmapro; From ac87fc483e3a5ff256ae6950465b3892cc1a7b77 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Tue, 20 Aug 2024 14:03:19 -0400 Subject: [PATCH 59/65] auto: increment master version to 18.0.94 --- HISTORY.md | 8 ++++++++ VERSION.md | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 5d82f22e40a..0c527e2390e 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,13 @@ # Keyman Version History +## 18.0.93 alpha 2024-08-20 + +* (#12188) +* fix(web): fix malformed reversion display strings (#12201) +* feat(android): Add menu to specify long-press delay (#12170) +* feat(android): Pass longpress delay to KeymanWeb (#12185) +* (#12223) + ## 18.0.92 alpha 2024-08-19 * chore(deps-dev): bump @75lb/deep-merge from 1.1.1 to 1.1.2 (#12118) diff --git a/VERSION.md b/VERSION.md index f74f9c87c90..8f14bdc62b3 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -18.0.93 \ No newline at end of file +18.0.94 \ No newline at end of file From 45dee1c504afdd40f5df000b08d07f7a810acbb3 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Wed, 21 Aug 2024 09:05:48 +0700 Subject: [PATCH 60/65] docs(web): extends doc-comment per review comment --- web/src/engine/osk/src/visualKeyboard.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/web/src/engine/osk/src/visualKeyboard.ts b/web/src/engine/osk/src/visualKeyboard.ts index 0d529af651e..3a439c1db4e 100644 --- a/web/src/engine/osk/src/visualKeyboard.ts +++ b/web/src/engine/osk/src/visualKeyboard.ts @@ -1608,6 +1608,11 @@ export default class VisualKeyboard extends EventEmitter implements Ke // Unset the width + height we used thus far; this method's consumer may choose to rescale // the returned element. If so, we don't want to use our outdated value by mistake. + // + // While `kbdObj.setSize()` could be used in theory, it _also_ unsets the element styling. + // We actually wish to _leave_ this styling in place - one of our parameters is `height`, and + // it should remain in place in the styling on the output element as the default in case + // the consumer _doesn't_ add styling afterward. delete kbdObj._width; delete kbdObj._height; From 17f903d4c70efb164fa29534acc6766c74373de9 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 21 Aug 2024 15:08:51 +0700 Subject: [PATCH 61/65] fix(android): Fix navigation arrows in Info Activity for RTL --- .../src/main/res/layout/activity_info.xml | 52 +++++++++++-------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/android/KMAPro/kMAPro/src/main/res/layout/activity_info.xml b/android/KMAPro/kMAPro/src/main/res/layout/activity_info.xml index 3b71e871785..314a5034129 100644 --- a/android/KMAPro/kMAPro/src/main/res/layout/activity_info.xml +++ b/android/KMAPro/kMAPro/src/main/res/layout/activity_info.xml @@ -1,12 +1,12 @@ + xmlns:tools="http://schemas.android.com/tools" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:background="@color/ms_white" + tools:context=".InfoActivity" > - - + android:orientation="horizontal"> - + + + + + Date: Wed, 21 Aug 2024 14:24:10 +0200 Subject: [PATCH 62/65] chore(developer): enable build for emscripten 3.1.60+ Emscripten 3.1.60 made a breaking change to `BindingType::toWireType` (why is this done in a patch version?) so this change ensures that we can continue to build on 3.1.58 and 3.1.64 (which is needed for #12234), as a bridging strategy. We will need to merge this into 17.0-stable as well so that we can upgrade the build agents to 3.1.64. Relates-to: emscripten-core/emscripten#21692 Relates-to: #12234 --- developer/src/kmcmplib/src/CompilerInterfacesWasm.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/developer/src/kmcmplib/src/CompilerInterfacesWasm.cpp b/developer/src/kmcmplib/src/CompilerInterfacesWasm.cpp index a857b41dce4..1ddd45dd3f8 100644 --- a/developer/src/kmcmplib/src/CompilerInterfacesWasm.cpp +++ b/developer/src/kmcmplib/src/CompilerInterfacesWasm.cpp @@ -75,9 +75,16 @@ struct BindingType> { using ValBinding = BindingType; using WireType = ValBinding::WireType; +#if __EMSCRIPTEN_major__ == 3 && __EMSCRIPTEN_minor__ == 1 && __EMSCRIPTEN_tiny__ >= 60 + // emscripten-core/emscripten#21692 + static WireType toWireType(const std::vector &vec, rvp::default_tag) { + return ValBinding::toWireType(val::array(vec), rvp::default_tag{}); + } +#else static WireType toWireType(const std::vector &vec) { return ValBinding::toWireType(val::array(vec)); } +#endif static std::vector fromWireType(WireType value) { return vecFromJSArray(ValBinding::fromWireType(value)); From b0bd95d276eddae88b170671d8384af0418a04d3 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 21 Aug 2024 15:02:18 +0200 Subject: [PATCH 63/65] chore(common): allow build agents to automatically select emsdk version The build agents will now automatically install and activate the Emscripten version found in minimum-versions.inc.sh when configuring WASM projects. For developer machines, this behaviour can be enabled by setting the environment variable `KEYMAN_USE_EMSDK` (recommended). This will be back-ported to 17.0 so that we can ensure that all builds use a consistent Emscripten version. --- resources/build/minimum-versions.inc.sh | 3 +-- resources/locate_emscripten.inc.sh | 36 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/resources/build/minimum-versions.inc.sh b/resources/build/minimum-versions.inc.sh index c060d31c58f..97f25094067 100644 --- a/resources/build/minimum-versions.inc.sh +++ b/resources/build/minimum-versions.inc.sh @@ -20,8 +20,7 @@ KEYMAN_MIN_TARGET_VERSION_CHROME=95.0 # Final version that runs on Andro # Dependency versions KEYMAN_MIN_VERSION_NODE_MAJOR=20 # node version source of truth is /package.json:/engines/node KEYMAN_MIN_VERSION_NPM=10.5.1 # 10.5.0 has bug, discussed in #10350 -KEYMAN_MIN_VERSION_EMSCRIPTEN=3.1.44 # Warning: 3.1.45 is bad (#9529); newer versions work -KEYMAN_MAX_VERSION_EMSCRIPTEN=3.1.58 # See #9529 +KEYMAN_MIN_VERSION_EMSCRIPTEN=3.1.58 # Use KEYMAN_USE_EMSDK to automatically update to this version KEYMAN_MIN_VERSION_VISUAL_STUDIO=2019 KEYMAN_MIN_VERSION_MESON=1.0.0 diff --git a/resources/locate_emscripten.inc.sh b/resources/locate_emscripten.inc.sh index 20923770e2a..f678e8449e6 100644 --- a/resources/locate_emscripten.inc.sh +++ b/resources/locate_emscripten.inc.sh @@ -1,6 +1,8 @@ # shellcheck shell=bash # no hashbang for .inc.sh +. "$KEYMAN_ROOT/resources/build/minimum-versions.inc.sh" + # # We don't want to rely on emcc being on the path, because Emscripten puts far # too many things onto the path (in particular for us, node). @@ -34,4 +36,38 @@ locate_emscripten() { fi [[ -f ${EMSCRIPTEN_BASE}/${EMCC_EXECUTABLE} && ! -x ${EMSCRIPTEN_BASE}/${EMCC_EXECUTABLE} ]] && builder_die "locate_emscripten: Variable EMSCRIPTEN_BASE ($EMSCRIPTEN_BASE) contains ${EMCC_EXECUTABLE} but it is not executable" [[ -x ${EMSCRIPTEN_BASE}/${EMCC_EXECUTABLE} ]] || builder_die "locate_emscripten: Variable EMSCRIPTEN_BASE ($EMSCRIPTEN_BASE) does not point to ${EMCC_EXECUTABLE}'s folder" + + verify_emscripten_version +} + +# Ensure that we use correct version of emsdk on build agents. +# For developers, define KEYMAN_USE_SDK to do this on your +# build machine. +verify_emscripten_version() { + if [[ "$VERSION_ENVIRONMENT" != local || ! -z "${KEYMAN_USE_EMSDK+x}" ]]; then + _select_emscripten_version_with_emsdk + fi +} + +# Use emsdk to select the appropriate version of Emscripten +# according to minimum-versions.inc.sh +_select_emscripten_version_with_emsdk() { + if [[ -z "${EMSCRIPTEN_BASE+x}" ]]; then + builder_die "Variable EMSCRIPTEN_BASE must be set" + fi + + if [[ -z "${KEYMAN_MIN_VERSION_EMSCRIPTEN+x}" ]]; then + builder_die "Variable KEYMAN_MIN_VERSION_EMSCRIPTEN must be set" + fi + + pushd "${EMSCRIPTEN_BASE}/../.." > /dev/null + if [[ ! -f emsdk ]]; then + builder_die "emsdk[.bat] should be in $(pwd)" + fi + + export EMSDK_KEEP_DOWNLOADS=1 + git pull + ./emsdk install "$KEYMAN_MIN_VERSION_EMSCRIPTEN" + ./emsdk activate "$KEYMAN_MIN_VERSION_EMSCRIPTEN" + popd > /dev/null } From 98409dc81085f3799f35fcd2762a75eaf7fafc82 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Wed, 21 Aug 2024 14:04:21 -0400 Subject: [PATCH 64/65] auto: increment master version to 18.0.95 --- HISTORY.md | 10 ++++++++++ VERSION.md | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 0c527e2390e..7bb236717bb 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,15 @@ # Keyman Version History +## 18.0.94 alpha 2024-08-21 + +* fix(core): look for `emcc` instead of `emcc.py` (#12235) +* fix(web): improve tokenization output when wordbreaker breaks spec for span properties in output (#12229) +* chore(android): Use RTL-aware alignment and padding for layouts (#12225) +* fix(web): disable fat-finger data use when mayCorrect = false (#12220) +* fix(android): Auto-mirror back and forward arrows for RTL support (#12227) +* feat(android): Add localization for Arabic (#12228) +* fix(android): Auto-mirror increment and decrement arrows for RTL support (#12230) + ## 18.0.93 alpha 2024-08-20 * (#12188) diff --git a/VERSION.md b/VERSION.md index 8f14bdc62b3..a41e5425c0a 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -18.0.94 \ No newline at end of file +18.0.95 \ No newline at end of file From 5fb374341677db19b0b48c6503ef9cd4e050bb47 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Thu, 22 Aug 2024 14:02:35 -0400 Subject: [PATCH 65/65] auto: increment master version to 18.0.96 --- HISTORY.md | 4 ++++ VERSION.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 7bb236717bb..2ee27cd1989 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,9 @@ # Keyman Version History +## 18.0.95 alpha 2024-08-22 + +* chore(common): allow build agents to automatically select emsdk version, and enable support for 3.1.60+ (#12243) + ## 18.0.94 alpha 2024-08-21 * fix(core): look for `emcc` instead of `emcc.py` (#12235) diff --git a/VERSION.md b/VERSION.md index a41e5425c0a..998f9bf6fd3 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -18.0.95 \ No newline at end of file +18.0.96 \ No newline at end of file