diff --git a/HISTORY.md b/HISTORY.md
index 4183ecb614..33c89d3e26 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,5 +1,45 @@
# Keyman Version History
+## 19.0.34 alpha 2025-05-08
+
+* docs(common): update `builder_echo` documentation for TC blocks (#13855)
+* fix(windows): add breadcrumb to download failures (#13826)
+* fix(web): sustain active batched-layout mode when keyboard is switched (#13860)
+* maint(common): remove obsolete code from docker-images `build.sh` (#13861)
+* maint(common): output start/end messages if not running on TC (#13868)
+
+## 19.0.33 alpha 2025-05-07
+
+* maint(common): automatically set --debug option for local-environment builder-script uses (#13827)
+* docs(web): add a Web engine keystroke lifecycle internal doc (#13759)
+* maint(common): use function to detect if running on TC (#13844)
+* docs(common): document new `builder_is_running_on_teamcity` function (#13852)
+
+## 19.0.32 alpha 2025-05-06
+
+* change(web): replace USVString with string in predictive-text engine (#13785)
+* chore(web): replace --ci flag with builder_is_ci_build (#13819)
+* maint(web): simplify worker-main test.sh (#13820)
+* change(web): lint kmwstring web-utility (#13800)
+* fix(web): fix extraction of gesture-engine fixture used in DOM-based unit tests (#13805)
+* fix(web): add robustness for bad touch-layout fontsize specs (#13774)
+* fix(web): fix var declaration affected by linter strictness + length-style fix (#13839)
+* chore(ios): Update inuktitut_pirurvik to 1.4.1 (#13840)
+* chore(common): override check when running on TC (#13779)
+* change(linux): add ICU dependency needed to build on Arch Linux (#13842)
+* maint(common): add support for TC blocks (#13810)
+
+## 19.0.31 alpha 2025-05-05
+
+* fix(mac): add version metadata after building tests (#13818)
+* maint(common): remove `eslint:recommended` configuration for .ts (#13825)
+* maint(common): Update write_download_info() to be cross-platform (#13813)
+* change(ios): limit reports about devices without predefined scaling entries (#13806)
+* change(web): lint engine/common/web-utils (#13797)
+* chore(web): replace kmwFromCharCode with its ES6 equivalent (#13716)
+* chore(web): add unit tests for SMP-aware string-handling helper methods (#13719)
+* refactor(web): refactor string-helper library to eliminate its module side-effect (#13726)
+
## 19.0.30 alpha 2025-05-02
* chore(android): Use `builder_is_ci_build` rather than `--ci` flag (#13772)
diff --git a/VERSION.md b/VERSION.md
index f472c402af..d8676f6b6a 100644
--- a/VERSION.md
+++ b/VERSION.md
@@ -1 +1 @@
-19.0.31
\ No newline at end of file
+19.0.35
\ No newline at end of file
diff --git a/common/web/types/build.sh b/common/web/types/build.sh
index a392ec022c..5a9243e6cd 100755
--- a/common/web/types/build.sh
+++ b/common/web/types/build.sh
@@ -82,7 +82,7 @@ function do_configure() {
function do_test() {
local MOCHA_FLAGS=
- if [[ "${TEAMCITY_GIT_PATH:-}" != "" ]]; then
+ if builder_is_running_on_teamcity; then
# we're running in TeamCity
MOCHA_FLAGS="-reporter mocha-teamcity-reporter"
fi
diff --git a/common/web/types/src/lexical-model-types.ts b/common/web/types/src/lexical-model-types.ts
index 7c5cfdf643..e2670d2e21 100644
--- a/common/web/types/src/lexical-model-types.ts
+++ b/common/web/types/src/lexical-model-types.ts
@@ -5,18 +5,6 @@
/****************************** Lexical Models ******************************/
-/**
- * A JavaScript string with the restriction that it must only
- * contain Unicode scalar values.
- *
- * This means that any lone high surrogate must be paired with
- * a low surrogate, if it exists. Lone surrogate code units are
- * forbidden.
- *
- * See also: https://developer.mozilla.org/en-US/docs/Web/API/USVString
- */
-export type USVString = string;
-
export type CasingForm = 'lower' | 'initial' | 'upper';
/**
@@ -67,7 +55,7 @@ export interface LexiconTraversal {
* - If `char` = 'e', the child represents a prefix of 'the'.
* - Then `traversal` allows traversing the part of the lexicon prefixed by 'the'.
*/
- children(): Generator<{char: USVString, traversal: () => LexiconTraversal}>;
+ children(): Generator<{char: string, traversal: () => LexiconTraversal}>;
/**
* Allows direct access to the traversal state that results when appending one
@@ -81,7 +69,7 @@ export interface LexiconTraversal {
* That is, if a model "keys" `è` to `e`, there will be no `è` child.
* @param char
*/
- child(char: USVString): LexiconTraversal | undefined;
+ child(char: string): LexiconTraversal | undefined;
/**
* Any entries directly keyed by the currently-represented lookup prefix. Entries and
@@ -178,7 +166,7 @@ export interface LexicalModel {
* @param text The original input text.
* @returns The 'keyed' form of that text.
*/
- toKey?(text: USVString): USVString;
+ toKey?(text: string): string;
/**
* Generates predictive suggestions corresponding to the state of context after the proposed
@@ -248,7 +236,7 @@ export interface LexicalModel {
* @param context
* @deprecated
*/
- wordbreak?(context: Context): USVString;
+ wordbreak?(context: Context): string;
/**
* Lexical models _may_ provide a LexiconTraversal object usable to enhance
@@ -279,7 +267,7 @@ export interface Transform {
*
* Corresponds to `s` in com.keyman.KeyboardInterface.output.
*/
- insert: USVString;
+ insert: string;
/**
* The number of code units to delete to the left of the cursor.
@@ -380,7 +368,7 @@ export interface Context {
* buffer. If there is nothing to the left of the buffer, this is
* an empty string.
*/
- readonly left: USVString;
+ readonly left: string;
/**
* Up to maxRightContextCodeUnits code units of Unicode scalar value
@@ -390,7 +378,7 @@ export interface Context {
*
* This property may be missing entirely.
*/
- readonly right?: USVString;
+ readonly right?: string;
/**
* Whether the insertion point is at the start of the buffer.
diff --git a/common/web/types/tests/lexical-model-types.tests.ts b/common/web/types/tests/lexical-model-types.tests.ts
index ef8bed28a5..3075582a39 100644
--- a/common/web/types/tests/lexical-model-types.tests.ts
+++ b/common/web/types/tests/lexical-model-types.tests.ts
@@ -7,7 +7,7 @@
import { KMXPlus, LdmlKeyboardTypes, LexicalModelTypes } from "@keymanapp/common-types";
-export let u: LexicalModelTypes.USVString;
+export let u: string;
export let l: LexicalModelTypes.Transform;
export let s: LexicalModelTypes.Suggestion;
export let st: LexicalModelTypes.SuggestionTag;
diff --git a/common/windows/delphi/general/DUnitX.Loggers.TeamCity.pas b/common/windows/delphi/general/DUnitX.Loggers.TeamCity.pas
index 1277d8436c..a8cec8047d 100644
--- a/common/windows/delphi/general/DUnitX.Loggers.TeamCity.pas
+++ b/common/windows/delphi/general/DUnitX.Loggers.TeamCity.pas
@@ -14,7 +14,7 @@ var
KeymanRoot: string;
ReportPath: string;
begin
- if GetEnvironmentVariable('TEAMCITY_VERSION') <> '' then
+ if GetEnvironmentVariable('TEAMCITY_GIT_PATH') <> '' then
begin
KeymanRoot := ExcludeTrailingPathDelimiter(GetEnvironmentVariable('KEYMAN_ROOT'));
ReportPath := ExtractRelativePath(KeymanRoot, ExtractFilePath(ParamStr(0)) + 'dunitx-results.xml');
diff --git a/docs/builder.md b/docs/builder.md
index 1e097fcc17..6c3ffd7c3e 100644
--- a/docs/builder.md
+++ b/docs/builder.md
@@ -634,6 +634,10 @@ Wraps the `echo` command with color and a script identifier prefix.
```bash
builder_echo [mode] message
+or
+builder_echo start blockname message
+or
+builder_echo end blockname status message
```
### Parameters
@@ -647,6 +651,12 @@ mode will be `white`.
* `warning`: A warning message, represented with yellow text
* `error`: An error message, represented with red text (consider [`builder_die`])
* `debug`: A debug string, represented with teal text (consider [`builder_echo_debug`])
+ * `start`: The beginning of a foldable block when running on TeamCity. The
+ blockname will show up as the title of the collapsable block,
+ the message as heading inside of the block. If not running on TeamCity
+ the message is output as heading.
+ * `end`: The end of the foldable block `blockname` when running on TeamCity.
+ Ignored if not running on TeamCity identical to `builder_echo status message`.
Or color identifiers:
* `white`: Normal white text, the default if **mode** is omitted
@@ -666,6 +676,9 @@ mode will be `white`.
* `setmark`: A marker for a section heading, represented with purple text
* **message**: a string (surround with quote marks)
+* **blockname**: a string with the name of the collapsable block (surround with quote marks)
+* **status**: one of the `mode` values representing the result of an action
+ (`success`, `warning`, or `error`)
### Description
@@ -867,6 +880,21 @@ fi
--------------------------------------------------------------------------------
+## `builder_is_running_on_teamcity` function
+
+Returns `true` (aka 0) if the script runs on TeamCity (i.e. if the
+`TEAMCITY_GIT_PATH` environment variable is set).
+
+### Usage
+
+```bash
+if builder_is_running_on_teamcity; then
+ ...
+fi
+```
+
+--------------------------------------------------------------------------------
+
## `builder_parse` function
Initializes a build.sh script, parses command line. Will abort the script if
diff --git a/linux/ibus-keyman/meson.build b/linux/ibus-keyman/meson.build
index 401da66004..710bcd1dac 100644
--- a/linux/ibus-keyman/meson.build
+++ b/linux/ibus-keyman/meson.build
@@ -18,7 +18,7 @@ conf = configuration_data()
ibus = dependency('ibus-1.0', version: '>= 1.2.0')
gtk = dependency('gtk+-3.0', version: '>= 2.4')
json_glib = dependency('json-glib-1.0', version: '>= 1.0')
-icu = dependency('icu-i18n')
+icu = [dependency('icu-i18n'), dependency('icu-uc')]
systemd = dependency('libsystemd', 'libelogind', required: false)
if systemd.found()
diff --git a/linux/keyman-config/run-tests.sh b/linux/keyman-config/run-tests.sh
index 41904e4cf3..3fa49f081d 100755
--- a/linux/keyman-config/run-tests.sh
+++ b/linux/keyman-config/run-tests.sh
@@ -12,9 +12,22 @@ if [[ "$1" == "--coverage" ]]; then
coverage="-m coverage run --source=. --data-file=build/.coverage"
fi
-if [[ -n "${TEAMCITY_VERSION}" ]]; then
+if [[ -n "${TEAMCITY_GIT_PATH}" ]]; then
if ! pip3 list --format=columns | grep -q teamcity-messages; then
- pip3 install teamcity-messages
+ if [[ -n "${TEAMCITY_PLATFORM}" ]] || [[ -n "${DOCKER_RUNNING}" ]]; then
+ # Ubuntu 24.04+ prevents mixing pip and system packages and wants us
+ # to use a virtualenv. However, that causes other problems, so we
+ # override this check only if we're running in a TC agent or docker
+ # so that we don't accidentally break the local system.
+ # Note: it is intentional that we use TEAMCITY_GIT_PATH as well
+ # as TEAMCITY_PLATFORM here so that it is possible to simulate
+ # running in a TC agent and still not break your local system
+ # (run in a docker container or explicitly set TEAMCITY_PLATFORM
+ # to cause the script to install the package).
+ PIP_ARGS="--break-system-packages"
+ fi
+ # shellcheck disable=SC2086
+ pip3 install --user ${PIP_ARGS:-} teamcity-messages
fi
test_module=teamcity.unittestpy
else
diff --git a/oem/firstvoices/keyboards.csv b/oem/firstvoices/keyboards.csv
index ed13eb5aaa..5628d4f9b1 100644
--- a/oem/firstvoices/keyboards.csv
+++ b/oem/firstvoices/keyboards.csv
@@ -1,6 +1,6 @@
Shortname,ID,Name,Region,9.0 Web Keyboard,Version,Language ID,Language Name
fv,fv_inuvialuktun,Inuvialuktun,Arctic,fv_inuvialuktun_kmw-9.0.js,9.1.1,ikt-Latn,Inuinnaqtun (Latin)
-i,inuktitut_pirurvik,Kiputtijjut | ᑭᐳᑦᑎᔾᔪᑦ,Arctic,inuktitut_pirurvik-1.1.js,1.4,ike-Cans,Eastern Canadian Inuktitut (Unified Canadian Aboriginal Syllabics)
+i,inuktitut_pirurvik,Kiputtijjut | ᑭᐳᑦᑎᔾᔪᑦ,Arctic,inuktitut_pirurvik-1.1.js,1.4.1,ike-Cans,Eastern Canadian Inuktitut (Unified Canadian Aboriginal Syllabics)
i,inuktitut_latin,Qaliujaaqpait | ᖃᓕᐅᔮᖅᐸᐃᑦ,Arctic,inuktitut_latin-1.1.js,1.4,ike-Latn,Eastern Canadian Inuktitut (Latin)
i,inuktitut_naqittaut,Qaniujaaqpait | ᖃᓂᐅᔮᖅᐸᐃᑦ,Arctic,inuktitut_naqittaut-1.3.js,1.6,ike-Cans,Eastern Canadian Inuktitut (Unified Canadian Aboriginal Syllabics)
fv,fv_uummarmiutun,Uummarmiutun,Arctic,fv_uummarmiutun_kmw-9.0.js,9.1.1,ikt-Latn,Inuinnaqtun (Latin)
diff --git a/resources/build/README.md b/resources/build/README.md
index ead7975b8b..79e953a066 100644
--- a/resources/build/README.md
+++ b/resources/build/README.md
@@ -16,9 +16,9 @@ including this file...
See [build-utils.md](build-utils.md)
-### jq-win64
+### jq/jq-win64
-jq-win64.exe is used by various builds for json query.
+jq resp. jq-win64.exe is used by various builds for json query.
Official source:
predictions (async)
+ Note over User, Predictive-text engine: After async delay
+ Predictive-text engine --)- User: Return new predictions, update banner
+end
+```
+
+## Keystroke pre-processing
+
+Both the `app/browser` and `app/webview` products are capable of handling
+keystrokes from the on-screen keyboard as well as hardware keystrokes. For
+hardware keystrokes, this varies between the two, while the majority of
+on-screen keyboard keystrokes are handled identically.
+
+### `app/browser` - hardware keystrokes
+
+The `app/browser` version of the engine is designed to integrate with the active
+page of the user's browser. As a result of this, contexts for text manipulation
+are directly implemented within Web elements that the engine has direct access
+to. It can thus attach DOM event handlers (for
+[`keydown`](https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event),
+[`keyup`](https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event),
+and
+[`keypress`](https://developer.mozilla.org/en-US/docs/Web/API/Element/keypress_event))
+in order to process hardware keystrokes. Its `HardwareEventKeyboard` class is
+the primary module for handling hardware keystrokes - it establishes the needed
+engine event hooks and methods used to fully handle and preprocess their
+keystroke data for further use later in the keystroke lifecycle.
+
+The bulk of DOM key events trigger keystroke processing on key-down, though modifier keys also receive key-up handling. Key-press events are handled selectively for held backspaces and possibly certain keystrokes for mnemonic keyboards. In all cases, DOM keyboard event objects are preprocessed by the centralized `preprocessKeyboardEvent` method, which converts the DOM event [`KeyboardEvent`](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent) format into the Web engine's `KeyEvent` format, which is the form required by the keyboard rules within compiled JS keyboards. This includes mnemonic keystroke preprocessing and remapping in addition to AltGr emulation.
+
+### `app/webview` - hardware keystrokes
+
+The `app/webview` version of the engine, which is designed to be used while embedded in a platform-specific host app, does not have direct access to standard hardware keystroke events, as those are handled by the host app's OS and by native code handlers run outside the host app's WebView containing the app/webview Web engine. It is the responsibility of the host app to handle hardware keystroke events and preprocess them on behalf of the Web engine, then forward them to the Web engine via JS call into the WebView. The `PassthroughKeyboard` class within `app/webview` space provides the method `raiseKeyEvent` as an internal API for this purpose, which converts the mobile-app format for hardware keystroke into the internal `KeyEvent` format. `raiseKeyEvent` also handles mnemonic keystroke processing and remapping.
+
+Also note that this variant does not model the user's text context with Web elements - it is entirely managed through the `Mock` type.
+
+### On-screen keyboard
+
+For both `app/browser` and `app/webview`, the on-screen keyboard delegates mouse
+and touch processing to [our internal gesture engine](./gestures/index.md) for
+most keyboards. (Keyboards that instead display "help pages", such as
+`sil_euro_latin` on desktop, have specialized handling.) The gesture engine is
+responsible for interpreting all DOM mouse and touch events for OSKs based on
+the touch-layout format, which are managed by the `VisualKeyboard` class. The
+gesture engine will raise events about the gesture lifecycle that, when
+appropriate, will emit `KeyElement` instances - elements of the constructed OSK
+corresponding to elements of the OSK directly representing keyboard keys.
+
+OSK keystroke preprocessing operates a little differently from hardware
+keystrokes. The `ActiveLayout` object for the current form-factor of the
+`Keyboard` maintains a "base" `KeyEvent` object, per key, that is
+lazy-constructed (by the `.baseKeyEvent` property) when first needed - the meat
+of which is performed by the `ActiveKeyBase.constructBaseKeyEvent` method. This
+is only evaluated up to once per key per activation of the keyboard. As
+keystrokes are received during OSK use, `VisualKeyboard.keyEventFromSpec` calls
+the `Keyboard.constructKeyEvent` method to clone that base `KeyEvent` object for
+the incoming keystroke and then adjust it to match current modifier and
+state-key settings.
+
+### Passing `KeyEvent` on for processing
+
+Regardless of the path taken to generate the `KeyEvent` object, _all_ keystroke
+handling modules of Keyman Engine for Web then raise that `KeyEvent` object via
+their `keyevent` event as specified by the `KeyEventSourceInterface` type. This
+event also permits a callback that is used by the final phase of the lifecycle -
+keystroke resolution - as needed. The main `KeymanEngine` base class listens
+for these events and forwards them for next phase of the lifecycle - keystroke
+processing - to the `InputProcessor` module, which passes control to whichever
+`KeystrokeProcessor` type is active for the keyboard when appropriate.
+
+## Keystroke processing
+
+Once the `KeyEvent` object for a keystroke has been passed into the
+`InputProcessor` module and its `processKeyEvent` method, the
+keystroke-processing stage has been reached. There are a number of subprocesses
+that trigger here in sequence - keystrokes don't go _straight_ to evaluation
+against keyboard rules.
+
+### Pre-keystroke state management
+
+First, the engine checks the keyboard associated with the `KeyEvent`, ensuring
+that it is still in place. (See [#7543](https://github.com/keymanapp/keyman/issues/7543) for more details.) With that assertion
+in place, it then performs a check needed to support multitaps - it checks to
+see if the key event has an associated "base context" and reverts the current
+context to match it if so. Once those checks are fulfilled, the engine then
+checks to see if the key event corresponds to a pure layer-switching or
+modifier/state-key interaction. If those are detected, rule-evaluation is
+bypassed.
+
+On a similar note, backspace and spacebar keystrokes receive special handling
+next in associated with predictive-text functionality. When autocorrect is
+enabled, the spacebar in particular can be used to accept the current suggestion
+instead of acting as whitespace; if this is triggered, its `KeyEvent` will be
+swallowed - no rule processing will occur for the it. The backspace may trigger
+display of a "reversion" suggestion when applicable but will not be swallowed.
+
+Once this phase is reached, the engine will then snapshot the current state of
+the context, then trigger standard rule processing against the original context
+by calling the current `KeyboardProcessor`'s `processKeystroke` method. Any
+operations against the context will be persisted and take full effect; DOM input
+elements (for `app/browser`) are updated during rule evaluation.
+
+### Determining direct keystroke effects
+
+The `KeyboardProcessor` classes, which each embody how one keyboard
+specification pattern interprets keystrokes, are responsible for determining the
+effects that should arise when evaluating the incoming keystroke with the
+current context state. While the exact mechanisms of this may vary depending
+upon the type of keyboard - be it JS, KMX, or KMX+ (LDML), the role is the same
+- interpreting the keystroke in context.
+
+### JS keyboards
+
+Before proceeding further, `KeyboardProcessor` does a context check to see
+whether or not the context contains anything considered deletable - in the case
+of a BKSP, we need to ensure that the keystroke passes through to the engine's
+host cleanly, as it may have special implications for the site or host app.
+
+With that out of the way, the JS keyboard's main group is then provided with the
+`KeyEvent` object in order to evaluate the keyboard's rules against the
+keystroke. This involves constructing a `RuleBehavior` object to track any and
+all needed side-effects for the keystroke. Such changes are generally not
+applied to the engine at large at this time in order to prevent unwanted side
+effects that may arise to and from predictive text operations that follow
+shortly afterward.
+
+The `KeyboardInterface` class defines the internal API used by keyboards for
+their evaluation of keyboard rules.
+
+Once the keyboard's script returns control to the main engine, the engine then
+determines the net effects to the context that resulted from applying the
+keyboard rule and preserves that as a `Transcription`, part of includes a
+`Transform` that most directly represents the changes to text surrounding the
+text insertion point.
+
+For JS keyboards, if no keyboard rule is defined for a non-frame key on the
+`default` or `shift` layer, there is an additional set of implied "default"
+keyboard rules that is applied. (A keyboard's source must _explicitly_ specify
+to not emit anything for such keys if such an outcome is desired.) This occurs
+regardless of the keystroke's source, as such effects are necessary to
+incorporate for predictive-text operations. If no such rule exists, the
+processor will add a note to the `RuleBehavior` object that default processing
+could not be provided and is thus needed from the engine's host.
+
+### KMX keyboards & KMX+ (LDML) keyboards
+
+For KMX and KMX+ keyboards, keystrokes are evaluated by using the embedded WASM
+version of Keyman Core.
+
+TODO: add link to specific mechanisms here once available.
+
+### "Alternate" processing (predictive-text)
+
+Once the incoming `KeyEvent` has been processed, if predictive-text is active
+and the `KeyEvent` includes fat-finger oriented data, the engine will then build
+a set of "alternates" - of "phantom" keystrokes - and process _them_ against
+headless clones of the original context in the same manner as the original
+keystroke.
+
+Once all relevant "alternates" have been evaluated, the engine will then signal
+the predictive-text engine with all relevant data, including the original,
+snapshotted state of the context. It does not actually trigger predictive-text
+at this time; processing of alternates is done before keystroke post-processing
+in order to avoid cross-effects from JS-keyboard variable store manipulations
+and similar mechanisms. Fat-finger "alternate" `KeyEvent`s are evaluated as if
+they occurred under the exact same conditions as the keystroke that was actually
+detected.
+
+### Keystroke post-processing
+
+At this stage, the side-effects desired for the original keystroke, as saved to
+its `RuleBehavior`, are then applied. Note that this includes changes to the
+`&layer` store - this update will also trigger an event that updates the state
+of the OSK to match the desired layer.
+
+Once that is done, the engine will then save data relevant to the original
+context state, the `KeyEvent`, and the `RuleBehavior` to the "context cache"
+supporting multitap context reversion. These effects include layer-change
+effects that result from JS keyboard rules, which modify the KMN-style keyboard
+stores `&oldlayer` and `&newlayer` in preparation for `begin PostKeystroke`
+group processing, which is then executed (and which can trigger another `&layer`
+& OSK-layer update).
+
+Once post-keystroke effects have been determined, the engine then signals
+predictive-text to generate new predictions associated with the keystroke. For
+`app/browser` variants of the engine, changes to the context will then also
+trigger the DOM `input` event on the context's element in case third parties
+wish to leverage such events for their website's pages.
+
+### Keystroke resolution
+
+At this stage, `InputProcessor` passes control back to the main `KeymanEngine`
+module, which then triggers the "on rule finalization" setting if configured.
+This setting is mostly used for page-integration within `app/browser`,
+supporting DOM element `change` event emulation whenever focus shifts away from
+the active context element.
+
+For OSK keystrokes, an identifier associated with the `KeyEvent`'s context
+snapshot will be made accessible through the `keyevent` event's callback
+parameter - a feature utilized by multitap gesture support.
+
+For hardware-keyboard keystrokes, the `keyevent` callback is used to determine
+whether or not native handling for the keystroke should be triggered - such as
+for TAB and ENTER keys, which may have semantic command-like functionality
+depending on the state of the Web engine's host - be that a web page or an
+Android/iOS app utilizing the keyboard. ENTER keys are often used to submit
+forms, and this helps ensure we trigger such functionality when appropriate.
\ No newline at end of file
diff --git a/web/docs/internal/keystroke-processing.md b/web/docs/internal/keystroke-processing.md
index 4406b1dcab..8606d18cba 100644
--- a/web/docs/internal/keystroke-processing.md
+++ b/web/docs/internal/keystroke-processing.md
@@ -1,6 +1,6 @@
# Keystroke Processing
-In addition to handling keystroke events produced from hardware keyboards, Keyman Engine for Web manages an on-screen keyboard that can also be used to generate such events. This document will enumerate the various components of data management and control flow used to handle and process keystrokes.
+In addition to handling keystroke events produced from hardware keyboards, Keyman Engine for Web manages an on-screen keyboard that can also be used to generate such events. This document will enumerate the various components of data management and control flow used to handle and process keystrokes. For a more thorough examination of the keystroke lifecycle, see the [keystroke-lifecycle](./keystroke-lifecycle.md) page.
## Input: KeyEvent - the pre-processed keystroke
diff --git a/web/src/app/browser/build.sh b/web/src/app/browser/build.sh
index d4c1023314..85c696ba4a 100755
--- a/web/src/app/browser/build.sh
+++ b/web/src/app/browser/build.sh
@@ -19,8 +19,7 @@ builder_describe "Builds the Keyman Engine for Web's website-integrating version
"clean" \
"configure" \
"build" \
- "test" \
- "--ci+ Set to utilize CI-based test configurations & reporting."
+ "test"
# Possible TODO?s
# "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \
diff --git a/web/src/app/ui/build.sh b/web/src/app/ui/build.sh
index a0ac5c4007..3a431f9a0a 100755
--- a/web/src/app/ui/build.sh
+++ b/web/src/app/ui/build.sh
@@ -18,8 +18,7 @@ builder_describe "Builds the Keyman Engine for Web's desktop form-factor keyboar
"clean" \
"configure" \
"build" \
- "test" \
- "--ci+ Set to utilize CI-based test configurations & reporting."
+ "test"
# Possible TODO?s
# "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \
diff --git a/web/src/app/webview/build.sh b/web/src/app/webview/build.sh
index 371c9325f2..1c2b2fe7dd 100755
--- a/web/src/app/webview/build.sh
+++ b/web/src/app/webview/build.sh
@@ -18,8 +18,7 @@ builder_describe "Builds the Keyman Engine for Web's puppetable version designed
"clean" \
"configure" \
"build" \
- "test" \
- "--ci+ Set to utilize CI-based test configurations & reporting."
+ "test"
# Possible TODO?s
# "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \
diff --git a/web/src/engine/attachment/build.sh b/web/src/engine/attachment/build.sh
index 32d781a5b0..497e65e9a1 100755
--- a/web/src/engine/attachment/build.sh
+++ b/web/src/engine/attachment/build.sh
@@ -19,8 +19,7 @@ builder_describe "Builds the Keyman Engine for Web (KMW) attachment engine." \
"clean" \
"configure" \
"build" \
- "test" \
- "--ci+ Set to utilize CI-based test configurations & reporting."
+ "test"
# Possible TODO?
# "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \
diff --git a/web/src/engine/common/web-utils/.eslintrc.cjs b/web/src/engine/common/web-utils/.eslintrc.cjs
deleted file mode 100644
index 30334ae3dc..0000000000
--- a/web/src/engine/common/web-utils/.eslintrc.cjs
+++ /dev/null
@@ -1,4 +0,0 @@
-module.exports = {
- // Temporarily ignored due to noise it would cause within the refactor
- ignorePatterns: ["**/kmwstring.ts"]
-};
diff --git a/web/src/engine/common/web-utils/build.sh b/web/src/engine/common/web-utils/build.sh
index b8e28eae1b..c487e22c91 100755
--- a/web/src/engine/common/web-utils/build.sh
+++ b/web/src/engine/common/web-utils/build.sh
@@ -22,8 +22,7 @@ builder_describe \
"Compiles the web-oriented utility function module." \
"@/common/web/keyman-version" \
"@/web/src/tools/es-bundling" \
- clean configure build test \
- "--ci For use with action ${BUILDER_TERM_START}test${BUILDER_TERM_END} - emits CI-friendly test reports"
+ clean configure build test
builder_describe_outputs \
configure "/node_modules" \
@@ -49,7 +48,7 @@ function do_test() {
builder_heading "Running web-utils test suite"
local FLAGS=
- if builder_has_option --ci; then
+ if builder_is_ci_build; then
echo "Replacing user-friendly test reports with CI-friendly versions."
FLAGS="$FLAGS --reporter mocha-teamcity-reporter"
fi
diff --git a/web/src/engine/common/web-utils/src/kmwstring.ts b/web/src/engine/common/web-utils/src/kmwstring.ts
index d901f4adf8..8d45e4ee11 100644
--- a/web/src/engine/common/web-utils/src/kmwstring.ts
+++ b/web/src/engine/common/web-utils/src/kmwstring.ts
@@ -55,9 +55,9 @@ export function charCodeAt(s: string, index: number) {
}
}
- let first = str.charCodeAt(codeUnitIndex);
+ const first = str.charCodeAt(codeUnitIndex);
if(first >= 0xD800 && first <= 0xDBFF && str.length > codeUnitIndex + 1) {
- let second = str.charCodeAt(codeUnitIndex + 1);
+ const second = str.charCodeAt(codeUnitIndex + 1);
if(second >= 0xDC00 && second <= 0xDFFF) {
return ((first - 0xD800) << 10) + (second - 0xDC00) + 0x10000;
}
@@ -248,7 +248,7 @@ export function substring(s: string, indexA: number, indexB?: number) {
indexBCodeUnit = str.length;
} else {
if(indexA > indexB) {
- let c = indexA;
+ const c = indexA;
indexA = indexB;
indexB = c;
}
diff --git a/web/src/engine/dom-utils/build.sh b/web/src/engine/dom-utils/build.sh
index f842655c45..10cf2b660c 100755
--- a/web/src/engine/dom-utils/build.sh
+++ b/web/src/engine/dom-utils/build.sh
@@ -20,8 +20,7 @@ builder_describe "Builds DOM-utility modules used by the Keyman Engine for Web (
"clean" \
"configure" \
"build" \
- "test" \
- "--ci+ Set to utilize CI-based test configurations & reporting."
+ "test"
# Possible TODO?
# "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \
diff --git a/web/src/engine/element-wrappers/build.sh b/web/src/engine/element-wrappers/build.sh
index e188c7dd41..aeee72241a 100755
--- a/web/src/engine/element-wrappers/build.sh
+++ b/web/src/engine/element-wrappers/build.sh
@@ -17,8 +17,7 @@ builder_describe "Builds DOM-based OutputTarget subclasses used by the Keyman En
"clean" \
"configure" \
"build" \
- "test" \
- "--ci+ Set to utilize CI-based test configurations & reporting."
+ "test"
# Possible TODO?
# "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \
diff --git a/web/src/engine/events/build.sh b/web/src/engine/events/build.sh
index 600ca8dc0c..e1f804908f 100755
--- a/web/src/engine/events/build.sh
+++ b/web/src/engine/events/build.sh
@@ -18,8 +18,7 @@ builder_describe "Builds specialized event-related modules utilized by Keyman En
"clean" \
"configure" \
"build" \
- "test" \
- "--ci+ Set to utilize CI-based test configurations & reporting."
+ "test"
# Possible TODO?
# "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \
diff --git a/web/src/engine/interfaces/build.sh b/web/src/engine/interfaces/build.sh
index 94bb267cbc..502e1f7172 100755
--- a/web/src/engine/interfaces/build.sh
+++ b/web/src/engine/interfaces/build.sh
@@ -19,8 +19,7 @@ builder_describe "Builds configuration subclasses used by the Keyman Engine for
"clean" \
"configure" \
"build" \
- "test" \
- "--ci+ Set to utilize CI-based test configurations & reporting."
+ "test"
# Possible TODO?s
# "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \
diff --git a/web/src/engine/js-processor/build.sh b/web/src/engine/js-processor/build.sh
index db00593166..620670276b 100755
--- a/web/src/engine/js-processor/build.sh
+++ b/web/src/engine/js-processor/build.sh
@@ -17,8 +17,7 @@ builder_describe "Builds configuration subclasses used by the Keyman Engine for
"clean" \
"configure" \
"build" \
- "test" \
- "--ci+ Set to utilize CI-based test configurations & reporting."
+ "test"
builder_describe_outputs \
configure "/node_modules" \
diff --git a/web/src/engine/keyboard-storage/build.sh b/web/src/engine/keyboard-storage/build.sh
index b7ffc4d6b3..86755c613a 100755
--- a/web/src/engine/keyboard-storage/build.sh
+++ b/web/src/engine/keyboard-storage/build.sh
@@ -17,8 +17,7 @@ builder_describe "Builds Keyman Engine modules for keyboard cloud-querying & cac
"clean" \
"configure" \
"build" \
- "test" \
- "--ci+ Set to utilize CI-based test configurations & reporting."
+ "test"
# Possible TODO?s
# "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \
diff --git a/web/src/engine/keyboard/build.sh b/web/src/engine/keyboard/build.sh
index fd15e59bc1..dc1283a7f2 100755
--- a/web/src/engine/keyboard/build.sh
+++ b/web/src/engine/keyboard/build.sh
@@ -25,8 +25,7 @@ builder_describe \
configure \
clean \
build \
- test \
- "--ci For use with action $(builder_term test) - emits CI-friendly test reports"
+ test
builder_describe_outputs \
configure /node_modules \
diff --git a/web/src/engine/main/build.sh b/web/src/engine/main/build.sh
index 8d6e39e0d2..a90e9f7660 100755
--- a/web/src/engine/main/build.sh
+++ b/web/src/engine/main/build.sh
@@ -24,8 +24,7 @@ builder_describe "Builds the Keyman Engine for Web's common top-level base class
"clean" \
"configure" \
"build" \
- "test" \
- "--ci+ Set to utilize CI-based test configurations & reporting."
+ "test"
# Possible TODO?s
# "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \
diff --git a/web/src/engine/osk/build.sh b/web/src/engine/osk/build.sh
index 74bd2c03cc..307d5b7a08 100755
--- a/web/src/engine/osk/build.sh
+++ b/web/src/engine/osk/build.sh
@@ -21,8 +21,7 @@ builder_describe "Builds the Keyman Engine for Web's On-Screen Keyboard package
"clean" \
"configure" \
"build" \
- "test" \
- "--ci+ Set to utilize CI-based test configurations & reporting."
+ "test"
# Possible TODO?s
# "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \
@@ -60,10 +59,10 @@ do_build() {
do_test() {
test-headless-typescript "${SUBPROJECT_NAME}"
- ./gesture-recognizer/build.sh test
+ ./gesture-processor/build.sh test
}
builder_run_action configure do_configure
builder_run_action clean do_clean
builder_run_action build do_build
-builder_run_action test
\ No newline at end of file
+builder_run_action test do_test
diff --git a/web/src/engine/osk/gesture-processor/build.sh b/web/src/engine/osk/gesture-processor/build.sh
index 26750246c9..5bee378fca 100755
--- a/web/src/engine/osk/gesture-processor/build.sh
+++ b/web/src/engine/osk/gesture-processor/build.sh
@@ -25,8 +25,7 @@ builder_describe "Builds the gesture-recognition model for Web-based on-screen k
"build" \
"test" \
":module" \
- ":tools tools for testing & developing test resources for this module" \
- "--ci sets the --ci option for child scripts (i.e, the $(builder_term test) action)"
+ ":tools tools for testing & developing test resources for this module"
builder_describe_outputs \
configure /node_modules \
diff --git a/web/src/engine/osk/gesture-processor/src/tools/host-fixture/host-fixture.html b/web/src/engine/osk/gesture-processor/src/tools/host-fixture/host-fixture.html
index 2565ac5c4b..83cf84ef33 100644
--- a/web/src/engine/osk/gesture-processor/src/tools/host-fixture/host-fixture.html
+++ b/web/src/engine/osk/gesture-processor/src/tools/host-fixture/host-fixture.html
@@ -23,6 +23,7 @@
-->