diff --git a/android/KMEA/app/src/main/assets/android-host.js b/android/KMEA/app/src/main/assets/android-host.js index ad440d493a2..48672c05728 100644 --- a/android/KMEA/app/src/main/assets/android-host.js +++ b/android/KMEA/app/src/main/assets/android-host.js @@ -247,7 +247,7 @@ function deregisterModel(modelID) { } function enableSuggestions(model, suggestionType) { - // Set the options first so that KMW's ModelManager can properly handle model enablement states + // Set the options first so that KMW's ModelCache can properly handle model enablement states // the moment we actually register the new model. // Use console_debug console_debug('enableSuggestions(model, maySuggest='+suggestionType+')'); diff --git a/android/KMEA/build.sh b/android/KMEA/build.sh index f4d77058155..28d9877285c 100755 --- a/android/KMEA/build.sh +++ b/android/KMEA/build.sh @@ -23,7 +23,7 @@ JUNIT_RESULTS="##teamcity[importData type='junit' path='keyman\android\KMEA\app\ builder_describe "Builds Keyman Engine for Android." \ "@/web/src/app/webview" \ - "@/web/src/engine/sentry-manager" \ + "@/common/web/sentry-manager" \ "clean" \ "configure" \ "build" \ @@ -81,7 +81,7 @@ if builder_start_action build:engine; then cp "$KEYMAN_WEB_ROOT/build/app/resources/osk/kmwosk.css" "$ENGINE_ASSETS/kmwosk.css" cp "$KEYMAN_WEB_ROOT/build/app/resources/osk/globe-hint.css" "$ENGINE_ASSETS/globe-hint.css" cp "$KEYMAN_WEB_ROOT/build/app/resources/osk/keymanweb-osk.ttf" "$ENGINE_ASSETS/keymanweb-osk.ttf" - cp "$KEYMAN_ROOT/web/src/engine/sentry-manager/build/lib/index.js" "$ENGINE_ASSETS/keyman-sentry.js" + cp "$KEYMAN_ROOT/common/web/sentry-manager/build/lib/index.js" "$ENGINE_ASSETS/keyman-sentry.js" echo "Copying es6-shim polyfill" cp "$KEYMAN_ROOT/node_modules/es6-shim/es6-shim.min.js" "$ENGINE_ASSETS/es6-shim.min.js" diff --git a/common/include/km_types.h b/common/include/km_types.h index 05bc0aa432b..cd0ca7f8d07 100644 --- a/common/include/km_types.h +++ b/common/include/km_types.h @@ -11,12 +11,20 @@ #if defined(__LP64__) || defined(_LP64) /* 64-bit, g++ */ -#define KMX_64BIT +#define KMX_REQUIRES_REALIGNMENT #endif #if defined(_WIN64) && !defined(USE_64) /* 64-bit, Windows */ -#define KMX_64BIT +#define KMX_REQUIRES_REALIGNMENT +#endif + +#if defined(__EMSCRIPTEN__) +// Emscripten/WASM. Emscripten even though it uses 32-bit (and not 64-bit +// pointers like the 64-bit architectures above) requires 32-bit alignment +// for pointers which we don't always have in the KMX data from file +// (see #12844). +#define KMX_REQUIRES_REALIGNMENT #endif typedef uint32_t KMX_DWORD; diff --git a/common/test/keyboards/baseline/README.md b/common/test/keyboards/baseline/README.md index cede1070851..28106b6f1db 100644 --- a/common/test/keyboards/baseline/README.md +++ b/common/test/keyboards/baseline/README.md @@ -4,11 +4,13 @@ This folder contains a set of keyboards that are used by multiple projects to verify behaviour, both for compilation, and for runtime tests. The following projects are known to use these keyboards: + * core -- .kmn files only, compiled with kmc during tests * developer/kmcmplib -- .kmn files, compiled for tests, and .kmx as reference * linux -- .kmn files for test steps only, .kmx files +* web -- .kmn files for test steps, .kmx and .js files -The .kmx files were built with kmcomp, not kmc, in order to ensure that +The .kmx and .js files were built with kmcomp, not kmc, in order to ensure that developer/kmcmplib gets a valid baseline reference. Once kmc is stable, it is possible that we will be able to use the kmc npm @@ -16,9 +18,34 @@ module to build .kmx for all projects that need them. ## Build parameters -Keyboards were built with debug information and no compiler version embedded, -with kmcomp 16.0.138: +The keyboards can be built with: -```bat -for %d in (*.kmn) do kmcomp -no-compiler-version -d %d +```bash +./build.sh build ``` + +This builds the keyboards with debug information and no compiler version +embedded. + +## Grouping of the test fixtures + +Fixtures that test similar functionality are roughly grouped together. +There is some overlap between different groups, so this was done +mainly by test name. + +| Name | Test group | +|----------|------------------------------------------| +| k_00xx_* | Tests that didn't fit in any other group | +| k_01xx_* | Basic rules | +| k_02xx_* | RALT | +| k_03xx_* | deadkeys | +| k_04xx_* | Using multiple groups | +| k_05xx_* | Options | +| k_06xx_* | System stores | +| k_07xx_* | Caps related tests | +| k_08xx_* | Context related | + +## Description of file format + +See [README.md](/core/tests/unit/kmx/README.md) in core for a description +of the file format. diff --git a/common/test/keyboards/baseline/baseline.kpj b/common/test/keyboards/baseline/baseline.kpj index 3ce7e9b83c1..5e7c461aac6 100644 --- a/common/test/keyboards/baseline/baseline.kpj +++ b/common/test/keyboards/baseline/baseline.kpj @@ -9,324 +9,324 @@ - id_k_000___null_keyboard - k_000___null_keyboard.kmn - k_000___null_keyboard.kmn + id_k_0000___null_keyboard + k_0000___null_keyboard.kmn + k_0000___null_keyboard.kmn 1.0 .kmn - id_k_001___basic_input_unicodei - k_001___basic_input_unicodei.kmn - k_001___basic_input_unicodei.kmn + id_k_0100___basic_input_unicodei + k_0100___basic_input_unicodei.kmn + k_0100___basic_input_unicodei.kmn 1.0 .kmn - id_k_002___basic_input_unicode - k_002___basic_input_unicode.kmn - k_002___basic_input_unicode.kmn + id_k_0101___basic_input_unicode + k_0101___basic_input_unicode.kmn + k_0101___basic_input_unicode.kmn 1.0 .kmn - id_k_003___nul - k_003___nul.kmn - k_003___nul.kmn + id_k_0001___nul + k_0001___nul.kmn + k_0001___nul.kmn 1.0 .kmn - id_k_004___basic_input__shift_2_ - k_004___basic_input__shift_2_.kmn - k_004___basic_input__shift_2_.kmn + id_k_0102___basic_input__shift_2_ + k_0102___basic_input__shift_2_.kmn + k_0102___basic_input__shift_2_.kmn 1.0 .kmn - id_k_005___nul_with_initial_context - k_005___nul_with_initial_context.kmn - k_005___nul_with_initial_context.kmn + id_k_0002___nul_with_initial_context + k_0002___nul_with_initial_context.kmn + k_0002___nul_with_initial_context.kmn 1.0 .kmn - id_k_006___vkey_input__shift_ctrl_ - k_006___vkey_input__shift_ctrl_.kmn - k_006___vkey_input__shift_ctrl_.kmn + id_k_0103___vkey_input__shift_ctrl_ + k_0103___vkey_input__shift_ctrl_.kmn + k_0103___vkey_input__shift_ctrl_.kmn 1.0 .kmn - id_k_007___vkey_input__ctrl_alt_ - k_007___vkey_input__ctrl_alt_.kmn - k_007___vkey_input__ctrl_alt_.kmn + id_k_0104___vkey_input__ctrl_alt_ + k_0104___vkey_input__ctrl_alt_.kmn + k_0104___vkey_input__ctrl_alt_.kmn 1.0 .kmn - id_k_008___vkey_input__ctrl_alt_2_ - k_008___vkey_input__ctrl_alt_2_.kmn - k_008___vkey_input__ctrl_alt_2_.kmn + id_k_0105___vkey_input__ctrl_alt_2_ + k_0105___vkey_input__ctrl_alt_2_.kmn + k_0105___vkey_input__ctrl_alt_2_.kmn 1.0 .kmn - id_k_012___ralt - k_012___ralt.kmn - k_012___ralt.kmn + id_k_0200___ralt + k_0200___ralt.kmn + k_0200___ralt.kmn 1.0 .kmn - id_k_013___deadkeys - k_013___deadkeys.kmn - k_013___deadkeys.kmn + id_k_0300___deadkeys + k_0300___deadkeys.kmn + k_0300___deadkeys.kmn 1.0 .kmn - id_k_014___groups_and_virtual_keys - k_014___groups_and_virtual_keys.kmn - k_014___groups_and_virtual_keys.kmn + id_k_0400___groups_and_virtual_keys + k_0400___groups_and_virtual_keys.kmn + k_0400___groups_and_virtual_keys.kmn 1.0 .kmn - id_k_015___ralt_2 - k_015___ralt_2.kmn - k_015___ralt_2.kmn + id_k_0201___ralt_2 + k_0201___ralt_2.kmn + k_0201___ralt_2.kmn 1.0 .kmn - id_k_017___space_mnemonic_kbd - k_017___space_mnemonic_kbd.kmn - k_017___space_mnemonic_kbd.kmn + id_k_0004___space_mnemonic_kbd + k_0004___space_mnemonic_kbd.kmn + k_0004___space_mnemonic_kbd.kmn 1.0 .kmn - id_k_018___nul_testing - k_018___nul_testing.kmn - k_018___nul_testing.kmn + id_k_0003___nul_testing + k_0003___nul_testing.kmn + k_0003___nul_testing.kmn 1.0 .kmn - id_k_019___multiple_deadkeys - k_019___multiple_deadkeys.kmn - k_019___multiple_deadkeys.kmn + id_k_0301___multiple_deadkeys + k_0301___multiple_deadkeys.kmn + k_0301___multiple_deadkeys.kmn 1.0 .kmn - id_k_020___deadkeys_and_backspace - k_020___deadkeys_and_backspace.kmn - k_020___deadkeys_and_backspace.kmn + id_k_0302___deadkeys_and_backspace + k_0302___deadkeys_and_backspace.kmn + k_0302___deadkeys_and_backspace.kmn 1.0 .kmn - id_k_021___options - k_021___options.kmn - k_021___options.kmn + id_k_0500___options + k_0500___options.kmn + k_0500___options.kmn 1.0 .kmn - id_k_022___options_with_preset - k_022___options_with_preset.kmn - k_022___options_with_preset.kmn + id_k_0501___options_with_preset + k_0501___options_with_preset.kmn + k_0501___options_with_preset.kmn 1.0 .kmn - id_k_023___options_with_save - k_023___options_with_save.kmn - k_023___options_with_save.kmn + id_k_0502___options_with_save + k_0502___options_with_save.kmn + k_0502___options_with_save.kmn 1.0 .kmn - id_k_024___options_with_save_and_preset - k_024___options_with_save_and_preset.kmn - k_024___options_with_save_and_preset.kmn + id_k_0503___options_with_save_and_preset + k_0503___options_with_save_and_preset.kmn + k_0503___options_with_save_and_preset.kmn 1.0 .kmn - id_k_025___options_with_reset - k_025___options_with_reset.kmn - k_025___options_with_reset.kmn + id_k_0504___options_with_reset + k_0504___options_with_reset.kmn + k_0504___options_with_reset.kmn 1.0 .kmn - id_k_026___system_stores - k_026___system_stores.kmn - k_026___system_stores.kmn + id_k_0600___system_stores + k_0600___system_stores.kmn + k_0600___system_stores.kmn 1.0 .kmn - id_k_027___system_stores_2 - k_027___system_stores_2.kmn - k_027___system_stores_2.kmn + id_k_0601___system_stores_2 + k_0601___system_stores_2.kmn + k_0601___system_stores_2.kmn 1.0 .kmn - id_k_028___smp - k_028___smp.kmn - k_028___smp.kmn + id_k_0106___smp + k_0106___smp.kmn + k_0106___smp.kmn 1.0 .kmn - id_k_029___beep - k_029___beep.kmn - k_029___beep.kmn + id_k_0005___beep + k_0005___beep.kmn + k_0005___beep.kmn 1.0 .kmn - id_k_030___multiple_groups - k_030___multiple_groups.kmn - k_030___multiple_groups.kmn + id_k_0401___multiple_groups + k_0401___multiple_groups.kmn + k_0401___multiple_groups.kmn 1.0 .kmn - id_k_031___caps_lock - k_031___caps_lock.kmn - k_031___caps_lock.kmn + id_k_0700___caps_lock + k_0700___caps_lock.kmn + k_0700___caps_lock.kmn 1.0 .kmn - id_k_032___caps_control - k_032___caps_control.kmn - k_032___caps_control.kmn + id_k_0701___caps_control + k_0701___caps_control.kmn + k_0701___caps_control.kmn 1.0 .kmn - id_k_033___caps_always_off - k_033___caps_always_off.kmn - k_033___caps_always_off.kmn + id_k_0702___caps_always_off + k_0702___caps_always_off.kmn + k_0702___caps_always_off.kmn 1.0 .kmn - id_k_034___options_double_set_reset - k_034___options_double_set_reset.kmn - k_034___options_double_set_reset.kmn + id_k_0505___options_double_set_reset + k_0505___options_double_set_reset.kmn + k_0505___options_double_set_reset.kmn 1.0 .kmn - id_k_035___options_double_set_staged - k_035___options_double_set_staged.kmn - k_035___options_double_set_staged.kmn + id_k_0506___options_double_set_staged + k_0506___options_double_set_staged.kmn + k_0506___options_double_set_staged.kmn 1.0 .kmn - id_k_036___options___double_reset_staged - k_036___options___double_reset_staged.kmn - k_036___options___double_reset_staged.kmn + id_k_0507___options___double_reset_staged + k_0507___options___double_reset_staged.kmn + k_0507___options___double_reset_staged.kmn 1.0 .kmn - id_k_037___options___double_reset - k_037___options___double_reset.kmn - k_037___options___double_reset.kmn + id_k_0508___options___double_reset + k_0508___options___double_reset.kmn + k_0508___options___double_reset.kmn 1.0 .kmn - id_k_038___punctkeys - k_038___punctkeys.kmn - k_038___punctkeys.kmn + id_k_0107___punctkeys + k_0107___punctkeys.kmn + k_0107___punctkeys.kmn 1.0 .kmn - id_k_039___generic_ctrlalt - k_039___generic_ctrlalt.kmn - k_039___generic_ctrlalt.kmn + id_k_0203___generic_ctrlalt + k_0203___generic_ctrlalt.kmn + k_0203___generic_ctrlalt.kmn 1.0 .kmn - id_k_040___long_context - k_040___long_context.kmn - k_040___long_context.kmn + id_k_0800___long_context + k_0800___long_context.kmn + k_0800___long_context.kmn 1.0 .kmn - id_k_041___long_context_and_deadkeys - k_041___long_context_and_deadkeys.kmn - k_041___long_context_and_deadkeys.kmn + id_k_0801___long_context_and_deadkeys + k_0801___long_context_and_deadkeys.kmn + k_0801___long_context_and_deadkeys.kmn 1.0 .kmn - id_k_042___long_context_and_split_deadkeys - k_042___long_context_and_split_deadkeys.kmn - k_042___long_context_and_split_deadkeys.kmn + id_k_0802___long_context_and_split_deadkeys + k_0802___long_context_and_split_deadkeys.kmn + k_0802___long_context_and_split_deadkeys.kmn 1.0 .kmn - id_k_043___output_and_keystroke - k_043___output_and_keystroke.kmn - k_043___output_and_keystroke.kmn + id_k_0402___output_and_keystroke + k_0402___output_and_keystroke.kmn + k_0402___output_and_keystroke.kmn 1.0 .kmn - id_k_044___if_and_context - k_044___if_and_context.kmn - k_044___if_and_context.kmn + id_k_0803___if_and_context + k_0803___if_and_context.kmn + k_0803___if_and_context.kmn 1.0 .kmn - id_k_045___deadkey_and_context - k_045___deadkey_and_context.kmn - k_045___deadkey_and_context.kmn + id_k_0804___deadkey_and_context + k_0804___deadkey_and_context.kmn + k_0804___deadkey_and_context.kmn 1.0 .kmn - id_k_046___deadkey_and_contextex - k_046___deadkey_and_contextex.kmn - k_046___deadkey_and_contextex.kmn + id_k_0805___deadkey_and_contextex + k_0805___deadkey_and_contextex.kmn + k_0805___deadkey_and_contextex.kmn 1.0 .kmn - id_k_047___caps_always_off_initially_on - k_047___caps_always_off_initially_on.kmn - k_047___caps_always_off_initially_on.kmn + id_k_0703___caps_always_off_initially_on + k_0703___caps_always_off_initially_on.kmn + k_0703___caps_always_off_initially_on.kmn 1.0 .kmn - id_k_048___modifier_keys_keep_context - k_048___modifier_keys_keep_context.kmn - k_048___modifier_keys_keep_context.kmn + id_k_0806___modifier_keys_keep_context + k_0806___modifier_keys_keep_context.kmn + k_0806___modifier_keys_keep_context.kmn 1.0 .kmn - id_k_049___enter_invalidates_context - k_049___enter_invalidates_context.kmn - k_049___enter_invalidates_context.kmn + id_k_0807___enter_invalidates_context + k_0807___enter_invalidates_context.kmn + k_0807___enter_invalidates_context.kmn 1.0 .kmn diff --git a/common/test/keyboards/baseline/build.sh b/common/test/keyboards/baseline/build.sh index 1428b5e0c48..3a1e8d9f1ec 100755 --- a/common/test/keyboards/baseline/build.sh +++ b/common/test/keyboards/baseline/build.sh @@ -17,7 +17,7 @@ builder_parse "$@" builder_describe_outputs \ configure kmcomp/kmcomp.exe \ - build k_000___null_keyboard.kmx + build k_0000___null_keyboard.kmx do_configure() { mkdir -p kmcomp @@ -25,9 +25,15 @@ do_configure() { } do_build() { - local name + local name jsname for name in *.kmn; do - ./kmcomp/kmcomp.exe -no-compiler-version -d "$name" + jsname="$(basename "${name%.kmn}").js" + ./kmcomp/kmcomp.exe -no-compiler-version -d "${name}" + if [[ "${name}" != "k_0812___nul_and_contextex.kmn" ]]; then + # k_0812___nul_and_contextex.kmn fails to compile because contextex + # is not currently supported in context() match, so we skip it + ./kmcomp/kmcomp.exe -no-compiler-version -d "${name}" "${jsname}" + fi done } diff --git a/common/test/keyboards/baseline/k_0000___null_keyboard.js b/common/test/keyboards/baseline/k_0000___null_keyboard.js new file mode 100644 index 00000000000..076ec597c48 --- /dev/null +++ b/common/test/keyboards/baseline/k_0000___null_keyboard.js @@ -0,0 +1,28 @@ + +KeymanWeb.KR(new Keyboard_k_0000___null_keyboard()); + +function Keyboard_k_0000___null_keyboard() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0000___null_keyboard"; + this.KN="0000 - null keyboard"; + this.KMINVER="6.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0000; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_000___null_keyboard.kmn b/common/test/keyboards/baseline/k_0000___null_keyboard.kmn similarity index 84% rename from common/test/keyboards/baseline/k_000___null_keyboard.kmn rename to common/test/keyboards/baseline/k_0000___null_keyboard.kmn index ecae49acde0..57321e6d63d 100644 --- a/common/test/keyboards/baseline/k_000___null_keyboard.kmn +++ b/common/test/keyboards/baseline/k_0000___null_keyboard.kmn @@ -1,4 +1,4 @@ -store(&NAME) '000 - null keyboard' +store(&NAME) '0000 - null keyboard' c Description: Tests null keyboard c keys: [K_A][RALT K_B][SHIFT K_C] c expected: aC diff --git a/common/test/keyboards/baseline/k_0000___null_keyboard.kmx b/common/test/keyboards/baseline/k_0000___null_keyboard.kmx new file mode 100644 index 00000000000..dfc85b5e2a7 Binary files /dev/null and b/common/test/keyboards/baseline/k_0000___null_keyboard.kmx differ diff --git a/common/test/keyboards/baseline/k_0001___nul.js b/common/test/keyboards/baseline/k_0001___nul.js new file mode 100644 index 00000000000..d33ee337cf4 --- /dev/null +++ b/common/test/keyboards/baseline/k_0001___nul.js @@ -0,0 +1,42 @@ + +KeymanWeb.KR(new Keyboard_k_0001___nul()); + +function Keyboard_k_0001___nul() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0001___nul"; + this.KN="0001 - nul"; + this.KMINVER="6.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0000; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4000, 0x41)) { + if(k.KN(0,t)){ + r=m=1; // Line 13 + k.KO(0,t,"b"); + } + else if(k.KCM(1,t,"b",1)){ + r=m=1; // Line 14 + k.KO(1,t,"c"); + } + else if(1){ + r=m=1; // Line 15 + k.KO(0,t,"d"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_003___nul.kmn b/common/test/keyboards/baseline/k_0001___nul.kmn similarity index 83% rename from common/test/keyboards/baseline/k_003___nul.kmn rename to common/test/keyboards/baseline/k_0001___nul.kmn index 32f6e84839a..44d92b628c7 100644 --- a/common/test/keyboards/baseline/k_003___nul.kmn +++ b/common/test/keyboards/baseline/k_0001___nul.kmn @@ -1,8 +1,8 @@ -store(&NAME) '003 - nul' +store(&NAME) '0001 - nul' c Description: Tests nul context c keys: [K_A][K_A][K_A] c expected: cd -c context: +c context: store(&version) '6.0' diff --git a/common/test/keyboards/baseline/k_0001___nul.kmx b/common/test/keyboards/baseline/k_0001___nul.kmx new file mode 100644 index 00000000000..6795c349f5c Binary files /dev/null and b/common/test/keyboards/baseline/k_0001___nul.kmx differ diff --git a/common/test/keyboards/baseline/k_0002___nul_with_initial_context.js b/common/test/keyboards/baseline/k_0002___nul_with_initial_context.js new file mode 100644 index 00000000000..ca42f2a1f3e --- /dev/null +++ b/common/test/keyboards/baseline/k_0002___nul_with_initial_context.js @@ -0,0 +1,42 @@ + +KeymanWeb.KR(new Keyboard_k_0002___nul_with_initial_context()); + +function Keyboard_k_0002___nul_with_initial_context() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0002___nul_with_initial_context"; + this.KN="0002 - nul with initial context"; + this.KMINVER="6.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0000; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4000, 0x41)) { + if(k.KN(0,t)){ + r=m=1; // Line 13 + k.KO(0,t,"b"); + } + else if(k.KCM(1,t,"b",1)){ + r=m=1; // Line 14 + k.KO(1,t,"c"); + } + else if(1){ + r=m=1; // Line 15 + k.KO(0,t,"d"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_005___nul_with_initial_context.kmn b/common/test/keyboards/baseline/k_0002___nul_with_initial_context.kmn similarity index 83% rename from common/test/keyboards/baseline/k_005___nul_with_initial_context.kmn rename to common/test/keyboards/baseline/k_0002___nul_with_initial_context.kmn index f59016cbe18..4ae05e6ba4a 100644 --- a/common/test/keyboards/baseline/k_005___nul_with_initial_context.kmn +++ b/common/test/keyboards/baseline/k_0002___nul_with_initial_context.kmn @@ -1,4 +1,4 @@ -store(&NAME) '005 - nul with initial context' +store(&NAME) '0002 - nul with initial context' c Description: Tests nul context with an initial context supplied c keys: [K_A][K_A] c expected: xdd diff --git a/common/test/keyboards/baseline/k_0002___nul_with_initial_context.kmx b/common/test/keyboards/baseline/k_0002___nul_with_initial_context.kmx new file mode 100644 index 00000000000..3d89b790f5c Binary files /dev/null and b/common/test/keyboards/baseline/k_0002___nul_with_initial_context.kmx differ diff --git a/common/test/keyboards/baseline/k_0003___nul_testing.js b/common/test/keyboards/baseline/k_0003___nul_testing.js new file mode 100644 index 00000000000..330a614dba6 --- /dev/null +++ b/common/test/keyboards/baseline/k_0003___nul_testing.js @@ -0,0 +1,34 @@ + +KeymanWeb.KR(new Keyboard_k_0003___nul_testing()); + +function Keyboard_k_0003___nul_testing() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0003___nul_testing"; + this.KN="0003 - nul testing"; + this.KMINVER="9.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0000; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4000, 0x41)) { + if(k.KN(0,t)){ + r=m=1; // Line 12 + k.KO(0,t,"OK"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_018___nul_testing.kmn b/common/test/keyboards/baseline/k_0003___nul_testing.kmn similarity index 87% rename from common/test/keyboards/baseline/k_018___nul_testing.kmn rename to common/test/keyboards/baseline/k_0003___nul_testing.kmn index 20da4d4af70..87fc78f86fe 100644 --- a/common/test/keyboards/baseline/k_018___nul_testing.kmn +++ b/common/test/keyboards/baseline/k_0003___nul_testing.kmn @@ -1,4 +1,4 @@ -store(&NAME) '018 - nul testing' +store(&NAME) '0003 - nul testing' c Description: Tests the processing of nul in LHS of rules c keys: [K_A][K_A] c expected: OKa diff --git a/common/test/keyboards/baseline/k_0003___nul_testing.kmx b/common/test/keyboards/baseline/k_0003___nul_testing.kmx new file mode 100644 index 00000000000..e30ca2494d2 Binary files /dev/null and b/common/test/keyboards/baseline/k_0003___nul_testing.kmx differ diff --git a/common/test/keyboards/baseline/k_0004___space_mnemonic_kbd.js b/common/test/keyboards/baseline/k_0004___space_mnemonic_kbd.js new file mode 100644 index 00000000000..a4ee094cb5c --- /dev/null +++ b/common/test/keyboards/baseline/k_0004___space_mnemonic_kbd.js @@ -0,0 +1,46 @@ + +KeymanWeb.KR(new Keyboard_k_0004___space_mnemonic_kbd()); + +function Keyboard_k_0004___space_mnemonic_kbd() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0004___space_mnemonic_kbd"; + this.KN="0004 - space mnemonic kbd"; + this.KMINVER="9.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=1; + this.KBVER="1.0"; + this.KMBM=0x0000; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.g_main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4000, 0x20)) { + if(k.KCM(2,t,"ab",2)){ + r=m=1; // Line 14 + k.KO(2,t,"X"); + } + } + else if(k.KKM(e, 0x4000, 0x64)) { + if(k.KCM(2,t,"c ",2)){ + r=m=1; // Line 15 + k.KO(2,t,"Y"); + } + } + else if(k.KKM(e, 0x4000, 0x65)) { + if(k.KCM(2,t," d",2)){ + r=m=1; // Line 16 + k.KO(2,t,"Z"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_017___space_mnemonic_kbd.kmn b/common/test/keyboards/baseline/k_0004___space_mnemonic_kbd.kmn similarity index 90% rename from common/test/keyboards/baseline/k_017___space_mnemonic_kbd.kmn rename to common/test/keyboards/baseline/k_0004___space_mnemonic_kbd.kmn index 07e37ee681b..2660d114d4e 100644 --- a/common/test/keyboards/baseline/k_017___space_mnemonic_kbd.kmn +++ b/common/test/keyboards/baseline/k_0004___space_mnemonic_kbd.kmn @@ -1,4 +1,4 @@ -store(&NAME) '017 - space mnemonic kbd' +store(&NAME) '0004 - space mnemonic kbd' c Description: Tests Space handling in mnemonic keyboards (failed with Win 98) c keys: [K_A][K_B][K_SPACE][K_C][K_SPACE][K_D][K_SPACE][K_D][K_E] c expected: XYZ diff --git a/common/test/keyboards/baseline/k_0004___space_mnemonic_kbd.kmx b/common/test/keyboards/baseline/k_0004___space_mnemonic_kbd.kmx new file mode 100644 index 00000000000..b256ace5368 Binary files /dev/null and b/common/test/keyboards/baseline/k_0004___space_mnemonic_kbd.kmx differ diff --git a/common/test/keyboards/baseline/k_0005___beep.js b/common/test/keyboards/baseline/k_0005___beep.js new file mode 100644 index 00000000000..e0d19f0651e --- /dev/null +++ b/common/test/keyboards/baseline/k_0005___beep.js @@ -0,0 +1,40 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0005___beep()); +} +function Keyboard_k_0005___beep() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0005___beep"; + this.KN="0005 - beep"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 13 + k.KDC(0,t); + k.KB(t); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_029___beep.kmn b/common/test/keyboards/baseline/k_0005___beep.kmn similarity index 79% rename from common/test/keyboards/baseline/k_029___beep.kmn rename to common/test/keyboards/baseline/k_0005___beep.kmn index 65e650ee44b..b9b9fcab8cb 100644 --- a/common/test/keyboards/baseline/k_029___beep.kmn +++ b/common/test/keyboards/baseline/k_0005___beep.kmn @@ -1,8 +1,8 @@ -store(&NAME) '029 - beep' +store(&NAME) '0005 - beep' c Description: Tests beep c keys: [K_1] c expected: \b -c context: +c context: store(&version) '10.0' diff --git a/common/test/keyboards/baseline/k_0005___beep.kmx b/common/test/keyboards/baseline/k_0005___beep.kmx new file mode 100644 index 00000000000..c491183f26c Binary files /dev/null and b/common/test/keyboards/baseline/k_0005___beep.kmx differ diff --git a/common/test/keyboards/baseline/k_000___null_keyboard.kmx b/common/test/keyboards/baseline/k_000___null_keyboard.kmx deleted file mode 100644 index 2ac1a0f65f7..00000000000 Binary files a/common/test/keyboards/baseline/k_000___null_keyboard.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_001___basic_input_unicodei.kmx b/common/test/keyboards/baseline/k_001___basic_input_unicodei.kmx deleted file mode 100644 index 82f60cd001d..00000000000 Binary files a/common/test/keyboards/baseline/k_001___basic_input_unicodei.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_002___basic_input_unicode.kmx b/common/test/keyboards/baseline/k_002___basic_input_unicode.kmx deleted file mode 100644 index 5f1497a29e0..00000000000 Binary files a/common/test/keyboards/baseline/k_002___basic_input_unicode.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_003___nul.kmx b/common/test/keyboards/baseline/k_003___nul.kmx deleted file mode 100644 index 9a5e835e04a..00000000000 Binary files a/common/test/keyboards/baseline/k_003___nul.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_004___basic_input__shift_2_.kmx b/common/test/keyboards/baseline/k_004___basic_input__shift_2_.kmx deleted file mode 100644 index c465d596d5f..00000000000 Binary files a/common/test/keyboards/baseline/k_004___basic_input__shift_2_.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_005___nul_with_initial_context.kmx b/common/test/keyboards/baseline/k_005___nul_with_initial_context.kmx deleted file mode 100644 index 53f9889b32f..00000000000 Binary files a/common/test/keyboards/baseline/k_005___nul_with_initial_context.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_006___vkey_input__shift_ctrl_.kmx b/common/test/keyboards/baseline/k_006___vkey_input__shift_ctrl_.kmx deleted file mode 100644 index 6651a91b196..00000000000 Binary files a/common/test/keyboards/baseline/k_006___vkey_input__shift_ctrl_.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_007___vkey_input__ctrl_alt_.kmx b/common/test/keyboards/baseline/k_007___vkey_input__ctrl_alt_.kmx deleted file mode 100644 index 3000af8a802..00000000000 Binary files a/common/test/keyboards/baseline/k_007___vkey_input__ctrl_alt_.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_008___vkey_input__ctrl_alt_2_.kmx b/common/test/keyboards/baseline/k_008___vkey_input__ctrl_alt_2_.kmx deleted file mode 100644 index b12a0f15c85..00000000000 Binary files a/common/test/keyboards/baseline/k_008___vkey_input__ctrl_alt_2_.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_0100___basic_input_unicodei.js b/common/test/keyboards/baseline/k_0100___basic_input_unicodei.js new file mode 100644 index 00000000000..86e960301a9 --- /dev/null +++ b/common/test/keyboards/baseline/k_0100___basic_input_unicodei.js @@ -0,0 +1,52 @@ + +KeymanWeb.KR(new Keyboard_k_0100___basic_input_unicodei()); + +function Keyboard_k_0100___basic_input_unicodei() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0100___basic_input_unicodei"; + this.KN="0100 - basic input UnicodeI"; + this.KMINVER="6.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0010; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4010, 0x41)) { + if(1){ + r=m=1; // Line 13 + k.KO(0,t,"a"); + } + } + else if(k.KKM(e, 0x4010, 0x42)) { + if(1){ + r=m=1; // Line 14 + k.KO(0,t,"b"); + } + } + else if(k.KKM(e, 0x4010, 0x43)) { + if(1){ + r=m=1; // Line 15 + k.KO(0,t,"c"); + } + } + else if(k.KKM(e, 0x4010, 0x46)) { + if(k.KCM(2,t,"DE",2)){ + r=m=1; // Line 17 + k.KO(2,t,"def"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_001___basic_input_unicodei.kmn b/common/test/keyboards/baseline/k_0100___basic_input_unicodei.kmn similarity index 85% rename from common/test/keyboards/baseline/k_001___basic_input_unicodei.kmn rename to common/test/keyboards/baseline/k_0100___basic_input_unicodei.kmn index 446c0e8f1d9..da80e98ca71 100644 --- a/common/test/keyboards/baseline/k_001___basic_input_unicodei.kmn +++ b/common/test/keyboards/baseline/k_0100___basic_input_unicodei.kmn @@ -1,8 +1,8 @@ -store(&NAME) '001 - basic input UnicodeI' +store(&NAME) '0100 - basic input UnicodeI' c Description: Tests basic input with simple context rules, ANSI characters used only c keys: [SHIFT K_A][SHIFT K_B][SHIFT K_C][SHIFT K_SPACE][SHIFT K_D][SHIFT K_E][SHIFT K_F] c expected: abc def -c context: +c context: store(&version) '6.0' diff --git a/common/test/keyboards/baseline/k_0100___basic_input_unicodei.kmx b/common/test/keyboards/baseline/k_0100___basic_input_unicodei.kmx new file mode 100644 index 00000000000..b31daddd07f Binary files /dev/null and b/common/test/keyboards/baseline/k_0100___basic_input_unicodei.kmx differ diff --git a/common/test/keyboards/baseline/k_0101___basic_input_unicode.js b/common/test/keyboards/baseline/k_0101___basic_input_unicode.js new file mode 100644 index 00000000000..74dc5e3ddb7 --- /dev/null +++ b/common/test/keyboards/baseline/k_0101___basic_input_unicode.js @@ -0,0 +1,52 @@ + +KeymanWeb.KR(new Keyboard_k_0101___basic_input_unicode()); + +function Keyboard_k_0101___basic_input_unicode() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0101___basic_input_unicode"; + this.KN="0101 - basic input Unicode"; + this.KMINVER="6.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0010; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4010, 0x41)) { + if(1){ + r=m=1; // Line 13 + k.KO(0,t,"ก"); + } + } + else if(k.KKM(e, 0x4010, 0x42)) { + if(1){ + r=m=1; // Line 14 + k.KO(0,t,"ข"); + } + } + else if(k.KKM(e, 0x4010, 0x43)) { + if(1){ + r=m=1; // Line 15 + k.KO(0,t,"ฃ"); + } + } + else if(k.KKM(e, 0x4010, 0x46)) { + if(k.KCM(2,t,"DE",2)){ + r=m=1; // Line 17 + k.KO(2,t,"คฅฆ"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_002___basic_input_unicode.kmn b/common/test/keyboards/baseline/k_0101___basic_input_unicode.kmn similarity index 90% rename from common/test/keyboards/baseline/k_002___basic_input_unicode.kmn rename to common/test/keyboards/baseline/k_0101___basic_input_unicode.kmn index 04c6df9f4a6..a14821c8b6e 100644 --- a/common/test/keyboards/baseline/k_002___basic_input_unicode.kmn +++ b/common/test/keyboards/baseline/k_0101___basic_input_unicode.kmn @@ -1,4 +1,4 @@ -store(&NAME) '002 - basic input Unicode' +store(&NAME) '0101 - basic input Unicode' c Description: Tests basic input with simple context rules (Unicode) c keys: [SHIFT K_A][SHIFT K_B][SHIFT K_C][SHIFT K_SPACE][SHIFT K_D][SHIFT K_E][SHIFT K_F] c expected: \u0E01\u0E02\u0E03\u0020\u0E04\u0E05\u0E06 diff --git a/common/test/keyboards/baseline/k_0101___basic_input_unicode.kmx b/common/test/keyboards/baseline/k_0101___basic_input_unicode.kmx new file mode 100644 index 00000000000..acf956d6b4b Binary files /dev/null and b/common/test/keyboards/baseline/k_0101___basic_input_unicode.kmx differ diff --git a/common/test/keyboards/baseline/k_0102___basic_input__shift_2_.js b/common/test/keyboards/baseline/k_0102___basic_input__shift_2_.js new file mode 100644 index 00000000000..a7ce73ed872 --- /dev/null +++ b/common/test/keyboards/baseline/k_0102___basic_input__shift_2_.js @@ -0,0 +1,52 @@ + +KeymanWeb.KR(new Keyboard_k_0102___basic_input__shift_2_()); + +function Keyboard_k_0102___basic_input__shift_2_() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0102___basic_input__shift_2_"; + this.KN="0102 - basic input (shift 2)"; + this.KMINVER="6.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0010; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4010, 0x41)) { + if(1){ + r=m=1; // Line 13 + k.KO(0,t,"ก"); + } + } + else if(k.KKM(e, 0x4010, 0x42)) { + if(1){ + r=m=1; // Line 14 + k.KO(0,t,"ข"); + } + } + else if(k.KKM(e, 0x4010, 0x43)) { + if(1){ + r=m=1; // Line 15 + k.KO(0,t,"ฃ"); + } + } + else if(k.KKM(e, 0x4010, 0x46)) { + if(k.KCM(2,t,"DE",2)){ + r=m=1; // Line 17 + k.KO(2,t,"คฅฆ"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_004___basic_input__shift_2_.kmn b/common/test/keyboards/baseline/k_0102___basic_input__shift_2_.kmn similarity index 85% rename from common/test/keyboards/baseline/k_004___basic_input__shift_2_.kmn rename to common/test/keyboards/baseline/k_0102___basic_input__shift_2_.kmn index d8782144273..0b072799ac5 100644 --- a/common/test/keyboards/baseline/k_004___basic_input__shift_2_.kmn +++ b/common/test/keyboards/baseline/k_0102___basic_input__shift_2_.kmn @@ -1,13 +1,13 @@ -store(&NAME) '004 - basic input (shift 2)' +store(&NAME) '0102 - basic input (shift 2)' c Description: Tests basic vkey input with shift only (Unicode) c keys: [SHIFT K_A][SHIFT K_B][SHIFT K_C][SHIFT K_SPACE][SHIFT K_D][SHIFT K_E][SHIFT K_F] c expected: \u0E01\u0E02\u0E03\u0020\u0E04\u0E05\u0E06 -c context: +c context: store(&version) '6.0' begin Unicode > use(Main) - + group(Main) using keys + [SHIFT K_A] > U+0E01 diff --git a/common/test/keyboards/baseline/k_0102___basic_input__shift_2_.kmx b/common/test/keyboards/baseline/k_0102___basic_input__shift_2_.kmx new file mode 100644 index 00000000000..2e431a12ef9 Binary files /dev/null and b/common/test/keyboards/baseline/k_0102___basic_input__shift_2_.kmx differ diff --git a/common/test/keyboards/baseline/k_0103___vkey_input__shift_ctrl_.js b/common/test/keyboards/baseline/k_0103___vkey_input__shift_ctrl_.js new file mode 100644 index 00000000000..0775346e75f --- /dev/null +++ b/common/test/keyboards/baseline/k_0103___vkey_input__shift_ctrl_.js @@ -0,0 +1,52 @@ + +KeymanWeb.KR(new Keyboard_k_0103___vkey_input__shift_ctrl_()); + +function Keyboard_k_0103___vkey_input__shift_ctrl_() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0103___vkey_input__shift_ctrl_"; + this.KN="0103 - vkey input (shift ctrl)"; + this.KMINVER="6.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0030; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4030, 0x41)) { + if(1){ + r=m=1; // Line 13 + k.KO(0,t,"ก"); + } + } + else if(k.KKM(e, 0x4010, 0x42)) { + if(1){ + r=m=1; // Line 14 + k.KO(0,t,"ข"); + } + } + else if(k.KKM(e, 0x4030, 0x43)) { + if(1){ + r=m=1; // Line 15 + k.KO(0,t,"ฃ"); + } + } + else if(k.KKM(e, 0x4010, 0x46)) { + if(k.KCM(2,t,"DE",2)){ + r=m=1; // Line 17 + k.KO(2,t,"คฅฆ"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_006___vkey_input__shift_ctrl_.kmn b/common/test/keyboards/baseline/k_0103___vkey_input__shift_ctrl_.kmn similarity index 86% rename from common/test/keyboards/baseline/k_006___vkey_input__shift_ctrl_.kmn rename to common/test/keyboards/baseline/k_0103___vkey_input__shift_ctrl_.kmn index 9a966aa651d..c9947cfcc54 100644 --- a/common/test/keyboards/baseline/k_006___vkey_input__shift_ctrl_.kmn +++ b/common/test/keyboards/baseline/k_0103___vkey_input__shift_ctrl_.kmn @@ -1,13 +1,13 @@ -store(&NAME) '006 - vkey input (shift ctrl)' +store(&NAME) '0103 - vkey input (shift ctrl)' c Description: Tests basic vkey input with shift and control (Unicode) c keys: [LCTRL SHIFT K_A][SHIFT K_B][RCTRL SHIFT K_C][K_SPACE][SHIFT K_D][SHIFT K_E][SHIFT K_F] c expected: \u0E01\u0E02\u0E03\u0020\u0E04\u0E05\u0E06 -c context: +c context: store(&version) '6.0' begin Unicode > use(Main) - + group(Main) using keys + [SHIFT CTRL K_A] > U+0E01 diff --git a/common/test/keyboards/baseline/k_0103___vkey_input__shift_ctrl_.kmx b/common/test/keyboards/baseline/k_0103___vkey_input__shift_ctrl_.kmx new file mode 100644 index 00000000000..9a9747c33db Binary files /dev/null and b/common/test/keyboards/baseline/k_0103___vkey_input__shift_ctrl_.kmx differ diff --git a/common/test/keyboards/baseline/k_0104___vkey_input__ctrl_alt_.js b/common/test/keyboards/baseline/k_0104___vkey_input__ctrl_alt_.js new file mode 100644 index 00000000000..ee6e25596f3 --- /dev/null +++ b/common/test/keyboards/baseline/k_0104___vkey_input__ctrl_alt_.js @@ -0,0 +1,52 @@ + +KeymanWeb.KR(new Keyboard_k_0104___vkey_input__ctrl_alt_()); + +function Keyboard_k_0104___vkey_input__ctrl_alt_() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0104___vkey_input__ctrl_alt_"; + this.KN="0104 - vkey input (ctrl alt)"; + this.KMINVER="6.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0060; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4060, 0x41)) { + if(1){ + r=m=1; // Line 13 + k.KO(0,t,"ก"); + } + } + else if(k.KKM(e, 0x4000, 0x42)) { + if(1){ + r=m=1; // Line 14 + k.KO(0,t,"ข"); + } + } + else if(k.KKM(e, 0x4060, 0x43)) { + if(1){ + r=m=1; // Line 15 + k.KO(0,t,"ฃ"); + } + } + else if(k.KKM(e, 0x4060, 0x46)) { + if(k.KCM(2,t,"de",2)){ + r=m=1; // Line 17 + k.KO(2,t,"คฅฆ"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_007___vkey_input__ctrl_alt_.kmn b/common/test/keyboards/baseline/k_0104___vkey_input__ctrl_alt_.kmn similarity index 85% rename from common/test/keyboards/baseline/k_007___vkey_input__ctrl_alt_.kmn rename to common/test/keyboards/baseline/k_0104___vkey_input__ctrl_alt_.kmn index 3c2eb42bfe0..a7e7b608105 100644 --- a/common/test/keyboards/baseline/k_007___vkey_input__ctrl_alt_.kmn +++ b/common/test/keyboards/baseline/k_0104___vkey_input__ctrl_alt_.kmn @@ -1,15 +1,15 @@ -store(&NAME) '007 - vkey input (ctrl alt)' +store(&NAME) '0104 - vkey input (ctrl alt)' c Description: Tests basic vkey input with control and alt (Unicode) c keys: [LCTRL LALT K_A][K_B][RCTRL RALT K_C][K_SPACE][K_D][K_E][LCTRL LALT K_F] c expected: \u0E01\u0E02\u0E03\u0020\u0E04\u0E05\u0E06 -c context: +c context: store(&version) '6.0' begin Unicode > use(Main) group(Main) using keys - + + [CTRL ALT K_A] > U+0E01 + [K_B] > U+0E02 + [CTRL ALT K_C] > U+0E03 diff --git a/common/test/keyboards/baseline/k_0104___vkey_input__ctrl_alt_.kmx b/common/test/keyboards/baseline/k_0104___vkey_input__ctrl_alt_.kmx new file mode 100644 index 00000000000..ae53a86547b Binary files /dev/null and b/common/test/keyboards/baseline/k_0104___vkey_input__ctrl_alt_.kmx differ diff --git a/common/test/keyboards/baseline/k_0105___vkey_input__ctrl_alt_2_.js b/common/test/keyboards/baseline/k_0105___vkey_input__ctrl_alt_2_.js new file mode 100644 index 00000000000..2a6c8c0d029 --- /dev/null +++ b/common/test/keyboards/baseline/k_0105___vkey_input__ctrl_alt_2_.js @@ -0,0 +1,40 @@ + +KeymanWeb.KR(new Keyboard_k_0105___vkey_input__ctrl_alt_2_()); + +function Keyboard_k_0105___vkey_input__ctrl_alt_2_() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0105___vkey_input__ctrl_alt_2_"; + this.KN="0105 - vkey input (ctrl alt 2)"; + this.KMINVER="6.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0060; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4060, 0x41)) { + if(1){ + r=m=1; // Line 14 + k.KO(0,t,"ก"); + } + } + else if(k.KKM(e, 0x4060, 0x43)) { + if(1){ + r=m=1; // Line 15 + k.KO(0,t,"ฃ"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_008___vkey_input__ctrl_alt_2_.kmn b/common/test/keyboards/baseline/k_0105___vkey_input__ctrl_alt_2_.kmn similarity index 87% rename from common/test/keyboards/baseline/k_008___vkey_input__ctrl_alt_2_.kmn rename to common/test/keyboards/baseline/k_0105___vkey_input__ctrl_alt_2_.kmn index d1660c40f26..6baa092327a 100644 --- a/common/test/keyboards/baseline/k_008___vkey_input__ctrl_alt_2_.kmn +++ b/common/test/keyboards/baseline/k_0105___vkey_input__ctrl_alt_2_.kmn @@ -1,4 +1,4 @@ -store(&NAME) '008 - vkey input (ctrl alt 2)' +store(&NAME) '0105 - vkey input (ctrl alt 2)' c Description: Tests basic vkey input with control and alt (Unicode) c keys: [LCTRL LALT K_A][LCTRL LALT K_B][LCTRL LALT K_C] c expected: \u0E01\u0E03 diff --git a/common/test/keyboards/baseline/k_0105___vkey_input__ctrl_alt_2_.kmx b/common/test/keyboards/baseline/k_0105___vkey_input__ctrl_alt_2_.kmx new file mode 100644 index 00000000000..6f88e253897 Binary files /dev/null and b/common/test/keyboards/baseline/k_0105___vkey_input__ctrl_alt_2_.kmx differ diff --git a/common/test/keyboards/baseline/k_0106___smp.js b/common/test/keyboards/baseline/k_0106___smp.js new file mode 100644 index 00000000000..e7c75e32d7d --- /dev/null +++ b/common/test/keyboards/baseline/k_0106___smp.js @@ -0,0 +1,80 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0106___smp()); +} +function Keyboard_k_0106___smp() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0106___smp"; + this.KN="0106 - smp"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.KS=1; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 15 + k.KDC(0,t); + k.KO(-1,t,"🙂"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_2 /* 0x32 */)) { + if(k.KFCM(1,t,['🙂'])){ + r=m=1; // Line 16 + k.KDC(1,t); + k.KO(-1,t,"🙂hi😀"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_3 /* 0x33 */)) { + if(k.KFCM(1,t,['😀'])){ + r=m=1; // Line 17 + k.KDC(1,t); + k.KO(-1,t,"x"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_4 /* 0x34 */)) { + if(k.KFCM(4,t,['🙂','h','i','x'])){ + r=m=1; // Line 18 + k.KDC(4,t); + k.KO(-1,t,"😁y"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_5 /* 0x35 */)) { + if(1){ + r=m=1; // Line 22 + k.KDC(0,t); + k.KO(-1,t,"𐌳"); + r=this.g_second_1(t,e); + m=2; + } + } + return r; + }; + this.g_second_1=function(t,e) { + var k=KeymanWeb,r=1,m=0; + if(k.KFCM(1,t,['𐌳'])){ + m=1; // Line 26 + k.KDC(1,t); + k.KO(-1,t,"x"); + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_028___smp.kmn b/common/test/keyboards/baseline/k_0106___smp.kmn similarity index 94% rename from common/test/keyboards/baseline/k_028___smp.kmn rename to common/test/keyboards/baseline/k_0106___smp.kmn index 7c1eaaba960..3ce026ca4c7 100644 --- a/common/test/keyboards/baseline/k_028___smp.kmn +++ b/common/test/keyboards/baseline/k_0106___smp.kmn @@ -1,4 +1,4 @@ -store(&NAME) '028 - smp' +store(&NAME) '0106 - smp' c Description: Tests SMP characters; see #4361 [1-4], #5561 [5] c keys: [K_1][K_2][K_3][K_4][K_5] c expected: \U0001F601yx diff --git a/common/test/keyboards/baseline/k_0106___smp.kmx b/common/test/keyboards/baseline/k_0106___smp.kmx new file mode 100644 index 00000000000..cfbb429d0b7 Binary files /dev/null and b/common/test/keyboards/baseline/k_0106___smp.kmx differ diff --git a/common/test/keyboards/baseline/k_0107___punctkeys.js b/common/test/keyboards/baseline/k_0107___punctkeys.js new file mode 100644 index 00000000000..a5455156e99 --- /dev/null +++ b/common/test/keyboards/baseline/k_0107___punctkeys.js @@ -0,0 +1,100 @@ + +KeymanWeb.KR(new Keyboard_k_0107___punctkeys()); + +function Keyboard_k_0107___punctkeys() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0107___punctkeys"; + this.KN="0107 - punctkeys"; + this.KMINVER="6.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0000; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4000, 0xE2)) { + if(k.KCM(1,t,"a",1)){ + r=m=1; // Line 24 + k.KO(1,t,"p"); + } + } + else if(k.KKM(e, 0x4000, 0xDE)) { + if(k.KCM(1,t,"a",1)){ + r=m=1; // Line 23 + k.KO(1,t,"o"); + } + } + else if(k.KKM(e, 0x4000, 0xBC)) { + if(k.KCM(1,t,"a",1)){ + r=m=1; // Line 15 + k.KO(1,t,"g"); + } + } + else if(k.KKM(e, 0x4000, 0xBD)) { + if(k.KCM(1,t,"a",1)){ + r=m=1; // Line 16 + k.KO(1,t,"h"); + } + } + else if(k.KKM(e, 0x4000, 0xBE)) { + if(k.KCM(1,t,"a",1)){ + r=m=1; // Line 17 + k.KO(1,t,"i"); + } + } + else if(k.KKM(e, 0x4000, 0xBF)) { + if(k.KCM(1,t,"a",1)){ + r=m=1; // Line 18 + k.KO(1,t,"j"); + } + } + else if(k.KKM(e, 0x4000, 0xBA)) { + if(k.KCM(1,t,"a",1)){ + r=m=1; // Line 13 + k.KO(1,t,"e"); + } + } + else if(k.KKM(e, 0x4000, 0xBB)) { + if(k.KCM(1,t,"a",1)){ + r=m=1; // Line 14 + k.KO(1,t,"f"); + } + } + else if(k.KKM(e, 0x4000, 0xDB)) { + if(k.KCM(1,t,"a",1)){ + r=m=1; // Line 20 + k.KO(1,t,"l"); + } + } + else if(k.KKM(e, 0x4000, 0xDC)) { + if(k.KCM(1,t,"a",1)){ + r=m=1; // Line 21 + k.KO(1,t,"m"); + } + } + else if(k.KKM(e, 0x4000, 0xDD)) { + if(k.KCM(1,t,"a",1)){ + r=m=1; // Line 22 + k.KO(1,t,"n"); + } + } + else if(k.KKM(e, 0x4000, 0xC0)) { + if(k.KCM(1,t,"a",1)){ + r=m=1; // Line 19 + k.KO(1,t,"k"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_038___punctkeys.kmn b/common/test/keyboards/baseline/k_0107___punctkeys.kmn similarity index 92% rename from common/test/keyboards/baseline/k_038___punctkeys.kmn rename to common/test/keyboards/baseline/k_0107___punctkeys.kmn index 33f9c052973..86edfb9dc65 100644 --- a/common/test/keyboards/baseline/k_038___punctkeys.kmn +++ b/common/test/keyboards/baseline/k_0107___punctkeys.kmn @@ -1,13 +1,13 @@ -store(&NAME) '038 - punctkeys' +store(&NAME) '0107 - punctkeys' c Description: Tests punctuation keys (Unicode) c keys: [K_A][K_COLON][K_A][K_EQUAL][K_A][K_COMMA][K_A][K_HYPHEN][K_A][K_PERIOD][K_A][K_SLASH][K_A][K_BKQUOTE][K_A][K_LBRKT][K_A][K_BKSLASH][K_A][K_RBRKT][K_A][K_QUOTE][K_A][K_oE2] c expected: efghijklmnop -c context: +c context: store(&version) '6.0' begin Unicode > use(Main) - + group(Main) using keys 'a' + [K_COLON] > 'e' diff --git a/common/test/keyboards/baseline/k_0107___punctkeys.kmx b/common/test/keyboards/baseline/k_0107___punctkeys.kmx new file mode 100644 index 00000000000..d55d4d2c972 Binary files /dev/null and b/common/test/keyboards/baseline/k_0107___punctkeys.kmx differ diff --git a/common/test/keyboards/baseline/k_012___ralt.kmx b/common/test/keyboards/baseline/k_012___ralt.kmx deleted file mode 100644 index 3ac57c165b5..00000000000 Binary files a/common/test/keyboards/baseline/k_012___ralt.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_013___deadkeys.kmx b/common/test/keyboards/baseline/k_013___deadkeys.kmx deleted file mode 100644 index 7f93d7d9ae9..00000000000 Binary files a/common/test/keyboards/baseline/k_013___deadkeys.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_014___groups_and_virtual_keys.kmx b/common/test/keyboards/baseline/k_014___groups_and_virtual_keys.kmx deleted file mode 100644 index 03bb1508a55..00000000000 Binary files a/common/test/keyboards/baseline/k_014___groups_and_virtual_keys.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_015___ralt_2.kmn b/common/test/keyboards/baseline/k_015___ralt_2.kmn deleted file mode 100644 index 631bea8d8d8..00000000000 --- a/common/test/keyboards/baseline/k_015___ralt_2.kmn +++ /dev/null @@ -1,12 +0,0 @@ -store(&NAME) '015 - ralt 2' -c Description: Tests Right Alt processing with non-US kbds. -c keys: [K_A][K_B][K_C][RALT K_A] -c expected: abcd - -store(&VERSION) '9.0' - -begin Unicode > use(main) - -group(main) using keys - -'c' + [RAlt K_A] > "cd" diff --git a/common/test/keyboards/baseline/k_015___ralt_2.kmx b/common/test/keyboards/baseline/k_015___ralt_2.kmx deleted file mode 100644 index 0a5e1bbf434..00000000000 Binary files a/common/test/keyboards/baseline/k_015___ralt_2.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_017___space_mnemonic_kbd.kmx b/common/test/keyboards/baseline/k_017___space_mnemonic_kbd.kmx deleted file mode 100644 index ffb5e1ac098..00000000000 Binary files a/common/test/keyboards/baseline/k_017___space_mnemonic_kbd.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_018___nul_testing.kmx b/common/test/keyboards/baseline/k_018___nul_testing.kmx deleted file mode 100644 index 7c54781918f..00000000000 Binary files a/common/test/keyboards/baseline/k_018___nul_testing.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_019___multiple_deadkeys.kmx b/common/test/keyboards/baseline/k_019___multiple_deadkeys.kmx deleted file mode 100644 index fe22a2819a5..00000000000 Binary files a/common/test/keyboards/baseline/k_019___multiple_deadkeys.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_0200___ralt.js b/common/test/keyboards/baseline/k_0200___ralt.js new file mode 100644 index 00000000000..1e4672f5685 --- /dev/null +++ b/common/test/keyboards/baseline/k_0200___ralt.js @@ -0,0 +1,52 @@ + +KeymanWeb.KR(new Keyboard_k_0200___ralt()); + +function Keyboard_k_0200___ralt() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0200___ralt"; + this.KN="0200 - ralt"; + this.KMINVER="9.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0060; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.g_main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4000, 0x41)) { + if(1){ + r=m=1; // Line 14 + k.KO(0,t,"ז"); + } + } + else if(k.KKM(e, 0x4000, 0x4F)) { + if(1){ + r=m=1; // Line 15 + k.KO(0,t,"ר"); + } + } + else if(k.KKM(e, 0x4060, 0x41)) { + if(1){ + r=m=1; // Line 16 + k.KO(0,t,"b"); + } + } + else if(k.KKM(e, 0x4060, 0x4F)) { + if(1){ + r=m=1; // Line 17 + k.KO(0,t,"c"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_012___ralt.kmn b/common/test/keyboards/baseline/k_0200___ralt.kmn similarity index 78% rename from common/test/keyboards/baseline/k_012___ralt.kmn rename to common/test/keyboards/baseline/k_0200___ralt.kmn index 8e041ad99e0..5dd8e09ab1a 100644 --- a/common/test/keyboards/baseline/k_012___ralt.kmn +++ b/common/test/keyboards/baseline/k_0200___ralt.kmn @@ -1,9 +1,9 @@ -store(&NAME) '012 - ralt' +store(&NAME) '0200 - ralt' c Description: Tests Right Alt processing: requires Ctrl+Alt simulation off. c env.simulate_altgr: 0 c keys: [RALT K_A][RALT K_O][LCTRL LALT K_A][LCTRL LALT K_O] c expected: \u05d6\u05e8\u0062\u0063 -c context: +c context: store(&VERSION) '9.0' @@ -11,7 +11,7 @@ begin Unicode > use(main) group(main) using keys -+ [RAlt K_A] > U+05D6 ++ [RAlt K_A] > U+05D6 + [RAlt K_O] > U+05E8 -+ [Ctrl Alt K_A] > "b" ++ [Ctrl Alt K_A] > "b" + [Ctrl Alt K_O] > "c" diff --git a/common/test/keyboards/baseline/k_0200___ralt.kmx b/common/test/keyboards/baseline/k_0200___ralt.kmx new file mode 100644 index 00000000000..6fd03a1b6cb Binary files /dev/null and b/common/test/keyboards/baseline/k_0200___ralt.kmx differ diff --git a/common/test/keyboards/baseline/k_0201___ralt_2.js b/common/test/keyboards/baseline/k_0201___ralt_2.js new file mode 100644 index 00000000000..b4504c909d0 --- /dev/null +++ b/common/test/keyboards/baseline/k_0201___ralt_2.js @@ -0,0 +1,34 @@ + +KeymanWeb.KR(new Keyboard_k_0201___ralt_2()); + +function Keyboard_k_0201___ralt_2() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0201___ralt_2"; + this.KN="0201 - ralt 2"; + this.KMINVER="9.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0000; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.g_main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4000, 0x41)) { + if(k.KCM(1,t,"c",1)){ + r=m=1; // Line 13 + k.KO(1,t,"cd"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_0201___ralt_2.kmn b/common/test/keyboards/baseline/k_0201___ralt_2.kmn new file mode 100644 index 00000000000..d22af03e742 --- /dev/null +++ b/common/test/keyboards/baseline/k_0201___ralt_2.kmn @@ -0,0 +1,13 @@ +store(&VERSION) '9.0' +store(&NAME) '0201 - ralt 2' +c Description: Tests Right Alt processing with non-US kbds. +c keys: [K_A][K_B][K_C][RALT K_A][K_A][K_B][K_C][K_A] +c expected: abcdabca + +store(&TARGETS) 'any' + +begin Unicode > use(main) + +group(main) using keys + +'c' + [RAlt K_A] > "cd" diff --git a/common/test/keyboards/baseline/k_0201___ralt_2.kmx b/common/test/keyboards/baseline/k_0201___ralt_2.kmx new file mode 100644 index 00000000000..79ead9aea3c Binary files /dev/null and b/common/test/keyboards/baseline/k_0201___ralt_2.kmx differ diff --git a/common/test/keyboards/baseline/k_0202___alt.js b/common/test/keyboards/baseline/k_0202___alt.js new file mode 100644 index 00000000000..c0643cfca44 --- /dev/null +++ b/common/test/keyboards/baseline/k_0202___alt.js @@ -0,0 +1,34 @@ + +KeymanWeb.KR(new Keyboard_k_0202___alt()); + +function Keyboard_k_0202___alt() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0202___alt"; + this.KN="0202 - alt"; + this.KMINVER="9.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0040; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.g_main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4040, 0x41)) { + if(k.KCM(1,t,"c",1)){ + r=m=1; // Line 13 + k.KO(1,t,"cd"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_0202___alt.kmn b/common/test/keyboards/baseline/k_0202___alt.kmn new file mode 100755 index 00000000000..3c5415f7293 --- /dev/null +++ b/common/test/keyboards/baseline/k_0202___alt.kmn @@ -0,0 +1,13 @@ +store(&VERSION) '9.0' +store(&NAME) '0202 - alt' +c Description: Tests Alt processing with non-US kbds. +c keys: [K_A][K_B][K_C][RALT K_A][K_A][K_B][K_C][K_A] +c expected: abcdabca + +store(&TARGETS) 'any' + +begin Unicode > use(main) + +group(main) using keys + +'c' + [Alt K_A] > "cd" diff --git a/common/test/keyboards/baseline/k_0202___alt.kmx b/common/test/keyboards/baseline/k_0202___alt.kmx new file mode 100644 index 00000000000..14a61fc01b4 Binary files /dev/null and b/common/test/keyboards/baseline/k_0202___alt.kmx differ diff --git a/common/test/keyboards/baseline/k_0203___generic_ctrlalt.js b/common/test/keyboards/baseline/k_0203___generic_ctrlalt.js new file mode 100644 index 00000000000..de496127b2d --- /dev/null +++ b/common/test/keyboards/baseline/k_0203___generic_ctrlalt.js @@ -0,0 +1,40 @@ + +KeymanWeb.KR(new Keyboard_k_0203___generic_ctrlalt()); + +function Keyboard_k_0203___generic_ctrlalt() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0203___generic_ctrlalt"; + this.KN="0203 - generic ctrlalt"; + this.KMINVER="6.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0060; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4020, 0x42)) { + if(k.KCM(1,t,"a",1)){ + r=m=1; // Line 13 + k.KO(1,t,"b"); + } + } + else if(k.KKM(e, 0x4040, 0x43)) { + if(k.KCM(1,t,"a",1)){ + r=m=1; // Line 14 + k.KO(1,t,"c"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_039___generic_ctrlalt.kmn b/common/test/keyboards/baseline/k_0203___generic_ctrlalt.kmn similarity index 84% rename from common/test/keyboards/baseline/k_039___generic_ctrlalt.kmn rename to common/test/keyboards/baseline/k_0203___generic_ctrlalt.kmn index 1bbb1de6611..8221e7d62c0 100644 --- a/common/test/keyboards/baseline/k_039___generic_ctrlalt.kmn +++ b/common/test/keyboards/baseline/k_0203___generic_ctrlalt.kmn @@ -1,8 +1,8 @@ -store(&NAME) '039 - generic ctrlalt' +store(&NAME) '0203 - generic ctrlalt' c Description: Tests generic alt and control (Unicode) c keys: [K_A][K_A][LCTRL K_B][K_A][LALT K_C][K_A][RCTRL K_B][K_A][RALT K_C] c expected: abcbc -c context: +c context: store(&version) '6.0' diff --git a/common/test/keyboards/baseline/k_0203___generic_ctrlalt.kmx b/common/test/keyboards/baseline/k_0203___generic_ctrlalt.kmx new file mode 100644 index 00000000000..c2ac5c2f2f2 Binary files /dev/null and b/common/test/keyboards/baseline/k_0203___generic_ctrlalt.kmx differ diff --git a/common/test/keyboards/baseline/k_021___options.kmx b/common/test/keyboards/baseline/k_021___options.kmx deleted file mode 100644 index f35da34878a..00000000000 Binary files a/common/test/keyboards/baseline/k_021___options.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_022___options_with_preset.kmx b/common/test/keyboards/baseline/k_022___options_with_preset.kmx deleted file mode 100644 index e681df83394..00000000000 Binary files a/common/test/keyboards/baseline/k_022___options_with_preset.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_023___options_with_save.kmx b/common/test/keyboards/baseline/k_023___options_with_save.kmx deleted file mode 100644 index 3668b7a066e..00000000000 Binary files a/common/test/keyboards/baseline/k_023___options_with_save.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_024___options_with_save_and_preset.kmx b/common/test/keyboards/baseline/k_024___options_with_save_and_preset.kmx deleted file mode 100644 index 1fecdfac213..00000000000 Binary files a/common/test/keyboards/baseline/k_024___options_with_save_and_preset.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_025___options_with_reset.kmx b/common/test/keyboards/baseline/k_025___options_with_reset.kmx deleted file mode 100644 index 028f81cb5fe..00000000000 Binary files a/common/test/keyboards/baseline/k_025___options_with_reset.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_026___system_stores.kmx b/common/test/keyboards/baseline/k_026___system_stores.kmx deleted file mode 100644 index bb918cf1429..00000000000 Binary files a/common/test/keyboards/baseline/k_026___system_stores.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_027___system_stores_2.kmx b/common/test/keyboards/baseline/k_027___system_stores_2.kmx deleted file mode 100644 index dac90ab985b..00000000000 Binary files a/common/test/keyboards/baseline/k_027___system_stores_2.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_028___smp.kmx b/common/test/keyboards/baseline/k_028___smp.kmx deleted file mode 100644 index f343f969e9b..00000000000 Binary files a/common/test/keyboards/baseline/k_028___smp.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_029___beep.kmx b/common/test/keyboards/baseline/k_029___beep.kmx deleted file mode 100644 index abf8b899836..00000000000 Binary files a/common/test/keyboards/baseline/k_029___beep.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_0300___deadkeys.js b/common/test/keyboards/baseline/k_0300___deadkeys.js new file mode 100644 index 00000000000..0ceda698246 --- /dev/null +++ b/common/test/keyboards/baseline/k_0300___deadkeys.js @@ -0,0 +1,40 @@ + +KeymanWeb.KR(new Keyboard_k_0300___deadkeys()); + +function Keyboard_k_0300___deadkeys() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0300___deadkeys"; + this.KN="0300 - deadkeys"; + this.KMINVER="9.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0010; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.g_main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4010, 0x36)) { + if(1){ + r=m=1; // Line 13 + k.KDO(0,t,0); + } + } + else if(k.KKM(e, 0x4000, 0x41)) { + if(k.KDM(0,t,0)){ + r=m=1; // Line 15 + k.KO(0,t,"â"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_013___deadkeys.kmn b/common/test/keyboards/baseline/k_0300___deadkeys.kmn similarity index 87% rename from common/test/keyboards/baseline/k_013___deadkeys.kmn rename to common/test/keyboards/baseline/k_0300___deadkeys.kmn index d0f4876455e..528a0929a01 100644 --- a/common/test/keyboards/baseline/k_013___deadkeys.kmn +++ b/common/test/keyboards/baseline/k_0300___deadkeys.kmn @@ -1,4 +1,4 @@ -store(&NAME) '013 - deadkeys' +store(&NAME) '0300 - deadkeys' c Description: Tests a simple deadkey rule in Unicode c keys: [SHIFT K_6][K_A] c expected: \u00E2 diff --git a/common/test/keyboards/baseline/k_0300___deadkeys.kmx b/common/test/keyboards/baseline/k_0300___deadkeys.kmx new file mode 100644 index 00000000000..a575f19954b Binary files /dev/null and b/common/test/keyboards/baseline/k_0300___deadkeys.kmx differ diff --git a/common/test/keyboards/baseline/k_0301___multiple_deadkeys.js b/common/test/keyboards/baseline/k_0301___multiple_deadkeys.js new file mode 100644 index 00000000000..67b3f4987c4 --- /dev/null +++ b/common/test/keyboards/baseline/k_0301___multiple_deadkeys.js @@ -0,0 +1,176 @@ + +KeymanWeb.KR(new Keyboard_k_0301___multiple_deadkeys()); + +function Keyboard_k_0301___multiple_deadkeys() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0301___multiple_deadkeys"; + this.KN="0301 - multiple deadkeys"; + this.KMINVER="9.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0000; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.g_main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4000, 0x31)) { + if(1){ + r=m=1; // Line 22 + k.KDO(0,t,0); + } + } + else if(k.KKM(e, 0x4000, 0x32)) { + if(1){ + r=m=1; // Line 25 + k.KO(0,t,"a"); + k.KDO(-1,t,1); + } + } + else if(k.KKM(e, 0x4000, 0x33)) { + if(1){ + r=m=1; // Line 28 + k.KDO(0,t,2); + k.KO(-1,t,"a"); + } + } + else if(k.KKM(e, 0x4000, 0x34)) { + if(1){ + r=m=1; // Line 31 + k.KDO(0,t,3); + k.KDO(-1,t,4); + } + } + else if(k.KKM(e, 0x4000, 0x35)) { + if(1){ + r=m=1; // Line 34 + k.KO(0,t,"a"); + k.KDO(-1,t,5); + k.KDO(-1,t,6); + } + } + else if(k.KKM(e, 0x4000, 0x36)) { + if(1){ + r=m=1; // Line 37 + k.KO(0,t,"a"); + k.KDO(-1,t,7); + k.KDO(-1,t,8); + k.KO(-1,t,"b"); + } + } + else if(k.KKM(e, 0x4000, 0x37)) { + if(1){ + r=m=1; // Line 40 + k.KDO(0,t,9); + k.KDO(-1,t,10); + k.KO(-1,t,"a"); + } + } + else if(k.KKM(e, 0x4000, 0x38)) { + if(1){ + r=m=1; // Line 45 + k.KDO(0,t,11); + k.KDO(-1,t,12); + k.KDO(-1,t,13); + } + } + else if(k.KKM(e, 0x4000, 0x39)) { + if(1){ + r=m=1; // Line 56 + k.KO(0,t,"{"); + k.KDO(-1,t,14); + k.KDO(-1,t,15); + k.KO(-1,t,"}"); + k.KDO(-1,t,16); + k.KDO(-1,t,17); + } + } + else if(k.KKM(e, 0x4000, 0x58)) { + if(k.KCM(2,t,"{",1)&&k.KDM(1,t,14)&&k.KDM(1,t,18)&&k.KCM(1,t,"}",1)&&k.KDM(0,t,19)&&k.KDM(0,t,20)){ + r=m=1; // Line 59 + k.KO(2,t,"9=OK"); + } + else if(k.KCM(2,t,"a",1)&&k.KDM(1,t,7)&&k.KDM(1,t,8)&&k.KCM(1,t,"b",1)){ + r=m=1; // Line 38 + k.KO(2,t,"6=OK "); + } + else if(k.KDM(1,t,15)&&k.KCM(1,t,"}",1)&&k.KDM(0,t,16)&&k.KDM(0,t,17)){ + r=m=1; // Line 58 + k.KDO(1,t,18); + k.KO(-1,t,"}"); + k.KDO(-1,t,19); + k.KDO(-1,t,20); + } + else if(k.KCM(1,t,"a",1)&&k.KDM(0,t,5)&&k.KDM(0,t,6)){ + r=m=1; // Line 35 + k.KO(1,t,"5=OK "); + } + else if(k.KDM(1,t,9)&&k.KDM(1,t,10)&&k.KCM(1,t,"a",1)){ + r=m=1; // Line 41 + k.KO(1,t,"7=OK "); + } + else if(k.KDM(0,t,11)&&k.KDM(0,t,12)&&k.KDM(0,t,13)){ + r=m=1; // Line 46 + k.KO(0,t,"8=OK "); + } + else if(k.KCM(1,t,"a",1)&&k.KDM(0,t,1)){ + r=m=1; // Line 26 + k.KO(1,t,"2=OK "); + } + else if(k.KDM(1,t,2)&&k.KCM(1,t,"a",1)){ + r=m=1; // Line 29 + k.KO(1,t,"3=OK "); + } + else if(k.KDM(0,t,3)&&k.KDM(0,t,4)){ + r=m=1; // Line 32 + k.KO(0,t,"4=OK "); + } + else if(k.KDM(1,t,9)&&k.KCM(1,t,"a",1)){ + r=m=1; // Line 42 + k.KO(1,t,"7=Fail1 "); + } + else if(k.KDM(1,t,10)&&k.KCM(1,t,"a",1)){ + r=m=1; // Line 43 + k.KO(1,t,"7=Fail2 "); + } + else if(k.KDM(0,t,11)&&k.KDM(0,t,12)){ + r=m=1; // Line 50 + k.KO(0,t,"8=Fail4 "); + } + else if(k.KDM(0,t,11)&&k.KDM(0,t,13)){ + r=m=1; // Line 51 + k.KO(0,t,"8=Fail5 "); + } + else if(k.KDM(0,t,12)&&k.KDM(0,t,13)){ + r=m=1; // Line 52 + k.KO(0,t,"8=Fail6 "); + } + else if(k.KDM(0,t,0)){ + r=m=1; // Line 23 + k.KO(0,t,"1=OK "); + } + else if(k.KDM(0,t,11)){ + r=m=1; // Line 47 + k.KO(0,t,"8=Fail1 "); + } + else if(k.KDM(0,t,12)){ + r=m=1; // Line 48 + k.KO(0,t,"8=Fail2 "); + } + else if(k.KDM(0,t,13)){ + r=m=1; // Line 49 + k.KO(0,t,"8=Fail3 "); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_019___multiple_deadkeys.kmn b/common/test/keyboards/baseline/k_0301___multiple_deadkeys.kmn similarity index 97% rename from common/test/keyboards/baseline/k_019___multiple_deadkeys.kmn rename to common/test/keyboards/baseline/k_0301___multiple_deadkeys.kmn index e70b30f08c5..ea7b8535816 100644 --- a/common/test/keyboards/baseline/k_019___multiple_deadkeys.kmn +++ b/common/test/keyboards/baseline/k_0301___multiple_deadkeys.kmn @@ -1,4 +1,4 @@ -store(&NAME) '019 - multiple deadkeys' +store(&NAME) '0301 - multiple deadkeys' c Description: Tests deadkey scenarios c 1. One deadkey in context dk(1) + '1' c 2. One char and one deadkey in context 'a' dk(2) + '2' diff --git a/common/test/keyboards/baseline/k_0301___multiple_deadkeys.kmx b/common/test/keyboards/baseline/k_0301___multiple_deadkeys.kmx new file mode 100644 index 00000000000..68804c91dd9 Binary files /dev/null and b/common/test/keyboards/baseline/k_0301___multiple_deadkeys.kmx differ diff --git a/common/test/keyboards/baseline/k_0302___deadkeys_and_backspace.js b/common/test/keyboards/baseline/k_0302___deadkeys_and_backspace.js new file mode 100644 index 00000000000..2322275bdde --- /dev/null +++ b/common/test/keyboards/baseline/k_0302___deadkeys_and_backspace.js @@ -0,0 +1,93 @@ + +KeymanWeb.KR(new Keyboard_k_0302___deadkeys_and_backspace()); + +function Keyboard_k_0302___deadkeys_and_backspace() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0302___deadkeys_and_backspace"; + this.KN="0302- deadkeys and backspace"; + this.KMINVER="9.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0000; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.g_main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4000, 0x08)) { + if(k.KCM(2,t,"c",1)&&k.KDM(1,t,11)&&k.KCM(1,t,"d",1)){ + r=m=1; // Line 32 + k.KO(2,t," ok"); + } + else if(k.KCM(2,t,"cd",2)){ + r=m=1; // Line 31 + k.KO(2,t," fail"); + } + } + else if(k.KKM(e, 0x4000, 0x31)) { + if(1){ + r=m=1; // Line 24 + k.KDO(0,t,0); + } + } + else if(k.KKM(e, 0x4000, 0x32)) { + if(1){ + r=m=1; // Line 25 + k.KO(0,t,"a"); + k.KDO(-1,t,1); + } + } + else if(k.KKM(e, 0x4000, 0x33)) { + if(1){ + r=m=1; // Line 26 + k.KDO(0,t,2); + k.KO(-1,t,"a"); + } + } + else if(k.KKM(e, 0x4000, 0x34)) { + if(1){ + r=m=1; // Line 27 + k.KDO(0,t,3); + k.KDO(-1,t,4); + } + } + else if(k.KKM(e, 0x4000, 0x35)) { + if(1){ + r=m=1; // Line 28 + k.KO(0,t,"a"); + k.KDO(-1,t,5); + k.KDO(-1,t,6); + k.KO(-1,t,"b"); + } + } + else if(k.KKM(e, 0x4000, 0x36)) { + if(1){ + r=m=1; // Line 29 + k.KO(0,t,"a"); + k.KDO(-1,t,7); + k.KDO(-1,t,8); + k.KO(-1,t,"b"); + k.KDO(-1,t,9); + k.KDO(-1,t,10); + } + } + else if(k.KKM(e, 0x4000, 0x37)) { + if(1){ + r=m=1; // Line 30 + k.KO(0,t,"c"); + k.KDO(-1,t,11); + k.KO(-1,t,"de"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_020___deadkeys_and_backspace.kmn b/common/test/keyboards/baseline/k_0302___deadkeys_and_backspace.kmn similarity index 96% rename from common/test/keyboards/baseline/k_020___deadkeys_and_backspace.kmn rename to common/test/keyboards/baseline/k_0302___deadkeys_and_backspace.kmn index af7c80f21d9..8049e44a86c 100644 --- a/common/test/keyboards/baseline/k_020___deadkeys_and_backspace.kmn +++ b/common/test/keyboards/baseline/k_0302___deadkeys_and_backspace.kmn @@ -1,4 +1,4 @@ -store(&NAME) '020 - deadkeys and backspace' +store(&NAME) '0302- deadkeys and backspace' c Description: Tests deadkey backspacing c 1. One deadkey in context dk(1) + BKSP = nul c 2. One char and one deadkey in context 'a' dk(2) + BKSP = nul diff --git a/common/test/keyboards/baseline/k_020___deadkeys_and_backspace.kmx b/common/test/keyboards/baseline/k_0302___deadkeys_and_backspace.kmx similarity index 87% rename from common/test/keyboards/baseline/k_020___deadkeys_and_backspace.kmx rename to common/test/keyboards/baseline/k_0302___deadkeys_and_backspace.kmx index 68271160736..71e4f50f3ed 100644 Binary files a/common/test/keyboards/baseline/k_020___deadkeys_and_backspace.kmx and b/common/test/keyboards/baseline/k_0302___deadkeys_and_backspace.kmx differ diff --git a/common/test/keyboards/baseline/k_031___caps_lock.kmx b/common/test/keyboards/baseline/k_031___caps_lock.kmx deleted file mode 100644 index 5fe3e4fbd74..00000000000 Binary files a/common/test/keyboards/baseline/k_031___caps_lock.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_032___caps_control.kmx b/common/test/keyboards/baseline/k_032___caps_control.kmx deleted file mode 100644 index 1914d1954bb..00000000000 Binary files a/common/test/keyboards/baseline/k_032___caps_control.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_033___caps_always_off.kmx b/common/test/keyboards/baseline/k_033___caps_always_off.kmx deleted file mode 100644 index cb9a71a0460..00000000000 Binary files a/common/test/keyboards/baseline/k_033___caps_always_off.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_034___options_double_set_reset.kmx b/common/test/keyboards/baseline/k_034___options_double_set_reset.kmx deleted file mode 100644 index df8eb8062a5..00000000000 Binary files a/common/test/keyboards/baseline/k_034___options_double_set_reset.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_035___options_double_set_staged.kmx b/common/test/keyboards/baseline/k_035___options_double_set_staged.kmx deleted file mode 100644 index e112a0740f5..00000000000 Binary files a/common/test/keyboards/baseline/k_035___options_double_set_staged.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_037___options___double_reset.kmx b/common/test/keyboards/baseline/k_037___options___double_reset.kmx deleted file mode 100644 index eed688349c9..00000000000 Binary files a/common/test/keyboards/baseline/k_037___options___double_reset.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_038___punctkeys.kmx b/common/test/keyboards/baseline/k_038___punctkeys.kmx deleted file mode 100644 index 8166409f5f3..00000000000 Binary files a/common/test/keyboards/baseline/k_038___punctkeys.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_039___generic_ctrlalt.kmx b/common/test/keyboards/baseline/k_039___generic_ctrlalt.kmx deleted file mode 100644 index 1bf180a31c8..00000000000 Binary files a/common/test/keyboards/baseline/k_039___generic_ctrlalt.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_0400___groups_and_virtual_keys.js b/common/test/keyboards/baseline/k_0400___groups_and_virtual_keys.js new file mode 100644 index 00000000000..32aebaea242 --- /dev/null +++ b/common/test/keyboards/baseline/k_0400___groups_and_virtual_keys.js @@ -0,0 +1,69 @@ + +KeymanWeb.KR(new Keyboard_k_0400___groups_and_virtual_keys()); + +function Keyboard_k_0400___groups_and_virtual_keys() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0400___groups_and_virtual_keys"; + this.KN="0400 - groups and virtual keys"; + this.KMINVER="9.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0070; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_UMain_0(t,e); + }; + this.gs=function(t,e) { + return this.g_UMain_0(t,e); + }; + this.g_UMain_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4020, 0x32)) { + if(1){ + r=m=1; // Line 16 + k.KDO(0,t,0); + } + } + else if(k.KKM(e, 0x4040, 0x32)) { + if(1){ + r=m=1; // Line 17 + k.KDO(0,t,0); + } + } + else if(k.KKM(e, 0x4010, 0x32)) { + if(1){ + r=m=1; // Line 18 + k.KDO(0,t,1); + } + } + else if(k.KKM(e, 0x4000, 0x41)) { + if(1){ + r=m=1; // Line 15 + k.KO(0,t,"α"); + } + } + if(m==1) { + + r=this.g_DK1_1(t,e); + m=2; + } + return r; + }; + this.g_DK1_1=function(t,e) { + var k=KeymanWeb,r=1,m=0; + if(k.KDM(1,t,0)&&k.KCM(1,t,"α",1)){ + m=1; // Line 25 + k.KO(1,t,"ᾱ"); + } + else if(k.KDM(1,t,1)&&k.KCM(1,t,"α",1)){ + m=1; // Line 26 + k.KO(1,t,"ᾰ"); + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_014___groups_and_virtual_keys.kmn b/common/test/keyboards/baseline/k_0400___groups_and_virtual_keys.kmn similarity index 92% rename from common/test/keyboards/baseline/k_014___groups_and_virtual_keys.kmn rename to common/test/keyboards/baseline/k_0400___groups_and_virtual_keys.kmn index 0e32c432eb6..67e63340a1c 100644 --- a/common/test/keyboards/baseline/k_014___groups_and_virtual_keys.kmn +++ b/common/test/keyboards/baseline/k_0400___groups_and_virtual_keys.kmn @@ -1,4 +1,4 @@ -store(&NAME) '014 - groups and virtual keys' +store(&NAME) '0400 - groups and virtual keys' c Description: Tests multiple groups and virtual keys with mnemonic layout c keys: [K_A][SHIFT K_2][K_A][LCTRL K_2][K_A] c expected: \u03B1\u1FB0\u1FB1 diff --git a/common/test/keyboards/baseline/k_0400___groups_and_virtual_keys.kmx b/common/test/keyboards/baseline/k_0400___groups_and_virtual_keys.kmx new file mode 100644 index 00000000000..c0ab17f6577 Binary files /dev/null and b/common/test/keyboards/baseline/k_0400___groups_and_virtual_keys.kmx differ diff --git a/common/test/keyboards/baseline/k_0401___multiple_groups.js b/common/test/keyboards/baseline/k_0401___multiple_groups.js new file mode 100644 index 00000000000..12bc00f9e61 --- /dev/null +++ b/common/test/keyboards/baseline/k_0401___multiple_groups.js @@ -0,0 +1,73 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0401___multiple_groups()); +} +function Keyboard_k_0401___multiple_groups() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0401___multiple_groups"; + this.KN="401 - multiple groups"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 13 + k.KDC(0,t); + k.KO(-1,t,"a"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_2 /* 0x32 */)) { + if(k.KFCM(1,t,['b'])){ + r=m=1; // Line 14 + k.KDC(1,t); + k.KO(-1,t,"b"); + r=this.g_b_2(t,e); + m=2; + } + } + if(m==1) { + + k.KDC(-1,t); + r=this.g_a_1(t,e); + m=2; + } + return r; + }; + this.g_a_1=function(t,e) { + var k=KeymanWeb,r=1,m=0; + if(k.KFCM(1,t,['a'])){ + m=1; // Line 20 + k.KDC(1,t); + k.KO(-1,t,"b"); + } + return r; + }; + this.g_b_2=function(t,e) { + var k=KeymanWeb,r=1,m=0; + if(k.KFCM(1,t,['b'])){ + m=1; // Line 24 + k.KDC(1,t); + k.KO(-1,t,"abc"); + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_030___multiple_groups.kmn b/common/test/keyboards/baseline/k_0401___multiple_groups.kmn similarity index 90% rename from common/test/keyboards/baseline/k_030___multiple_groups.kmn rename to common/test/keyboards/baseline/k_0401___multiple_groups.kmn index b9148827bc8..87097387aa2 100644 --- a/common/test/keyboards/baseline/k_030___multiple_groups.kmn +++ b/common/test/keyboards/baseline/k_0401___multiple_groups.kmn @@ -1,4 +1,4 @@ -store(&NAME) "030 - multiple groups" +store(&NAME) "401 - multiple groups" c Description: Tests multiple groups. Purpose here is to interleave output and backspaces from kmx processor to consumer c keys: [K_1][K_2] c expected: abc diff --git a/common/test/keyboards/baseline/k_030___multiple_groups.kmx b/common/test/keyboards/baseline/k_0401___multiple_groups.kmx similarity index 67% rename from common/test/keyboards/baseline/k_030___multiple_groups.kmx rename to common/test/keyboards/baseline/k_0401___multiple_groups.kmx index e27ee4dd08c..415a932ccb7 100644 Binary files a/common/test/keyboards/baseline/k_030___multiple_groups.kmx and b/common/test/keyboards/baseline/k_0401___multiple_groups.kmx differ diff --git a/common/test/keyboards/baseline/k_0402___output_and_keystroke.js b/common/test/keyboards/baseline/k_0402___output_and_keystroke.js new file mode 100644 index 00000000000..aa1e8903298 --- /dev/null +++ b/common/test/keyboards/baseline/k_0402___output_and_keystroke.js @@ -0,0 +1,87 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0402___output_and_keystroke()); +} +function Keyboard_k_0402___output_and_keystroke() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0402___output_and_keystroke"; + this.KN="0402 - output and keystroke"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 13 + k.KDC(0,t); + k.KO(-1,t,"a"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_2 /* 0x32 */)) { + if(k.KFCM(1,t,['b'])){ + r=m=1; // Line 14 + k.KDC(1,t); + k.KO(-1,t,"b"); + r=this.g_b_2(t,e); + m=2; + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_3 /* 0x33 */)) { + if(k.KFCM(3,t,['a','b','c'])){ + r=m=1; // Line 15 + k.KDC(3,t); + k.KO(-1,t,"a"); + k.KO(-1,t,"bd"); + r=this.g_emit_3(t,e); + m=2; + } + } + if(m==1) { + + k.KDC(-1,t); + r=this.g_a_1(t,e); + m=2; + } + return r; + }; + this.g_a_1=function(t,e) { + var k=KeymanWeb,r=1,m=0; + if(k.KFCM(1,t,['a'])){ + m=1; // Line 21 + k.KDC(1,t); + k.KO(-1,t,"b"); + } + return r; + }; + this.g_b_2=function(t,e) { + var k=KeymanWeb,r=1,m=0; + if(k.KFCM(1,t,['b'])){ + m=1; // Line 25 + k.KDC(1,t); + k.KO(-1,t,"abc"); + } + return r; + }; + this.g_emit_3=function(t,e) { + var k=KeymanWeb,r=0,m=0; + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_043___output_and_keystroke.kmn b/common/test/keyboards/baseline/k_0402___output_and_keystroke.kmn similarity index 90% rename from common/test/keyboards/baseline/k_043___output_and_keystroke.kmn rename to common/test/keyboards/baseline/k_0402___output_and_keystroke.kmn index 4c6409c1c71..dd8df421841 100644 --- a/common/test/keyboards/baseline/k_043___output_and_keystroke.kmn +++ b/common/test/keyboards/baseline/k_0402___output_and_keystroke.kmn @@ -1,4 +1,4 @@ -store(&NAME) '043 - output and keystroke' +store(&NAME) '0402 - output and keystroke' c Description: Tests the 'emit default key' function by having an empty 'using keys' final group c keys: [K_1][K_2][K_3] c expected: abd3 diff --git a/common/test/keyboards/baseline/k_0402___output_and_keystroke.kmx b/common/test/keyboards/baseline/k_0402___output_and_keystroke.kmx new file mode 100644 index 00000000000..a6a883d2fd2 Binary files /dev/null and b/common/test/keyboards/baseline/k_0402___output_and_keystroke.kmx differ diff --git a/common/test/keyboards/baseline/k_040___long_context.kmx b/common/test/keyboards/baseline/k_040___long_context.kmx deleted file mode 100644 index 55a88a77abb..00000000000 Binary files a/common/test/keyboards/baseline/k_040___long_context.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_041___long_context_and_deadkeys.kmx b/common/test/keyboards/baseline/k_041___long_context_and_deadkeys.kmx deleted file mode 100644 index de2b1d5020c..00000000000 Binary files a/common/test/keyboards/baseline/k_041___long_context_and_deadkeys.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_042___long_context_and_split_deadkeys.kmx b/common/test/keyboards/baseline/k_042___long_context_and_split_deadkeys.kmx deleted file mode 100644 index fbe552d53b0..00000000000 Binary files a/common/test/keyboards/baseline/k_042___long_context_and_split_deadkeys.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_043___output_and_keystroke.kmx b/common/test/keyboards/baseline/k_043___output_and_keystroke.kmx deleted file mode 100644 index a25aae26a64..00000000000 Binary files a/common/test/keyboards/baseline/k_043___output_and_keystroke.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_044___if_and_context.kmx b/common/test/keyboards/baseline/k_044___if_and_context.kmx deleted file mode 100644 index 60c0c6300a6..00000000000 Binary files a/common/test/keyboards/baseline/k_044___if_and_context.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_045___deadkey_and_context.kmx b/common/test/keyboards/baseline/k_045___deadkey_and_context.kmx deleted file mode 100644 index 4b1e3bfb2aa..00000000000 Binary files a/common/test/keyboards/baseline/k_045___deadkey_and_context.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_046___deadkey_and_contextex.kmx b/common/test/keyboards/baseline/k_046___deadkey_and_contextex.kmx deleted file mode 100644 index 618eefbf27f..00000000000 Binary files a/common/test/keyboards/baseline/k_046___deadkey_and_contextex.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_047___caps_always_off_initially_on.kmx b/common/test/keyboards/baseline/k_047___caps_always_off_initially_on.kmx deleted file mode 100644 index 301fcddc046..00000000000 Binary files a/common/test/keyboards/baseline/k_047___caps_always_off_initially_on.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_048___modifier_keys_keep_context.kmx b/common/test/keyboards/baseline/k_048___modifier_keys_keep_context.kmx deleted file mode 100644 index 98ca5a6dbe3..00000000000 Binary files a/common/test/keyboards/baseline/k_048___modifier_keys_keep_context.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_049___enter_invalidates_context.kmx b/common/test/keyboards/baseline/k_049___enter_invalidates_context.kmx deleted file mode 100644 index 916a4a46625..00000000000 Binary files a/common/test/keyboards/baseline/k_049___enter_invalidates_context.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_0500___options.js b/common/test/keyboards/baseline/k_0500___options.js new file mode 100644 index 00000000000..a9eb29cc71d --- /dev/null +++ b/common/test/keyboards/baseline/k_0500___options.js @@ -0,0 +1,64 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0500___options()); +} +function Keyboard_k_0500___options() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0500___options"; + this.KN="0500 - options"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.s_foo_4=KeymanWeb.KLOAD(this.KI,"foo","0"); + this.s7="1"; + this.s8="0"; + this.s9="1"; + this.s10="0"; + this.KVS=['s_foo_4']; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_0 /* 0x30 */)) { + if(1){ + r=m=1; // Line 18 + k.KDC(0,t); + this.s_foo_4=this.s10; + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 17 + k.KDC(0,t); + this.s_foo_4=this.s9; + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_A /* 0x41 */)) { + if(this.s_foo_4===this.s7){ + r=m=1; // Line 15 + k.KDC(0,t); + k.KO(-1,t,"foo."); + } + else if(this.s_foo_4===this.s8){ + r=m=1; // Line 16 + k.KDC(0,t); + k.KO(-1,t,"no foo."); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_021___options.kmn b/common/test/keyboards/baseline/k_0500___options.kmn similarity index 88% rename from common/test/keyboards/baseline/k_021___options.kmn rename to common/test/keyboards/baseline/k_0500___options.kmn index 3851896b84e..428168cadbc 100644 --- a/common/test/keyboards/baseline/k_021___options.kmn +++ b/common/test/keyboards/baseline/k_0500___options.kmn @@ -1,8 +1,8 @@ -store(&NAME) '021 - options' +store(&NAME) '0500 - options' c Description: Tests basic option rules c keys: [K_A][K_1][K_A][K_0][K_A] c expected: no foo.foo.no foo. -c context: +c context: store(&version) '10.0' diff --git a/common/test/keyboards/baseline/k_0500___options.kmx b/common/test/keyboards/baseline/k_0500___options.kmx new file mode 100644 index 00000000000..df17de841b1 Binary files /dev/null and b/common/test/keyboards/baseline/k_0500___options.kmx differ diff --git a/common/test/keyboards/baseline/k_0501___options_with_preset.js b/common/test/keyboards/baseline/k_0501___options_with_preset.js new file mode 100644 index 00000000000..bf48622b987 --- /dev/null +++ b/common/test/keyboards/baseline/k_0501___options_with_preset.js @@ -0,0 +1,66 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0501___options_with_preset()); +} +function Keyboard_k_0501___options_with_preset() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0501___options_with_preset"; + this.KN="0501 - options with preset"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.s_foo_4=KeymanWeb.KLOAD(this.KI,"foo","0"); + this.s7="1"; + this.s8="0"; + this.s9="1"; + this.s10="0"; + this.KVS=['s_foo_4']; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_0 /* 0x30 */)) { + if(1){ + r=m=1; // Line 21 + k.KDC(0,t); + this.s_foo_4=this.s10; + k.KSAVE("foo",this.s_foo_4); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 20 + k.KDC(0,t); + this.s_foo_4=this.s9; + k.KSAVE("foo",this.s_foo_4); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_A /* 0x41 */)) { + if(this.s_foo_4===this.s7){ + r=m=1; // Line 18 + k.KDC(0,t); + k.KO(-1,t,"foo."); + } + else if(this.s_foo_4===this.s8){ + r=m=1; // Line 19 + k.KDC(0,t); + k.KO(-1,t,"no foo."); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_022___options_with_preset.kmn b/common/test/keyboards/baseline/k_0501___options_with_preset.kmn similarity index 88% rename from common/test/keyboards/baseline/k_022___options_with_preset.kmn rename to common/test/keyboards/baseline/k_0501___options_with_preset.kmn index dbaad6e63c8..98184fca342 100644 --- a/common/test/keyboards/baseline/k_022___options_with_preset.kmn +++ b/common/test/keyboards/baseline/k_0501___options_with_preset.kmn @@ -1,8 +1,8 @@ -store(&NAME) '022 - options with preset' +store(&NAME) '0501 - options with preset' c Description: Tests basic option rules with a preset supplied c keys: [K_A][K_1][K_A][K_0][K_A] c expected: foo.foo.no foo. -c context: +c context: c option: foo=1 c expected option: foo=0 c saved option: foo=0 diff --git a/common/test/keyboards/baseline/k_0501___options_with_preset.kmx b/common/test/keyboards/baseline/k_0501___options_with_preset.kmx new file mode 100644 index 00000000000..0ed8c43f5e5 Binary files /dev/null and b/common/test/keyboards/baseline/k_0501___options_with_preset.kmx differ diff --git a/common/test/keyboards/baseline/k_0502___options_with_save.js b/common/test/keyboards/baseline/k_0502___options_with_save.js new file mode 100644 index 00000000000..26c4fa041bd --- /dev/null +++ b/common/test/keyboards/baseline/k_0502___options_with_save.js @@ -0,0 +1,71 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0502___options_with_save()); +} +function Keyboard_k_0502___options_with_save() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0502___options_with_save"; + this.KN="0502 - options with save"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.s_foo_4=KeymanWeb.KLOAD(this.KI,"foo","0"); + this.s7="1"; + this.s8="0"; + this.s9="1"; + this.s10="0"; + this.KVS=['s_foo_4']; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_0 /* 0x30 */)) { + if(1){ + r=m=1; // Line 20 + k.KDC(0,t); + this.s_foo_4=this.s10; + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 19 + k.KDC(0,t); + this.s_foo_4=this.s9; + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_2 /* 0x32 */)) { + if(1){ + r=m=1; // Line 21 + k.KDC(0,t); + k.KSAVE("foo",this.s_foo_4); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_A /* 0x41 */)) { + if(this.s_foo_4===this.s7){ + r=m=1; // Line 17 + k.KDC(0,t); + k.KO(-1,t,"foo."); + } + else if(this.s_foo_4===this.s8){ + r=m=1; // Line 18 + k.KDC(0,t); + k.KO(-1,t,"no foo."); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_023___options_with_save.kmn b/common/test/keyboards/baseline/k_0502___options_with_save.kmn similarity index 88% rename from common/test/keyboards/baseline/k_023___options_with_save.kmn rename to common/test/keyboards/baseline/k_0502___options_with_save.kmn index 913bea076f3..987b30055c0 100644 --- a/common/test/keyboards/baseline/k_023___options_with_save.kmn +++ b/common/test/keyboards/baseline/k_0502___options_with_save.kmn @@ -1,8 +1,8 @@ -store(&NAME) '023 - options with save' +store(&NAME) '0502 - options with save' c Description: Tests basic option rules with save c keys: [K_A][K_1][K_A][K_0][K_A][K_2] c expected: no foo.foo.no foo. -c context: +c context: c expected option: foo=0 c saved option: foo=0 diff --git a/common/test/keyboards/baseline/k_0502___options_with_save.kmx b/common/test/keyboards/baseline/k_0502___options_with_save.kmx new file mode 100644 index 00000000000..5277a9c6e31 Binary files /dev/null and b/common/test/keyboards/baseline/k_0502___options_with_save.kmx differ diff --git a/common/test/keyboards/baseline/k_0503___options_with_save_and_preset.js b/common/test/keyboards/baseline/k_0503___options_with_save_and_preset.js new file mode 100644 index 00000000000..0ce89bd875a --- /dev/null +++ b/common/test/keyboards/baseline/k_0503___options_with_save_and_preset.js @@ -0,0 +1,72 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0503___options_with_save_and_preset()); +} +function Keyboard_k_0503___options_with_save_and_preset() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0503___options_with_save_and_preset"; + this.KN="0503 - options with save and preset"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.s_foo_4=KeymanWeb.KLOAD(this.KI,"foo","0"); + this.s7="1"; + this.s8="0"; + this.s9="1"; + this.s10="0"; + this.s11="0"; + this.KVS=['s_foo_4']; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_0 /* 0x30 */)) { + if(1){ + r=m=1; // Line 21 + k.KDC(0,t); + this.s_foo_4=this.s10; + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 20 + k.KDC(0,t); + this.s_foo_4=this.s9; + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_2 /* 0x32 */)) { + if(this.s_foo_4===this.s11){ + r=m=1; // Line 22 + k.KDC(0,t); + k.KSAVE("foo",this.s_foo_4); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_A /* 0x41 */)) { + if(this.s_foo_4===this.s7){ + r=m=1; // Line 18 + k.KDC(0,t); + k.KO(-1,t,"foo."); + } + else if(this.s_foo_4===this.s8){ + r=m=1; // Line 19 + k.KDC(0,t); + k.KO(-1,t,"no foo."); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_024___options_with_save_and_preset.kmn b/common/test/keyboards/baseline/k_0503___options_with_save_and_preset.kmn similarity index 86% rename from common/test/keyboards/baseline/k_024___options_with_save_and_preset.kmn rename to common/test/keyboards/baseline/k_0503___options_with_save_and_preset.kmn index 0c3004c3e32..9688ed8e616 100644 --- a/common/test/keyboards/baseline/k_024___options_with_save_and_preset.kmn +++ b/common/test/keyboards/baseline/k_0503___options_with_save_and_preset.kmn @@ -1,8 +1,8 @@ -store(&NAME) '024 - options with save and preset' +store(&NAME) '0503 - options with save and preset' c Description: Tests basic option rules with save c keys: [K_A][K_1][K_A][K_0][K_A][K_2] c expected: foo.foo.no foo. -c context: +c context: c option: foo=1 c expected option: foo=0 c saved option: foo=0 diff --git a/common/test/keyboards/baseline/k_0503___options_with_save_and_preset.kmx b/common/test/keyboards/baseline/k_0503___options_with_save_and_preset.kmx new file mode 100644 index 00000000000..49b55208b61 Binary files /dev/null and b/common/test/keyboards/baseline/k_0503___options_with_save_and_preset.kmx differ diff --git a/common/test/keyboards/baseline/k_0504___options_with_reset.js b/common/test/keyboards/baseline/k_0504___options_with_reset.js new file mode 100644 index 00000000000..5cb7dc19aeb --- /dev/null +++ b/common/test/keyboards/baseline/k_0504___options_with_reset.js @@ -0,0 +1,71 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0504___options_with_reset()); +} +function Keyboard_k_0504___options_with_reset() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0504___options_with_reset"; + this.KN="0504 - options with reset"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.s_foo_4=KeymanWeb.KLOAD(this.KI,"foo","0"); + this.s7="1"; + this.s8="0"; + this.s9="1"; + this.s10="0"; + this.KVS=['s_foo_4']; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_0 /* 0x30 */)) { + if(1){ + r=m=1; // Line 20 + k.KDC(0,t); + this.s_foo_4=this.s10; + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 19 + k.KDC(0,t); + this.s_foo_4=this.s9; + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_3 /* 0x33 */)) { + if(1){ + r=m=1; // Line 21 + k.KDC(0,t); + this.s_foo_4=k.KLOAD(this.KI,"foo","0"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_A /* 0x41 */)) { + if(this.s_foo_4===this.s7){ + r=m=1; // Line 17 + k.KDC(0,t); + k.KO(-1,t,"foo."); + } + else if(this.s_foo_4===this.s8){ + r=m=1; // Line 18 + k.KDC(0,t); + k.KO(-1,t,"no foo."); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_025___options_with_reset.kmn b/common/test/keyboards/baseline/k_0504___options_with_reset.kmn similarity index 87% rename from common/test/keyboards/baseline/k_025___options_with_reset.kmn rename to common/test/keyboards/baseline/k_0504___options_with_reset.kmn index 13a0d692837..caeb29c25d0 100644 --- a/common/test/keyboards/baseline/k_025___options_with_reset.kmn +++ b/common/test/keyboards/baseline/k_0504___options_with_reset.kmn @@ -1,8 +1,8 @@ -store(&NAME) '025 - options with reset' +store(&NAME) '0504 - options with reset' c Description: Tests basic option rules with reset c keys: [K_A][K_1][K_A][K_0][K_A][K_3] c expected: foo.foo.no foo. -c context: +c context: c option: foo=1 c expected option: foo=1 diff --git a/common/test/keyboards/baseline/k_0504___options_with_reset.kmx b/common/test/keyboards/baseline/k_0504___options_with_reset.kmx new file mode 100644 index 00000000000..413060deca8 Binary files /dev/null and b/common/test/keyboards/baseline/k_0504___options_with_reset.kmx differ diff --git a/common/test/keyboards/baseline/k_0505___options_double_set_reset.js b/common/test/keyboards/baseline/k_0505___options_double_set_reset.js new file mode 100644 index 00000000000..7e89315cdaa --- /dev/null +++ b/common/test/keyboards/baseline/k_0505___options_double_set_reset.js @@ -0,0 +1,66 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0505___options_double_set_reset()); +} +function Keyboard_k_0505___options_double_set_reset() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0505___options_double_set_reset"; + this.KN="0505 - options double set reset"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.s_foo_4=KeymanWeb.KLOAD(this.KI,"foo","0"); + this.s7="1"; + this.s8="2"; + this.s9="3"; + this.s10="2"; + this.s11="3"; + this.s12="0"; + this.KVS=['s_foo_4']; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_A /* 0x41 */)) { + if(this.s_foo_4===this.s7){ + r=m=1; // Line 17 + k.KDC(0,t); + k.KO(-1,t,"foo."); + this.s_foo_4=this.s8; + this.s_foo_4=k.KLOAD(this.KI,"foo","0"); + this.s_foo_4=this.s9; + this.s_foo_4=k.KLOAD(this.KI,"foo","0"); + } + else if(this.s_foo_4===this.s10){ + r=m=1; // Line 18 + k.KDC(0,t); + k.KO(-1,t,"bar."); + } + else if(this.s_foo_4===this.s11){ + r=m=1; // Line 19 + k.KDC(0,t); + k.KO(-1,t,"baz."); + } + else if(this.s_foo_4===this.s12){ + r=m=1; // Line 20 + k.KDC(0,t); + k.KO(-1,t,"no foo."); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_034___options_double_set_reset.kmn b/common/test/keyboards/baseline/k_0505___options_double_set_reset.kmn similarity index 87% rename from common/test/keyboards/baseline/k_034___options_double_set_reset.kmn rename to common/test/keyboards/baseline/k_0505___options_double_set_reset.kmn index 3fe9225ecad..e91f95e26b7 100644 --- a/common/test/keyboards/baseline/k_034___options_double_set_reset.kmn +++ b/common/test/keyboards/baseline/k_0505___options_double_set_reset.kmn @@ -1,8 +1,8 @@ -store(&NAME) '034 - options double set reset' +store(&NAME) '0505 - options double set reset' c Description: Tests basic option rules with save reset+set+reset c keys: [K_A][K_A] c expected: foo.foo. -c context: +c context: c option: foo=1 c expected option: foo=1 diff --git a/common/test/keyboards/baseline/k_0505___options_double_set_reset.kmx b/common/test/keyboards/baseline/k_0505___options_double_set_reset.kmx new file mode 100644 index 00000000000..f44ef699c0f Binary files /dev/null and b/common/test/keyboards/baseline/k_0505___options_double_set_reset.kmx differ diff --git a/common/test/keyboards/baseline/k_0506___options_double_set_staged.js b/common/test/keyboards/baseline/k_0506___options_double_set_staged.js new file mode 100644 index 00000000000..d0e5bb58ff6 --- /dev/null +++ b/common/test/keyboards/baseline/k_0506___options_double_set_staged.js @@ -0,0 +1,77 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0506___options_double_set_staged()); +} +function Keyboard_k_0506___options_double_set_staged() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0506___options_double_set_staged"; + this.KN="0506 - options double set staged"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.s_foo_4=KeymanWeb.KLOAD(this.KI,"foo","0"); + this.s7="1"; + this.s8="2"; + this.s9="3"; + this.s10="2"; + this.s11="3"; + this.s12="0"; + this.KVS=['s_foo_4']; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_A /* 0x41 */)) { + if(this.s_foo_4===this.s7){ + r=m=1; // Line 17 + k.KDC(0,t); + k.KO(-1,t,"foo."); + this.s_foo_4=this.s8; + } + else if(this.s_foo_4===this.s10){ + r=m=1; // Line 20 + k.KDC(0,t); + k.KO(-1,t,"bar."); + } + else if(this.s_foo_4===this.s11){ + r=m=1; // Line 21 + k.KDC(0,t); + k.KO(-1,t,"baz."); + } + else if(this.s_foo_4===this.s12){ + r=m=1; // Line 22 + k.KDC(0,t); + k.KO(-1,t,"no foo."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_B /* 0x42 */)) { + if(1){ + r=m=1; // Line 18 + k.KDC(0,t); + this.s_foo_4=k.KLOAD(this.KI,"foo","0"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_C /* 0x43 */)) { + if(1){ + r=m=1; // Line 19 + k.KDC(0,t); + this.s_foo_4=this.s9; + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_035___options_double_set_staged.kmn b/common/test/keyboards/baseline/k_0506___options_double_set_staged.kmn similarity index 90% rename from common/test/keyboards/baseline/k_035___options_double_set_staged.kmn rename to common/test/keyboards/baseline/k_0506___options_double_set_staged.kmn index 75d1b81b89b..c78bee2fcf7 100644 --- a/common/test/keyboards/baseline/k_035___options_double_set_staged.kmn +++ b/common/test/keyboards/baseline/k_0506___options_double_set_staged.kmn @@ -1,4 +1,4 @@ -store(&NAME) '035 - options double set staged' +store(&NAME) '0506 - options double set staged' c Description: Tests basic option rules with save reset+set+reset c keys: [K_A][K_B][K_C][K_B][K_A] c expected: foo.foo. diff --git a/common/test/keyboards/baseline/k_0506___options_double_set_staged.kmx b/common/test/keyboards/baseline/k_0506___options_double_set_staged.kmx new file mode 100644 index 00000000000..c6f03efa7cd Binary files /dev/null and b/common/test/keyboards/baseline/k_0506___options_double_set_staged.kmx differ diff --git a/common/test/keyboards/baseline/k_0507___options___double_reset_staged.js b/common/test/keyboards/baseline/k_0507___options___double_reset_staged.js new file mode 100644 index 00000000000..754fd8ae658 --- /dev/null +++ b/common/test/keyboards/baseline/k_0507___options___double_reset_staged.js @@ -0,0 +1,63 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0507___options___double_reset_staged()); +} +function Keyboard_k_0507___options___double_reset_staged() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0507___options___double_reset_staged"; + this.KN="0507- options - double reset staged"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.s_foo_4=KeymanWeb.KLOAD(this.KI,"foo","0"); + this.s7="1"; + this.s8="2"; + this.s9="2"; + this.s10="0"; + this.KVS=['s_foo_4']; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_A /* 0x41 */)) { + if(this.s_foo_4===this.s7){ + r=m=1; // Line 17 + k.KDC(0,t); + k.KO(-1,t,"foo."); + this.s_foo_4=this.s8; + } + else if(this.s_foo_4===this.s9){ + r=m=1; // Line 19 + k.KDC(0,t); + k.KO(-1,t,"bar."); + } + else if(this.s_foo_4===this.s10){ + r=m=1; // Line 20 + k.KDC(0,t); + k.KO(-1,t,"no foo."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_B /* 0x42 */)) { + if(1){ + r=m=1; // Line 18 + k.KDC(0,t); + this.s_foo_4=k.KLOAD(this.KI,"foo","0"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_036___options___double_reset_staged.kmn b/common/test/keyboards/baseline/k_0507___options___double_reset_staged.kmn similarity index 88% rename from common/test/keyboards/baseline/k_036___options___double_reset_staged.kmn rename to common/test/keyboards/baseline/k_0507___options___double_reset_staged.kmn index 53157b487d3..e250695af1d 100644 --- a/common/test/keyboards/baseline/k_036___options___double_reset_staged.kmn +++ b/common/test/keyboards/baseline/k_0507___options___double_reset_staged.kmn @@ -1,4 +1,4 @@ -store(&NAME) '036 - options - double reset staged' +store(&NAME) '0507- options - double reset staged' c Description: Tests basic option rules with save reset+reset c keys: [K_A][K_B][K_B][K_A] c expected: foo.foo. diff --git a/common/test/keyboards/baseline/k_036___options___double_reset_staged.kmx b/common/test/keyboards/baseline/k_0507___options___double_reset_staged.kmx similarity index 79% rename from common/test/keyboards/baseline/k_036___options___double_reset_staged.kmx rename to common/test/keyboards/baseline/k_0507___options___double_reset_staged.kmx index ccb05e04c1f..2aba8f9cdbc 100644 Binary files a/common/test/keyboards/baseline/k_036___options___double_reset_staged.kmx and b/common/test/keyboards/baseline/k_0507___options___double_reset_staged.kmx differ diff --git a/common/test/keyboards/baseline/k_0508___options___double_reset.js b/common/test/keyboards/baseline/k_0508___options___double_reset.js new file mode 100644 index 00000000000..9f208eaaafb --- /dev/null +++ b/common/test/keyboards/baseline/k_0508___options___double_reset.js @@ -0,0 +1,58 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0508___options___double_reset()); +} +function Keyboard_k_0508___options___double_reset() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0508___options___double_reset"; + this.KN="0508 - options - double reset"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.s_foo_4=KeymanWeb.KLOAD(this.KI,"foo","0"); + this.s7="1"; + this.s8="2"; + this.s9="2"; + this.s10="0"; + this.KVS=['s_foo_4']; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_A /* 0x41 */)) { + if(this.s_foo_4===this.s7){ + r=m=1; // Line 17 + k.KDC(0,t); + k.KO(-1,t,"foo."); + this.s_foo_4=this.s8; + this.s_foo_4=k.KLOAD(this.KI,"foo","0"); + this.s_foo_4=k.KLOAD(this.KI,"foo","0"); + } + else if(this.s_foo_4===this.s9){ + r=m=1; // Line 18 + k.KDC(0,t); + k.KO(-1,t,"bar."); + } + else if(this.s_foo_4===this.s10){ + r=m=1; // Line 19 + k.KDC(0,t); + k.KO(-1,t,"no foo."); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_037___options___double_reset.kmn b/common/test/keyboards/baseline/k_0508___options___double_reset.kmn similarity index 86% rename from common/test/keyboards/baseline/k_037___options___double_reset.kmn rename to common/test/keyboards/baseline/k_0508___options___double_reset.kmn index 05e5fe7b024..766cf5f87c9 100644 --- a/common/test/keyboards/baseline/k_037___options___double_reset.kmn +++ b/common/test/keyboards/baseline/k_0508___options___double_reset.kmn @@ -1,8 +1,8 @@ -store(&NAME) '037 - options - double reset' +store(&NAME) '0508 - options - double reset' c Description: Tests basic option rules with save reset+reset c keys: [K_A][K_A] c expected: foo.foo. -c context: +c context: c option: foo=1 c expected option: foo=1 diff --git a/common/test/keyboards/baseline/k_0508___options___double_reset.kmx b/common/test/keyboards/baseline/k_0508___options___double_reset.kmx new file mode 100644 index 00000000000..f34e800c022 Binary files /dev/null and b/common/test/keyboards/baseline/k_0508___options___double_reset.kmx differ diff --git a/common/test/keyboards/baseline/k_050___nul_and_context.kmx b/common/test/keyboards/baseline/k_050___nul_and_context.kmx deleted file mode 100644 index a777f48e2c8..00000000000 Binary files a/common/test/keyboards/baseline/k_050___nul_and_context.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_051___if_and_context.kmx b/common/test/keyboards/baseline/k_051___if_and_context.kmx deleted file mode 100644 index facfe918590..00000000000 Binary files a/common/test/keyboards/baseline/k_051___if_and_context.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_052___nul_and_index.kmx b/common/test/keyboards/baseline/k_052___nul_and_index.kmx deleted file mode 100644 index 7e533db7912..00000000000 Binary files a/common/test/keyboards/baseline/k_052___nul_and_index.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_053___if_and_index.kmx b/common/test/keyboards/baseline/k_053___if_and_index.kmx deleted file mode 100644 index ee426130348..00000000000 Binary files a/common/test/keyboards/baseline/k_053___if_and_index.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_054___nul_and_contextex.kmx b/common/test/keyboards/baseline/k_054___nul_and_contextex.kmx deleted file mode 100644 index 3c75d606f44..00000000000 Binary files a/common/test/keyboards/baseline/k_054___nul_and_contextex.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_055___deadkey_cancelled_by_arrow.kmx b/common/test/keyboards/baseline/k_055___deadkey_cancelled_by_arrow.kmx deleted file mode 100644 index 551a2639209..00000000000 Binary files a/common/test/keyboards/baseline/k_055___deadkey_cancelled_by_arrow.kmx and /dev/null differ diff --git a/common/test/keyboards/baseline/k_0600___system_stores.js b/common/test/keyboards/baseline/k_0600___system_stores.js new file mode 100644 index 00000000000..b72c56cc1cd --- /dev/null +++ b/common/test/keyboards/baseline/k_0600___system_stores.js @@ -0,0 +1,211 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0600___system_stores()); +} +function Keyboard_k_0600___system_stores() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0600___system_stores"; + this.KN="0600 - system stores"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.s_digit_4="1234567890"; + this.s_letter_5="abcdefghij"; + this.s8="windows"; + this.s9="desktop"; + this.s10="hardware"; + this.s11="native"; + this.s12="en-US"; + this.s13="kbdus.dll"; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_0 /* 0x30 */)) { + if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_1 /* 0x31 */)) { + if(k.KIFS(31,this.s8,t)){ + r=m=1; // Line 19 + k.KDC(0,t); + k.KO(-1,t,"windows."); + } + else if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_2 /* 0x32 */)) { + if(k.KIFS(31,this.s9,t)){ + r=m=1; // Line 20 + k.KDC(0,t); + k.KO(-1,t,"desktop."); + } + else if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_3 /* 0x33 */)) { + if(k.KIFS(31,this.s10,t)){ + r=m=1; // Line 21 + k.KDC(0,t); + k.KO(-1,t,"hardware."); + } + else if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_4 /* 0x34 */)) { + if(k.KIFS(31,this.s11,t)){ + r=m=1; // Line 22 + k.KDC(0,t); + k.KO(-1,t,"native."); + } + else if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_5 /* 0x35 */)) { + if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_6 /* 0x36 */)) { + if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_7 /* 0x37 */)) { + if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_8 /* 0x38 */)) { + if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_9 /* 0x39 */)) { + if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_A /* 0x41 */)) { + if(k.KIFS(32,this.s12,t)){ + r=m=1; // Line 25 + k.KDC(0,t); + k.KO(-1,t,"en-US."); + } + else if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_B /* 0x42 */)) { + if(k.KIFS(32,this.s13,t)){ + r=m=1; // Line 26 + k.KDC(0,t); + k.KO(-1,t,"kbdus.dll."); + } + else if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_C /* 0x43 */)) { + if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_D /* 0x44 */)) { + if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_E /* 0x45 */)) { + if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_F /* 0x46 */)) { + if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_G /* 0x47 */)) { + if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_H /* 0x48 */)) { + if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_I /* 0x49 */)) { + if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_J /* 0x4A */)) { + if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_026___system_stores.kmn b/common/test/keyboards/baseline/k_0600___system_stores.kmn similarity index 94% rename from common/test/keyboards/baseline/k_026___system_stores.kmn rename to common/test/keyboards/baseline/k_0600___system_stores.kmn index 0538c51364b..9b63ffb576c 100644 --- a/common/test/keyboards/baseline/k_026___system_stores.kmn +++ b/common/test/keyboards/baseline/k_0600___system_stores.kmn @@ -1,8 +1,8 @@ -store(&NAME) '026 - system stores' +store(&NAME) '0600 - system stores' c Description: Tests platform and baselayout system store rules c keys: [K_1][K_2][K_3][K_4][K_A][K_B] c expected: windows.desktop.hardware.native.en-US.kbdus.dll. -c context: +c context: c (default) option: &platform=windows desktop hardware native <-- ignored by test c (default) option: &baseLayout=kbdus.dll <-- ignored by test c (default) option: &baseLayoutAlt=en-US <-- ignored by test diff --git a/common/test/keyboards/baseline/k_0600___system_stores.kmx b/common/test/keyboards/baseline/k_0600___system_stores.kmx new file mode 100644 index 00000000000..54c86383bc3 Binary files /dev/null and b/common/test/keyboards/baseline/k_0600___system_stores.kmx differ diff --git a/common/test/keyboards/baseline/k_0601___system_stores_2.js b/common/test/keyboards/baseline/k_0601___system_stores_2.js new file mode 100644 index 00000000000..2a2d14135ea --- /dev/null +++ b/common/test/keyboards/baseline/k_0601___system_stores_2.js @@ -0,0 +1,211 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0601___system_stores_2()); +} +function Keyboard_k_0601___system_stores_2() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0601___system_stores_2"; + this.KN="0601 - system stores 2"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.s_digit_4="1234567890"; + this.s_letter_5="abcdefghij"; + this.s8="linux"; + this.s9="desktop"; + this.s10="hardware"; + this.s11="native"; + this.s12="fr-FR"; + this.s13="kbdfr.dll"; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_0 /* 0x30 */)) { + if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_1 /* 0x31 */)) { + if(k.KIFS(31,this.s8,t)){ + r=m=1; // Line 19 + k.KDC(0,t); + k.KO(-1,t,"linux."); + } + else if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_2 /* 0x32 */)) { + if(k.KIFS(31,this.s9,t)){ + r=m=1; // Line 20 + k.KDC(0,t); + k.KO(-1,t,"desktop."); + } + else if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_3 /* 0x33 */)) { + if(k.KIFS(31,this.s10,t)){ + r=m=1; // Line 21 + k.KDC(0,t); + k.KO(-1,t,"hardware."); + } + else if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_4 /* 0x34 */)) { + if(k.KIFS(31,this.s11,t)){ + r=m=1; // Line 22 + k.KDC(0,t); + k.KO(-1,t,"native."); + } + else if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_5 /* 0x35 */)) { + if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_6 /* 0x36 */)) { + if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_7 /* 0x37 */)) { + if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_8 /* 0x38 */)) { + if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_9 /* 0x39 */)) { + if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"platform-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_A /* 0x41 */)) { + if(k.KIFS(32,this.s12,t)){ + r=m=1; // Line 25 + k.KDC(0,t); + k.KO(-1,t,"fr-FR."); + } + else if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_B /* 0x42 */)) { + if(k.KIFS(32,this.s13,t)){ + r=m=1; // Line 26 + k.KDC(0,t); + k.KO(-1,t,"kbdfr.dll."); + } + else if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_C /* 0x43 */)) { + if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_D /* 0x44 */)) { + if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_E /* 0x45 */)) { + if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_F /* 0x46 */)) { + if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_G /* 0x47 */)) { + if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_H /* 0x48 */)) { + if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_I /* 0x49 */)) { + if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_J /* 0x4A */)) { + if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"baselayout-fail."); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_027___system_stores_2.kmn b/common/test/keyboards/baseline/k_0601___system_stores_2.kmn similarity index 93% rename from common/test/keyboards/baseline/k_027___system_stores_2.kmn rename to common/test/keyboards/baseline/k_0601___system_stores_2.kmn index 95457c84639..3e30cbf5e5d 100644 --- a/common/test/keyboards/baseline/k_027___system_stores_2.kmn +++ b/common/test/keyboards/baseline/k_0601___system_stores_2.kmn @@ -1,8 +1,8 @@ -store(&NAME) '027 - system stores 2' +store(&NAME) '0601 - system stores 2' c Description: Tests platform and baselayout system store rules c keys: [K_1][K_2][K_3][K_4][K_A][K_B] c expected: linux.desktop.hardware.native.fr-FR.kbdfr.dll. -c context: +c context: c option: &platform=linux desktop hardware native c option: &baseLayout=kbdfr.dll c option: &baseLayoutAlt=fr-FR diff --git a/common/test/keyboards/baseline/k_0601___system_stores_2.kmx b/common/test/keyboards/baseline/k_0601___system_stores_2.kmx new file mode 100644 index 00000000000..f19063be7d9 Binary files /dev/null and b/common/test/keyboards/baseline/k_0601___system_stores_2.kmx differ diff --git a/common/test/keyboards/baseline/k_0700___caps_lock.js b/common/test/keyboards/baseline/k_0700___caps_lock.js new file mode 100644 index 00000000000..a89cef36e44 --- /dev/null +++ b/common/test/keyboards/baseline/k_0700___caps_lock.js @@ -0,0 +1,103 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0700___caps_lock()); +} +function Keyboard_k_0700___caps_lock() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0700___caps_lock"; + this.KN="0700 - caps lock"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=modCodes.SHIFT | modCodes.CAPS | modCodes.NO_CAPS /* 0x0310 */; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_3 /* 0x33 */)) { + if(1){ + r=m=1; // Line 20 + k.KDC(0,t); + k.KO(-1,t,"pass."); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 14 + k.KDC(0,t); + k.KO(-1,t,"fail."); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 15 + k.KDC(0,t); + k.KO(-1,t,"pass."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_3 /* 0x33 */)) { + if(1){ + r=m=1; // Line 21 + k.KDC(0,t); + k.KO(-1,t,"fail."); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4210 */, keyCodes.K_2 /* 0x32 */)) { + if(1){ + r=m=1; // Line 17 + k.KDC(0,t); + k.KO(-1,t,"fail."); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4110 */, keyCodes.K_2 /* 0x32 */)) { + if(1){ + r=m=1; // Line 18 + k.KDC(0,t); + k.KO(-1,t,"pass."); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_A /* 0x41 */)) { + if(1){ + r=m=1; // Line 24 + k.KDC(0,t); + k.KO(-1,t,"pass."); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_B /* 0x42 */)) { + if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_A /* 0x41 */)) { + if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"fail."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_B /* 0x42 */)) { + if(1){ + r=m=1; // Line 26 + k.KDC(0,t); + k.KO(-1,t,"pass."); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_031___caps_lock.kmn b/common/test/keyboards/baseline/k_0700___caps_lock.kmn similarity index 93% rename from common/test/keyboards/baseline/k_031___caps_lock.kmn rename to common/test/keyboards/baseline/k_0700___caps_lock.kmn index d14b8ad56ba..27fc5b6b739 100644 --- a/common/test/keyboards/baseline/k_031___caps_lock.kmn +++ b/common/test/keyboards/baseline/k_0700___caps_lock.kmn @@ -1,4 +1,4 @@ -store(&NAME) '031 - caps lock' +store(&NAME) '0700 - caps lock' c Description: Tests Caps Lock c keys: [K_1][SHIFT K_2][SHIFT K_3][K_A][SHIFT K_B] c expected: pass.pass.pass.pass.pass. diff --git a/common/test/keyboards/baseline/k_0700___caps_lock.kmx b/common/test/keyboards/baseline/k_0700___caps_lock.kmx new file mode 100644 index 00000000000..072520eb51e Binary files /dev/null and b/common/test/keyboards/baseline/k_0700___caps_lock.kmx differ diff --git a/common/test/keyboards/baseline/k_0701___caps_control.js b/common/test/keyboards/baseline/k_0701___caps_control.js new file mode 100644 index 00000000000..0b4ee57e6d9 --- /dev/null +++ b/common/test/keyboards/baseline/k_0701___caps_control.js @@ -0,0 +1,131 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0701___caps_control()); +} +function Keyboard_k_0701___caps_control() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0701___caps_control"; + this.KN="0701 - caps control"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=modCodes.SHIFT | modCodes.CAPS | modCodes.NO_CAPS /* 0x0310 */; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.SHIFT | modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4210 */, keyCodes.K_3 /* 0x33 */)) { + if(1){ + r=m=1; // Line 24 + k.KDC(0,t); + k.KO(-1,t,"fail."); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4110 */, keyCodes.K_3 /* 0x33 */)) { + if(1){ + r=m=1; // Line 25 + k.KDC(0,t); + k.KO(-1,t,"pass."); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 17 + k.KDC(0,t); + k.KO(-1,t,"fail."); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 18 + k.KDC(0,t); + k.KO(-1,t,"pass."); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_2 /* 0x32 */)) { + if(1){ + r=m=1; // Line 20 + k.KDC(0,t); + k.KO(-1,t,"fail."); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_2 /* 0x32 */)) { + if(1){ + r=m=1; // Line 21 + k.KDC(0,t); + k.KO(-1,t,"pass."); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_4 /* 0x34 */)) { + if(1){ + r=m=1; // Line 27 + k.KDC(0,t); + k.KO(-1,t,"fail."); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_4 /* 0x34 */)) { + if(1){ + r=m=1; // Line 28 + k.KDC(0,t); + k.KO(-1,t,"pass."); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_5 /* 0x35 */)) { + if(1){ + r=m=1; // Line 30 + k.KDC(0,t); + k.KO(-1,t,"fail."); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_5 /* 0x35 */)) { + if(1){ + r=m=1; // Line 31 + k.KDC(0,t); + k.KO(-1,t,"pass."); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_6 /* 0x36 */)) { + if(1){ + r=m=1; // Line 33 + k.KDC(0,t); + k.KO(-1,t,"fail."); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_6 /* 0x36 */)) { + if(1){ + r=m=1; // Line 34 + k.KDC(0,t); + k.KO(-1,t,"pass."); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_7 /* 0x37 */)) { + if(1){ + r=m=1; // Line 37 + k.KDC(0,t); + k.KO(-1,t,"fail."); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_7 /* 0x37 */)) { + if(1){ + r=m=1; // Line 38 + k.KDC(0,t); + k.KO(-1,t,"pass."); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_032___caps_control.kmn b/common/test/keyboards/baseline/k_0701___caps_control.kmn similarity index 96% rename from common/test/keyboards/baseline/k_032___caps_control.kmn rename to common/test/keyboards/baseline/k_0701___caps_control.kmn index 884fb41a6d5..13c9aa29a05 100644 --- a/common/test/keyboards/baseline/k_032___caps_control.kmn +++ b/common/test/keyboards/baseline/k_0701___caps_control.kmn @@ -1,4 +1,4 @@ -store(&NAME) '032 - caps control' +store(&NAME) '0701 - caps control' c Description: Tests Caps Lock env set c keys: [K_1][K_CAPS][K_2][SHIFT K_3][K_4][K_CAPS][K_5][K_CAPS][K_6][K_SHIFT][K_7] c expected: pass.pass.pass.pass.pass.pass.pass. diff --git a/common/test/keyboards/baseline/k_0701___caps_control.kmx b/common/test/keyboards/baseline/k_0701___caps_control.kmx new file mode 100644 index 00000000000..c9f04435d20 Binary files /dev/null and b/common/test/keyboards/baseline/k_0701___caps_control.kmx differ diff --git a/common/test/keyboards/baseline/k_0702___caps_always_off.js b/common/test/keyboards/baseline/k_0702___caps_always_off.js new file mode 100644 index 00000000000..48455fb1a99 --- /dev/null +++ b/common/test/keyboards/baseline/k_0702___caps_always_off.js @@ -0,0 +1,75 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0702___caps_always_off()); +} +function Keyboard_k_0702___caps_always_off() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0702___caps_always_off"; + this.KN="0702 - caps always off"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=modCodes.CAPS | modCodes.NO_CAPS /* 0x0300 */; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 16 + k.KDC(0,t); + k.KO(-1,t,"fail."); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 17 + k.KDC(0,t); + k.KO(-1,t,"pass."); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_2 /* 0x32 */)) { + if(1){ + r=m=1; // Line 19 + k.KDC(0,t); + k.KO(-1,t,"fail."); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_2 /* 0x32 */)) { + if(1){ + r=m=1; // Line 20 + k.KDC(0,t); + k.KO(-1,t,"pass."); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_3 /* 0x33 */)) { + if(1){ + r=m=1; // Line 22 + k.KDC(0,t); + k.KO(-1,t,"fail."); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_3 /* 0x33 */)) { + if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"pass."); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_033___caps_always_off.kmn b/common/test/keyboards/baseline/k_0702___caps_always_off.kmn similarity index 90% rename from common/test/keyboards/baseline/k_033___caps_always_off.kmn rename to common/test/keyboards/baseline/k_0702___caps_always_off.kmn index 912f2c5ac0d..fb2099bbe9b 100644 --- a/common/test/keyboards/baseline/k_033___caps_always_off.kmn +++ b/common/test/keyboards/baseline/k_0702___caps_always_off.kmn @@ -1,4 +1,4 @@ -store(&NAME) '033 - caps always off' +store(&NAME) '0702 - caps always off' c Description: Tests Caps Lock always off c keys: [K_1][K_CAPS][K_2][K_CAPS][K_3] c expected: pass.pass.pass. diff --git a/common/test/keyboards/baseline/k_0702___caps_always_off.kmx b/common/test/keyboards/baseline/k_0702___caps_always_off.kmx new file mode 100644 index 00000000000..f8d6c0c9df5 Binary files /dev/null and b/common/test/keyboards/baseline/k_0702___caps_always_off.kmx differ diff --git a/common/test/keyboards/baseline/k_0703___caps_always_off_initially_on.js b/common/test/keyboards/baseline/k_0703___caps_always_off_initially_on.js new file mode 100644 index 00000000000..a482844beca --- /dev/null +++ b/common/test/keyboards/baseline/k_0703___caps_always_off_initially_on.js @@ -0,0 +1,75 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0703___caps_always_off_initially_on()); +} +function Keyboard_k_0703___caps_always_off_initially_on() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0703___caps_always_off_initially_on"; + this.KN="0703 - caps always off initially on"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=modCodes.CAPS | modCodes.NO_CAPS /* 0x0300 */; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 17 + k.KDC(0,t); + k.KO(-1,t,"fail."); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 18 + k.KDC(0,t); + k.KO(-1,t,"pass."); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_2 /* 0x32 */)) { + if(1){ + r=m=1; // Line 20 + k.KDC(0,t); + k.KO(-1,t,"fail."); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_2 /* 0x32 */)) { + if(1){ + r=m=1; // Line 21 + k.KDC(0,t); + k.KO(-1,t,"pass."); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_3 /* 0x33 */)) { + if(1){ + r=m=1; // Line 23 + k.KDC(0,t); + k.KO(-1,t,"fail."); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_3 /* 0x33 */)) { + if(1){ + r=m=1; // Line 24 + k.KDC(0,t); + k.KO(-1,t,"pass."); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_047___caps_always_off_initially_on.kmn b/common/test/keyboards/baseline/k_0703___caps_always_off_initially_on.kmn similarity index 90% rename from common/test/keyboards/baseline/k_047___caps_always_off_initially_on.kmn rename to common/test/keyboards/baseline/k_0703___caps_always_off_initially_on.kmn index 4c0b6913658..140a3167e00 100644 --- a/common/test/keyboards/baseline/k_047___caps_always_off_initially_on.kmn +++ b/common/test/keyboards/baseline/k_0703___caps_always_off_initially_on.kmn @@ -1,4 +1,4 @@ -store(&NAME) '047 - caps always off initially on' +store(&NAME) '0703 - caps always off initially on' c Description: Tests Caps Lock always off, entry to the test has Caps Lock c on to test that it is then switched off on first keystroke event. c keys: [K_1][K_CAPS][K_2][K_CAPS][K_3] diff --git a/common/test/keyboards/baseline/k_0703___caps_always_off_initially_on.kmx b/common/test/keyboards/baseline/k_0703___caps_always_off_initially_on.kmx new file mode 100644 index 00000000000..bd9c41c9dc5 Binary files /dev/null and b/common/test/keyboards/baseline/k_0703___caps_always_off_initially_on.kmx differ diff --git a/common/test/keyboards/baseline/k_0800___long_context.js b/common/test/keyboards/baseline/k_0800___long_context.js new file mode 100644 index 00000000000..9870e97456e --- /dev/null +++ b/common/test/keyboards/baseline/k_0800___long_context.js @@ -0,0 +1,40 @@ + +KeymanWeb.KR(new Keyboard_k_0800___long_context()); + +function Keyboard_k_0800___long_context() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0800___long_context"; + this.KN="0800 - long context"; + this.KMINVER="6.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0000; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4000, 0x20)) { + if(1){ + r=m=1; // Line 13 + k.KO(0,t," "); + } + } + else if(k.KKM(e, 0x4000, 0x46)) { + if(k.KCM(1,t," ",1)){ + r=m=1; // Line 16 + k.KO(1,t," "); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_040___long_context.kmn b/common/test/keyboards/baseline/k_0800___long_context.kmn similarity index 91% rename from common/test/keyboards/baseline/k_040___long_context.kmn rename to common/test/keyboards/baseline/k_0800___long_context.kmn index f570d257108..b14373ae3d0 100644 --- a/common/test/keyboards/baseline/k_040___long_context.kmn +++ b/common/test/keyboards/baseline/k_0800___long_context.kmn @@ -1,4 +1,4 @@ -store(&NAME) '040 - long context' +store(&NAME) '0800 - long context' c Description: Tests context longer than 64 chars c keys: [K_SPACE][K_F] c expected: 012345678901234567890123456789012345678901234567890123456789012\u0020 diff --git a/common/test/keyboards/baseline/k_0800___long_context.kmx b/common/test/keyboards/baseline/k_0800___long_context.kmx new file mode 100644 index 00000000000..7ff3b9dc82e Binary files /dev/null and b/common/test/keyboards/baseline/k_0800___long_context.kmx differ diff --git a/common/test/keyboards/baseline/k_0801___long_context_and_deadkeys.js b/common/test/keyboards/baseline/k_0801___long_context_and_deadkeys.js new file mode 100644 index 00000000000..01f5f0f0d20 --- /dev/null +++ b/common/test/keyboards/baseline/k_0801___long_context_and_deadkeys.js @@ -0,0 +1,75 @@ + +KeymanWeb.KR(new Keyboard_k_0801___long_context_and_deadkeys()); + +function Keyboard_k_0801___long_context_and_deadkeys() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0801___long_context_and_deadkeys"; + this.KN="0801 - long context and deadkeys"; + this.KMINVER="6.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0000; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4000, 0x31)) { + if(k.KDM(60,t,0)&&k.KCM(60,t,"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh",60)){ + r=m=1; // Line 18 + k.KO(-1,t,"1"); + } + } + else if(k.KKM(e, 0x4000, 0x32)) { + if(k.KCM(63,t,"\x08\x01abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh1",63)){ + r=m=1; // Line 22 + k.KO(63,t,"FAIL TEST 2"); + } + else if(k.KCM(62,t,"\x01abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh1",62)){ + r=m=1; // Line 23 + k.KO(62,t,"FAIL TEST 2"); + } + else if(k.KCM(61,t,"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh1",61)){ + r=m=1; // Line 24 + k.KO(-1,t,"2"); + } + } + else if(k.KKM(e, 0x4000, 0x33)) { + if(k.KCM(64,t,"\x08\x01abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh12",64)){ + r=m=1; // Line 28 + k.KO(64,t,"FAIL TEST 3"); + } + else if(k.KCM(63,t,"\x01abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh12",63)){ + r=m=1; // Line 29 + k.KO(63,t,"FAIL TEST 3"); + } + else if(k.KCM(62,t,"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh12",62)){ + r=m=1; // Line 30 + k.KO(62,t,"abcdefghijklmnopqrstuvwxyz123"); + } + } + else if(k.KKM(e, 0x4000, 0x34)) { + if(k.KDM(29,t,0)&&k.KCM(29,t,"abcdefghijklmnopqrstuvwxyz123",29)){ + r=m=1; // Line 33 + k.KO(29,t,"PASS"); + } + } + else if(k.KKM(e, 0x4000, 0x5A)) { + if(1){ + r=m=1; // Line 15 + k.KDO(0,t,0); + k.KO(-1,t,"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_041___long_context_and_deadkeys.kmn b/common/test/keyboards/baseline/k_0801___long_context_and_deadkeys.kmn similarity index 96% rename from common/test/keyboards/baseline/k_041___long_context_and_deadkeys.kmn rename to common/test/keyboards/baseline/k_0801___long_context_and_deadkeys.kmn index 455fa1c41cb..29fea905903 100644 --- a/common/test/keyboards/baseline/k_041___long_context_and_deadkeys.kmn +++ b/common/test/keyboards/baseline/k_0801___long_context_and_deadkeys.kmn @@ -1,4 +1,4 @@ -store(&NAME) '041 - long context and deadkeys' +store(&NAME) '0801 - long context and deadkeys' c Description: Tests that we don't split a dk in context:set. Note that we start with a context c with length MAXCONTEXT-1 (abc...fgh is 60 characters/bytes long + 3 bytes for dk(1)). c keys: [K_Z][K_1][K_2][K_3][K_4] diff --git a/common/test/keyboards/baseline/k_0801___long_context_and_deadkeys.kmx b/common/test/keyboards/baseline/k_0801___long_context_and_deadkeys.kmx new file mode 100644 index 00000000000..ff8c7a55ba2 Binary files /dev/null and b/common/test/keyboards/baseline/k_0801___long_context_and_deadkeys.kmx differ diff --git a/common/test/keyboards/baseline/k_0802___long_context_and_split_deadkeys.js b/common/test/keyboards/baseline/k_0802___long_context_and_split_deadkeys.js new file mode 100644 index 00000000000..467eb874724 --- /dev/null +++ b/common/test/keyboards/baseline/k_0802___long_context_and_split_deadkeys.js @@ -0,0 +1,57 @@ + +KeymanWeb.KR(new Keyboard_k_0802___long_context_and_split_deadkeys()); + +function Keyboard_k_0802___long_context_and_split_deadkeys() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0802___long_context_and_split_deadkeys"; + this.KN="0802 - long context and split deadkeys"; + this.KMINVER="6.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0000; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4000, 0x20)) { + if(k.KCM(64,t,"\x01abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk",64)){ + r=m=1; // Line 18 + k.KO(64,t,"FAIL"); + } + else if(k.KDM(63,t,0)&&k.KCM(63,t,"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk",63)){ + r=m=1; // Line 19 + k.KO(63,t,"UNEXPECTED"); + } + } + else if(k.KKM(e, 0x4000, 0x31)) { + if(k.KCM(61,t,"defghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk ",61)){ + r=m=1; // Line 22 + k.KO(61,t,"def"); + } + } + else if(k.KKM(e, 0x4000, 0x32)) { + if(k.KDM(6,t,0)&&k.KCM(6,t,"abcdef",6)){ + r=m=1; // Line 23 + k.KO(6,t,"PASS"); + } + } + else if(k.KKM(e, 0x4000, 0x5A)) { + if(1){ + r=m=1; // Line 14 + k.KDO(0,t,0); + k.KO(-1,t,"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_042___long_context_and_split_deadkeys.kmn b/common/test/keyboards/baseline/k_0802___long_context_and_split_deadkeys.kmn similarity index 93% rename from common/test/keyboards/baseline/k_042___long_context_and_split_deadkeys.kmn rename to common/test/keyboards/baseline/k_0802___long_context_and_split_deadkeys.kmn index ce31d18e282..a6d883886a1 100644 --- a/common/test/keyboards/baseline/k_042___long_context_and_split_deadkeys.kmn +++ b/common/test/keyboards/baseline/k_0802___long_context_and_split_deadkeys.kmn @@ -1,4 +1,4 @@ -store(&NAME) '042 - long context and split deadkeys' +store(&NAME) '0802 - long context and split deadkeys' c Description: Tests that we don't split a dk in context. Note that we start with a context with length MAXCONTEXT. c keys: [K_Z][K_SPACE][K_1][K_2] c context: diff --git a/common/test/keyboards/baseline/k_0802___long_context_and_split_deadkeys.kmx b/common/test/keyboards/baseline/k_0802___long_context_and_split_deadkeys.kmx new file mode 100644 index 00000000000..f26e1e43866 Binary files /dev/null and b/common/test/keyboards/baseline/k_0802___long_context_and_split_deadkeys.kmx differ diff --git a/common/test/keyboards/baseline/k_0803___if_and_context.js b/common/test/keyboards/baseline/k_0803___if_and_context.js new file mode 100644 index 00000000000..68ac3f6dcfc --- /dev/null +++ b/common/test/keyboards/baseline/k_0803___if_and_context.js @@ -0,0 +1,51 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0803___if_and_context()); +} +function Keyboard_k_0803___if_and_context() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0803___if_and_context"; + this.KN="0803 - if and context"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.s_nfc_5=KeymanWeb.KLOAD(this.KI,"nfc","0"); + this.s_diaeresisBase_6="ae"; + this.s8="0"; + this.KVS=['s_nfc_5']; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_A /* 0x41 */)) { + if(1){ + r=m=1; // Line 16 + k.KDC(0,t); + k.KO(-1,t,"exay"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_B /* 0x42 */)) { + if(k.KFCM(4,t,[{t:'a',a:this.s_diaeresisBase_6},'x',{t:'a',a:this.s_diaeresisBase_6},'y'])&&this.s_nfc_5===this.s8){ + r=m=1; // Line 20 + k.KDC(4,t); + k.KIO(-1,this.s_diaeresisBase_6,1,t); + k.KO(-1,t,"x"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_044___if_and_context.kmn b/common/test/keyboards/baseline/k_0803___if_and_context.kmn similarity index 91% rename from common/test/keyboards/baseline/k_044___if_and_context.kmn rename to common/test/keyboards/baseline/k_0803___if_and_context.kmn index 352490325cc..e19a96c17a1 100644 --- a/common/test/keyboards/baseline/k_044___if_and_context.kmn +++ b/common/test/keyboards/baseline/k_0803___if_and_context.kmn @@ -1,4 +1,4 @@ -store(&NAME) '044 - if and context' +store(&NAME) '0803 - if and context' c Description: Tests that context(x) takes if() statements into account. See #4275. c keys: [K_A][K_B] c expected: ex diff --git a/common/test/keyboards/baseline/k_0803___if_and_context.kmx b/common/test/keyboards/baseline/k_0803___if_and_context.kmx new file mode 100644 index 00000000000..17e648142b5 Binary files /dev/null and b/common/test/keyboards/baseline/k_0803___if_and_context.kmx differ diff --git a/common/test/keyboards/baseline/k_0804___deadkey_and_context.js b/common/test/keyboards/baseline/k_0804___deadkey_and_context.js new file mode 100644 index 00000000000..0b233bdc24d --- /dev/null +++ b/common/test/keyboards/baseline/k_0804___deadkey_and_context.js @@ -0,0 +1,64 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0804___deadkey_and_context()); +} +function Keyboard_k_0804___deadkey_and_context() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0804___deadkey_and_context"; + this.KN="0804 - deadkey and context"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=modCodes.SHIFT /* 0x0010 */; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_SLASH /* 0xBF */)) { + if(k.KFCM(7,t,['<',{t:'d',d:0},'a',{t:'d',d:1},'b',{t:'d',d:2},'>'])){ + r=m=1; // Line 18 + k.KDC(7,t); + k.KO(-1,t,"correct"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_Y /* 0x59 */)) { + if(1){ + r=m=1; // Line 13 + k.KDC(0,t); + k.KDO(-1,t,0); + k.KO(-1,t,"a"); + k.KDO(-1,t,1); + k.KO(-1,t,"b"); + k.KDO(-1,t,2); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_Z /* 0x5A */)) { + if(k.KFCM(5,t,[{t:'d',d:0},'a',{t:'d',d:1},'b',{t:'d',d:2}])){ + r=m=1; // Line 17 + k.KDC(5,t); + k.KO(-1,t,"<"); + k.KDO(-1,t,0); + k.KO(-1,t,"a"); + k.KDO(-1,t,1); + k.KO(-1,t,"b"); + k.KDO(-1,t,2); + k.KO(-1,t,">"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_045___deadkey_and_context.kmn b/common/test/keyboards/baseline/k_0804___deadkey_and_context.kmn similarity index 90% rename from common/test/keyboards/baseline/k_045___deadkey_and_context.kmn rename to common/test/keyboards/baseline/k_0804___deadkey_and_context.kmn index c79953a05b8..3c6522d4704 100644 --- a/common/test/keyboards/baseline/k_045___deadkey_and_context.kmn +++ b/common/test/keyboards/baseline/k_0804___deadkey_and_context.kmn @@ -1,4 +1,4 @@ -store(&NAME) '045 - deadkey and context' +store(&NAME) '0804 - deadkey and context' c Description: Tests that context emits deadkeys correctly. See #4275. c keys: [K_Y][K_Z][SHIFT K_SLASH] c expected: correct diff --git a/common/test/keyboards/baseline/k_0804___deadkey_and_context.kmx b/common/test/keyboards/baseline/k_0804___deadkey_and_context.kmx new file mode 100644 index 00000000000..c0a8199fa5d Binary files /dev/null and b/common/test/keyboards/baseline/k_0804___deadkey_and_context.kmx differ diff --git a/common/test/keyboards/baseline/k_0805___deadkey_and_contextex.js b/common/test/keyboards/baseline/k_0805___deadkey_and_contextex.js new file mode 100644 index 00000000000..b58f22a2230 --- /dev/null +++ b/common/test/keyboards/baseline/k_0805___deadkey_and_contextex.js @@ -0,0 +1,60 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0805___deadkey_and_contextex()); +} +function Keyboard_k_0805___deadkey_and_contextex() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0805___deadkey_and_contextex"; + this.KN="0805 - deadkey and contextex"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=modCodes.SHIFT /* 0x0010 */; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_SLASH /* 0xBF */)) { + if(k.KFCM(3,t,['<',{t:'d',d:0},'>'])){ + r=m=1; // Line 18 + k.KDC(3,t); + k.KO(-1,t,"correct"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_M /* 0x4D */)) { + if(k.KFCM(5,t,[{t:'d',d:0},'a',{t:'d',d:1},'b',{t:'d',d:2}])){ + r=m=1; // Line 17 + k.KDC(5,t); + k.KO(-1,t,"<"); + k.KDO(-1,t,0); + k.KO(-1,t,">"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_Y /* 0x59 */)) { + if(1){ + r=m=1; // Line 13 + k.KDC(0,t); + k.KDO(-1,t,0); + k.KO(-1,t,"a"); + k.KDO(-1,t,1); + k.KO(-1,t,"b"); + k.KDO(-1,t,2); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_046___deadkey_and_contextex.kmn b/common/test/keyboards/baseline/k_0805___deadkey_and_contextex.kmn similarity index 89% rename from common/test/keyboards/baseline/k_046___deadkey_and_contextex.kmn rename to common/test/keyboards/baseline/k_0805___deadkey_and_contextex.kmn index 48ad796c3e5..f120a982520 100644 --- a/common/test/keyboards/baseline/k_046___deadkey_and_contextex.kmn +++ b/common/test/keyboards/baseline/k_0805___deadkey_and_contextex.kmn @@ -1,4 +1,4 @@ -store(&NAME) '046 - deadkey and contextex' +store(&NAME) '0805 - deadkey and contextex' c Description: Tests that context() emits deadkeys correctly. See #4275. c keys: [K_Y][SHIFT K_M][SHIFT K_SLASH] c expected: correct diff --git a/common/test/keyboards/baseline/k_0805___deadkey_and_contextex.kmx b/common/test/keyboards/baseline/k_0805___deadkey_and_contextex.kmx new file mode 100644 index 00000000000..73811a388ad Binary files /dev/null and b/common/test/keyboards/baseline/k_0805___deadkey_and_contextex.kmx differ diff --git a/common/test/keyboards/baseline/k_0806___modifier_keys_keep_context.js b/common/test/keyboards/baseline/k_0806___modifier_keys_keep_context.js new file mode 100644 index 00000000000..afb8164deec --- /dev/null +++ b/common/test/keyboards/baseline/k_0806___modifier_keys_keep_context.js @@ -0,0 +1,40 @@ + +KeymanWeb.KR(new Keyboard_k_0806___modifier_keys_keep_context()); + +function Keyboard_k_0806___modifier_keys_keep_context() +{ + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0806___modifier_keys_keep_context"; + this.KN="0806 - modifier keys keep context"; + this.KMINVER="9.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0x0000; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.g_main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, 0x4000, 0x41)) { + if(1){ + r=m=1; // Line 13 + k.KO(0,t,"a"); + } + } + else if(k.KKM(e, 0x4000, 0x42)) { + if(k.KCM(1,t,"a",1)){ + r=m=1; // Line 15 + k.KO(1,t,"pass."); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_048___modifier_keys_keep_context.kmn b/common/test/keyboards/baseline/k_0806___modifier_keys_keep_context.kmn similarity index 85% rename from common/test/keyboards/baseline/k_048___modifier_keys_keep_context.kmn rename to common/test/keyboards/baseline/k_0806___modifier_keys_keep_context.kmn index bb0cfc4df5d..97cce24a6bc 100644 --- a/common/test/keyboards/baseline/k_048___modifier_keys_keep_context.kmn +++ b/common/test/keyboards/baseline/k_0806___modifier_keys_keep_context.kmn @@ -1,4 +1,4 @@ -store(&NAME) '048 - modifier keys keep context' +store(&NAME) '0806 - modifier keys keep context' c Description: Tests that modifier keys don't reset context (#5591) c keys: [K_A][K_SHIFT][K_B][K_A][K_ALT][K_B][K_A][K_CAPS][K_B] c expected: pass.pass.pass. diff --git a/common/test/keyboards/baseline/k_0806___modifier_keys_keep_context.kmx b/common/test/keyboards/baseline/k_0806___modifier_keys_keep_context.kmx new file mode 100644 index 00000000000..fcf3ca65c5b Binary files /dev/null and b/common/test/keyboards/baseline/k_0806___modifier_keys_keep_context.kmx differ diff --git a/common/test/keyboards/baseline/k_0807___enter_invalidates_context.js b/common/test/keyboards/baseline/k_0807___enter_invalidates_context.js new file mode 100644 index 00000000000..90948d0648e --- /dev/null +++ b/common/test/keyboards/baseline/k_0807___enter_invalidates_context.js @@ -0,0 +1,40 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0807___enter_invalidates_context()); +} +function Keyboard_k_0807___enter_invalidates_context() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0807___enter_invalidates_context"; + this.KN="0807 - enter_invalidates_context"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_C /* 0x43 */)) { + if(k.KFCM(2,t,['a','b'])){ + r=m=1; // Line 17 + k.KDC(2,t); + k.KO(-1,t,"abd"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_049___enter_invalidates_context.kmn b/common/test/keyboards/baseline/k_0807___enter_invalidates_context.kmn similarity index 89% rename from common/test/keyboards/baseline/k_049___enter_invalidates_context.kmn rename to common/test/keyboards/baseline/k_0807___enter_invalidates_context.kmn index 78363865ef3..c66f2fccf03 100644 --- a/common/test/keyboards/baseline/k_049___enter_invalidates_context.kmn +++ b/common/test/keyboards/baseline/k_0807___enter_invalidates_context.kmn @@ -1,4 +1,4 @@ -store(&NAME) '049 - enter_invalidates_context' +store(&NAME) '0807 - enter_invalidates_context' c Description: Tests that core context is cleared when kb processor c determines its invalid. eg Enter key See #10182. c keys: [K_A][K_B][K_ENTER][K_C] diff --git a/common/test/keyboards/baseline/k_0807___enter_invalidates_context.kmx b/common/test/keyboards/baseline/k_0807___enter_invalidates_context.kmx new file mode 100644 index 00000000000..863379d98c8 Binary files /dev/null and b/common/test/keyboards/baseline/k_0807___enter_invalidates_context.kmx differ diff --git a/common/test/keyboards/baseline/k_0808___nul_and_context.js b/common/test/keyboards/baseline/k_0808___nul_and_context.js new file mode 100644 index 00000000000..cca0be5e355 --- /dev/null +++ b/common/test/keyboards/baseline/k_0808___nul_and_context.js @@ -0,0 +1,43 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0808___nul_and_context()); +} +function Keyboard_k_0808___nul_and_context() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0808___nul_and_context"; + this.KN="0808 - nul_and_context"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.s_cons_4="mnpqrstv"; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_B /* 0x42 */)) { + if(k.KFCM(2,t,[{t:'n'},{t:'a',a:this.s_cons_4}])){ + r=m=1; // Line 15 + k.KDC(1,t); + k.KO(-1,t,"2"); + k.KIO(-1,this.s_cons_4,1,t); + k.KO(-1,t,"3"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_050___nul_and_context.kmn b/common/test/keyboards/baseline/k_0808___nul_and_context.kmn similarity index 87% rename from common/test/keyboards/baseline/k_050___nul_and_context.kmn rename to common/test/keyboards/baseline/k_0808___nul_and_context.kmn index 206777b7f06..fabac4155c6 100644 --- a/common/test/keyboards/baseline/k_050___nul_and_context.kmn +++ b/common/test/keyboards/baseline/k_0808___nul_and_context.kmn @@ -1,4 +1,4 @@ -store(&NAME) '050 - nul_and_context' +store(&NAME) '0808 - nul_and_context' c Description: Tests that context has the right offset when used with nul c keys: [K_T][K_B] c expected: 2t3 diff --git a/common/test/keyboards/baseline/k_0808___nul_and_context.kmx b/common/test/keyboards/baseline/k_0808___nul_and_context.kmx new file mode 100644 index 00000000000..2304b23fe76 Binary files /dev/null and b/common/test/keyboards/baseline/k_0808___nul_and_context.kmx differ diff --git a/common/test/keyboards/baseline/k_0809___if_and_context.js b/common/test/keyboards/baseline/k_0809___if_and_context.js new file mode 100644 index 00000000000..a2e3ecd0356 --- /dev/null +++ b/common/test/keyboards/baseline/k_0809___if_and_context.js @@ -0,0 +1,45 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0809___if_and_context()); +} +function Keyboard_k_0809___if_and_context() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0809___if_and_context"; + this.KN="0809 - if_and_context"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.s_cons_4="mnpqrstv"; + this.s_ifx_5=KeymanWeb.KLOAD(this.KI,"ifx","1"); + this.s8="1"; + this.KVS=['s_ifx_5']; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_D /* 0x44 */)) { + if(k.KFCM(1,t,[{t:'a',a:this.s_cons_4}])&&this.s_ifx_5===this.s8){ + r=m=1; // Line 16 + k.KDC(1,t); + k.KO(-1,t,"4"); + k.KIO(-1,this.s_cons_4,1,t); + k.KO(-1,t,"5"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_051___if_and_context.kmn b/common/test/keyboards/baseline/k_0809___if_and_context.kmn similarity index 88% rename from common/test/keyboards/baseline/k_051___if_and_context.kmn rename to common/test/keyboards/baseline/k_0809___if_and_context.kmn index 7a6a3e3f63f..29c7c48ddb8 100644 --- a/common/test/keyboards/baseline/k_051___if_and_context.kmn +++ b/common/test/keyboards/baseline/k_0809___if_and_context.kmn @@ -1,4 +1,4 @@ -store(&NAME) '051 - if_and_context' +store(&NAME) '0809 - if_and_context' c Description: Tests that context has the right offset when used with if c keys: [K_T][K_D] c expected: 4t5 diff --git a/common/test/keyboards/baseline/k_0809___if_and_context.kmx b/common/test/keyboards/baseline/k_0809___if_and_context.kmx new file mode 100644 index 00000000000..ac1e467c9c2 Binary files /dev/null and b/common/test/keyboards/baseline/k_0809___if_and_context.kmx differ diff --git a/common/test/keyboards/baseline/k_0810___nul_and_index.js b/common/test/keyboards/baseline/k_0810___nul_and_index.js new file mode 100644 index 00000000000..1f86fe5ac04 --- /dev/null +++ b/common/test/keyboards/baseline/k_0810___nul_and_index.js @@ -0,0 +1,44 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0810___nul_and_index()); +} +function Keyboard_k_0810___nul_and_index() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0810___nul_and_index"; + this.KN="0810 - nul_and_index"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.s_cons_4="mnpqrstv"; + this.s_outs_5="MNPQRSTV"; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_B /* 0x42 */)) { + if(k.KFCM(2,t,[{t:'n'},{t:'a',a:this.s_cons_4}])){ + r=m=1; // Line 16 + k.KDC(1,t); + k.KO(-1,t,"2"); + k.KIO(-1,this.s_outs_5,1,t); + k.KO(-1,t,"3"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_052___nul_and_index.kmn b/common/test/keyboards/baseline/k_0810___nul_and_index.kmn similarity index 88% rename from common/test/keyboards/baseline/k_052___nul_and_index.kmn rename to common/test/keyboards/baseline/k_0810___nul_and_index.kmn index c56c411c076..91940d089c8 100644 --- a/common/test/keyboards/baseline/k_052___nul_and_index.kmn +++ b/common/test/keyboards/baseline/k_0810___nul_and_index.kmn @@ -1,4 +1,4 @@ -store(&NAME) '052 - nul_and_index' +store(&NAME) '0810 - nul_and_index' c Description: Tests that context has the right offset when used with nul c keys: [K_T][K_B] c expected: 2T3 diff --git a/common/test/keyboards/baseline/k_0810___nul_and_index.kmx b/common/test/keyboards/baseline/k_0810___nul_and_index.kmx new file mode 100644 index 00000000000..ea1a20064e4 Binary files /dev/null and b/common/test/keyboards/baseline/k_0810___nul_and_index.kmx differ diff --git a/common/test/keyboards/baseline/k_0811___if_and_index.js b/common/test/keyboards/baseline/k_0811___if_and_index.js new file mode 100644 index 00000000000..68205a31e72 --- /dev/null +++ b/common/test/keyboards/baseline/k_0811___if_and_index.js @@ -0,0 +1,46 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0811___if_and_index()); +} +function Keyboard_k_0811___if_and_index() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0811___if_and_index"; + this.KN="0811 - if_and_index"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.s_cons_4="mnpqrstv"; + this.s_outs_5="MNPQRSTV"; + this.s_ifx_6=KeymanWeb.KLOAD(this.KI,"ifx","1"); + this.s9="1"; + this.KVS=['s_ifx_6']; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_D /* 0x44 */)) { + if(k.KFCM(1,t,[{t:'a',a:this.s_cons_4}])&&this.s_ifx_6===this.s9){ + r=m=1; // Line 17 + k.KDC(1,t); + k.KO(-1,t,"4"); + k.KIO(-1,this.s_outs_5,1,t); + k.KO(-1,t,"5"); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_053___if_and_index.kmn b/common/test/keyboards/baseline/k_0811___if_and_index.kmn similarity index 89% rename from common/test/keyboards/baseline/k_053___if_and_index.kmn rename to common/test/keyboards/baseline/k_0811___if_and_index.kmn index 86479a8e88e..b019ffcc2b2 100644 --- a/common/test/keyboards/baseline/k_053___if_and_index.kmn +++ b/common/test/keyboards/baseline/k_0811___if_and_index.kmn @@ -1,4 +1,4 @@ -store(&NAME) '053 - if_and_index' +store(&NAME) '0811 - if_and_index' c Description: Tests that index() has the right offset when used with if c keys: [K_T][K_D] c expected: 4T5 diff --git a/common/test/keyboards/baseline/k_0811___if_and_index.kmx b/common/test/keyboards/baseline/k_0811___if_and_index.kmx new file mode 100644 index 00000000000..3313e890f9c Binary files /dev/null and b/common/test/keyboards/baseline/k_0811___if_and_index.kmx differ diff --git a/common/test/keyboards/baseline/k_054___nul_and_contextex.kmn b/common/test/keyboards/baseline/k_0812___nul_and_contextex.kmn similarity index 88% rename from common/test/keyboards/baseline/k_054___nul_and_contextex.kmn rename to common/test/keyboards/baseline/k_0812___nul_and_contextex.kmn index 39ef0d4534d..ae57598e1c9 100644 --- a/common/test/keyboards/baseline/k_054___nul_and_contextex.kmn +++ b/common/test/keyboards/baseline/k_0812___nul_and_contextex.kmn @@ -1,4 +1,4 @@ -store(&NAME) '054 - nul_and_contextex' +store(&NAME) '0812 - nul_and_contextex' c Description: Tests that context in context part of rule has the right offset when used with nul c keys: [K_T][K_T][K_B] c expected: 2tt3 diff --git a/common/test/keyboards/baseline/k_0812___nul_and_contextex.kmx b/common/test/keyboards/baseline/k_0812___nul_and_contextex.kmx new file mode 100644 index 00000000000..ae1dd8d8f84 Binary files /dev/null and b/common/test/keyboards/baseline/k_0812___nul_and_contextex.kmx differ diff --git a/common/test/keyboards/baseline/k_0813___deadkey_cancelled_by_arrow.js b/common/test/keyboards/baseline/k_0813___deadkey_cancelled_by_arrow.js new file mode 100644 index 00000000000..3991bda76c8 --- /dev/null +++ b/common/test/keyboards/baseline/k_0813___deadkey_cancelled_by_arrow.js @@ -0,0 +1,52 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_k_0813___deadkey_cancelled_by_arrow()); +} +function Keyboard_k_0813___deadkey_cancelled_by_arrow() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_k_0813___deadkey_cancelled_by_arrow"; + this.KN="0813 - deadkey cancelled by arrow"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=modCodes.SHIFT /* 0x0010 */; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_6 /* 0x36 */)) { + if(1){ + r=m=1; // Line 13 + k.KDC(0,t); + k.KDO(-1,t,0); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_E /* 0x45 */)) { + if(k.KFCM(1,t,[{t:'d',d:0}])){ + r=m=1; // Line 14 + k.KDC(1,t); + k.KO(-1,t,"FAIL."); + } + else if(1){ + r=m=1; // Line 15 + k.KDC(0,t); + k.KO(-1,t,"PASS."); + } + } + return r; + }; +} diff --git a/common/test/keyboards/baseline/k_055___deadkey_cancelled_by_arrow.kmn b/common/test/keyboards/baseline/k_0813___deadkey_cancelled_by_arrow.kmn similarity index 88% rename from common/test/keyboards/baseline/k_055___deadkey_cancelled_by_arrow.kmn rename to common/test/keyboards/baseline/k_0813___deadkey_cancelled_by_arrow.kmn index b84e9a4ab72..f52c747f362 100644 --- a/common/test/keyboards/baseline/k_055___deadkey_cancelled_by_arrow.kmn +++ b/common/test/keyboards/baseline/k_0813___deadkey_cancelled_by_arrow.kmn @@ -1,4 +1,4 @@ -store(&NAME) '050 - deadkey cancelled by arrow' +store(&NAME) '0813 - deadkey cancelled by arrow' c Description: Tests that context gets reset if we encounter a right-arrow c after a deadkey (#12968) c keys: [SHIFT K_6][K_RIGHT][K_E][SHIFT K_6][K_LEFT][K_E][SHIFT K_6][K_UP][K_E][SHIFT K_6][K_DOWN][K_E] diff --git a/common/test/keyboards/baseline/k_0813___deadkey_cancelled_by_arrow.kmx b/common/test/keyboards/baseline/k_0813___deadkey_cancelled_by_arrow.kmx new file mode 100644 index 00000000000..526c9300b56 Binary files /dev/null and b/common/test/keyboards/baseline/k_0813___deadkey_cancelled_by_arrow.kmx differ diff --git a/common/test/resources/keyboards/options_with_save.js b/common/test/resources/keyboards/options_with_save.js index 8252b516604..aa8507e0734 100644 --- a/common/test/resources/keyboards/options_with_save.js +++ b/common/test/resources/keyboards/options_with_save.js @@ -1,4 +1,4 @@ -// Original source may be found within the repo at /common/tests/keyboards/baseline/k_023___options_with_save.kmn +// Original source may be found within the repo at /common/tests/keyboards/baseline/k_0502___options_with_save.kmn if(typeof keyman === 'undefined') { console.log('Keyboard requires KeymanWeb 10.0 or later'); @@ -61,4 +61,4 @@ function Keyboard_options_with_save() { } return r; }; -} \ No newline at end of file +} diff --git a/common/test/resources/keyboards/test_8568_deadkeys.kmn b/common/test/resources/keyboards/test_8568_deadkeys.kmn index 4cf7cc799d1..f7f3067daa4 100644 --- a/common/test/resources/keyboards/test_8568_deadkeys.kmn +++ b/common/test/resources/keyboards/test_8568_deadkeys.kmn @@ -1,6 +1,6 @@ store(&NAME) 'Testcases for deadkeys bug (#8568)' c Description: Tests deadkey backspacing -c See also common/test/keyboards/baseline/k_020___deadkeys_and_backspace.kmn +c See also common/test/keyboards/baseline/k_0302___deadkeys_and_backspace.kmn c 1. One deadkey in context dk(1) + BKSP = nul c 2. One char and one deadkey in context 'a' dk(2) + BKSP = nul c 3. One deadkey and one char in context dk(3) 'a' + BKSP = nul diff --git a/common/test/resources/keyboards/test_rtl.js b/common/test/resources/keyboards/test_rtl.js new file mode 100644 index 00000000000..9ec0d156a35 --- /dev/null +++ b/common/test/resources/keyboards/test_rtl.js @@ -0,0 +1,48 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_test_rtl()); +} +function Keyboard_test_rtl() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_test_rtl"; + this.KN ="RTL Keyboard"; + this.KMINVER="10.0"; + this.KV=null; + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.0"; + this.KMBM=0 /* 0x0000 */; + this.KRTL=1; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_Main_0(t,e); + }; + this.g_Main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_A /* 0x41 */)) { + if(1){ + r=m=1; // Line 10 + k.KDC(0,t); + k.KO(-1,t,"ش"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_B /* 0x42 */)) { + if(1){ + r=m=1; // Line 11 + k.KDC(0,t); + k.KO(-1,t,"ال"); + } + } + return r; + }; +} diff --git a/common/test/resources/keyboards/test_rtl.kmn b/common/test/resources/keyboards/test_rtl.kmn new file mode 100644 index 00000000000..52efb684c53 --- /dev/null +++ b/common/test/resources/keyboards/test_rtl.kmn @@ -0,0 +1,11 @@ +store(&NAME) 'RTL Keyboard' + +store(&version) '10.0' +store(&KMW_RTL) '1' + +begin Unicode > use(Main) + +group(Main) using keys + ++ [K_A] > 'ش' ++ [K_B] > 'ال' diff --git a/common/test/resources/keyboards/test_rtl.kmx b/common/test/resources/keyboards/test_rtl.kmx new file mode 100644 index 00000000000..3571b6aa43c Binary files /dev/null and b/common/test/resources/keyboards/test_rtl.kmx differ diff --git a/common/test/resources/playwright-TC-reporter.ts b/common/test/resources/playwright-TC-reporter.ts new file mode 100644 index 00000000000..84f3eede0d0 --- /dev/null +++ b/common/test/resources/playwright-TC-reporter.ts @@ -0,0 +1,203 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + */ + +import type { + FullConfig, FullResult, Reporter, Suite, TestCase, TestResult +} from '@playwright/test/reporter'; + + +class TestNode { + public static Nodes = new Map(); + private static OpenNodes: string[] = []; + public static RootFlow: string; + private id: string; + private suiteOrTest: Suite | TestCase; + private flowId: number; + private parent: TestNode; + private childrenToVisit: TestNode[] = []; + + public constructor(suiteOrTest: Suite | TestCase) { + this.suiteOrTest = suiteOrTest; + this.id = this.suiteOrTest.titlePath().toString(); + this.flowId = Math.floor(Math.random() * 100000 + 1); + this.parent = null; // will be set by parent + if (!this.isTest) { + for (const child of (suiteOrTest).entries()) { + const node = new TestNode(child); + this.childrenToVisit.push(node); + node.parent = this; + } + } + TestNode.Nodes.set(this.id, this); + } + + private get isTest(): boolean { + return this.suiteOrTest.type == 'test'; + } + + public get parentFlowId(): number | string { + return this.parent?.flowId ?? TestNode.RootFlow; + } + + private start(): void { + this.parent?.start(); + if (TestNode.OpenNodes.includes(this.id)) { + // already started, nothing to do + if (this.isTest) { + console.error(`Test '${this.suiteOrTest.title}' is already started!`) + } + return; + } + + if (this.suiteOrTest.title !== '') { + console.log(`##teamcity[flowStarted flowId='${this.flowId}' parent='${this.parentFlowId}']`); + if (this.isTest) { + console.log(`##teamcity[testStarted name='${this.suiteOrTest.title}' captureStandardOutput='true']`); + } else { + console.log(`##teamcity[testSuiteStarted name='${this.suiteOrTest.title}']`); + } + } + + TestNode.OpenNodes.push(this.id); + } + + private escape(message: string): string { + // TeamCity escaping rules for: ' | [ ] \n \r \uNNNN + // See: https://www.jetbrains.com/help/teamcity/service-messages.html#Escaped+Values + return message?.replace(/['|\[\]]/g, (matched) => `|${matched}`) + .replace(/\n/g, '|n') + .replace(/\r/g, '|r') + .replace(/[\u0080-\uFFFF]/g, c => `|0x${c.charCodeAt(0).toString(16).padStart(4, '0')}`) ?? ''; + } + + private getTestResult(result: TestResult): { msgTitle: string, details: string } { + if (!result) { + return null; + } + switch (result.status) { + case 'passed': + return { msgTitle: 'testFinished', details: `duration='${result.duration}'` }; + case 'failed': + case 'interrupted': + case 'timedOut': + return { msgTitle: 'testFailed', details: `message='${this.escape(result.error?.message)}' details='${this.escape(result.error?.value ?? result.error?.cause)}'` }; + case 'skipped': + return { msgTitle: 'testIgnored', details: `message='${this.escape(result.annotations?.toString()) ?? ''}'` }; + } + } + + private end(result: TestResult, force: boolean = false): void { + if (this.childrenToVisit.length > 0 && force) { + while (this.childrenToVisit.length > 0) { + const child = this.childrenToVisit[0]; + child.end(result, force); + } + } + + if (!force) { + if (this.suiteOrTest.title !== '') { + if (this.isTest) { + const { msgTitle, details } = this.getTestResult(result) ?? { msgTitle: 'testFinished', details: '' }; + console.log(`##teamcity[${msgTitle} name='${this.suiteOrTest.title}' ${details}]`); + } else { + console.log(`##teamcity[testSuiteFinished name='${this.suiteOrTest.title}']`); + } + console.log(`##teamcity[flowFinished flowId = '${this.flowId}']`); + } + this.removeFromOpenNodes(); + + this.parent?.removeChild(this); + TestNode.Nodes.delete(this.id); + } + } + + private removeFromOpenNodes(): void { + const ourIndex = TestNode.OpenNodes.indexOf(this.id); + if (ourIndex < 0) { + console.error(`Can't find '${this.id}' in open nodes`); + return; + } + TestNode.OpenNodes.splice(ourIndex, 1); + } + + private removeChild(child: TestNode) { + const childIndex = this.childrenToVisit.indexOf(child); + if (childIndex < 0) { + console.error(`Can't find child '${child.id}' in parent '${this.id}'`); + return; + } + this.childrenToVisit.splice(childIndex, 1); + + if (this.childrenToVisit.length > 0) { + return; + } + + // No more children, so close this node + this.end(null, false); + } + + public static startTest(test: TestCase): void { + const node = TestNode.Nodes.get(test.titlePath().toString()); + if (!node) { + console.error(`Can't find test node for ${test.titlePath().toString()}`); + return; + } + node.start(); + } + + public static endTest(test: TestCase, result: TestResult): void { + const node = TestNode.Nodes.get(test.titlePath().toString()); + if (!node) { + console.error(`Can't find test node for ${test.titlePath().toString()}`); + return; + } + node.end(result); + } + + public endAll(): void { + if (this.childrenToVisit.length > 0) { + console.error(`Root node still has ${this.childrenToVisit.length} open children`); + } + this.end(null, true); + if (TestNode.OpenNodes.length > 0) { + console.error(`Still have ${TestNode.OpenNodes.length} open nodes`); + while (TestNode.OpenNodes.length > 0) { + const id = TestNode.OpenNodes[TestNode.OpenNodes.length - 1]; + console.log(`Closing '${id}'`); + const node = TestNode.Nodes.get(id); + node.end(null); + } + } + if (TestNode.Nodes.size > 0) { + console.error(`Still have ${TestNode.Nodes.size} nodes hanging around`); + for (const [id, node] of Array.from(TestNode.Nodes.entries())) { + console.error(`Remaining node title: '${node.suiteOrTest.title}' (id: '${id}')`); + } + } + } +} + +export default class PlaywrightTeamcityReporter implements Reporter { + private root: TestNode = null; + + public constructor(options: { parentFlow?: string } = {}) { + TestNode.RootFlow = options.parentFlow ?? 'unit_tests'; + } + + public onBegin(config: FullConfig, suite: Suite) { + this.root = new TestNode(suite); + } + + public onTestBegin(test: TestCase, result: TestResult) { + TestNode.startTest(test); + } + + public onTestEnd(test: TestCase, result: TestResult) { + TestNode.endTest(test, result); + } + + public onEnd(result: FullResult) { + this.root.endAll(); + } +} diff --git a/common/tools/es-bundling/.gitignore b/common/tools/es-bundling/.gitignore new file mode 100644 index 00000000000..07ed7069a24 --- /dev/null +++ b/common/tools/es-bundling/.gitignore @@ -0,0 +1 @@ +build/* \ No newline at end of file diff --git a/web/src/tools/es-bundling/README.md b/common/tools/es-bundling/README.md similarity index 100% rename from web/src/tools/es-bundling/README.md rename to common/tools/es-bundling/README.md diff --git a/web/src/tools/es-bundling/build.sh b/common/tools/es-bundling/build.sh similarity index 68% rename from web/src/tools/es-bundling/build.sh rename to common/tools/es-bundling/build.sh index 3a05714120c..8ff7f035f40 100755 --- a/web/src/tools/es-bundling/build.sh +++ b/common/tools/es-bundling/build.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/builder-full.inc.sh" +. "${THIS_SCRIPT%/*}/../../../resources/build/builder-full.inc.sh" ## END STANDARD BUILD SCRIPT INCLUDE . "$KEYMAN_ROOT/resources/build/utils.inc.sh" @@ -11,17 +11,17 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" ################################ Main script ################################ -builder_describe "Builds KMW's esbuild-oriented common configuration & tooling" \ +builder_describe "esbuild style bundling tooling for web and common/web" \ "clean" \ "configure" \ "build" builder_describe_outputs \ configure /node_modules \ - build /web/src/tools/es-bundling/build/index.mjs + build /common/tools/es-bundling/build/index.mjs builder_parse "$@" builder_run_action configure node_select_version_and_npm_ci builder_run_action clean rm -rf build/ -builder_run_action build tsc -b tsconfig.json +builder_run_action build tsc -b diff --git a/web/src/tools/es-bundling/src/classTreeshaker.mts b/common/tools/es-bundling/src/classTreeshaker.mts similarity index 100% rename from web/src/tools/es-bundling/src/classTreeshaker.mts rename to common/tools/es-bundling/src/classTreeshaker.mts diff --git a/web/src/tools/es-bundling/src/common-bundle.mts b/common/tools/es-bundling/src/common-bundle.mts similarity index 100% rename from web/src/tools/es-bundling/src/common-bundle.mts rename to common/tools/es-bundling/src/common-bundle.mts diff --git a/web/src/tools/es-bundling/src/configuration.mts b/common/tools/es-bundling/src/configuration.mts similarity index 100% rename from web/src/tools/es-bundling/src/configuration.mts rename to common/tools/es-bundling/src/configuration.mts diff --git a/web/src/tools/es-bundling/src/index.mts b/common/tools/es-bundling/src/index.mts similarity index 100% rename from web/src/tools/es-bundling/src/index.mts rename to common/tools/es-bundling/src/index.mts diff --git a/web/src/tools/es-bundling/src/tslibTreeshaking.mts b/common/tools/es-bundling/src/tslibTreeshaking.mts similarity index 100% rename from web/src/tools/es-bundling/src/tslibTreeshaking.mts rename to common/tools/es-bundling/src/tslibTreeshaking.mts diff --git a/web/src/tools/es-bundling/tsconfig.json b/common/tools/es-bundling/tsconfig.json similarity index 75% rename from web/src/tools/es-bundling/tsconfig.json rename to common/tools/es-bundling/tsconfig.json index 1c317aabec6..5870280035f 100644 --- a/web/src/tools/es-bundling/tsconfig.json +++ b/common/tools/es-bundling/tsconfig.json @@ -1,8 +1,7 @@ { - "extends": "../../../../tsconfig.base.json", + "extends": "../../../tsconfig.base.json", "compilerOptions": { "allowSyntheticDefaultImports": true, - "baseUrl": "./", "outDir": "build/", "tsBuildInfoFile": "build/tsconfig.tsbuildinfo", "rootDir": "./src" diff --git a/common/web/sentry-manager/build.sh b/common/web/sentry-manager/build.sh new file mode 100755 index 00000000000..b2bcea8d94f --- /dev/null +++ b/common/web/sentry-manager/build.sh @@ -0,0 +1,35 @@ +#!/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-full.inc.sh" +## END STANDARD BUILD SCRIPT INCLUDE + +. "${KEYMAN_ROOT}/resources/build/utils.inc.sh" +. "${KEYMAN_ROOT}/resources/build/node.inc.sh" + +builder_describe "Sentry error reporting module for embedded Keyman Engine for Web" \ + "@/common/tools/es-bundling" \ + "@/common/web/keyman-version" \ + clean configure build test + +builder_describe_outputs \ + configure /node_modules \ + build /common/web/sentry-manager/build/lib/index.js + +builder_parse "$@" + +# --------------------------------------------------------------------------------- + +function do_build() { + tsc --build + + node_es_bundle "${KEYMAN_ROOT}/common/web/sentry-manager/build/obj/src/index.js" \ + --out "${KEYMAN_ROOT}/common/web/sentry-manager/build/lib/index.js" \ + --sourceRoot "@keymanapp/keyman/common/web/sentry-manager/build/lib/" +} + +builder_run_action clean rm -rf build/ +builder_run_action configure node_select_version_and_npm_ci +builder_run_action build do_build + diff --git a/web/src/engine/sentry-manager/package.json b/common/web/sentry-manager/package.json similarity index 100% rename from web/src/engine/sentry-manager/package.json rename to common/web/sentry-manager/package.json diff --git a/web/src/engine/sentry-manager/src/index.ts b/common/web/sentry-manager/src/index.ts similarity index 100% rename from web/src/engine/sentry-manager/src/index.ts rename to common/web/sentry-manager/src/index.ts diff --git a/common/web/sentry-manager/tsconfig.json b/common/web/sentry-manager/tsconfig.json new file mode 100644 index 00000000000..0967154d905 --- /dev/null +++ b/common/web/sentry-manager/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "baseUrl": "./", + "lib": ["es6", "dom"], + "outDir": "./build/obj", + "rootDir": "./", + "tsBuildInfoFile": "./build/obj/tsconfig.tsbuildinfo", + }, + + "include": [ + "src/*.ts" + ] +} \ No newline at end of file diff --git a/common/web/types/package.json b/common/web/types/package.json index 2b2122f6828..2c66de8a632 100644 --- a/common/web/types/package.json +++ b/common/web/types/package.json @@ -77,7 +77,6 @@ "src/schemas/*", "tests/", "src/keyboard-object.ts", - "src/outputTarget.interface.ts", "src/*.d.ts", "src/main.ts", "src/schema-validators.ts", diff --git a/common/web/types/src/consts/virtual-key-constants.ts b/common/web/types/src/consts/virtual-key-constants.ts index 7b083241bdc..0ce728b2f9f 100644 --- a/common/web/types/src/consts/virtual-key-constants.ts +++ b/common/web/types/src/consts/virtual-key-constants.ts @@ -127,6 +127,10 @@ export const USVirtualKeyCodes = { 'k_?C1':193, K_oDF:0xDF, K_ODF:0xDF, + + // Key codes > 50000 are special virtual key codes that are only used + // in touch layouts and should probably not be used elsewhere. + // See https://github.com/keymanapp/keyman/pull/15343#discussion_r2674949933 K_LOPT:50001, K_ROPT:50002, K_NUMERALS:50003, diff --git a/common/web/types/src/keyboard-object.ts b/common/web/types/src/keyboard-object.ts index afd0029af0d..3ce697ef4b1 100644 --- a/common/web/types/src/keyboard-object.ts +++ b/common/web/types/src/keyboard-object.ts @@ -8,8 +8,8 @@ export type ComplexKeyboardStore = (string | { t: 'd', d: number } | { ['t']: 'b // A stub for KeyEvent which is properly defined in KeymanWeb type KeyEventStub = {}; -// A stub for OutputTarget which is properly defined in KeymanWeb -type OutputTargetStub = {}; +// A stub for TextStore which is properly defined in KeymanWeb +type TextStoreStub = {}; export interface EncodedVisualKeyboard { /** Represents CSS font styling to use for VisualKeyboard text */ @@ -43,31 +43,31 @@ export type KeyboardObject = { * group-start: the function triggering processing for the keyboard's * "Unicode" start group, corresponding to `begin Unicode > use(_____)` in * Keyman keyboard language. - * @param outputTarget The context to which the keystroke applies + * @param textStore The context to which the keystroke applies * @param keystroke The full, pre-processed keystroke triggering * keyboard-rule application. */ - gs(outputTarget: OutputTargetStub, keystroke: KeyEventStub): boolean; + gs(textStore: TextStoreStub, keystroke: KeyEventStub): boolean; /** * group-newcontext: the function triggering processing for the keyboard's * "NewContext" start group, corresponding to `begin NewContext > use(_____)` * in Keyman keyboard language. - * @param outputTarget The new context to be used with future keystrokes + * @param textStore The new context to be used with future keystrokes * @param keystroke A 'null' `KeyEvent` providing current modifier + state information. */ - gn?(outputTarget: OutputTargetStub, keystroke: KeyEventStub): boolean; + gn?(textStore: TextStoreStub, keystroke: KeyEventStub): boolean; /** * group-postkeystroke: the function triggering processing for the keyboard's * "PostKeystroke" start group, corresponding to `begin PostKeystroke > * use(_____)` in Keyman keyboard language. - * @param outputTarget The context altered by a recent keystroke. As a + * @param textStore The context altered by a recent keystroke. As a * precondition, all changes due to `gs` / `begin Unicode` should already be * applied. * @param keystroke A 'null' `KeyEvent` providing current modifier + state information. */ - gpk?(outputTarget: OutputTargetStub, keystroke: KeyEventStub): boolean; + gpk?(textStore: TextStoreStub, keystroke: KeyEventStub): boolean; /** * Keyboard ID: the uniquely-identifying name for this keyboard. Includes the standard @@ -175,6 +175,6 @@ export type KeyboardObject = { * @param {number} _PData 1 or 0 * @returns */ - KNS?: (_PCommand: number, _PTarget: OutputTargetStub, _PData: number) => void; + KNS?: (_PCommand: number, _PTarget: TextStoreStub, _PData: number) => void; } & Record<`s${number}`, string> diff --git a/common/web/types/src/kmx/kmx.ts b/common/web/types/src/kmx/kmx.ts index 4f53e29fde1..651a6db0d13 100644 --- a/common/web/types/src/kmx/kmx.ts +++ b/common/web/types/src/kmx/kmx.ts @@ -3,7 +3,8 @@ import { ModifierKeyConstants } from '../consts/modifier-key-constants.js'; /* Definitions from kmx_file.h. Must be kept in sync */ -// TODO: split kmx-file from kmx in-memory, similar to what I've done for kvk (keep restructure decl + BUILDER_ interfaces together) +// TODO-embed-osk-in-kmx: split kmx-file from kmx in-memory, similar to what I've done for kvk (keep restructure decl + BUILDER_ interfaces together) +// this will make it possible to use these declarations in KeymanWeb // In memory representations of KMX structures // kmx-builder will transform these to the corresponding COMP_xxxx diff --git a/core/docs/api/changes.md b/core/docs/api/changes.md index e5736494abc..f7f250f3376 100644 --- a/core/docs/api/changes.md +++ b/core/docs/api/changes.md @@ -2,6 +2,17 @@ title: Changes - Keyman Core API --- +## Changes between 18.0 and 19.0 + +* Removed deprecated `km_core_keyboard_attrs.folder_path` + +## Changes between 17.0 and 18.0 + +* Replaced `km_core_keyboard_load` with `km_core_keyboard_load_from_blob`. + Keyboard loading is now done in the engine, and the content of the + keyboard passed to Core as a blob. +* Deprecated `km_core_keyboard_attrs.folder_path` + ## Changes between 16.0 and 17.0 * The namespace identifier has changed from `km_kbp_` to `km_core_`. @@ -61,4 +72,4 @@ title: Changes - Keyman Core API [km_core_event_flags]: processor#km_core_event_flags "km_core_event_flags enum" [km_core_process_event]: processor#km_core_process_event "km_core_process_event function" [km_core_event]: processor#km_core_event "km_core_event function" -[km_core_event_code]: processor#km_core_event_code "km_core_event_code enum" \ No newline at end of file +[km_core_event_code]: processor#km_core_event_code "km_core_event_code enum" diff --git a/core/docs/api/keyboards.md b/core/docs/api/keyboards.md index 3439e20722b..07a30921c9c 100644 --- a/core/docs/api/keyboards.md +++ b/core/docs/api/keyboards.md @@ -20,7 +20,6 @@ Provides read-only information about a keyboard. typedef struct { km_core_cp const * version_string; km_core_cp const * id; - km_core_path_name folder_path; km_core_option_item const * default_options; } km_core_keyboard_attrs; @@ -33,9 +32,6 @@ typedef struct { `id` : Keyman keyboard ID string. -`folder_path` -: Path to the unpacked folder containing the keyboard and associated resources. - `default_options` : Set of default values for any options included in the keyboard. @@ -662,4 +658,4 @@ km_core_state_to_json(km_core_state const *state, [km_core_event_flags]: processor#km_core_event_flags "km_core_event_flags enum" [km_core_process_event]: processor#km_core_process_event "km_core_process_event function" [km_core_event]: processor#km_core_event "km_core_event function" -[km_core_event_code]: processor#km_core_event_code "km_core_event_code enum" \ No newline at end of file +[km_core_event_code]: processor#km_core_event_code "km_core_event_code enum" diff --git a/core/include/keyman/keyman_core_api.h b/core/include/keyman/keyman_core_api.h index c26cbdf9ff5..981aa59d11a 100644 --- a/core/include/keyman/keyman_core_api.h +++ b/core/include/keyman/keyman_core_api.h @@ -302,11 +302,15 @@ typedef uint8_t (*km_core_keyboard_imx_platform)(km_core_state*, uint32_t, void* ## Description -An error code mechanism similar to COM’s `HRESULT` scheme (unlike COM, any +An error code mechanism similar to COM's `HRESULT` scheme (unlike COM, any non-zero value is an error). ## Specification +--> +// keep in sync with web/src/engine/src/core-adapter/KM_Core.ts +// (see https://github.com/emscripten-core/emscripten/issues/18585) +KeyboardSpec; - WebUtils["@keymanapp/web-utils
(/web/src/engine/common/web-utils)"]; + WebUtils["/web/src/common/web-utils"]; KeyboardSpec---->WebUtils; Wordbreakers["@keymanapp/models-wordbreakers
(/web/src/engine/predictive-text/wordbreakers)"]; Models["@keymanapp/models-templates
(/web/src/engine/predictive-text/templates/)"]; @@ -94,7 +95,7 @@ graph TD; LMWorker-->Wordbreakers; LMLayer["@keymanapp/lexical-model-layer
(/web/src/engine/predictive-text/worker-main)"]; LMLayer-->LMWorker; - Gestures["@keymanapp/gesture-recognizer
(/web/src/engine/osk/gesture-recognizer)"]; + Gestures["/web/src/engine/gesture-processor"]; Gestures-->WebUtils; subgraph PredText["PredText: WebWorker + its interface"] @@ -116,7 +117,7 @@ graph TD; subgraph ClassicWeb["`**ClassicWeb** Intermediate-level engine modules`"] - Elements["/web/src/engine/element-wrappers"]; + Elements["/web/src/engine/element-text-stores"]; Elements-->JSProc; KeyboardStorage["/web/src/engine/keyboard-storage"]; KeyboardStorage-->Interfaces; diff --git a/web/build.sh b/web/build.sh index cbbaaca1832..d047b7dece0 100755 --- a/web/build.sh +++ b/web/build.sh @@ -9,43 +9,39 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" ## END STANDARD BUILD SCRIPT INCLUDE . "$KEYMAN_ROOT/resources/build/utils.inc.sh" -. "$KEYMAN_ROOT/web/common.inc.sh" +. "$KEYMAN_ROOT/resources/build/node.inc.sh" # ################################ Main script ################################ builder_set_child_base src builder_describe "Builds engine modules for Keyman Engine for Web (KMW)." \ \ + "@/common/tools/es-bundling build" \ "@/resources/tools/check-markdown test:help" \ \ "clean" \ "configure" \ "build" \ + "start Starts the test server" \ "test" \ - "coverage Create an HTML page with code coverage" \ - ":app/browser The form of Keyman Engine for Web for use on websites" \ - ":app/webview A puppetable version of KMW designed for use in a host app's WebView" \ - ":app/ui Builds KMW's desktop form-factor keyboard-selection UI modules" \ - ":engine/attachment Subset used for detecting valid page contexts for use in text editing " \ - ":engine/common/web-utils Low-level, headless utility methods and classes used across multiple modules" \ - ":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/predictive-text Builds KMW's predictive text module" \ + "coverage Create an HTML page with code coverage report" \ + \ + ":app/browser KeymanWeb build for use on websites" \ + ":app/webview KeymanWeb build for embedding in Keyman for Android and Keyman for iOS" \ + ":app/ui KeymanWeb desktop form-factor keyboard-selection UI modules" \ + ":common/web-utils Shared utils" \ + ":engine Keyman Engine for Web" \ ":help Online documentation" \ - ":samples Builds all needed resources for the KMW sample-page set" \ - ":tools Builds engine-related development resources" \ + ":samples Resources for the KMW sample-page set" \ + ":tools/building Build tools" \ + ":tools/testing Test tools" \ ":test-pages=src/test/manual Builds resources needed for the KMW manual testing pages" \ - ":_all (Meta build target used when targets are not specified)" - -# Possible TODO? -# "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ + ":_all (Meta build target used when targets are not specified)" \ + \ + "--test-dom-only For test, run only DOM-oriented unit tests (reduced footprint, nothing browser-specific)" \ + "--test-integrated-only For test, run only KMW's integration test suite" \ + "--test-e2e-only For test, run only KMW's end-to-end test suite" \ + "--test-inspect For test, run browser-based unit tests in an inspectable mode" builder_parse "$@" @@ -56,42 +52,27 @@ fi builder_describe_outputs \ configure "/node_modules" \ - build "/web/build/test/dom/cases/attachment/outputTargetForElement.tests.html" \ + build "/web/build/test/dom/cases/attachment/textStoreForElement.tests.html" \ build:app/browser "/web/build/app/browser/lib/index.mjs" \ build:app/webview "/web/build/app/webview/${config}/keymanweb-webview.js" \ build:app/ui "/web/build/app/ui/${config}/kmwuitoggle.js" \ - build:engine/attachment "/web/build/engine/attachment/lib/index.mjs" \ - 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/predictive-text "/web/src/engine/predictive-text/worker-main/build/lib/web/index.mjs" \ - build:engine/common/web-utils "/web/src/engine/common/web-utils/build/lib/index.mjs" \ + build:common/web-utils "/web/build/common/web-utils/lib/index.mjs" \ + build:engine "/web/build/engine/lib/index.mjs" \ build:samples "/web/src/samples/simplest/keymanweb.js" \ - build:tools "/web/build/tools/building/sourcemap-root/index.js" \ + build:tools/building "/web/build/tools/building/sourcemap-root/index.js" \ + build:tools/testing "/web/build/tools/testing/test-utils/lib/index.d.ts" \ build:test-pages "/web/build/test-resources/sentry-manager.js" #### Build action definitions #### -##################### TODO: call child action, verify things work as expected! - # We can run all clean & configure actions at once without much issue. +## Clean actions + builder_run_action clean:_all rm -rf build/ builder_run_child_actions clean -## Clean actions - -###--- Future tie-in: if #8831 gets accepted, uncomment the next two lines. ---### -# # If a full-on general clean was requested, we can nuke the entire build folder. -# builder_run_action clean:project rm -rf ./build - builder_run_child_actions configure ## Build actions @@ -106,20 +87,22 @@ precompile() { # types built-in to Node aren't available, and @web/test-runner doesn't do # treeshaking when loading the imports. We work around by pre-compiling. for f in "${DIR}"/*.js; do - node "${LIB_BUNDLER}" "${f}" \ - --out "${f%.js}".mjs \ + node_es_bundle "${f}" \ + --out "${f%.js}".mjs \ --format esm done } -build_action() { +build_tests_action() { builder_echo "Building auto tests..." # The currently-bundled declaration file for gesture-processor generates # errors when compiling against it with current tsc versions. rm -f "${KEYMAN_ROOT}/node_modules/promise-status-async/lib/index.d.ts" - tsc --project "${KEYMAN_ROOT}/web/src/test/auto/tsconfig.json" + tsc -b "${KEYMAN_ROOT}/web/src/test/auto/tsconfig.json" + + builder_echo "Copying some files" for dir in \ "${KEYMAN_ROOT}/web/build/test/dom/cases"/*/ \ @@ -129,7 +112,7 @@ build_action() { precompile "${dir}" done - cp "${KEYMAN_ROOT}/web/src/test/auto/dom/cases/attachment/outputTargetForElement.tests.html" \ + cp "${KEYMAN_ROOT}/web/src/test/auto/dom/cases/attachment/textStoreForElement.tests.html" \ "${KEYMAN_ROOT}/web/build/test/dom/cases/attachment/" } @@ -157,31 +140,14 @@ coverage_action() { rm -rf build/coverage/tmp } -builder_run_child_actions build:engine/common/web-utils -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 +builder_run_child_actions build:tools/building -# Uses engine/dom-utils and engine/interfaces -builder_run_child_actions build:engine/osk +builder_run_child_actions build:common/web-utils -# Uses engine/element-wrappers -builder_run_child_actions build:engine/attachment +builder_run_child_actions build:engine +# builder_run_child_actions build:engine/predictive-text -# Uses engine/interfaces (due to resource-path config interface) -builder_run_child_actions build:engine/keyboard-storage - -# Builds the predictive-text components -builder_run_child_actions build:engine/predictive-text - -# Uses engine/interfaces, engine/keyboard-storage, engine/predictive-text, & engine/osk -builder_run_child_actions build:engine/main - -# Uses all but engine/element-wrappers and engine/attachment +# Uses all but engine/element-text-stores and engine/attachment builder_run_child_actions build:app/webview # Uses literally everything `engine/` above @@ -193,17 +159,64 @@ builder_run_child_actions build:app/ui # Needs both app/browser and app/ui. builder_run_child_actions build:samples -builder_run_child_actions build:tools - # Some test pages refer to KMW tools. builder_run_child_actions build:test-pages # Build tests -builder_run_action build:_all build_action +builder_run_child_actions build:tools/testing +builder_run_action build:_all build_tests_action # Run tests builder_run_child_actions test -builder_run_action test:_all builder_launch /web/test.sh test + +function is_test_included() { + local test_opt=$1 + local run_dom_tests=true run_integrated_tests=true run_e2e_tests=true + local var_name="run_${test_opt}_tests" + + if builder_has_option --test-integrated-only || builder_has_option --test-e2e-only; then + run_dom_tests=false + fi + if builder_has_option --test-dom-only || builder_has_option --test-e2e-only; then + run_integrated_tests=false + fi + if builder_has_option --test-dom-only || builder_has_option --test-integrated-only; then + run_e2e_tests=false + fi + + ${!var_name} +} + +function do_browser_tests() { + # Browser-based tests: common configs & kill-switches + + # Select the right CONFIG file. + local WTR_CONFIG= + if builder_is_ci_build; then + WTR_CONFIG=.CI + export KEYMAN_IS_CI_BUILD=1 + fi + + # Prepare the flags for the karma command. + local WTR_INSPECT= + if builder_has_option --test-inspect; then + WTR_INSPECT="--manual" + fi + + pushd "${KEYMAN_ROOT}" + if is_test_included dom; then + web-test-runner --config "web/src/test/auto/dom/web-test-runner${WTR_CONFIG}.config.mjs" ${WTR_INSPECT} + fi + if is_test_included integrated; then + web-test-runner --config "web/src/test/auto/integrated/web-test-runner${WTR_CONFIG}.config.mjs" ${WTR_INSPECT} + fi + if is_test_included e2e; then + npx playwright test --config "web/src/test/auto/e2e/playwright.config.ts" + fi + popd +} + +builder_run_action test:_all do_browser_tests function do_test_help() { check-markdown "$KEYMAN_ROOT/web/docs/engine" @@ -213,3 +226,6 @@ builder_run_action test:help do_test_help # Create coverage report builder_run_action coverage:_all coverage_action + +# Start the test server +builder_run_action start node src/tools/testing/test-server/index.cjs diff --git a/web/ci.sh b/web/ci.sh index 9008d56a503..f9c4e4263d8 100755 --- a/web/ci.sh +++ b/web/ci.sh @@ -24,6 +24,7 @@ cd "${THIS_SCRIPT_PATH}" S_KEYMAN_COM= builder_describe "CI processes for Keyman Engine for Web releases (KMW)." \ + "@/common/web/sentry-manager" \ "@/web/src/tools/building/sourcemap-root prepare:s.keyman.com" \ "build" \ "test Runs all unit tests" \ @@ -69,10 +70,10 @@ function build_action() { if builder_is_ci_build && builder_is_ci_build_level_release; then # Upload the sentry-configuration engine used by the mobile apps to sentry # Also, clean 'em first. - for sourcemap in "${KEYMAN_ROOT}/web/src/engine/sentry-manager/build/lib/"*.map; do + for sourcemap in "${KEYMAN_ROOT}/common/web/sentry-manager/build/lib/"*.map; do node "${KEYMAN_ROOT}/web/build/tools/building/sourcemap-root/index.js" null "${sourcemap}" --clean done - web_sentry_upload "${KEYMAN_ROOT}/web/src/engine/sentry-manager/build/lib/" + web_sentry_upload "${KEYMAN_ROOT}/common/web/sentry-manager/build/lib/" # And, of course, the main build-products too web_sentry_upload "${KEYMAN_ROOT}/web/build/app/webview/release/" diff --git a/web/common.inc.sh b/web/common.inc.sh index c88c081900b..2d222bc34c6 100644 --- a/web/common.inc.sh +++ b/web/common.inc.sh @@ -1,8 +1,6 @@ #!/usr/bin/env bash # -LIB_BUNDLER="${KEYMAN_ROOT}/web/src/tools/es-bundling/build/common-bundle.mjs" - # Compiles all build products corresponding to the specified target. # This should be called from the working directory of a child project's # build script. @@ -19,7 +17,7 @@ LIB_BUNDLER="${KEYMAN_ROOT}/web/src/tools/es-bundling/build/common-bundle.mjs" # compile engine/main # ``` function compile() { - if [ $# -lt 1 ]; then + if [[ $# -lt 1 ]]; then builder_die "Scripting error: insufficient argument count!" fi @@ -29,10 +27,10 @@ function compile() { local SRC_DIR=${2:-"${KEYMAN_ROOT}/web/src"} local BUILD_DIR=${3:-"${KEYMAN_ROOT}/web/build"} - tsc -b "${SRC_DIR}/$COMPILE_TARGET" + tsc -b "${SRC_DIR}/${COMPILE_TARGET}" # So... tsc does declaration-bundling on its own pretty well, at least for local development. - tsc --emitDeclarationOnly --outFile "${BUILD_DIR}/$COMPILE_TARGET/lib/index.d.ts" -p "${SRC_DIR}/$COMPILE_TARGET" + tsc --emitDeclarationOnly --outFile "${BUILD_DIR}/${COMPILE_TARGET}/lib/index.d.ts" -p "${SRC_DIR}/${COMPILE_TARGET}" } function _copy_dir_if_exists() { @@ -90,28 +88,36 @@ function prepare() { # test-headless engine/osk # ``` function test-headless() { - TEST_FOLDER=$1 - TEST_BASE="${KEYMAN_ROOT}/web/src/test/auto/headless/" - TEST_EXTENSIONS=${2:-} - if [ ! -z "${2:-}" ]; then + local TEST_FOLDER=$1 + local TEST_BASE="${KEYMAN_ROOT}/web/src/test/auto/headless/" + local TEST_EXTENSIONS=${2:-} + shift $(( $# < 2 ? $# : 2 )) + + if [[ ! -z "${TEST_EXTENSIONS}" ]]; then TEST_BASE="${KEYMAN_ROOT}/web/build/test/headless/" # Ensure the compiled tests are available. tsc --project "${KEYMAN_ROOT}/web/src/test/auto/tsconfig.json" fi - TEST_OPTS=() + local TEST_OPTS=() if builder_is_running_on_teamcity; then TEST_OPTS+=(--reporter "${KEYMAN_ROOT}/common/test/resources/mocha-teamcity-reporter/teamcity.cjs" --reporter-options parentFlowId="unit_tests") echo "##teamcity[flowStarted flowId='unit_tests']" fi if [[ -n "${TEST_EXTENSIONS}" ]]; then + # file extension of test files TEST_OPTS+=(--extension "${TEST_EXTENSIONS}") fi - if [[ -e .c8rc.json ]]; then + # Add any remaining arguments directly to Mocha. + TEST_OPTS+=("$@") + + if [[ -e .c8rc.json && -z "${SKIP_C8:-}" ]]; then + builder_echo '> ' c8 mocha --recursive "${TEST_BASE}${TEST_FOLDER}" "${TEST_OPTS[@]}" c8 mocha --recursive "${TEST_BASE}${TEST_FOLDER}" "${TEST_OPTS[@]}" else + builder_echo '> ' mocha --recursive "${TEST_BASE}${TEST_FOLDER}" "${TEST_OPTS[@]}" mocha --recursive "${TEST_BASE}${TEST_FOLDER}" "${TEST_OPTS[@]}" fi diff --git a/web/docs/engine/reference/interface/contextExOutput.md b/web/docs/engine/reference/interface/contextExOutput.md index 35a1801088a..73a1a97c8a0 100644 --- a/web/docs/engine/reference/interface/contextExOutput.md +++ b/web/docs/engine/reference/interface/contextExOutput.md @@ -11,13 +11,13 @@ gap between desktop and web core functionality for `context(n)` matching on `not ## Syntax ```js - keyman.interface.contextExOutput(dn, outputTarget, contextLength, contextOffset); + keyman.interface.contextExOutput(dn, textStore, contextLength, contextOffset); ``` or ```js - KeymanWeb.KCXO(dn, outputTarget, contextLength, contextOffset); // Shorthand + KeymanWeb.KCXO(dn, textStore, contextLength, contextOffset); // Shorthand ``` ## Parameters @@ -26,8 +26,8 @@ or : Type: `number` : number of characters to delete left of cursor -`outputTarget` -: Type: `OutputTarget` +`textStore` +: Type: `TextStore` : target to output to `contextLength` diff --git a/web/docs/internal/context-state-management.md b/web/docs/internal/context-state-management.md index 4c049a90921..9c25186f7bc 100644 --- a/web/docs/internal/context-state-management.md +++ b/web/docs/internal/context-state-management.md @@ -1,72 +1,169 @@ # Context State Management -## The `OutputTarget` Abstraction - -The `OutputTarget` abstraction and its associated types and classes exist to facilitate handling different types of context sources within Keyman Engine for Web through a common interface. In essence, any implementing type is valid within the engine as a "target" for "output" from any existing keyboard supported by the engine. Through 18.0, only JS-based keyboards were supported due to lack of implementation of alternate keystroke-processing engines. - -At the most basic level, the abstraction is defined at [web/src/engine/keyboard/outputTarget.interface.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/keyboard/src/outputTarget.interface.ts). The methods defined therein support properties and methods for fetching, setting, and manipulating deadkey markers, text-selection, and text within whatever context source it represents. JS-keyboard keystroke processing directly uses these methods during operation. -- `epic/web-core` note: moved to `outputTarget.ts` in the same folder, dropping the `.interface` component. - -The base implementation for this type may be found at [web/src/engine/js-processor/src/outputTarget.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/js-processor/src/outputTarget.ts). This implementation provides common support for deadkey tracking, matching, and handling - the same strategy is used regardless of context-source type. A few additional methods are provided to assist with comparison and contrast between two different context states and restoration of a prior context state. -- `epic/web-core` note: renamed `OutputTargetBase`, moved to `outputTargetBase.ts` in the same folder +## The `TextStore` Abstraction + +The `TextStore` abstraction and its associated types and classes exist +to facilitate handling different types of context sources within Keyman +Engine for Web through a common interface. In essence, any implementing +type is valid within the engine as a "target" for "output" from any +existing keyboard supported by the engine. Through 18.0, only JS-based +keyboards were supported due to lack of implementation of alternate +keystroke-processing engines. + +The base implmentation may be found at +[web/src/engine/keyboard/textStore.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/keyboard/src/textStore.ts). +The methods defined therein support properties and methods for fetching, +setting, and manipulating deadkey markers, text-selection, and text +within whatever context source it represents. JS-keyboard keystroke +processing directly uses these methods during operation. + +Since the context sources are the same for all keyboard processors, the +all use the same base implementation, although not all funcitonality is +needed by all keyboard processors (e.g. deadkey tracking functionality +is only needed by the JS-keyboard processor). This implementation +provides common support for deadkey tracking, matching, and handling - +the same strategy is used regardless of context-source type. A few +additional methods are provided to assist with comparison and contrast +between two different context states and restoration of a prior context +state. + +- note: previously called `OutputTarget` ### Deadkey management -Specifics for the implementation of JS-keyboard deadkeys can be found here: https://github.com/keymanapp/keyman/blob/b4df4ab80862bc90da42bcdbd333df0a14da01ca/web/src/engine/js-processor/src/deadkeys.ts#L2-L6 -- `epic/web-core` note: unaltered. +Specifics for the implementation of JS-keyboard deadkeys can be found +here: [web/src/engine/keyboard/src/deadkeys.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/keyboard/src/deadkeys.ts) -`ordinal`: if two deadkeys are in the same "virtual" position, this field resolves which came first. -`matched`: used during keyboard-rule processing. +`ordinal`: if two deadkeys are in the same "virtual" position, this +field resolves which came first. `matched`: used during keyboard-rule +processing. -Note that we do NOT actually insert the deadkeys into the raw text-context! Web's pattern here is different than that of Keyman Core. +Note that we do NOT actually insert the deadkeys into the raw +text-context! Web's pattern here is different than that of Keyman Core. ## Manipulating context-states -Initially used to support predictive-text, the `Transform` type aims to encapsulate the minimal information necessary to transition from one context-state to another. It is both selection-agnostic and deadkey-agnostic. `Transform`s are used both by predictive-text and by the webview-embedded build of the engine in order to succinctly communicate the data needed to update context upon receiving keystrokes. -- `Transform`'s specification may be found at [common/web/types/src/lexical-model-types.ts](https://github.com/keymanapp/keyman/blob/master/common/web/types/src/lexical-model-types.ts). - -`Transform`s consist of three values: -- `deleteLeft` - the number of codepoints prior to the caret/selection that should be deleted -- `insert` - the text to insert at the caret and/or replace currently-selected text -- `deleteRight` - the number of codepoints _after_ the caret/selection that should be deleted - - Note that `deleteRight` does not currently see actual use due to iOS platform limitations. - -This type may then be used as an argument to `OutputTarget.apply()` (defined on `OutputTarget` (`epic/web-core`: `OutputTargetBase`)) to update any context source accordingly. - -It is possible to determine the `Transform` needed to transition from one `OutputTarget` to another using `OutputTarget.buildTransformFrom` (defined on `OutputTarget` (`epic/web-core`: `OutputTargetBase`)). +Initially used to support predictive-text, the `Transform` type aims to +encapsulate the minimal information necessary to transition from one +context-state to another. It is both selection-agnostic and +deadkey-agnostic. `Transform`s are used both by predictive-text and by +the webview-embedded build of the engine in order to succinctly +communicate the data needed to update context upon receiving keystrokes. -### The `Mock` - representing context-state +- `Transform`'s specification may be found at + [common/web/types/src/lexical-model-types.ts](https://github.com/keymanapp/keyman/blob/master/common/web/types/src/lexical-model-types.ts). -The comparison and contrast methods mentioned above for `OutputTarget` are of particular use for predictive text, which usually operates with a headless implementation of the type, termed a `Mock`. This class may be found in [web/src/engine/js-processor/src/mock.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/js-processor/src/mock.ts). It is a fully-featured implementation of the `OutputTarget` interface. -- `epic/web-core` note: unaltered. - -It is possible to make a `Mock`-based clone of any `OutputTarget`-derived type - a feature leveraged significantly within the inner workings of Keyman Engine for Web. As JS keyboards can have side effects beyond text-manipulation, predictive text generally operates by first _cloning_ the "true" context source. `Mock`s are also used when saving context states within the engine for later reference and/or reuse - a feature also utilized significantly for multitap support. +`Transform`s consist of three values: -`Mock`s can also easily be constructed from scratch for a simple string. Optionally, caret position or selection data may be specified at construction time as well. `epic/web-core`: in theory, this should make them easy to utilize for integration with Keyman Core. +- `deleteLeft` - the number of codepoints prior to the caret/selection + that should be deleted +- `insert` - the text to insert at the caret and/or replace + currently-selected text +- `deleteRight` - the number of codepoints _after_ the caret/selection + that should be deleted + - Note that `deleteRight` does not currently see actual use due to iOS + platform limitations. + +This type may then be used as an argument to `TextStore.apply()` +(defined on `TextStore`) to update any context source accordingly. + +It is possible to determine the `Transform` needed to transition from +one `TextStore` to another using `TextStore.buildTransformFrom` +(defined on `TextStore`). + +### The `SyntheticTextStore` - representing context-state + +The comparison and contrast methods mentioned above for `TextStore` +are of particular use for predictive text, which usually operates with a +headless implementation of the type, termed a `SyntheticTextStore`. This class may be +found in +[web/src/engine/keyboard/src/syntheticTextStore.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/keyboard/src/syntheticTextStore.ts). +It is a fully-featured implementation of the `TextStore` interface. + +It is possible to make a `SyntheticTextStore`-based clone of any +`TextStore`-derived type - a feature leveraged significantly within +the inner workings of Keyman Engine for Web. As JS keyboards can have +side effects beyond text-manipulation, predictive text generally +operates by first _cloning_ the "true" context source. `SyntheticTextStore`s are +also used when saving context states within the engine for later +reference and/or reuse - a feature also utilized significantly for +multitap support. + +`SyntheticTextStore`s can also easily be constructed from scratch for a simple string. +Optionally, caret position or selection data may be specified at +construction time as well. `epic/web-core`: in theory, this should make +them easy to utilize for integration with Keyman Core. + +- note: previously called `Mock` ### The `Transcription` - representing context-state transitions -The `Transcription` class (defined within [web/src/engine/js-processor/src/outputTarget.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/js-processor/src/outputTarget.ts)) is the type within the engine that most closely matches a sense of transition in context state. These are generally constructed by comparing two `OutputTarget` instances to each other via `OutputTarget.buildTranscriptionFrom`, with the base instance corresponding to the "new" state and the first parameter matching the original state before transition. -- `epic/web-core` note: moved to `outputTargetBase.ts` in the same folder; the method is on `OutputTargetBase`. - -`Transcription`s are granted unique identifiers and are used within the engine for preservation of recent context states. These identifiers are currently generated within the class's constructor and are internally set. When predictive-text generates new suggestions or a multitap needs to revert to a prior context, both will use the `Transcription`'s unique identifier in order to find the corresponding context state and leverage it as needed for their operations. +The `Transcription` class (defined in +[web/src/engine/js-processor/src/transcription.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/js-processor/src/transcription.ts)) +is the type within the engine that most closely matches a sense of +transition in context state. These are generally constructed by +comparing two `TextStore` instances to each other via +`TextStore.buildTranscriptionFrom`, with the base instance +corresponding to the "new" state and the first parameter matching the +original state before transition. + +`Transcription`s are granted unique identifiers and are used within the +engine for preservation of recent context states. These identifiers are +currently generated within the class's constructor and are internally +set. When predictive-text generates new suggestions or a multitap needs +to revert to a prior context, both will use the `Transcription`'s unique +identifier in order to find the corresponding context state and leverage +it as needed for their operations. Important fields: -- `keystroke` - the keystroke that triggered the context change corresponding to this `Transcription` -- `transform` - the direct effects of the keystroke - - This uses a specialized variant that also notes if the transition destroyed previously-existing selected text. -- `preInput` - the state of the context immediately before the keystroke was processed -Note that the transition metadata does not include deadkeys generated by its triggering `keystroke`. The decision was made long ago to forgo directly recording deadkey changes when recording `Transcriptions`, as any operation that restores an old context also seeks to apply deadkey-destroying operations immediately afterward. Should we ever need to do so, PR #1611 contains code that was originally designed for actively detecting and recording deadkey transition data in `Transcription`s. +- `keystroke` - the keystroke that triggered the context change + corresponding to this `Transcription` +- `transform` - the direct effects of the keystroke -A cache of recent context-state transitions is stored at `keyman.core.contextCache`, with `keyman.core` being an instance of `InputProcessor` ([web/src/engine/main/src/headless/inputProcessor.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/main/src/headless/inputProcessor.ts)), the component responsible for linking keystroke processing with predictive-text support and restoration of context-state for multitap-generated keystrokes. + - This uses a specialized variant that also notes if the transition + destroyed previously-existing selected text. + +- `preInput` - the state of the context immediately before the keystroke + was processed + +Note that the transition metadata does not include deadkeys generated by +its triggering `keystroke`. The decision was made long ago to forgo +directly recording deadkey changes when recording `Transcriptions`, as +any operation that restores an old context also seeks to apply +deadkey-destroying operations immediately afterward. Should we ever +need to do so, PR #1611 contains code that was originally designed for +actively detecting and recording deadkey transition data in +`Transcription`s. + +A cache of recent context-state transitions is stored at +`keyman.core.contextCache`, with `keyman.core` being an instance of +`InputProcessor` +([web/src/engine/main/src/headless/inputProcessor.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/main/src/headless/inputProcessor.ts)), +the component responsible for linking keystroke processing with +predictive-text support and restoration of context-state for +multitap-generated keystrokes. ### JS-keyboard keystroke processing -For JS-keyboard keystroke processing, a `Mock` clone of the context is generated before any actual keyboard rule checks are applied. This provides a clear "before" state (eventually saved at `Transcription.preInput`) useful for determining the scope of the keystroke's changes once processing is completed via `buildTranscriptionFrom`. - -Once keystroke processing is completed by a JS-keyboard, the JS-processor constructs a `RuleBehavior` object describing all primary and side effects of the keystroke. Defined at [web/src/engine/js-processor/src/ruleBehavior.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/js-processor/src/ruleBehavior.ts), all of its fields aside from `transcription` are specific to JS-keyboard side effects, some of which do need special handling and support outside of the keystroke processor. None of these side effects apply for common-case keystrokes and so have default handling in place within the engine for cases where they are not needed. +For JS-keyboard keystroke processing, a `SyntheticTextStore` clone of the context is +generated before any actual keyboard rule checks are applied. This +provides a clear "before" state (eventually saved at +`Transcription.preInput`) useful for determining the scope of the +keystroke's changes once processing is completed via +`buildTranscriptionFrom`. + +Once keystroke processing is completed by a JS-keyboard, the +JS-processor constructs a `ProcessorAction` object describing all +primary and side effects of the keystroke. Defined at +[web/src/engine/keyboard/src/keyboards/processorAction.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/keyboard/src/keyboards/processorAction.ts), +all of its fields aside from `transcription` are specific to JS-keyboard +side effects, some of which do need special handling and support outside +of the keystroke processor. None of these side effects apply for +common-case keystrokes and so have default handling in place within the +engine for cases where they are not needed. --- -In case referenced classes/files have moved: this doc was last updated in 18.0-beta, based upon commit d1e45a0df49f81597887577a8c83af36d4a85283 \ No newline at end of file +In case referenced classes/files have moved: this doc was last updated +in 19.0-alpha, based upon PR #14001. diff --git a/web/docs/internal/keystroke-lifecycle.md b/web/docs/internal/keystroke-lifecycle.md index c2e401b0088..68dfc14d02f 100644 --- a/web/docs/internal/keystroke-lifecycle.md +++ b/web/docs/internal/keystroke-lifecycle.md @@ -126,7 +126,7 @@ The bulk of DOM key events trigger keystroke processing on key-down, though modi 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. +Also note that this variant does not model the user's text context with Web elements - it is entirely managed through the `SyntheticTextStore` type. ### On-screen keyboard @@ -212,13 +212,13 @@ 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 +keystroke. This involves constructing a `ProcessorAction` 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 +The `JSKeyboardInterface` 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 @@ -233,7 +233,7 @@ 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 +processor will add a note to the `ProcessorAction` object that default processing could not be provided and is thus needed from the engine's host. ### KMX keyboards & KMX+ (LDML) keyboards @@ -263,12 +263,12 @@ 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 +its `ProcessorAction`, 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" +context state, the `KeyEvent`, and the `ProcessorAction` 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` @@ -298,4 +298,4 @@ 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 +forms, and this helps ensure we trigger such functionality when appropriate. diff --git a/web/docs/internal/keystroke-processing.md b/web/docs/internal/keystroke-processing.md index 8606d18cba0..ca44e597833 100644 --- a/web/docs/internal/keystroke-processing.md +++ b/web/docs/internal/keystroke-processing.md @@ -6,7 +6,7 @@ In addition to handling keystroke events produced from hardware keyboards, Keyma Defined at [web/src/engine/keyboard/src/keyEvent.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/keyboard/src/keyEvent.ts), the `KeyEvent` is used to represent incoming _and_ potential keystrokes. This type is what the JS-keyboard processor references when evaluating keyboard rules during its keystroke processing. For versions of the engine that support AltGr aliasing, such aliasing will be applied during generation of `KeyEvent` objects. -Note that for predictive-text's fat-finger correction functionality, the engine will also generate versions of this type for nearby but _unpressed_ keys into the keystroke processing engine as well in order to facilitate predictions that follow context manipulations that could have resulted from specialized rules or reorders on neighboring keys. `Mock`-cloned copies of the active context-state will be leveraged to prevent unwanted manipulation of the true context source. +Note that for predictive-text's fat-finger correction functionality, the engine will also generate versions of this type for nearby but _unpressed_ keys into the keystroke processing engine as well in order to facilitate predictions that follow context manipulations that could have resulted from specialized rules or reorders on neighboring keys. `SyntheticTextStore`-cloned copies of the active context-state will be leveraged to prevent unwanted manipulation of the true context source. ### `isSynthetic` `isSynthetic` should be set to `true` if generated through interaction with an on-screen-keyboard or for fat-finger simulation. It should only be set to `false` if sending the basic key-event data through to the destination, without rule processing, leads to default handling picking up the slack. Browsers provide default handling of keystrokes not directly defined within keyboards, but this is not available for keystrokes against the engine's OSK without internal support. @@ -19,9 +19,9 @@ When `true`, the keystroke processor will need to simulate the results of "stand On-screen keyboard modules and hardware-keyboard event interception modules will produce instances of `KeyEvent` as noted above. Once this is completed, both module types will _signal_ the keystroke event by raising an event with ID `keyevent` and provide the `KeyEvent` instance as its first parameter. The main module of the engine will then forward that `KeyEvent` object to the input processing pipeline via `InputProcessor.processKeyEvent` (see below). -## Output: RuleBehavior +## Output: ProcessorAction -Once keystroke processing is completed, the outward-facing components of the engine expect to receive a `RuleBehavior` object describing all primary and side effects of the keystroke. Defined at [web/src/engine/js-processor/src/ruleBehavior.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/js-processor/src/ruleBehavior.ts), all of its fields aside from `transcription` are specific to existing JS-keyboard side effects. (Certain Keyman language features can make permanent side-effect changes to state that should only be persisted for the "true" keystroke - not for any predictive-text 'alternative' keys.) +Once keystroke processing is completed, the outward-facing components of the engine expect to receive a `ProcessorAction` object describing all primary and side effects of the keystroke. Defined at [web/src/engine/keyboard/src/keyboards/processorAction.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/keyboard/src/keyboards/processorAction.ts), all of its fields aside from `transcription` are specific to existing JS-keyboard side effects. (Certain Keyman language features can make permanent side-effect changes to state that should only be persisted for the "true" keystroke - not for any predictive-text 'alternative' keys.) See also: [context-state-management.md](context-state-management.md#js-keyboard-keystroke-processing) @@ -31,7 +31,7 @@ See also: [context-state-management.md](context-state-management.md#js-keyboard The "first stop" for incoming keystrokes is the `InputProcessor`, found at [web/src/engine/main/src/headless/inputProcessor.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/main/src/headless/.inputProcessor.ts), through its `processKeyEvent` method. This class manages higher-level functionality triggered by keystroke events while deferring actual interpretation of the incoming keystroke further down the line. Of particular note is that it also handles control-flows that require restoration of previously-occuring contexts. -This class is the connection point for generating prediction requests and receiving corresponding suggestions. In order to facilitate higher-quality predictive-text when enabled, the `InputProcessor` will _also_ generate and trigger processing for nearby keys. This process allows transforms, reorders, and KMN keyboard rules to take effect and be used as alternative context roots for predictions. These are generally run against `Mock`-based clones of the true context source and are additionally prevented from triggering long-term side-effects, such as changes to KMN-keyboard variable stores, by only calling `RuleBehavior.finalize` for the true input keystroke's result object. +This class is the connection point for generating prediction requests and receiving corresponding suggestions. In order to facilitate higher-quality predictive-text when enabled, the `InputProcessor` will _also_ generate and trigger processing for nearby keys. This process allows transforms, reorders, and KMN keyboard rules to take effect and be used as alternative context roots for predictions. These are generally run against `SyntheticTextStore`-based clones of the true context source and are additionally prevented from triggering long-term side-effects, such as changes to KMN-keyboard variable stores, by only calling `KeyboardProcessor.finalizeProcessorAction` for the true input keystroke's result object. Keys generated by OSK multitap need special handling here as well; they should always be applied to the context state as it existed at the time of the initial tap. To facilitate this, the `InputProcessor` will directly rewind the active context-source to match the corresponding context state before requesting that the `KeyEvent` be processed. @@ -64,18 +64,22 @@ The method linked above is the primary entrypoint for rule processing of individ #### JS-keyboard interfacing -Certain Keyman language features can make permanent side-effect changes to state. In order to prevent these from taking place for every keystroke, the method that interfaces with JS keyboards - `KeyboardInterface.process` - saves the context state (as a `Mock`) and current variable store values, then prepares a fresh `RuleBehavior` instance, before passing control off to the keyboard's backing script. (Note that `KeyboardInterface` itself primarily consists of keyboard-script API called by JS-keyboard script.) -- `epic/web-core` note: renamed to `JSKeyboardInterface`. +Certain Keyman language features can make permanent side-effect changes to state. In order to prevent these from taking place for every keystroke, the method that interfaces with JS keyboards - `JSKeyboardInterface.process` - saves the context state (as a `SyntheticTextStore`) and current variable store values, then prepares a fresh `ProcessorAction` instance, before passing control off to the keyboard's backing script. (Note that `JSKeyboardInterface` itself primarily consists of keyboard-script API called by JS-keyboard script.) -A few of the keyboard-script API methods will mark `RuleBehavior` properties directly when called, but the bulk of its data will be set once the keyboard-script returns control to Keyman Engine for Web. At this time, variable store values will also be reverted to prevent possible cross-contamination effects when predictive text is active - they're reapplied later if `RuleBehavior.finalize` is leveraged on the resulting instance. Components documented in [context-state-management.md](./context-state-management.md) are then leveraged to determine the total change to context caused by the keystroke. +A few of the keyboard-script API methods will mark `ProcessorAction` properties directly when called, but the bulk of its data will be set once the keyboard-script returns control to Keyman Engine for Web. At this time, variable store values will also be reverted to prevent possible cross-contamination effects when predictive text is active - they're reapplied later if `KeyboardProcessor.finalizeProcessorAction` is leveraged on the resulting instance. Components documented in [context-state-management.md](./context-state-management.md) are then leveraged to determine the total change to context caused by the keystroke. Note that for JS-keyboards, in 18.0 and before the true keystroke is processed against the _true_ context state, not a cloned copy, and thus its changes are applied immediately. #### Keystroke-default emulation -Note that browser-default keystroke processing is defined within the `DefaultRules` class found at [web/src/engine/keyboard/src/defaultRules.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/keyboard/src/defaultRules.ts). It currently produces a (possibly `null`) string output rather than a `RuleBehavior`, but the latter can be easily constructed based on the returned string and the existing context state. -- For `epic/web-core`, it may be wise to spin the `DefaultRules` component off as its own processor, serving as a backup for _all_ keystroke processing variants. +Note that browser-default keystroke processing is defined within the `DefaultOutputRules` class +found at +[web/src/engine/keyboard/src/defaultOutputRules.ts](https://github.com/keymanapp/keyman/blob/master/web/src/engine/keyboard/src/defaultOutputRules.ts). +It currently produces a (possibly `null`) string output rather than a `ProcessorAction`, but the +latter can be easily constructed based on the returned string and the existing context state. +- For `epic/web-core`, it may be wise to spin the `DefaultOutputRules` component off as its own + processor, serving as a backup for _all_ keystroke processing variants. ---- -In case referenced classes/files have moved: this doc was last updated in 18.0-beta, based upon commit d1e45a0df49f81597887577a8c83af36d4a85283 \ No newline at end of file +In case referenced classes/files have moved: this doc was last updated in 19.0-alpha, based upon PR #14001. diff --git a/web/package.json b/web/package.json index cfbab0fcbfd..712a8558a2e 100644 --- a/web/package.json +++ b/web/package.json @@ -7,84 +7,92 @@ "types": "./build/app/browser/obj/test-index.d.js", "import": "./build/app/browser/obj/test-index.js" }, + "./common/web-utils": { + "es6-bundling": "./src/common/web-utils/src/index.ts", + "types": "./build/common/web-utils/obj/index.d.js", + "import": "./build/common/web-utils/obj/index.js" + }, "./engine/attachment": { - "es6-bundling": "./src/engine/attachment/src/index.ts", - "types": "./build/engine/attachment/obj/index.d.ts", - "import": "./build/engine/attachment/obj/index.js" + "es6-bundling": "./src/engine/src/attachment/index.ts", + "types": "./build/engine/obj/attachment/index.d.ts", + "import": "./build/engine/obj/attachment/index.js" }, - "./engine/interfaces": { - "es6-bundling": "./src/engine/interfaces/src/index.ts", - "types": "./build/engine/interfaces/obj/index.d.ts", - "import": "./build/engine/interfaces/obj/index.js" + "./engine/core-adapter": { + "es6-bundling": "./src/engine/src/core-adapter/index.ts", + "types": "./build/engine/obj/core-adapter/index.d.ts", + "import": "./build/engine/obj/core-adapter/index.js" + }, + "./engine/core-processor": { + "es6-bundling": "./src/engine/src/core-processor/index.ts", + "types": "./build/engine/obj/core-processor/index.d.ts", + "import": "./build/engine/obj/core-processor/index.js" }, "./engine/dom-utils": { - "es6-bundling": "./src/engine/dom-utils/src/index.ts", - "types": "./build/engine/dom-utils/obj/index.d.ts", - "import": "./build/engine/dom-utils/obj/index.js" + "es6-bundling": "./src/engine/src/dom-utils/index.ts", + "types": "./build/engine/obj/dom-utils/index.d.ts", + "import": "./build/engine/obj/dom-utils/index.js" }, - "./engine/element-wrappers": { - "es6-bundling": "./src/engine/element-wrappers/src/index.ts", - "types": "./build/engine/element-wrappers/obj/index.d.ts", - "import": "./build/engine/element-wrappers/obj/index.js" + "./engine/element-text-stores": { + "es6-bundling": "./src/engine/src/element-text-stores/index.ts", + "types": "./build/engine/obj/element-text-stores/index.d.ts", + "import": "./build/engine/obj/element-text-stores/index.js" }, "./engine/events": { - "es6-bundling": "./src/engine/events/src/index.ts", - "types": "./build/engine/events/obj/index.d.ts", - "import": "./build/engine/events/obj/index.js" + "es6-bundling": "./src/engine/src/events/index.ts", + "types": "./build/engine/obj/events/index.d.ts", + "import": "./build/engine/obj/events/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/gesture-processor": { + "es6-bundling": "./src/engine/src/gesture-processor/index.ts", + "types": "./build/engine/obj/gesture-processor/index.d.ts", + "import": "./build/engine/obj/gesture-processor/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/interfaces": { + "es6-bundling": "./src/engine/src/interfaces/index.ts", + "types": "./build/engine/obj/interfaces/index.d.ts", + "import": "./build/engine/obj/interfaces/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/js-processor": { + "es6-bundling": "./src/engine/src/js-processor/index.ts", + "types": "./build/engine/obj/js-processor/index.d.ts", + "import": "./build/engine/obj/js-processor/index.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/keyboard": { + "es6-bundling": "./src/engine/src/keyboard/index.ts", + "types": "./build/engine/obj/keyboard/index.d.ts", + "import": "./build/engine/obj/keyboard/index.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" + "es6-bundling": "./src/engine/src/keyboard-storage/index.ts", + "types": "./build/engine/obj/keyboard-storage/index.d.ts", + "import": "./build/engine/obj/keyboard-storage/index.js", + "require": "./build/engine/obj/keyboard-storage/index.js" }, "./engine/main": { - "es6-bundling": "./src/engine/main/src/index.ts", - "types": "./build/engine/main/obj/index.d.ts", - "import": "./build/engine/main/obj/index.js" + "es6-bundling": "./src/engine/src/main/index.ts", + "types": "./build/engine/obj/main/index.d.ts", + "import": "./build/engine/obj/main/index.js" }, "./engine/osk": { - "es6-bundling": "./src/engine/osk/src/index.ts", - "types": "./build/engine/osk/obj/index.d.ts", - "import": "./build/engine/osk/obj/index.js" + "es6-bundling": "./src/engine/src/osk/index.ts", + "types": "./build/engine/obj/osk/index.d.ts", + "import": "./build/engine/obj/osk/index.js" + }, + "./tools/testing/test-utils": { + "types": "./build/tools/testing/test-utils/obj/index.d.ts", + "import": "./build/tools/testing/test-utils/obj/index.js" }, - "./engine/osk/internals": { - "types": "./build/engine/osk/obj/test-index.d.ts", - "import": "./build/engine/osk/obj/test-index.js" + "./test/resources": { + "types": "./src/test/auto/resources/build/index.d.ts", + "import": "./src/test/auto/resources/build/index.js" + }, + "./test/headless-resources": { + "types": "./src/test/auto/headless-resources/build/index.d.ts", + "import": "./src/test/auto/headless-resources/build/index.js" } }, "imports": { - "#gesture-tools": "./src/engine/osk/gesture-processor/build/tools/obj/index.js", + "#gesture-tools": "./build/tools/testing/gesture-processor/unit-test-resources/obj/index.js", "#recorder": "./build/tools/testing/recorder/obj/index.js", "#test-resources/*.js": "./build/test/resources/*.js" }, @@ -105,22 +113,23 @@ "homepage": "https://github.com/keymanapp/keyman#readme", "devDependencies": { "@keymanapp/resources-gosh": "*", - "@keymanapp/web-sentry-manager": "*", + "@playwright/test": "1.46.1", "@sentry/cli": "^2.31.0", "@zip.js/zip.js": "^2.7.32", "c8": "^7.12.0", + "express": "^4.19.2", "jsdom": "^23.0.1", + "promise-status-async": "^1.2.10", "tsx": "^4.19.0" }, "scripts": { "test": "gosh ./test.sh" }, "dependencies": { + "@keymanapp/common-types": "*", "@keymanapp/keyman-version": "*", "@keymanapp/lexical-model-layer": "*", - "@keymanapp/common-types": "*", "@keymanapp/recorder-core": "*", - "@keymanapp/web-utils": "*", "core-js": "^3.34.0", "eventemitter3": "^5.0.0", "tslib": "^2.5.2" diff --git a/web/src/app/browser/build.sh b/web/src/app/browser/build.sh index 7a168a5d463..d23b67987af 100755 --- a/web/src/app/browser/build.sh +++ b/web/src/app/browser/build.sh @@ -14,9 +14,9 @@ SUBPROJECT_NAME=app/browser # ################################ Main script ################################ builder_describe "Builds the Keyman Engine for Web's website-integrating version for use in non-puppeted browsers." \ - "@/web/src/engine/attachment build" \ - "@/web/src/engine/main build" \ - "@/web/src/tools/building/sourcemap-root" \ + "@/common/tools/es-bundling build" \ + "@/web/src/engine build" \ + "@/web/src/tools/building/sourcemap-root build" \ "clean" \ "configure" \ "build" \ @@ -49,29 +49,33 @@ compile_and_copy() { BUILD_ROOT="${KEYMAN_ROOT}/web/build/app/browser" SRC_ROOT="${KEYMAN_ROOT}/web/src/app/browser/src" - node "${LIB_BUNDLER}" "${SRC_ROOT}/debug-main.js" \ - --out "${BUILD_ROOT}/debug/keymanweb.js" \ - --charset "utf8" \ - --sourceRoot "@keymanapp/keyman/web/build/app/browser/debug" \ - --target "es6" - - node "${LIB_BUNDLER}" "${SRC_ROOT}/release-main.js" \ - --out "${BUILD_ROOT}/release/keymanweb.js" \ - --charset "utf8" \ - --profile "${BUILD_ROOT}/filesize-profile.log" \ - --sourceRoot "@keymanapp/keyman/web/build/app/browser/release" \ - --minify \ - --target "es6" - - node "${LIB_BUNDLER}" "${BUILD_ROOT}/obj/test-index.js" \ - --out "${BUILD_ROOT}/lib/index.mjs" \ - --charset "utf8" \ - --sourceRoot "@keymanapp/keyman/web/build/app/browser/lib" \ - --format esm + node_es_bundle "${SRC_ROOT}/debug-main.js" \ + --out "${BUILD_ROOT}/debug/keymanweb.js" \ + --charset "utf8" \ + --sourceRoot "@keymanapp/keyman/web/build/app/browser/debug" \ + --target "es6" + + node_es_bundle "${SRC_ROOT}/release-main.js" \ + --out "${BUILD_ROOT}/release/keymanweb.js" \ + --charset "utf8" \ + --profile "${BUILD_ROOT}/filesize-profile.log" \ + --sourceRoot "@keymanapp/keyman/web/build/app/browser/release" \ + --minify \ + --target "es6" + + node_es_bundle "${BUILD_ROOT}/obj/test-index.js" \ + --out "${BUILD_ROOT}/lib/index.mjs" \ + --charset "utf8" \ + --sourceRoot "@keymanapp/keyman/web/build/app/browser/lib" \ + --format esm mkdir -p "$KEYMAN_ROOT/web/build/app/resources/osk" cp -R "$KEYMAN_ROOT/web/src/resources/osk/." "$KEYMAN_ROOT/web/build/app/resources/osk/" + # Copy Keyman Core build artifacts for local reference + cp "${KEYMAN_ROOT}/web/build/engine/obj/core-adapter/import/core/"km-core.{js,wasm} "${KEYMAN_ROOT}/web/build/app/browser/debug/" + cp "${KEYMAN_ROOT}/web/build/engine/obj/core-adapter/import/core/"km-core.{js,wasm} "${KEYMAN_ROOT}/web/build/app/browser/release/" + # Update the build/publish copy of our build artifacts prepare diff --git a/web/src/app/browser/src/beepHandler.ts b/web/src/app/browser/src/beepHandler.ts index 6e23c094645..b520c709ce1 100644 --- a/web/src/app/browser/src/beepHandler.ts +++ b/web/src/app/browser/src/beepHandler.ts @@ -1,5 +1,5 @@ -import { type KeyboardInterface } from 'keyman/engine/js-processor'; -import { DesignIFrame, OutputTarget } from 'keyman/engine/element-wrappers'; +import { type KeyboardMinimalInterface } from 'keyman/engine/keyboard'; +import { DesignIFrameElementTextStore, AbstractElementTextStore } from 'keyman/engine/element-text-stores'; // Utility object used to handle beep (keyboard error response) operations. class BeepData { @@ -17,9 +17,9 @@ class BeepData { } export class BeepHandler { - readonly keyboardInterface: KeyboardInterface; + readonly keyboardInterface: KeyboardMinimalInterface; - constructor(keyboardInterface: KeyboardInterface) { + constructor(keyboardInterface: KeyboardMinimalInterface) { this.keyboardInterface = keyboardInterface; } @@ -32,15 +32,15 @@ export class BeepHandler { * @param {Object} Pelem element to flash * Description Flash body as substitute for audible beep; notify embedded device to vibrate */ - beep(outputTarget: OutputTarget) { - if(!(outputTarget instanceof OutputTarget)) { + beep(textStore: AbstractElementTextStore) { + if (!(textStore instanceof AbstractElementTextStore)) { return; } // All code after this point is DOM-based, triggered by the beep. - let Pelem: HTMLElement = outputTarget.getElement(); - if(outputTarget instanceof DesignIFrame) { - Pelem = outputTarget.docRoot; // I1446 - beep sometimes fails to flash when using OSK and rich control + let Pelem: HTMLElement = textStore.getElement(); + if(textStore instanceof DesignIFrameElementTextStore) { + Pelem = textStore.docRoot; // I1446 - beep sometimes fails to flash when using OSK and rich control } if(!Pelem) { @@ -75,11 +75,8 @@ export class BeepHandler { * Description Reset/terminate beep or flash (not currently used: Aug 2011) */ readonly reset = () => { - this.keyboardInterface.resetContextCache(); - - let Lbo; this._BeepTimeout = 0; - for(Lbo=0;Lbo { @@ -57,19 +57,19 @@ export class FocusAssistant extends EventEmitter { * Long-term idea here: about all of the relevant OSK events that would interact with this have "enter" and * "leave" variants - we could take a stack of `Promise`s. On a `Promise` fulfillment, remove it from the * stack. When the last one is removed, the focus-maintenance state would end, allowing further events - * to deactivate the active OutputTarget. + * to deactivate the active TextStore. */ /** - * Indicates that KMW is actively maintaining focus on the currently active OutputTarget control, rather + * Indicates that KMW is actively maintaining focus on the currently active TextStore control, rather * than losing focus while some UI element (the OSK, a keyboard-change UI) is the most direct recipient * of browser focus due to user-interaction - generally, with non-context engine components. * - * While the flag is active, the context-management system should not deactivate an OutputTarget upon - * its element's loss of focus within the page unless setting a different OutputTarget as active. + * While the flag is active, the context-management system should not deactivate an TextStore upon + * its element's loss of focus within the page unless setting a different TextStore as active. * * TODO: (potential) Future enhancement - this should not be possible to set if there is no currently-active - * context target to maintain. + * textStore to maintain. */ // Formerly `isActivating`. public get maintainingFocus(): boolean { @@ -80,7 +80,7 @@ export class FocusAssistant extends EventEmitter { const priorValue = this._maintainingFocus; this._maintainingFocus = value; - // Needed to properly update .activeTarget upon loss of maintaining-focus state. + // Needed to properly update .activeTextStore upon loss of maintaining-focus state. if(priorValue && !value) { this.emit('maintainingfocusend'); } diff --git a/web/src/app/browser/src/context/pageIntegrationHandlers.ts b/web/src/app/browser/src/context/pageIntegrationHandlers.ts index 3a997d9392f..eebf0ebde57 100644 --- a/web/src/app/browser/src/context/pageIntegrationHandlers.ts +++ b/web/src/app/browser/src/context/pageIntegrationHandlers.ts @@ -85,7 +85,7 @@ export class PageIntegrationHandlers { **/ private pageFocusHandler: (e: FocusEvent) => boolean = () => { if(!this.focusAssistant.maintainingFocus && this.engine.osk?.vkbd) { - this.engine.contextManager.deactivateCurrentTarget(); + this.engine.contextManager.deactivateCurrentTextStore(); this.engine.contextManager.resetContext(); } return false; @@ -138,7 +138,7 @@ export class PageIntegrationHandlers { private touchMoveActivationHandler: (e: TouchEvent) => boolean = (e) => { if(this.deactivateOnScroll) { // Android / Chrone case. this.focusAssistant.focusing = false; - this.engine.contextManager.deactivateCurrentTarget(); + this.engine.contextManager.deactivateCurrentTextStore(); } const y = e.touches[0].screenY; @@ -153,7 +153,7 @@ export class PageIntegrationHandlers { // Should not hide OSK if simply closing the language menu (30/4/15) // or if the focusing timer (focusAssistant.setFocusTimer) is still active. if(this.deactivateOnRelease && !this.engine.touchLanguageMenu && !this.focusAssistant.focusing) { - this.engine.contextManager.deactivateCurrentTarget(); + this.engine.contextManager.deactivateCurrentTextStore(); } this.deactivateOnRelease=false; return false; diff --git a/web/src/app/browser/src/contextManager.ts b/web/src/app/browser/src/contextManager.ts index c898544fb87..33e58f48891 100644 --- a/web/src/app/browser/src/contextManager.ts +++ b/web/src/app/browser/src/contextManager.ts @@ -1,12 +1,13 @@ import { type Keyboard, KeyboardScriptError } from 'keyman/engine/keyboard'; import { type KeyboardStub } from 'keyman/engine/keyboard-storage'; import { CookieSerializer } from 'keyman/engine/dom-utils'; -import { eventOutputTarget, outputTargetForElement, PageContextAttachment } from 'keyman/engine/attachment'; +import { textStoreForEvent, textStoreForElement, PageContextAttachment } from 'keyman/engine/attachment'; import { DomEventTracker, LegacyEventEmitter } from 'keyman/engine/events'; -import { DesignIFrame, OutputTarget, nestedInstanceOf } from 'keyman/engine/element-wrappers'; +import { DesignIFrameElementTextStore, AbstractElementTextStore, nestedInstanceOf } from 'keyman/engine/element-text-stores'; import { ContextManagerBase, - type KeyboardInterface, + type KeyboardInfoPair, + type KeyboardInterfaceBase, LegacyAPIEvents } from 'keyman/engine/main'; import { BrowserConfiguration } from './configuration.js'; @@ -23,7 +24,8 @@ export interface KeyboardCookie { * has the same directionality, text runs will be re-ordered which is confusing and causes * incorrect caret positioning * - * @param {Object} Ptarg Target element + * @param {Object} Ptarg Target element + * @param {Keyboard} activeKeyboard The active keyboard */ function _SetTargDir(Ptarg: HTMLElement, activeKeyboard: Keyboard) { const elDir = activeKeyboard?.isRTL ? 'rtl' : 'ltr'; @@ -40,20 +42,20 @@ function _SetTargDir(Ptarg: HTMLElement, activeKeyboard: Keyboard) { } } -export default class ContextManager extends ContextManagerBase { - private _activeKeyboard: {keyboard: Keyboard, metadata: KeyboardStub}; +export class ContextManager extends ContextManagerBase { + private _activeKeyboard: KeyboardInfoPair; private cookieManager = new CookieSerializer('KeymanWeb_Keyboard'); - readonly focusAssistant = new FocusAssistant(() => this.activeTarget?.isForcingScroll()); + readonly focusAssistant = new FocusAssistant(() => this.activeTextStore?.isForcingScroll()); readonly page: PageContextAttachment; - private mostRecentTarget: OutputTarget; - private currentTarget: OutputTarget; + private mostRecentTextStore: AbstractElementTextStore; + private currentTextStore: AbstractElementTextStore; - private globalKeyboard: {keyboard: Keyboard, metadata: KeyboardStub}; + private globalKeyboard: KeyboardInfoPair; private _eventsObj: () => LegacyEventEmitter; private domEventTracker = new DomEventTracker(); - constructor(engineConfig: BrowserConfiguration, eventsClosure: () => LegacyEventEmitter) { + public constructor(engineConfig: BrowserConfiguration, eventsClosure: () => LegacyEventEmitter) { super(engineConfig); this._eventsObj = eventsClosure; @@ -63,18 +65,18 @@ export default class ContextManager extends ContextManagerBase { - // Basically, if the maintaining state were the reason we still had an `activeTarget`... - if(!this.activeTarget && this.mostRecentTarget) { - this.emit('targetchange', this.activeTarget); + // Basically, if the maintaining state were the reason we still had an `activeTextStore`... + if(!this.activeTextStore && this.mostRecentTextStore) { + this.emit('textstorechange', this.activeTextStore); } }); } - get apiEvents(): LegacyEventEmitter { + public get apiEvents(): LegacyEventEmitter { return this._eventsObj(); } - initialize(): void { + public initialize(): void { this.on('keyboardasyncload', (stub, completion) => { this.engineConfig.alertHost?.wait('Installing keyboard
' + stub.name); @@ -90,7 +92,7 @@ export default class ContextManager extends ContextManagerBase { - if(!(elem._kmwAttachment.interface instanceof DesignIFrame)) { + if(!(elem._kmwAttachment.textStore instanceof DesignIFrameElementTextStore)) { // For anything attached but (design-mode) iframes... // This block: has to do with maintaining focus. @@ -124,7 +126,7 @@ export default class ContextManager extends ContextManagerBase { + public get activeTextStore(): AbstractElementTextStore { /* - * Assumption: the maintainingFocus flag may only be set when there is a current target. + * Assumption: the maintainingFocus flag may only be set when there is a current textStore. * This is not enforced proactively at present, but the assumption should hold. (2023-05-03) */ - const maintainingFocus = this.focusAssistant.maintainingFocus; - return this.currentTarget || (maintainingFocus ? this.mostRecentTarget : null); + const {maintainingFocus} = this.focusAssistant; + return this.currentTextStore || (maintainingFocus ? this.mostRecentTextStore : null); } - get lastActiveTarget(): OutputTarget { - return this.mostRecentTarget; + public get lastActiveTextStore(): AbstractElementTextStore { + return this.mostRecentTextStore; } - public deactivateCurrentTarget() { - const priorTarget = this.activeTarget || this.lastActiveTarget; + public deactivateCurrentTextStore() { + const priorTextStore = this.activeTextStore || this.lastActiveTextStore; /* During integrated tests, it was possible in the past for a `beforeAll` - * -initialized KMW to reach this state between tests. The target fixture - * got cleared, but the `mostRecentTarget` / `lastActiveTarget` was not - * - just the `currentTarget` / `activeTarget`. See #9718. + * -initialized KMW to reach this state between tests. The textstore fixture + * got cleared, but the `mostRecentTextStore` / `lastActiveTextStore` was not + * - just the `currentTextStore` / `activeTextStore`. See #9718. * - * Newly-added code in `forgetActiveTarget` seeks to prevent this scenario, + * Newly-added code in `forgetActiveTextStore` seeks to prevent this scenario, * but as there's no consistent repro to prove it sufficient, an appropriate * guard-condition has been added here too. */ - if(priorTarget && this.page.isAttached(priorTarget.getElement())) { - this._BlurKeyboardSettings(priorTarget.getElement()); + if(priorTextStore && this.page.isAttached(priorTextStore.getElement())) { + this._BlurKeyboardSettings(priorTextStore.getElement()); } // Because of focus-maintenance effects - if(!this.activeTarget) { - this.setActiveTarget(null, true); + if(!this.activeTextStore) { + this.setActiveTextStore(null, true); } } - public forgetActiveTarget() { + public forgetActiveTextStore() { this.focusAssistant.maintainingFocus = false; this.focusAssistant.restoringFocus = false; - const priorTarget = this.activeTarget || this.mostRecentTarget; - if(priorTarget) { - this._BlurKeyboardSettings(priorTarget.getElement()); + const priorTextStore = this.activeTextStore || this.mostRecentTextStore; + if(priorTextStore) { + this._BlurKeyboardSettings(priorTextStore.getElement()); } // Will ensure that the element is no longer active. Does not erase - // it from being the `lastActiveTarget`, though. - this.setActiveTarget(null, true); + // it from being the `lastActiveTextStore`, though. + this.setActiveTextStore(null, true); // So we erase it here. - if(priorTarget == this.lastActiveTarget) { - this.mostRecentTarget = null; + if(priorTextStore == this.lastActiveTextStore) { + this.mostRecentTextStore = null; } } - public setActiveTarget(target: OutputTarget, sendEvents?: boolean) { - const previousTarget = this.mostRecentTarget; - const originalTarget = this.activeTarget; // may differ, depending on focus state. + public setActiveTextStore(textStore: AbstractElementTextStore, sendEvents?: boolean) { + const previousTextStore = this.mostRecentTextStore; + const originalTextStore = this.activeTextStore; // may differ, depending on focus state. - if(target == originalTarget) { - // A focus state may have .currentTarget as null at this stage; if the func + if(textStore == originalTextStore) { + // A focus state may have .currentTextStore as null at this stage; if the func // is being called with a non-null parameter, we want this SET. #9404 - if(originalTarget) { - this.currentTarget = originalTarget; + if(originalTextStore) { + this.currentTextStore = originalTextStore; } /** @@ -259,7 +261,7 @@ export default class ContextManager extends ContextManagerBase, Ptext: string, PdeadKey: number) { - // Find the correct output target to manipulate. The user has likely be interacting with a + public insertText(kbdInterface: KeyboardInterfaceBase, text: string, deadkey: number): boolean { + // Find the correct text store to manipulate. The user has likely be interacting with a // 'help page' keyboard, like desktop `sil_euro_latin`, and active browser focus on the // original context element may have been lost. - this.restoreLastActiveTarget(); + this.restoreLastActiveTextStore(); - let outputTarget = this.activeTarget; - - if(outputTarget == null && this.mostRecentTarget) { - outputTarget = this.activeTarget; - } - - if(outputTarget != null) { - return super.insertText(kbdInterface, Ptext, PdeadKey); - } - return false; + return super.insertText(kbdInterface, text, deadkey); } /** - * Determines the 'target' currently used to determine which keyboard should be active. + * Determines the 'textStore' currently used to determine which keyboard should be active. * When `null`, keyboard-activation operations will affect the global default; otherwise, - * such operations affect only the specified `target`. + * such operations affect only the specified `textStore`. * - * This is based on the current `.activeTarget` and its related attachment metadata. + * This is based on the current `.activeTextStore` and its related attachment metadata. */ - protected currentKeyboardSrcTarget(): OutputTarget { - const target = this.currentTarget || this.mostRecentTarget; + protected currentKeyboardSrcTextStore(): AbstractElementTextStore { + const textStore = this.currentTextStore || this.mostRecentTextStore; - if(this.isTargetKeyboardIndependent(target)) { - return target; + if(this.isTextStoreKeyboardIndependent(textStore)) { + return textStore; } else { return null; } } - private isTargetKeyboardIndependent(target: OutputTarget): boolean { - const attachmentInfo = target?.getElement()._kmwAttachment; + private isTextStoreKeyboardIndependent(textStore: AbstractElementTextStore): boolean { + const attachment = textStore?.getElement()._kmwAttachment; // If null or undefined, we're in 'global' mode. - return !!(attachmentInfo?.keyboard || attachmentInfo?.keyboard === ''); + return !!(attachment?.keyboard || attachment?.keyboard === ''); } // Note: is part of the keyboard activation process. Not to be called directly by published API. - activateKeyboardForTarget(kbd: {keyboard: Keyboard, metadata: KeyboardStub}, target: OutputTarget) { - const attachment = target?.getElement()._kmwAttachment; + public activateKeyboardForTextStore(kbd: KeyboardInfoPair, textStore: AbstractElementTextStore): void { + const attachment = textStore?.getElement()._kmwAttachment; if(!attachment) { // if not set with an "independent keyboard", changes the global. this.globalKeyboard = kbd; } else { - // if set with an "independent keyboard", changes only the active target's keyboard. + // if set with an "independent keyboard", changes only the active textStore's keyboard. // // This method is not called on the pathway to shift a control back to 'global keyboard' mode; // only after. @@ -400,7 +393,7 @@ export default class ContextManager extends ContextManagerBase, kbdId: string, langId: string) { - if(target instanceof DesignIFrame) { + public setKeyboardForTextStore(textStore: AbstractElementTextStore, kbdId: string, langId: string): void { + if(textStore instanceof DesignIFrameElementTextStore) { console.warn("'keymanweb.setKeyboardForControl' cannot set keyboard on iframes."); return; } - const attachment = target.getElement()._kmwAttachment; + const attachment = textStore.getElement()._kmwAttachment; - // Catches if the target is already in independent-mode, even if it's being cancelled + // Catches if the textStore is already in independent-mode, even if it's being cancelled // during this call. - const wasPriorTarget = this.currentKeyboardSrcTarget() == target; + const wasPriorTextStore = this.currentKeyboardSrcTextStore() == textStore; if(!attachment) { return; } else { // Either establishes or cancels independent-keyboard mode by setting the // associated metadata. This will have direct effects on the results - // of .currentKeyboardSrcTarget(). + // of .currentKeyboardSrcTextStore(). attachment.keyboard = kbdId || null; attachment.languageCode = langId || null; // If it has just entered independent-keyboard mode, we need the second check. - if(wasPriorTarget || this.currentKeyboardSrcTarget() == target) { + if(wasPriorTextStore || this.currentKeyboardSrcTextStore() == textStore) { const globalKbd = this.globalKeyboard.metadata; // The `||` bits below - in case we're cancelling independent-keyboard mode. @@ -454,16 +448,16 @@ export default class ContextManager extends ContextManagerBase) { - if(!this.isTargetKeyboardIndependent(target)) { + public getKeyboardStubForTextStore(textStore: AbstractElementTextStore) { + if(!this.isTextStoreKeyboardIndependent(textStore)) { return this.globalKeyboard.metadata; } else { - const attachment = target.getElement()._kmwAttachment; + const attachment = textStore.getElement()._kmwAttachment; return this.keyboardCache.getStub(attachment.keyboard, attachment.languageCode); } } - protected getFallbackStubKey() { + protected getFallbackStubKey(): KeyboardStub | { id: string, langId: string } { const emptyCodes = { id: '', langId: '' @@ -487,7 +481,7 @@ export default class ContextManager extends ContextManagerBase { saveCookie ||= false; - const originalKeyboardTarget = this.currentKeyboardSrcTarget(); + const originalKeyboardTextStore = this.currentKeyboardSrcTextStore(); // If someone tries to activate a keyboard before we've had a chance to load it, // we should defer the activation, just as we'd have deferred the load attempt. @@ -508,17 +502,17 @@ export default class ContextManager extends ContextManagerBase): boolean { - const focusAssistant = this.focusAssistant; + public _CommonFocusHelper(textStore: AbstractElementTextStore): boolean { + const {focusAssistant} = this; const activeKeyboard = this.activeKeyboard?.keyboard; if(!focusAssistant.restoringFocus) { - outputTarget?.deadkeys().clear(); - activeKeyboard?.notify(0, outputTarget, 1); // I2187 + textStore?.deadkeys().clear(); + activeKeyboard?.notify(0, textStore, 1); // I2187 } - if(!focusAssistant.restoringFocus && this.mostRecentTarget != outputTarget) { + if(!focusAssistant.restoringFocus && this.mostRecentTextStore != textStore) { focusAssistant.maintainingFocus = false; } focusAssistant.restoringFocus = false; @@ -634,29 +628,27 @@ export default class ContextManager extends ContextManagerBase { - // Step 1: determine the corresponding OutputTarget instance. - const target = eventOutputTarget(e); - if(!target) { + public _ControlFocus = (e: FocusEvent): boolean => { + // Step 1: determine the corresponding TextStore instance. + const textStore = textStoreForEvent(e); + if(!textStore) { // Probably should also make a warning or error? return true; } // ???? ?: ensure it's properly active? - // if(target instanceof DesignIFrame) { //**TODO: check case reference + // if(textStore instanceof DesignIFrameElementTextStore) { //**TODO: check case reference // // But... the following should already have been done during attachment... // // attachmentEngine._AttachToIframe(Ltarg as HTMLIFrameElement); - // target.docRoot - // Ltarg=Ltarg.contentWindow.document.body; // And we only care about Ltarg b/c of finding the OutputTarget. + // textStore.docRoot + // Ltarg=Ltarg.contentWindow.document.body; // And we only care about Ltarg b/c of finding the TextStore. // } // Step 2: Make the newly-focused control the active control, and thus the active context. - this.setActiveTarget(target, true); + this.setActiveTextStore(textStore, true); return true; } @@ -664,7 +656,7 @@ export default class ContextManager extends ContextManagerBase { + public _ControlBlur = (e: FocusEvent): boolean => { // Step 0: if we're in a state where loss-of-focus should be outright-ignored, bypass the handler entirely. if(this.focusAssistant._IgnoreNextSelChange) { @@ -683,29 +675,29 @@ export default class ContextManager extends ContextManagerBase) { - if(target.changed) { + doChangeEvent(textStore: AbstractElementTextStore) { + if(textStore.changed) { const event = new Event('change', {"bubbles": true, "cancelable": false}); - target.getElement().dispatchEvent(event); + textStore.getElement().dispatchEvent(event); } - target.changed = false; + textStore.changed = false; } - _Click: (e: MouseEvent) => boolean = (e: MouseEvent) => { + public _Click: (e: MouseEvent) => boolean = (e: MouseEvent) => { this.resetContext(); return true; }; @@ -754,7 +746,7 @@ export default class ContextManager extends ContextManagerBase('KeymanWeb_Keyboard'); const v = cookie.load(decodeURIComponent); @@ -775,7 +767,7 @@ export default class ContextManager extends ContextManagerBase { + public nonKMWTouchHandler = (x: Event) => { this.focusAssistant.focusing=false; clearTimeout(this.focusAssistant.focusTimer); - this.forgetActiveTarget(); + this.forgetActiveTextStore(); // this.keyman.osk.hideNow(); // TODO: is more aggressive than the default - how to migrate this tidbit? }; - shutdown() { + public shutdown(): void { this.page.shutdown(); this.domEventTracker.shutdown(); } diff --git a/web/src/app/browser/src/defaultBrowserRules.ts b/web/src/app/browser/src/defaultBrowserRules.ts index 349fe4fed6d..75c1850868d 100644 --- a/web/src/app/browser/src/defaultBrowserRules.ts +++ b/web/src/app/browser/src/defaultBrowserRules.ts @@ -1,14 +1,14 @@ import { ModifierKeyConstants } from '@keymanapp/common-types'; import { Codes, - DefaultRules, - type KeyEvent + DefaultOutputRules, + type KeyEvent, + type TextStore } from 'keyman/engine/keyboard'; -import { type OutputTarget } from 'keyman/engine/js-processor'; -import ContextManager from './contextManager.js'; +import { ContextManager } from './contextManager.js'; -export default class DefaultBrowserRules extends DefaultRules { +export class DefaultBrowserRules extends DefaultOutputRules { private contextManager: ContextManager; constructor(contextManager: ContextManager) { @@ -30,21 +30,21 @@ export default class DefaultBrowserRules extends DefaultRules { } /** - * applyCommand - used when a RuleBehavior represents a non-text "command" within the Engine. + * applyCommand - used when a ProcessorAction represents a non-text "command" within the Engine. */ - applyCommand(Lkc: KeyEvent, outputTarget: OutputTarget): void { + applyCommand(Lkc: KeyEvent, textStore: TextStore): void { const code = this.codeForEvent(Lkc); const moveToNext = (back: boolean) => { const contextManager = this.contextManager; - const activeElement = contextManager.activeTarget?.getElement(); + const activeElement = contextManager.activeTextStore?.getElement(); const nextElement = contextManager.page.findNeighboringInput(activeElement, back); nextElement?.focus(); } switch(code) { // This method will be handled between `ContextManager` and PageContextAttachment: - // pageContextAttachment.findNeighboringInput(contextManager.activeTarget.getElement(), ) + // pageContextAttachment.findNeighboringInput(contextManager.activeTextStore.getElement(), ) case Codes.keyCodes['K_TAB']: moveToNext((Lkc.Lmodifiers & ModifierKeyConstants.K_SHIFTFLAG) != 0); break; @@ -56,6 +56,6 @@ export default class DefaultBrowserRules extends DefaultRules { break; } - super.applyCommand(Lkc, outputTarget); + super.applyCommand(Lkc, textStore); } } \ No newline at end of file diff --git a/web/src/app/browser/src/hardwareEventKeyboard.ts b/web/src/app/browser/src/hardwareEventKeyboard.ts index ae5fa680a30..b64fd760e14 100644 --- a/web/src/app/browser/src/hardwareEventKeyboard.ts +++ b/web/src/app/browser/src/hardwareEventKeyboard.ts @@ -1,13 +1,13 @@ -import { Codes, DeviceSpec, KeyEvent, KeyMapping, Keyboard } from 'keyman/engine/keyboard'; -import { KeyboardProcessor } from 'keyman/engine/js-processor'; +import { DeviceSpec } from 'keyman/common/web-utils'; +import { Codes, KeyEvent, KeyMapping, KeyboardProcessor, Keyboard } from 'keyman/engine/keyboard'; import { ModifierKeyConstants } from '@keymanapp/common-types'; import { HardKeyboardBase, processForMnemonicsAndLegacy } from 'keyman/engine/main'; import { DomEventTracker } from 'keyman/engine/events'; -import { DesignIFrame, nestedInstanceOf } from 'keyman/engine/element-wrappers'; -import { eventOutputTarget, outputTargetForElement } from 'keyman/engine/attachment'; +import { DesignIFrameElementTextStore, nestedInstanceOf } from 'keyman/engine/element-text-stores'; +import { textStoreForEvent, textStoreForElement } from 'keyman/engine/attachment'; -import ContextManager from './contextManager.js'; +import { ContextManager } from './contextManager.js'; type KeyboardState = { activeKeyboard: Keyboard, @@ -15,6 +15,12 @@ type KeyboardState = { baseLayout: string } +const DOM_KEY_LOCATION = { + STANDARD: 0, + LEFT: 1, + RIGHT: 2, +}; + // Important: the following two lines should not cause a compile error if left uncommented. // let dummy1: KeyboardProcessor; // let dummy2: KeyboardState = dummy1; @@ -38,15 +44,23 @@ export function _GetEventKeyCode(e: KeyboardEvent) { // Keeping this as a separate function affords us the opportunity to unit-test the method more simply. /** - * Function _GetKeyEventProperties - * Scope Private - * @param {Event} e Event object - * @return {Object.} KMW keyboard event object: - * Description Get object with target element, key code, shift state, virtual key state - * Lcode=keyCode - * Lmodifiers=shiftState - * LisVirtualKeyCode e.g. ctrl/alt key - * LisVirtualKey e.g. Virtual key or non-keypress event + * Translate a browser KeyboardEvent into a KeymanWeb KeyEvent + * + * The function calculates the true state of the keyboard's modifiers, taking + * into account chiral modifiers where applicable. + * Special handling is included for AltGr emulation and browser quirks, particularly + * for Firefox, which may use different key codes for certain keys. The code remaps + * these as needed for consistency. It adds the OS meta key if pressed, ensuring + * that system shortcuts can bypass Keyman processing. Adjustments are made for + * mnemonic and legacy keyboards, before finally returning a KeyEvent object + * with the computed key code, modifiers and state. + * + * @param {KeyboardEvent} e Event object + * @param {KeyboardState} keyboardState Keyboard state object + * @param {DeviceSpec} device Device object + * + * @return {KeyEvent} KeymanWeb KeyEvent object, or null for duplicate/spurious + * events or if there is no key code. */ export function preprocessKeyboardEvent(e: KeyboardEvent, keyboardState: KeyboardState, device: DeviceSpec): KeyEvent { if(e.cancelBubble === true) { @@ -60,7 +74,6 @@ export function preprocessKeyboardEvent(e: KeyboardEvent, keyboardState: Keyboar // Stage 1 - track the true state of the keyboard's modifiers. const prevModState = keyboardState.modStateFlags; - let curModState = 0x0000; let ctrlEvent = false, altEvent = false; const keyCodes = Codes.keyCodes; @@ -97,17 +110,22 @@ export function preprocessKeyboardEvent(e: KeyboardEvent, keyboardState: Keyboar * `e.location != 0` if true matches condition 1 and matches condition 2 if false. */ - curModState |= (e.getModifierState("Shift") ? 0x10 : 0); + let curModState = 0x0000; + curModState |= (e.getModifierState("Shift") ? ModifierKeyConstants.K_SHIFTFLAG : 0); if(e.getModifierState("Control")) { - curModState |= ((e.location != 0 && ctrlEvent) ? - (e.location == 1 ? ModifierKeyConstants.LCTRLFLAG : ModifierKeyConstants.RCTRLFLAG) : // Condition 1 - prevModState & 0x0003); // Condition 2 + curModState |= ((e.location != DOM_KEY_LOCATION.STANDARD && ctrlEvent) + ? (e.location == DOM_KEY_LOCATION.LEFT + ? ModifierKeyConstants.LCTRLFLAG + : ModifierKeyConstants.RCTRLFLAG) // Condition 1 + : prevModState & (ModifierKeyConstants.LCTRLFLAG | ModifierKeyConstants.RCTRLFLAG)); // Condition 2 } if(e.getModifierState("Alt")) { - curModState |= ((e.location != 0 && altEvent) ? - (e.location == 1 ? ModifierKeyConstants.LALTFLAG : ModifierKeyConstants.RALTFLAG) : // Condition 1 - prevModState & 0x000C); // Condition 2 + curModState |= ((e.location != DOM_KEY_LOCATION.STANDARD && altEvent) + ? (e.location == DOM_KEY_LOCATION.LEFT + ? ModifierKeyConstants.LALTFLAG + : ModifierKeyConstants.RALTFLAG) // Condition 1 + : prevModState & (ModifierKeyConstants.LALTFLAG | ModifierKeyConstants.RALTFLAG)); // Condition 2 } // Stage 2 - detect state key information. It can be looked up per keypress with no issue. @@ -122,7 +140,7 @@ export function preprocessKeyboardEvent(e: KeyboardEvent, keyboardState: Keyboar curModState |= Lstates; // Stage 3 - Set our modifier state tracking variable and perform basic AltGr-related management. - const LmodifierChange = keyboardState.modStateFlags != curModState; + const LmodifierChanged = keyboardState.modStateFlags != curModState; // KeyboardState update: save our known modifier/state analysis bits. // Note: `keyboardState` is typically the full-fledged KeyboardProcessor instance. As a result, @@ -136,15 +154,15 @@ export function preprocessKeyboardEvent(e: KeyboardEvent, keyboardState: Keyboar curModState &= ~ altGrMask; } // Perform basic filtering for Windows-based ALT_GR emulation on European keyboards. - if(curModState & ModifierKeyConstants.RALTFLAG) { + if((curModState & ModifierKeyConstants.RALTFLAG) != 0) { curModState &= ~ModifierKeyConstants.LCTRLFLAG; } - const modifierBitmasks = Codes.modifierBitmasks; // Stage 4 - map the modifier set to the appropriate keystroke's modifiers. + const modifierBitmasks = Codes.modifierBitmasks; const activeKeyboard = keyboardState.activeKeyboard; let Lmodifiers: number; - if(activeKeyboard && activeKeyboard.isChiral) { + if(activeKeyboard?.isChiral) { Lmodifiers = curModState & modifierBitmasks.CHIRAL; // Note for future - embedding a kill switch here would facilitate disabling AltGr / Right-alt simulation. @@ -155,9 +173,9 @@ export function preprocessKeyboardEvent(e: KeyboardEvent, keyboardState: Keyboar } else { // No need to sim AltGr here; we don't need chiral ALTs. Lmodifiers = - (curModState & 0x10) | // SHIFT - ((curModState & (ModifierKeyConstants.LCTRLFLAG | ModifierKeyConstants.RCTRLFLAG)) ? 0x20 : 0) | - ((curModState & (ModifierKeyConstants.LALTFLAG | ModifierKeyConstants.RALTFLAG)) ? 0x40 : 0); + (curModState & ModifierKeyConstants.K_SHIFTFLAG) | + ((curModState & (ModifierKeyConstants.LCTRLFLAG | ModifierKeyConstants.RCTRLFLAG)) != 0 ? ModifierKeyConstants.K_CTRLFLAG : 0) | + ((curModState & (ModifierKeyConstants.LALTFLAG | ModifierKeyConstants.RALTFLAG)) != 0 ? ModifierKeyConstants.K_ALTFLAG : 0); } @@ -187,7 +205,7 @@ export function preprocessKeyboardEvent(e: KeyboardEvent, keyboardState: Keyboar Lcode: Lcode, Lmodifiers: Lmodifiers, Lstates: Lstates, - LmodifierChange: LmodifierChange, + LmodifierChange: LmodifierChanged, // This is based on a KeyboardEvent, so it's not considered 'synthetic' within web-core. isSynthetic: false }); @@ -203,7 +221,7 @@ export function preprocessKeyboardEvent(e: KeyboardEvent, keyboardState: Keyboar return processedEvent; } -export default class HardwareEventKeyboard extends HardKeyboardBase { +export class HardwareEventKeyboard extends HardKeyboardBase { private readonly hardDevice: DeviceSpec; // Needed properties & methods: @@ -222,20 +240,20 @@ export default class HardwareEventKeyboard extends HardKeyboardBase { this.contextManager = contextManager; this.processor = processor; - const page = contextManager.page; + const {page} = contextManager; const eventTracker = this.domEventTracker; page.on('enabled', (Pelem) => { - const target = outputTargetForElement(Pelem); + const textStore = textStoreForElement(Pelem); - if(!(target instanceof DesignIFrame)) { + if(!(textStore instanceof DesignIFrameElementTextStore)) { // These need to be on the actual input element, as otherwise the keyboard will disappear on touch. eventTracker.attachDOMEvent(Pelem, 'keypress', this._KeyPress); eventTracker.attachDOMEvent(Pelem, 'keydown', this._KeyDown); eventTracker.attachDOMEvent(Pelem, 'keyup', this._KeyUp); } else { - const Lelem = target.getElement().contentDocument; + const Lelem = textStore.getElement().contentDocument; eventTracker.attachDOMEvent(Lelem.body,'keydown', this._KeyDown); eventTracker.attachDOMEvent(Lelem.body,'keypress', this._KeyPress); eventTracker.attachDOMEvent(Lelem.body,'keyup', this._KeyUp); @@ -243,14 +261,14 @@ export default class HardwareEventKeyboard extends HardKeyboardBase { }); page.on('disabled', (Pelem) => { - const target = outputTargetForElement(Pelem); + const textStore = textStoreForElement(Pelem); - if(!(target instanceof DesignIFrame)) { + if(!(textStore instanceof DesignIFrameElementTextStore)) { eventTracker.detachDOMEvent(Pelem, 'keypress', this._KeyPress); eventTracker.detachDOMEvent(Pelem, 'keydown', this._KeyDown); eventTracker.detachDOMEvent(Pelem, 'keyup', this._KeyUp); } else { - const Lelem = target.getElement().contentDocument; + const Lelem = textStore.getElement().contentDocument; eventTracker.detachDOMEvent(Lelem.body,'keydown', this._KeyDown); eventTracker.detachDOMEvent(Lelem.body,'keypress', this._KeyPress); eventTracker.detachDOMEvent(Lelem.body,'keyup', this._KeyUp); @@ -268,15 +286,15 @@ export default class HardwareEventKeyboard extends HardKeyboardBase { * not affected. */ _KeyDown: (e: KeyboardEvent) => boolean = (e) => { - const activeKeyboard = this.contextManager.activeKeyboard; - const target = eventOutputTarget(e); + const {activeKeyboard} = this.contextManager; + const textStore = textStoreForEvent(e); - if(!target || activeKeyboard == null) { + if(!textStore || activeKeyboard == null) { return true; } // Prevent mapping element is readonly or tagged as kmw-disabled - const el = target.getElement(); + const el = textStore.getElement(); if(el?.getAttribute('class')?.indexOf('kmw-disabled') >= 0) { return true; } @@ -290,8 +308,8 @@ export default class HardwareEventKeyboard extends HardKeyboardBase { * Description Processes keypress event (does not pass data to keyboard) */ _KeyPress: (e: KeyboardEvent) => boolean = (e) => { - const target = eventOutputTarget(e); - if(!target || this.contextManager.activeKeyboard?.keyboard == null) { + const textStore = textStoreForEvent(e); + if(!textStore || this.contextManager.activeKeyboard?.keyboard == null) { return true; } @@ -304,13 +322,13 @@ export default class HardwareEventKeyboard extends HardKeyboardBase { * Description Processes keyup event and passes event data to keyboard */ _KeyUp: (e: KeyboardEvent) => boolean = (e) => { - const target = eventOutputTarget(e); + const textStore = textStoreForEvent(e); const Levent = preprocessKeyboardEvent(e, this.processor, this.hardDevice); - if(Levent == null || target == null) { + if(Levent == null || textStore == null) { return true; } - const inputEle = target.getElement(); + const inputEle = textStore.getElement(); // Since this part concerns DOM element + browser interaction management, we preprocess it for // browser form commands before passing control to the Processor module. @@ -391,8 +409,8 @@ export default class HardwareEventKeyboard extends HardKeyboardBase { return true; } - const outputTarget = eventOutputTarget(e); - return this.processor.doModifierPress(Levent, outputTarget, false); + const textStore = textStoreForEvent(e); + return this.processor.doModifierPress(Levent, textStore, false); } private keyPress(e: KeyboardEvent): boolean { diff --git a/web/src/app/browser/src/keyboardInterface.ts b/web/src/app/browser/src/keyboardInterface.ts index e9b0bda3795..4da0579a007 100644 --- a/web/src/app/browser/src/keyboardInterface.ts +++ b/web/src/app/browser/src/keyboardInterface.ts @@ -1,11 +1,11 @@ -import { type OutputTarget } from 'keyman/engine/element-wrappers'; +import { type AbstractElementTextStore } from 'keyman/engine/element-text-stores'; import { FloatingOSKView } from 'keyman/engine/osk'; -import { KeyboardInterface as KeyboardInterfaceBase } from 'keyman/engine/main'; +import { KeyboardInterfaceBase } from 'keyman/engine/main'; -import ContextManager from './contextManager.js'; +import { ContextManager } from './contextManager.js'; import { KeymanEngine } from './keymanEngine.js'; -export default class KeyboardInterface extends KeyboardInterfaceBase { +export class KeyboardInterface extends KeyboardInterfaceBase { constructor( _jsGlobal: any, engine: KeymanEngine, @@ -29,12 +29,12 @@ export default class KeyboardInterface extends KeyboardInterfaceBase { - return this.engine.contextManager.lastActiveTarget; + getLastActiveElement(): AbstractElementTextStore { + return this.engine.contextManager.lastActiveTextStore; } focusLastActiveElement(): void { - this.engine.contextManager.restoreLastActiveTarget(); + this.engine.contextManager.restoreLastActiveTextStore(); } //The following entry points are defined but should not normally be used in a keyboard, as OSK display is no longer determined by the keyboard diff --git a/web/src/app/browser/src/keymanEngine.ts b/web/src/app/browser/src/keymanEngine.ts index 59987035ccf..b9663ca3747 100644 --- a/web/src/app/browser/src/keymanEngine.ts +++ b/web/src/app/browser/src/keymanEngine.ts @@ -1,32 +1,33 @@ import { KeymanWebKeyboard } from '@keymanapp/common-types'; import { KeymanEngineBase, DeviceDetector } from 'keyman/engine/main'; import { getAbsoluteY } from 'keyman/engine/dom-utils'; -import { OutputTarget } from 'keyman/engine/element-wrappers'; +import { AbstractElementTextStore } from 'keyman/engine/element-text-stores'; import { TwoStateActivator, VisualKeyboard } from 'keyman/engine/osk'; import { ErrorStub, KeyboardStub, CloudQueryResult, toPrefixedKeyboardId as prefixed } from 'keyman/engine/keyboard-storage'; -import { DeviceSpec, Keyboard } from "keyman/engine/keyboard"; +import { DeviceSpec } from 'keyman/common/web-utils'; +import { JSKeyboard, Keyboard, KMXKeyboard } from "keyman/engine/keyboard"; import KeyboardObject = KeymanWebKeyboard.KeyboardObject; import * as views from './viewsAnchorpoint.js'; import { BrowserConfiguration, BrowserInitOptionDefaults, BrowserInitOptionSpec } from './configuration.js'; -import { default as ContextManager } from './contextManager.js'; -import DefaultBrowserRules from './defaultBrowserRules.js'; -import HardwareEventKeyboard from './hardwareEventKeyboard.js'; +import { ContextManager } from './contextManager.js'; +import { DefaultBrowserRules } from './defaultBrowserRules.js'; +import { HardwareEventKeyboard } from './hardwareEventKeyboard.js'; import { FocusStateAPIObject } from './context/focusAssistant.js'; import { PageIntegrationHandlers } from './context/pageIntegrationHandlers.js'; import { LanguageMenu } from './languageMenu.js'; import { setupOskListeners } from './oskConfiguration.js'; import { whenDocumentReady } from './utils/documentReady.js'; -import { outputTargetForElement } from 'keyman/engine/attachment'; +import { textStoreForElement } from 'keyman/engine/attachment'; import { UtilApiEndpoint} from './utilApiEndpoint.js'; import { UIModule } from './uiModuleInterface.js'; import { HotkeyManager } from './hotkeyManager.js'; import { BeepHandler } from './beepHandler.js'; -import KeyboardInterface from './keyboardInterface.js'; +import { KeyboardInterface } from './keyboardInterface.js'; import { WorkerFactory } from '@keymanapp/lexical-model-layer/web'; export class KeymanEngine extends KeymanEngineBase { @@ -53,7 +54,7 @@ export class KeymanEngine extends KeymanEngineBase { - this.contextManager.restoreLastActiveTarget(); + this.contextManager.restoreLastActiveTextStore(); } constructor(workerFactory: WorkerFactory, sourceUri: string) { @@ -61,8 +62,7 @@ export class KeymanEngine extends KeymanEngineBase this.legacyAPIEvents), (engine) => { return { - // The `engine` parameter cannot be supplied with the constructing instance before calling - // `super`, hence the 'fun' rigging to supply it _from_ `super` via this closure. + baseLayout: 'us', keyboardInterface: new KeyboardInterface(window, engine as KeymanEngine), defaultOutputRules: new DefaultBrowserRules(engine.contextManager) }; @@ -70,18 +70,18 @@ export class KeymanEngine extends KeymanEngineBase this.beepHandler.beep(this.contextManager.activeTarget); + this.core.keyboardProcessor.beepHandler = () => this.beepHandler.beep(this.contextManager.activeTextStore); this.hardKeyboard = new HardwareEventKeyboard(config.hardDevice, this.core.keyboardProcessor, this.contextManager); // Scrolls the document-body to ensure that a focused element remains visible after the OSK appears. - this.contextManager.on('targetchange', (target) => { - const e = (target as OutputTarget)?.getElement(); + this.contextManager.on('textstorechange', (textStore) => { + const e = (textStore as AbstractElementTextStore)?.getElement(); if(this.osk) { (this.osk.activationModel as TwoStateActivator).activationTrigger = e; } - if(this.config.hostDevice.touchable && target) { + if(this.config.hostDevice.touchable && textStore) { this.ensureElementVisibility(e); } }); @@ -192,11 +192,11 @@ export class KeymanEngine extends KeymanEngineBase { + this.keyboardRequisitioner.cloudQueryEngine.once('unboundregister', async () => { if(!this.contextManager.activeKeyboard?.keyboard) { // Autoselects this.keyboardRequisitioner.cache.defaultStub, which will be // set to an actual keyboard on mobile devices. - this.setActiveKeyboard('', ''); + await this.setActiveKeyboard('', ''); } }); @@ -277,7 +277,7 @@ export class KeymanEngine extends KeymanEngineBase (and document!) + private _GetKeyboardDetail = function(Lstub: KeyboardStub, Lkbd: JSKeyboard) { // I2078 - Full keyboard detail const Lr = { Name: Lstub.KN, InternalName: Lstub.KI, @@ -437,13 +441,14 @@ export class KeymanEngine extends KeymanEngineBase { // K_ROPT if(osk) { osk.startHide(true); - contextManager.forgetActiveTarget(); + contextManager.forgetActiveTextStore(); } }); osk.addEventListener('hide', (params) => { // If hidden by the UI, be sure to restore the focus if(params?.HiddenByUser) { - contextManager.activeTarget?.focus(); + contextManager.activeTextStore?.focus(); } }); @@ -44,7 +44,7 @@ export function setupOskListeners(engine: KeymanEngine, osk: OSKView, contextMan await promise; - contextManager.restoreLastActiveTarget(); + contextManager.restoreLastActiveTextStore(); focusAssistant.restoringFocus = false; focusAssistant.setMaintainingFocus(false); @@ -54,7 +54,7 @@ export function setupOskListeners(engine: KeymanEngine, osk: OSKView, contextMan focusAssistant.restoringFocus = true; await promise; - contextManager.restoreLastActiveTarget(); + contextManager.restoreLastActiveTextStore(); focusAssistant.restoringFocus = false; focusAssistant.setMaintainingFocus(false); diff --git a/web/src/app/browser/src/release-main.ts b/web/src/app/browser/src/release-main.ts index da6b5be1092..3e3a168ccd9 100644 --- a/web/src/app/browser/src/release-main.ts +++ b/web/src/app/browser/src/release-main.ts @@ -1,5 +1,5 @@ import { KeymanEngine } from './keymanEngine.js' -import { Worker } from '@keymanapp/lexical-model-layer/web' +import { WebWorker } from '@keymanapp/lexical-model-layer/web' /** * Determine path and protocol of executing script, setting them as @@ -9,4 +9,4 @@ const ss = (document.currentScript as HTMLScriptElement)?.src; const sPath = ss ? ss.substring(0, ss.lastIndexOf('/') + 1) : './'; // @ts-ignore -window['keyman'] = new KeymanEngine(Worker, sPath); \ No newline at end of file +window['keyman'] = new KeymanEngine(WebWorker, sPath); \ No newline at end of file diff --git a/web/src/app/browser/src/test-index.ts b/web/src/app/browser/src/test-index.ts index 408b47cba6b..6f010f494e5 100644 --- a/web/src/app/browser/src/test-index.ts +++ b/web/src/app/browser/src/test-index.ts @@ -1,7 +1,7 @@ export { BrowserConfiguration, BrowserInitOptionSpec } from './configuration.js'; -export { default as ContextManager, KeyboardCookie } from "./contextManager.js"; -export { preprocessKeyboardEvent, default as HardwareEventKeyboard } from './hardwareEventKeyboard.js'; +export { ContextManager, KeyboardCookie } from "./contextManager.js"; +export { preprocessKeyboardEvent, HardwareEventKeyboard } from './hardwareEventKeyboard.js'; export { KeymanEngine } from './keymanEngine.js'; -export { default as KeyboardInterface } from './keyboardInterface.js'; +export { KeyboardInterface } from './keyboardInterface.js'; export { UIModule } from './uiModuleInterface.js'; diff --git a/web/src/app/browser/src/utils/rotationProcessor.ts b/web/src/app/browser/src/utils/rotationProcessor.ts index 07e1c1b202c..c6854aa8c03 100644 --- a/web/src/app/browser/src/utils/rotationProcessor.ts +++ b/web/src/app/browser/src/utils/rotationProcessor.ts @@ -59,12 +59,12 @@ export class RotationProcessor { this.rotState = null; } - const target = this.keyman.contextManager.activeTarget; - if(target) { + const textStore = this.keyman.contextManager.activeTextStore; + if(textStore) { // This seems to help with scrolling accuracy in iOS Safari; // the scroll tends to consistently go too far without it. window.setTimeout(() => { - this.keyman.ensureElementVisibility(target.getElement()); + this.keyman.ensureElementVisibility(textStore.getElement()); }, 0); } } diff --git a/web/src/app/browser/tsconfig.json b/web/src/app/browser/tsconfig.json index 4aeb519f295..de34dea8d77 100644 --- a/web/src/app/browser/tsconfig.json +++ b/web/src/app/browser/tsconfig.json @@ -2,16 +2,14 @@ "extends": "../../tsconfig.dom.json", "compilerOptions": { - "baseUrl": "./", "outDir": "../../../build/app/browser/obj/", "rootDir": "./src", - "tsBuildInfoFile": "../../../build/app/browser/obj/tsconfig.tsbuildinfo" + "tsBuildInfoFile": "../../../build/app/browser/obj/tsconfig.tsbuildinfo", }, "include": [ "**/*.ts" ], "references": [ - { "path": "../../engine/attachment" }, - { "path": "../../engine/main" } + { "path": "../../engine" }, ] } diff --git a/web/src/app/ui/build.sh b/web/src/app/ui/build.sh index 145cea8e4b8..1ac39c3fc09 100755 --- a/web/src/app/ui/build.sh +++ b/web/src/app/ui/build.sh @@ -14,8 +14,8 @@ SUBPROJECT_NAME=app/ui # ################################ Main script ################################ builder_describe "Builds the Keyman Engine for Web's desktop form-factor keyboard selection modules." \ - "@/web/src/app/browser build" \ - "@/web/src/tools/building/sourcemap-root" \ + "@/web/src/app/browser build" \ + "@/web/src/tools/building/sourcemap-root build" \ "clean" \ "configure" \ "build" \ @@ -48,22 +48,26 @@ compile_and_copy() { BUILD_ROOT="${KEYMAN_ROOT}/web/build/app/ui" types=(button float toggle toolbar) - for type in ${types[@]} + for type in "${types[@]}" do filename="kmwui${type}" - node "${LIB_BUNDLER}" "${BUILD_ROOT}/obj/$filename.js" \ - --out "${BUILD_ROOT}/debug/$filename.js" \ - --sourceRoot "@keymanapp/keyman/web/build/app/ui/debug" + node_es_bundle "${BUILD_ROOT}/obj/$filename.js" \ + --out "${BUILD_ROOT}/debug/$filename.js" \ + --sourceRoot "@keymanapp/keyman/web/build/app/ui/debug" - node "${LIB_BUNDLER}" "${BUILD_ROOT}/obj/$filename.js" \ - --out "${BUILD_ROOT}/release/$filename.js" \ - --sourceRoot "@keymanapp/keyman/web/build/app/ui/release" \ + node_es_bundle "${BUILD_ROOT}/obj/$filename.js" \ + --out "${BUILD_ROOT}/release/$filename.js" \ + --sourceRoot "@keymanapp/keyman/web/build/app/ui/release" \ --minify done mkdir -p "$KEYMAN_ROOT/web/build/app/resources/ui" cp -R "$KEYMAN_ROOT/web/src/resources/ui/." "$KEYMAN_ROOT/web/build/app/resources/ui/" + # Copy Keyman Core build artifacts for local reference + cp "${KEYMAN_ROOT}/web/build/engine/obj/core-adapter/import/core/"km-core.{js,wasm} "${KEYMAN_ROOT}/web/build/app/ui/debug/" + cp "${KEYMAN_ROOT}/web/build/engine/obj/core-adapter/import/core/"km-core.{js,wasm} "${KEYMAN_ROOT}/web/build/app/ui/release/" + # Update the build/publish copy of our build artifacts prepare } diff --git a/web/src/app/ui/kmwuifloat.ts b/web/src/app/ui/kmwuifloat.ts index f67463cf486..c60c6c9b51b 100644 --- a/web/src/app/ui/kmwuifloat.ts +++ b/web/src/app/ui/kmwuifloat.ts @@ -450,7 +450,7 @@ if(!keymanweb) { * @param {Object} e event * Description Change active keyboard in response to user selection event */ - private readonly SelectKeyboardChange = async (e: Event) => { + private readonly SelectKeyboardChange = async (e: Event): Promise => { keymanweb.activatingUI(true); if(this.KeyboardSelector.value != '-') { diff --git a/web/src/app/ui/kmwuitoolbar.ts b/web/src/app/ui/kmwuitoolbar.ts index daf1adf8cac..08bcd00a2c8 100644 --- a/web/src/app/ui/kmwuitoolbar.ts +++ b/web/src/app/ui/kmwuitoolbar.ts @@ -820,7 +820,7 @@ if(!keymanweb) { * @param {boolean} updateKeyman * @return {boolean} **/ - private async selectKeyboard(event: Event, lang: LanguageEntry, kbd: KeyboardDetail, updateKeyman: boolean) { + private async selectKeyboard(event: Event, lang: LanguageEntry, kbd: KeyboardDetail, updateKeyman: boolean): Promise { keymanweb.activatingUI(true); if(this.selectedLanguage) { @@ -943,7 +943,7 @@ if(!keymanweb) { * @return {boolean} * Description Update the UI when all keyboards disabled by user **/ - private readonly offButtonClickEvent = async (event: Event) => { + private readonly offButtonClickEvent = async (event: Event): Promise => { if(this.toolbarNode.className != 'kmw_controls_disabled') { this.hideKeyboardsForLanguage(null); if(this.selectedLanguage) { diff --git a/web/src/app/ui/tsconfig.json b/web/src/app/ui/tsconfig.json index 8d6da3884a7..b37d8bd681c 100644 --- a/web/src/app/ui/tsconfig.json +++ b/web/src/app/ui/tsconfig.json @@ -2,7 +2,6 @@ "extends": "../../tsconfig.dom.json", "compilerOptions": { - "baseUrl": "./", "outDir": "../../../build/app/ui/obj", "rootDir": "", "tsBuildInfoFile": "../../../build/app/ui/obj/tsconfig.tsbuildinfo", diff --git a/web/src/app/webview/build.sh b/web/src/app/webview/build.sh index 72708eabea7..e6ff4795d01 100755 --- a/web/src/app/webview/build.sh +++ b/web/src/app/webview/build.sh @@ -14,8 +14,9 @@ SUBPROJECT_NAME=app/webview # ################################ Main script ################################ builder_describe "Builds the Keyman Engine for Web's puppetable version designed for use within WebViews." \ - "@/web/src/engine/main build" \ - "@/web/src/tools/building/sourcemap-root" \ + "@/common/tools/es-bundling build" \ + "@/web/src/engine build" \ + "@/web/src/tools/building/sourcemap-root build" \ "clean" \ "configure" \ "build" \ @@ -43,25 +44,33 @@ compile_and_copy() { BUILD_ROOT="${KEYMAN_ROOT}/web/build/app/webview" SRC_ROOT="${KEYMAN_ROOT}/web/src/app/webview/src" - node "${LIB_BUNDLER}" "${SRC_ROOT}/debug-main.js" \ - --out "${BUILD_ROOT}/debug/keymanweb-webview.js" \ - --charset "utf8" \ - --sourceRoot "@keymanapp/keyman/web/build/app/webview/debug" \ - --target "es6" + node_es_bundle "${SRC_ROOT}/debug-main.js" \ + --out "${BUILD_ROOT}/debug/keymanweb-webview.js" \ + --charset "utf8" \ + --sourceRoot "@keymanapp/keyman/web/build/app/webview/debug" \ + --target "es6" - node "${LIB_BUNDLER}" "${SRC_ROOT}/release-main.js" \ - --out "${BUILD_ROOT}/release/keymanweb-webview.js" \ - --charset "utf8" \ - --profile "${BUILD_ROOT}/filesize-profile.log" \ - --sourceRoot "@keymanapp/keyman/web/build/app/webview/release" \ - --minify \ - --target "es6" + node_es_bundle "${SRC_ROOT}/release-main.js" \ + --out "${BUILD_ROOT}/release/keymanweb-webview.js" \ + --charset "utf8" \ + --profile "${BUILD_ROOT}/filesize-profile.log" \ + --sourceRoot "@keymanapp/keyman/web/build/app/webview/release" \ + --minify \ + --target "es6" mkdir -p "$KEYMAN_ROOT/web/build/app/resources/osk" cp -R "$KEYMAN_ROOT/web/src/resources/osk/." "$KEYMAN_ROOT/web/build/app/resources/osk/" + # Copy Keyman Core build artifacts for local reference + cp "${KEYMAN_ROOT}/web/build/engine/obj/core-adapter/import/core/"km-core.{js,wasm} "${KEYMAN_ROOT}/web/build/app/webview/debug/" + cp "${KEYMAN_ROOT}/web/build/engine/obj/core-adapter/import/core/"km-core.{js,wasm} "${KEYMAN_ROOT}/web/build/app/webview/release/" + # Clean the sourcemaps of .. and . components for script in "$KEYMAN_ROOT/web/build/$SUBPROJECT_NAME/debug/"*.js; do + if [[ "${script}" == *"/km-core.js" ]]; then + continue + fi + sourcemap="$script.map" node "$KEYMAN_ROOT/web/build/tools/building/sourcemap-root/index.js" \ "$script" "$sourcemap" --clean --inline @@ -70,6 +79,9 @@ compile_and_copy() { # Do NOT inline sourcemaps for release builds - we don't want them to affect # load time. for script in "$KEYMAN_ROOT/web/build/$SUBPROJECT_NAME/release/"*.js; do + if [[ "${script}" == *"/km-core.js" ]]; then + continue + fi sourcemap="$script.map" node "$KEYMAN_ROOT/web/build/tools/building/sourcemap-root/index.js" \ "$script" "$sourcemap" --clean diff --git a/web/src/app/webview/map-polyfill-bundler.js b/web/src/app/webview/map-polyfill-bundler.js index 72b7a832432..257f897e70f 100644 --- a/web/src/app/webview/map-polyfill-bundler.js +++ b/web/src/app/webview/map-polyfill-bundler.js @@ -6,7 +6,7 @@ */ import esbuild from 'esbuild'; -import { iifeConfiguration, prepareTslibTreeshaking } from '../../tools/es-bundling/build/index.mjs'; +import { iifeConfiguration, prepareTslibTreeshaking } from '../../../../common/tools/es-bundling/build/index.mjs'; const commonConfig = { ...iifeConfiguration, diff --git a/web/src/app/webview/src/contextManager.ts b/web/src/app/webview/src/contextManager.ts index da441de3ff8..971c207a50a 100644 --- a/web/src/app/webview/src/contextManager.ts +++ b/web/src/app/webview/src/contextManager.ts @@ -1,16 +1,20 @@ -import { type Keyboard } from 'keyman/engine/keyboard'; -import { Mock, OutputTarget, Transcription, findCommonSubstringEndIndex, isEmptyTransform, TextTransform } from 'keyman/engine/js-processor'; +import { JSKeyboard, Keyboard, TextStore, Transcription, TextTransform, SyntheticTextStore, findCommonSubstringEndIndex } from 'keyman/engine/keyboard'; import { KeyboardStub } from 'keyman/engine/keyboard-storage'; import { ContextManagerBase } from 'keyman/engine/main'; import { WebviewConfiguration } from './configuration.js'; import { LexicalModelTypes } from '@keymanapp/common-types'; -import { KMWString } from '@keymanapp/web-utils'; +import { KMWString, isEmptyTransform } from 'keyman/common/web-utils'; export type OnInsertTextFunc = (deleteLeft: number, text: string, deleteRight: number) => void; -export class ContextHost extends Mock { +/** + * WebView-specific synthetic TextStore implementation that can + * communicate and synchronize with the host app despite not being + * backed by any sort of Web element. + */ +export class HostTextStore extends SyntheticTextStore { readonly oninserttext?: OnInsertTextFunc; - private savedState: Mock; + private savedState: SyntheticTextStore; constructor(oninserttext: OnInsertTextFunc) { super(); @@ -30,7 +34,7 @@ export class ContextHost extends Mock { let transform: TextTransform = null; if(transcription) { - const preInput = transcription.preInput; + const { preInput } = transcription; // If our saved state matches the `preInput` from the incoming transcription, just reuse its transform. // Will generally not match during multitap operations, though. // @@ -55,18 +59,18 @@ export class ContextHost extends Mock { } saveState() { - this.savedState = Mock.from(this); + this.savedState = SyntheticTextStore.from(this); } - restoreTo(original: OutputTarget): void { - this.savedState = Mock.from(this); + restoreTo(original: TextStore): void { + this.savedState = SyntheticTextStore.from(this); super.restoreTo(original); } updateContext(text: string, selStart: number, selEnd: number): boolean { let shouldResetContext = false; - const tempMock = new Mock(text, selStart ?? KMWString.length(text), selEnd ?? KMWString.length(text)); - const newLeft = tempMock.getTextBeforeCaret(); + const tempTextStore = new SyntheticTextStore(text, selStart ?? KMWString.length(text), selEnd ?? KMWString.length(text)); + const newLeft = tempTextStore.getTextBeforeCaret(); const oldLeft = this.getTextBeforeCaret(); if(text != this.text) { @@ -107,15 +111,15 @@ export class ContextHost extends Mock { // and we want a consistent interface for context synchronization between // host app + app/webview KMW. this.setSelection(KMWString.length(this.text)); - this.savedState = Mock.from(this); + this.savedState = SyntheticTextStore.from(this); } } -export default class ContextManager extends ContextManagerBase { - // Change of context? Just replace the Mock. Context will be ENTIRELY controlled +export class ContextManager extends ContextManagerBase { + // Change of context? Just replace the SyntheticTextStore. Context will be ENTIRELY controlled // by whatever is hosting the WebView. (Some aspects of this context replacement have // yet to be modularized at this time, though.) - private _rawContext: ContextHost; + private _hostTextStore: HostTextStore; private _activeKeyboard: {keyboard: Keyboard, metadata: KeyboardStub}; @@ -124,31 +128,31 @@ export default class ContextManager extends ContextManagerBase { - kbd.refreshLayouts() + // TODO-embed-osk-in-kmx: Do we need to refresh layouts for KMX keyboards also? + if (kbd instanceof JSKeyboard) { + kbd.refreshLayouts(); + } return kbd; }); } @@ -214,6 +221,6 @@ export default class ContextManager extends ContextManagerBase { - (this.context as ContextHost).updateHost(ruleBehavior.transcription); + config.onRuleFinalization = (ruleBehavior: ProcessorAction) => { + (this.context as HostTextStore).updateHost(ruleBehavior.transcription); } config.stubNamespacer = (stub) => { @@ -33,10 +33,9 @@ export class KeymanEngine extends KeymanEngineBase { return { - // The `engine` parameter cannot be supplied with the constructing instance before calling - // `super`, hence the 'fun' rigging to supply it _from_ `super` via this closure. - keyboardInterface: new KeyboardInterface(window, engine, config.stubNamespacer), - defaultOutputRules: new DefaultRules() + baseLayout: 'us', + keyboardInterface: new KeyboardInterfaceBase(window, engine, config.stubNamespacer), + defaultOutputRules: new DefaultOutputRules() }; }); @@ -158,6 +157,6 @@ export class KeymanEngine extends KeymanEngineBase number = null; get context() { - return this.contextManager.activeTarget; + return this.contextManager.activeTextStore; } } diff --git a/web/src/app/webview/src/oskConfiguration.ts b/web/src/app/webview/src/oskConfiguration.ts index cd0bdd9b4fb..e71c6bab7f6 100644 --- a/web/src/app/webview/src/oskConfiguration.ts +++ b/web/src/app/webview/src/oskConfiguration.ts @@ -1,6 +1,5 @@ -import { OSKView } from "keyman/engine/osk"; -import { DeviceSpec } from "keyman/engine/keyboard"; -import { type EmbeddedGestureConfig } from "keyman/engine/osk"; +import { OSKView, type EmbeddedGestureConfig } from "keyman/engine/osk"; +import { DeviceSpec } from 'keyman/common/web-utils'; import { GlobeHint } from './osk/globeHint.js'; import { type KeymanEngine } from "./keymanEngine.js"; diff --git a/web/src/app/webview/src/passthroughKeyboard.ts b/web/src/app/webview/src/passthroughKeyboard.ts index c0361195089..293be9883b1 100644 --- a/web/src/app/webview/src/passthroughKeyboard.ts +++ b/web/src/app/webview/src/passthroughKeyboard.ts @@ -1,8 +1,9 @@ -import { DeviceSpec, Keyboard, KeyEvent, ManagedPromise } from 'keyman/engine/keyboard'; +import { DeviceSpec, ManagedPromise } from 'keyman/common/web-utils'; +import { Keyboard, KeyEvent } from 'keyman/engine/keyboard'; import { HardKeyboardBase, processForMnemonicsAndLegacy } from 'keyman/engine/main'; -export default class PassthroughKeyboard extends HardKeyboardBase { +export class PassthroughKeyboard extends HardKeyboardBase { readonly baseDevice: DeviceSpec; public activeKeyboard: Keyboard; diff --git a/web/src/app/webview/src/release-main.ts b/web/src/app/webview/src/release-main.ts index da6b5be1092..3e3a168ccd9 100644 --- a/web/src/app/webview/src/release-main.ts +++ b/web/src/app/webview/src/release-main.ts @@ -1,5 +1,5 @@ import { KeymanEngine } from './keymanEngine.js' -import { Worker } from '@keymanapp/lexical-model-layer/web' +import { WebWorker } from '@keymanapp/lexical-model-layer/web' /** * Determine path and protocol of executing script, setting them as @@ -9,4 +9,4 @@ const ss = (document.currentScript as HTMLScriptElement)?.src; const sPath = ss ? ss.substring(0, ss.lastIndexOf('/') + 1) : './'; // @ts-ignore -window['keyman'] = new KeymanEngine(Worker, sPath); \ No newline at end of file +window['keyman'] = new KeymanEngine(WebWorker, sPath); \ No newline at end of file diff --git a/web/src/app/webview/tsconfig.json b/web/src/app/webview/tsconfig.json index b595456aba2..06f6e0064ab 100644 --- a/web/src/app/webview/tsconfig.json +++ b/web/src/app/webview/tsconfig.json @@ -2,15 +2,15 @@ "extends": "../../tsconfig.dom.json", "compilerOptions": { - "baseUrl": "./", "outDir": "../../../build/app/webview/obj/", "rootDir": "./src", - "tsBuildInfoFile": "../../../build/app/webview/obj/tsconfig.tsbuildinfo" + "tsBuildInfoFile": "../../../build/app/webview/obj/tsconfig.tsbuildinfo", }, "include": [ "**/*.ts" ], "references": [ - { "path": "../../engine/main" } + { "path": "../../engine" }, + { "path": "../../common/web-utils" }, ] } diff --git a/web/src/engine/common/web-utils/.c8rc.json b/web/src/common/web-utils/.c8rc.json similarity index 78% rename from web/src/engine/common/web-utils/.c8rc.json rename to web/src/common/web-utils/.c8rc.json index 4c652ff8922..1b73d94074b 100644 --- a/web/src/engine/common/web-utils/.c8rc.json +++ b/web/src/common/web-utils/.c8rc.json @@ -10,7 +10,7 @@ ], "exclude-after-remap": true, "reporter": ["text", "text-summary"], - "reports-dir": "../../../build/coverage/raw/raw/engine/common/web-utils", + "reports-dir": "../../../build/coverage/raw/raw/common/web-utils", "src": [ "src/" ] diff --git a/web/src/engine/common/web-utils/build.sh b/web/src/common/web-utils/build.sh similarity index 83% rename from web/src/engine/common/web-utils/build.sh rename to web/src/common/web-utils/build.sh index 8be7be6df37..d74c1f2663b 100755 --- a/web/src/engine/common/web-utils/build.sh +++ b/web/src/common/web-utils/build.sh @@ -5,22 +5,23 @@ ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" -. "${THIS_SCRIPT%/*}/../../../../../resources/build/builder-full.inc.sh" +. "${THIS_SCRIPT%/*}/../../../../resources/build/builder-full.inc.sh" ## END STANDARD BUILD SCRIPT INCLUDE . "${KEYMAN_ROOT}/web/common.inc.sh" . "${KEYMAN_ROOT}/resources/build/utils.inc.sh" . "${KEYMAN_ROOT}/resources/build/node.inc.sh" -SUBPROJECT_NAME=engine/common/web-utils -BUILD_DIR="/web/src/engine/common/web-utils/build" +SUBPROJECT_NAME=common/web-utils +BUILD_DIR="/web/build/common/web-utils" ################################ Main script ################################ builder_describe \ "Compiles the web-oriented utility function module." \ - "@/common/web/keyman-version" \ - "@/web/src/tools/es-bundling" \ + "@/common/tools/es-bundling build" \ + "@/common/web/keyman-version build" \ + "@/common/web/types build" \ clean configure build test builder_describe_outputs \ @@ -37,8 +38,8 @@ function do_build() { tsc --emitDeclarationOnly --outFile "${KEYMAN_ROOT}/${BUILD_DIR}/lib/index.d.ts" # One of the functions (timedPromise) is quite helpful for automated testing, even in the DOM. # So, to make sure it's easily-accessible for the DOM-based tests... - node "${LIB_BUNDLER}" "${KEYMAN_ROOT}/${BUILD_DIR}/obj/index.js" \ - --out "${KEYMAN_ROOT}/${BUILD_DIR}/lib/index.mjs" \ + node_es_bundle "${KEYMAN_ROOT}/${BUILD_DIR}/obj/index.js" \ + --out "${KEYMAN_ROOT}/${BUILD_DIR}/lib/index.mjs" \ --format esm } diff --git a/web/src/engine/common/web-utils/src/deepCopy.ts b/web/src/common/web-utils/src/deepCopy.ts similarity index 88% rename from web/src/engine/common/web-utils/src/deepCopy.ts rename to web/src/common/web-utils/src/deepCopy.ts index c88f2556600..db0eb498343 100644 --- a/web/src/engine/common/web-utils/src/deepCopy.ts +++ b/web/src/common/web-utils/src/deepCopy.ts @@ -6,7 +6,7 @@ * Description Makes an actual copy (not a reference) of an object, copying simple members, * arrays and member objects but not functions, so use with care! */ -export default function deepCopy)>(p:T): T { +export function deepCopy)>(p:T): T { // typeof undefined == 'undefined', ![] == false, !{} == false if(typeof p != 'object' || !p) { return p; diff --git a/web/src/engine/common/web-utils/src/deviceSpec.ts b/web/src/common/web-utils/src/deviceSpec.ts similarity index 98% rename from web/src/engine/common/web-utils/src/deviceSpec.ts rename to web/src/common/web-utils/src/deviceSpec.ts index 3ab0352fc46..f993f94b82d 100644 --- a/web/src/engine/common/web-utils/src/deviceSpec.ts +++ b/web/src/common/web-utils/src/deviceSpec.ts @@ -80,5 +80,3 @@ export namespace DeviceSpec { export function physicalKeyDeviceAlias(device: DeviceSpec) { return new DeviceSpec(device.browser, DeviceSpec.FormFactor.Desktop, device.OS, false); } - -export default DeviceSpec; \ No newline at end of file diff --git a/web/src/engine/common/web-utils/src/globalObject.ts b/web/src/common/web-utils/src/globalObject.ts similarity index 95% rename from web/src/engine/common/web-utils/src/globalObject.ts rename to web/src/common/web-utils/src/globalObject.ts index b2686872169..c6c0af33e50 100644 --- a/web/src/engine/common/web-utils/src/globalObject.ts +++ b/web/src/common/web-utils/src/globalObject.ts @@ -4,7 +4,7 @@ * - In WebWorkers, returns `self`. * - In Node, returns `global`. */ -export default function getGlobalObject(): typeof globalThis { +export function globalObject(): typeof globalThis { // Evergreen browsers have started defining 'globalThis'. // Refer to https://devblogs.microsoft.com/typescript/announcing-typescript-3-4/#type-checking-for-globalthis // and its referenced polyfill. Said polyfill is very complex, so we opt for this far leaner variant. diff --git a/web/src/engine/common/web-utils/src/index.ts b/web/src/common/web-utils/src/index.ts similarity index 55% rename from web/src/engine/common/web-utils/src/index.ts rename to web/src/common/web-utils/src/index.ts index 30f48215900..f471946d713 100644 --- a/web/src/engine/common/web-utils/src/index.ts +++ b/web/src/common/web-utils/src/index.ts @@ -1,8 +1,8 @@ // References all utility includes from a single file, making import/export simple. -export { default as deepCopy } from "./deepCopy.js"; +export { deepCopy } from "./deepCopy.js"; -export { default as DeviceSpec, physicalKeyDeviceAlias } from "./deviceSpec.js"; +export { DeviceSpec, physicalKeyDeviceAlias } from "./deviceSpec.js"; /* // An example valid use, post-import: @@ -12,16 +12,18 @@ export { default as DeviceSpec, physicalKeyDeviceAlias } from "./deviceSpec.js"; true); */ -export { default as Version } from "./version.js"; +export { Version } from "./version.js"; -export { default as globalObject } from "./globalObject.js"; +export { globalObject } from "./globalObject.js"; export * as KMWString from './kmwstring.js'; -export { default as ManagedPromise } from "./managedPromise.js"; -export { default as TimeoutPromise, timedPromise } from "./timeoutPromise.js"; +export { ManagedPromise } from "./managedPromise.js"; +export { TimeoutPromise, timedPromise } from "./timeoutPromise.js"; -export { default as PriorityQueue, QueueComparator } from "./priority-queue.js" +export { PriorityQueue, QueueComparator } from "./priority-queue.js" + +export { isEmptyTransform } from './isEmptyTransform.js'; // // Uncomment the following line and run the bundled output to verify successful // // esbuild bundling of this submodule: diff --git a/web/src/common/web-utils/src/isEmptyTransform.ts b/web/src/common/web-utils/src/isEmptyTransform.ts new file mode 100644 index 00000000000..82832d1fdd6 --- /dev/null +++ b/web/src/common/web-utils/src/isEmptyTransform.ts @@ -0,0 +1,21 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + */ + +import { LexicalModelTypes } from '@keymanapp/common-types'; + +// Also relies on string-extensions provided by the web-utils package. + +/** + * Determines whether a lexical model transform is empty (has no effect). + * + * @param transform - The lexical model transform to check. + * @returns True if the transform is empty (null, or has no insertions or deletions), + * false otherwise. + */ +export function isEmptyTransform(transform: LexicalModelTypes.Transform) { + if (!transform) { + return true; + } + return transform.insert === '' && transform.deleteLeft === 0 && (transform.deleteRight ?? 0) === 0; +} diff --git a/web/src/engine/common/web-utils/src/kmwstring.ts b/web/src/common/web-utils/src/kmwstring.ts similarity index 100% rename from web/src/engine/common/web-utils/src/kmwstring.ts rename to web/src/common/web-utils/src/kmwstring.ts diff --git a/web/src/engine/common/web-utils/src/managedPromise.ts b/web/src/common/web-utils/src/managedPromise.ts similarity index 98% rename from web/src/engine/common/web-utils/src/managedPromise.ts rename to web/src/common/web-utils/src/managedPromise.ts index 52885319023..4319575709e 100644 --- a/web/src/engine/common/web-utils/src/managedPromise.ts +++ b/web/src/common/web-utils/src/managedPromise.ts @@ -1,7 +1,7 @@ type ResolveSignature = (value: Type | PromiseLike) => void; type RejectSignature = (reason?: any) => void; -export default class ManagedPromise { +export class ManagedPromise { /** * Calling this function will fulfill the Promise represented by this class. */ diff --git a/web/src/engine/common/web-utils/src/priority-queue.ts b/web/src/common/web-utils/src/priority-queue.ts similarity index 99% rename from web/src/engine/common/web-utils/src/priority-queue.ts rename to web/src/common/web-utils/src/priority-queue.ts index 66867f37ad5..2d75d62a928 100644 --- a/web/src/engine/common/web-utils/src/priority-queue.ts +++ b/web/src/common/web-utils/src/priority-queue.ts @@ -13,7 +13,7 @@ */ export type QueueComparator = (a: Type, b: Type) => number; -export default class PriorityQueue { +export class PriorityQueue { private comparator: QueueComparator; private heap: Type[]; diff --git a/web/src/engine/common/web-utils/src/tests/deepCopy.tests.js b/web/src/common/web-utils/src/tests/deepCopy.tests.js similarity index 97% rename from web/src/engine/common/web-utils/src/tests/deepCopy.tests.js rename to web/src/common/web-utils/src/tests/deepCopy.tests.js index 90e809dc116..5b2d8eb0ce4 100644 --- a/web/src/engine/common/web-utils/src/tests/deepCopy.tests.js +++ b/web/src/common/web-utils/src/tests/deepCopy.tests.js @@ -1,6 +1,6 @@ import { assert } from 'chai'; -import { deepCopy } from '@keymanapp/web-utils'; +import { deepCopy } from 'keyman/common/web-utils'; describe('deepCopy', function() { diff --git a/web/src/engine/common/web-utils/src/tests/managedPromise.tests.js b/web/src/common/web-utils/src/tests/managedPromise.tests.js similarity index 97% rename from web/src/engine/common/web-utils/src/tests/managedPromise.tests.js rename to web/src/common/web-utils/src/tests/managedPromise.tests.js index 6b7fe722059..2c2b0f5a569 100644 --- a/web/src/engine/common/web-utils/src/tests/managedPromise.tests.js +++ b/web/src/common/web-utils/src/tests/managedPromise.tests.js @@ -1,6 +1,6 @@ import { assert } from 'chai'; -import { ManagedPromise } from '@keymanapp/web-utils'; +import { ManagedPromise } from 'keyman/common/web-utils'; describe("ManagedPromise", () => { it(' resolution', async () => { diff --git a/web/src/engine/common/web-utils/src/tests/priorityQueue.tests.js b/web/src/common/web-utils/src/tests/priorityQueue.tests.js similarity index 98% rename from web/src/engine/common/web-utils/src/tests/priorityQueue.tests.js rename to web/src/common/web-utils/src/tests/priorityQueue.tests.js index 0aa4c50b964..2394718aec5 100644 --- a/web/src/engine/common/web-utils/src/tests/priorityQueue.tests.js +++ b/web/src/common/web-utils/src/tests/priorityQueue.tests.js @@ -3,7 +3,7 @@ */ import { assert } from 'chai'; -import { PriorityQueue } from '@keymanapp/web-utils'; +import { PriorityQueue } from 'keyman/common/web-utils'; describe('Priority queue', function() { it('can act as a min-heap', function () { diff --git a/web/src/engine/common/web-utils/src/tests/stringHandling.js b/web/src/common/web-utils/src/tests/stringHandling.js similarity index 99% rename from web/src/engine/common/web-utils/src/tests/stringHandling.js rename to web/src/common/web-utils/src/tests/stringHandling.js index e22ef633d18..be93a45c8b6 100644 --- a/web/src/engine/common/web-utils/src/tests/stringHandling.js +++ b/web/src/common/web-utils/src/tests/stringHandling.js @@ -1,6 +1,6 @@ import { assert } from 'chai'; // Trigger the String-extending methods. -import { KMWString } from '@keymanapp/web-utils'; +import { KMWString } from 'keyman/common/web-utils'; describe('Unicode string handling', () => { describe('disabled: BMP-mode, BMP-only strings', () => { diff --git a/web/src/engine/common/web-utils/src/tests/timeoutPromise.tests.js b/web/src/common/web-utils/src/tests/timeoutPromise.tests.js similarity index 97% rename from web/src/engine/common/web-utils/src/tests/timeoutPromise.tests.js rename to web/src/common/web-utils/src/tests/timeoutPromise.tests.js index 337cf286e2d..e8a14afbeca 100644 --- a/web/src/engine/common/web-utils/src/tests/timeoutPromise.tests.js +++ b/web/src/common/web-utils/src/tests/timeoutPromise.tests.js @@ -1,6 +1,6 @@ import { assert } from 'chai'; -import { TimeoutPromise, timedPromise } from '@keymanapp/web-utils'; +import { TimeoutPromise, timedPromise } from 'keyman/common/web-utils'; // Set this long enough to allow a bit of delay from OS context-switching (often on the // order of ~16ms for some OSes) to occur multiple times without breaking these tests. diff --git a/web/src/engine/common/web-utils/src/tests/versions.tests.js b/web/src/common/web-utils/src/tests/versions.tests.js similarity index 96% rename from web/src/engine/common/web-utils/src/tests/versions.tests.js rename to web/src/common/web-utils/src/tests/versions.tests.js index 36ed51cbacd..aa4c67c4544 100644 --- a/web/src/engine/common/web-utils/src/tests/versions.tests.js +++ b/web/src/common/web-utils/src/tests/versions.tests.js @@ -1,6 +1,6 @@ import { assert } from 'chai'; -import { Version } from '@keymanapp/web-utils'; +import { Version } from 'keyman/common/web-utils'; describe('Version Logic', function() { it('Should provide a default, fallback value when nothing is specified', function() { diff --git a/web/src/engine/common/web-utils/src/timeoutPromise.ts b/web/src/common/web-utils/src/timeoutPromise.ts similarity index 94% rename from web/src/engine/common/web-utils/src/timeoutPromise.ts rename to web/src/common/web-utils/src/timeoutPromise.ts index 4b6fb3a7d61..0f48d096717 100644 --- a/web/src/engine/common/web-utils/src/timeoutPromise.ts +++ b/web/src/common/web-utils/src/timeoutPromise.ts @@ -1,4 +1,4 @@ -import ManagedPromise from "./managedPromise.js"; +import { ManagedPromise } from "./managedPromise.js"; /** * This class represents a cancelable timeout, wrapped in Promise form. @@ -7,7 +7,7 @@ import ManagedPromise from "./managedPromise.js"; * `reject` is called earlier. Call `.resolve(false)` for early cancellation * or `.resolve(true)` to cancel the timer while resolving the Promise early. */ -export default class TimeoutPromise extends ManagedPromise { +export class TimeoutPromise extends ManagedPromise { private timerHandle: number | NodeJS.Timeout; constructor(timeoutInMillis: number) { // Helps marshal the internal timer handle to its member field despite being diff --git a/web/src/engine/common/web-utils/src/version.ts b/web/src/common/web-utils/src/version.ts similarity index 99% rename from web/src/engine/common/web-utils/src/version.ts rename to web/src/common/web-utils/src/version.ts index 145b3361064..61b94147b8d 100644 --- a/web/src/engine/common/web-utils/src/version.ts +++ b/web/src/common/web-utils/src/version.ts @@ -1,7 +1,7 @@ import KEYMAN_VERSION from "@keymanapp/keyman-version"; // Dotted-decimal version -export default class Version { +export class Version { public static readonly CURRENT = new Version(KEYMAN_VERSION.VERSION_RELEASE); // Represents a default version value for keyboards compiled before this was compiled into keyboards. diff --git a/web/src/engine/common/web-utils/tsconfig.json b/web/src/common/web-utils/tsconfig.json similarity index 51% rename from web/src/engine/common/web-utils/tsconfig.json rename to web/src/common/web-utils/tsconfig.json index 1747a622743..0e866bd4cc7 100644 --- a/web/src/engine/common/web-utils/tsconfig.json +++ b/web/src/common/web-utils/tsconfig.json @@ -1,13 +1,12 @@ { "extends": "../../../../tsconfig.base.json", "compilerOptions": { - "tsBuildInfoFile": "./build/obj/tsconfig.tsbuildinfo", - "baseUrl": "./", - "outDir": "./build/obj/", + "tsBuildInfoFile": "../../../build/common/web-utils/obj/tsconfig.tsbuildinfo", + "outDir": "../../../build/common/web-utils/obj/", "rootDir": "./src" }, "references": [ - { "path": "../../../../../common/web/keyman-version" }, + { "path": "../../../../common/web/keyman-version" }, ], "include": [ "src/*.ts" diff --git a/web/src/engine/events/.c8rc.json b/web/src/engine/.c8rc.json similarity index 69% rename from web/src/engine/events/.c8rc.json rename to web/src/engine/.c8rc.json index 65dd2858d45..dd274be9404 100644 --- a/web/src/engine/events/.c8rc.json +++ b/web/src/engine/.c8rc.json @@ -3,7 +3,7 @@ "clean": true, "exclude-after-remap": true, "reporter": ["text", "text-summary"], - "reports-dir": "../../../build/coverage/raw/engine/events", + "reports-dir": "../../build/coverage/raw/engine/", "src": [ "src/" ] diff --git a/web/src/engine/attachment/.c8rc.json b/web/src/engine/attachment/.c8rc.json deleted file mode 100644 index eea63036d20..00000000000 --- a/web/src/engine/attachment/.c8rc.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "check-coverage": false, - "clean": true, - "exclude-after-remap": true, - "reporter": ["text", "text-summary"], - "reports-dir": "../../../build/coverage/raw/engine/attachment", - "src": [ - "src/" - ] -} \ No newline at end of file diff --git a/web/src/engine/attachment/build.sh b/web/src/engine/attachment/build.sh deleted file mode 100755 index 0c37fb62c1c..00000000000 --- a/web/src/engine/attachment/build.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/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-full.inc.sh" -## END STANDARD BUILD SCRIPT INCLUDE - -# Imports common Web build-script definitions & functions -SUBPROJECT_NAME=engine/attachment -. "$KEYMAN_ROOT/resources/build/utils.inc.sh" -. "$KEYMAN_ROOT/resources/build/node.inc.sh" -. "$KEYMAN_ROOT/web/common.inc.sh" - -# ################################ Main script ################################ - -builder_describe "Builds the Keyman Engine for Web (KMW) attachment engine." \ - "@/web/src/engine/dom-utils" \ - "@/web/src/engine/element-wrappers" \ - "clean" \ - "configure" \ - "build" \ - "test" - -# Possible TODO? -# "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ - -builder_describe_outputs \ - configure /node_modules \ - build /web/build/$SUBPROJECT_NAME/lib/index.mjs - -builder_parse "$@" - -#### Build action definitions #### - -do_build () { - compile $SUBPROJECT_NAME - - node "${LIB_BUNDLER}" "${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 node_select_version_and_npm_ci -builder_run_action clean rm -rf "$KEYMAN_ROOT/web/build/$SUBPROJECT_NAME" -builder_run_action build do_build -builder_run_action test test-headless-typescript "${SUBPROJECT_NAME}" diff --git a/web/src/engine/attachment/src/attachmentInfo.ts b/web/src/engine/attachment/src/attachmentInfo.ts deleted file mode 100644 index 02a81114028..00000000000 --- a/web/src/engine/attachment/src/attachmentInfo.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { OutputTarget } from 'keyman/engine/element-wrappers'; - -export class AttachmentInfo { - /** - * Provides the core interface between the DOM and the actual keyboard. - */ - interface: OutputTarget; - - /** - * Tracks the control's independent keyboard selection, when applicable. - */ - keyboard: string; - - /** - * Tracks the language code corresponding to the `keyboard` field. - */ - languageCode: string; - - /** - * Tracks the inputmode originally set by the webpage. - */ - inputMode?: string; - - constructor(eleInterface: OutputTarget, kbd: string, touch?: boolean) { - this.interface = eleInterface; - this.keyboard = kbd; - } -} \ No newline at end of file diff --git a/web/src/engine/attachment/src/index.ts b/web/src/engine/attachment/src/index.ts deleted file mode 100644 index 8e75e7645f2..00000000000 --- a/web/src/engine/attachment/src/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -export { AttachmentInfo } from './attachmentInfo.js'; - -/* - * Note: for `instanceof` the attachment objects returned by the next module's - * to match that of the actual objects within the browser when bundled, the - * **same bundle** must contain reference points for those classes' definitions. - */ -export { eventOutputTarget, outputTargetForElement } from './outputTargetForElement.js'; -export { PageContextAttachment, PageAttachmentOptions } from './pageContextAttachment.js'; - -/* - * Following from the prior "Note:", we republish `engine/element-wrappers` here - - * this matters quite strongly for certain unit tests. - */ -export * from 'keyman/engine/element-wrappers'; \ No newline at end of file diff --git a/web/src/engine/attachment/tsconfig.json b/web/src/engine/attachment/tsconfig.json deleted file mode 100644 index 3ce6a07308f..00000000000 --- a/web/src/engine/attachment/tsconfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "extends": "../../tsconfig.dom.json", - - "compilerOptions": { - "baseUrl": "./", - "outDir": "../../../build/engine/attachment/obj/", - "tsBuildInfoFile": "../../../build/engine/attachment/obj/tsconfig.tsbuildinfo", - "rootDir": "./src" - }, - - "include": [ "src/**/*.ts" ], - - "references": [ - { "path": "../dom-utils" }, - { "path": "../element-wrappers" } - ] -} diff --git a/web/src/engine/build.sh b/web/src/engine/build.sh new file mode 100755 index 00000000000..cdf39ca569d --- /dev/null +++ b/web/src/engine/build.sh @@ -0,0 +1,99 @@ +#!/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-full.inc.sh" +## END STANDARD BUILD SCRIPT INCLUDE + +# Imports common Web build-script definitions & functions + +. "$KEYMAN_ROOT/resources/build/utils.inc.sh" +. "$KEYMAN_ROOT/resources/build/node.inc.sh" +. "$KEYMAN_ROOT/web/common.inc.sh" + +# ################################ Main script ################################ + +# dependency on kmc required for tests +builder_describe "Builds Keyman Engine for Web (KMW)" \ + "@/core:wasm build" \ + "@/common/tools/es-bundling build" \ + "@/developer/src/kmc build" \ + "@/web/src/common/web-utils build" \ + "clean" \ + "configure" \ + "build" \ + "test" \ + ":predictive-text" + +# Possible TODO? +# "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ + +builder_describe_outputs \ + configure /node_modules \ + build /web/build/engine/lib/index.mjs + +builder_parse "$@" + +#### Build action definitions #### + +copy_deps() { + mkdir -p "${KEYMAN_ROOT}/web/src/engine/src/core-adapter/import/core/" + # we don't need this file for release builds, but it's nice to have + # for reference and auto-completion + cp "${KEYMAN_ROOT}/core/build/wasm/${BUILDER_CONFIGURATION}/src/keymancore.d.ts" "${KEYMAN_ROOT}/web/src/engine/src/core-adapter/import/core/" + + mkdir -p "${KEYMAN_ROOT}/web/build/engine/obj/core-adapter/import/core/" + cp "${KEYMAN_ROOT}/core/build/wasm/${BUILDER_CONFIGURATION}/src/keymancore.d.ts" "${KEYMAN_ROOT}/web/build/engine/obj/core-adapter/import/core/" + cp "${KEYMAN_ROOT}/core/build/wasm/${BUILDER_CONFIGURATION}/src/"km-core{.js,.wasm} "${KEYMAN_ROOT}/web/build/engine/obj/core-adapter/import/core/" + cp "${KEYMAN_ROOT}/core/build/wasm/${BUILDER_CONFIGURATION}/src/"km-core-node{.mjs,.wasm} "${KEYMAN_ROOT}/web/build/engine/obj/core-adapter/import/core/" + + cp "${KEYMAN_ROOT}/common/resources/fonts/keymanweb-osk.ttf" "${KEYMAN_ROOT}/web/src/resources/osk/" +} + +do_build () { + # eslint . + + copy_deps + + tsc -b . + + # So... tsc does declaration-bundling on its own pretty well, at least for local development. + tsc --emitDeclarationOnly --outFile "${KEYMAN_ROOT}/web/build/engine/lib/index.d.ts" -p "." + + node_es_bundle "${KEYMAN_ROOT}/web/build/engine/obj/index.js" \ + --out "${KEYMAN_ROOT}/web/build/engine/lib/index.mjs" \ + --format esm + + # TODO-web-core: should this be in test/? + echo "Validating gesture model and set references" + node src/osk/validate-gesture-specs.js +} + +run_tests() { + # Run javascript tests + # + # Trying to run languageProcessor.tests.js with c8 coverage fails with: + # "TypeError [ERR_INVALID_URL_SCHEME]: The URL must be of scheme file" + # when c8 tries to create a report from the raw coverage data. The reason + # is a URL starting with `data:text/javascript` coming from + # `web/src/engine/predictive-text/worker-main/src/node/mappedWorker.ts`. + # + # So we first run all javascript tests except languageProcessor.tests.js + # with coverage, and then in a second step run languageProcessor.tests.js + # without coverage. + test-headless engine "" "--exclude" "**/languageProcessor.tests.js" + SKIP_C8=1 test-headless engine/main/headless/languageProcessor.tests.js + + # Run typescript tests + test-headless-typescript engine +} + +builder_run_action clean rm -rf "${KEYMAN_ROOT}/web/build/engine" +builder_run_child_actions clean +builder_run_action configure node_select_version_and_npm_ci +builder_run_child_actions configure +builder_run_child_actions build +builder_run_action build do_build +builder_run_action test run_tests +builder_run_child_actions test \ No newline at end of file diff --git a/web/src/engine/common/web-utils/.gitignore b/web/src/engine/common/web-utils/.gitignore deleted file mode 100644 index 56baafc8225..00000000000 --- a/web/src/engine/common/web-utils/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -# Build products -src/environment.inc.ts - -# Legacy build folders. -output/ -build/ -embedded/ - -# Current build output folder (matches standard node publish location). -dist/ - -# Other local files. -node_modules/ -source/environment.inc.ts -**/.idea/**/*.xml -**/*.iml -**/*.kpj.user \ No newline at end of file diff --git a/web/src/engine/common/web-utils/package.json b/web/src/engine/common/web-utils/package.json deleted file mode 100644 index 557878d43e4..00000000000 --- a/web/src/engine/common/web-utils/package.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "@keymanapp/web-utils", - "description": "Common utility functions used throughout other Keyman packages", - "main": "./build/obj/index.js", - "exports": { - ".": { - "es6-bundling": "./src/index.ts", - "types": "./build/obj/index.d.ts", - "import": "./build/obj/index.js" - } - }, - "scripts": { - "build": "gosh ./build.sh", - "clean": "gosh ./build.sh clean" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/keymanapp/keyman.git" - }, - "author": "SIL International", - "license": "MIT", - "bugs": { - "url": "https://github.com/keymanapp/keyman/issues" - }, - "homepage": "https://github.com/keymanapp/keyman#readme", - "devDependencies": { - "@keymanapp/keyman-version": "*", - "@keymanapp/resources-gosh": "*", - "c8": "^7.12.0", - "typescript": "^5.4.5" - }, - "type": "module", - "paths": { - "@keymanapp/keyman-version": "*" - } -} diff --git a/web/src/engine/dom-utils/build.sh b/web/src/engine/dom-utils/build.sh deleted file mode 100755 index df6180e2ed7..00000000000 --- a/web/src/engine/dom-utils/build.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/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-full.inc.sh" -## END STANDARD BUILD SCRIPT INCLUDE - -. "$KEYMAN_ROOT/resources/build/utils.inc.sh" -. "$KEYMAN_ROOT/resources/build/node.inc.sh" - -# Imports common Web build-script definitions & functions -SUBPROJECT_NAME=engine/dom-utils -. "$KEYMAN_ROOT/web/common.inc.sh" - -# ################################ Main script ################################ - -builder_describe "Builds DOM-utility modules used by the Keyman Engine for Web (KMW)." \ - "@/web/src/engine/common/web-utils" \ - "@/web/src/engine/keyboard" \ - "clean" \ - "configure" \ - "build" \ - "test" - -# Possible TODO? -# "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ - -builder_describe_outputs \ - configure /node_modules \ - build /web/build/$SUBPROJECT_NAME/obj/index.js - -builder_parse "$@" - -#### Build action definitions #### - -builder_run_action configure node_select_version_and_npm_ci -builder_run_action clean rm -rf "$KEYMAN_ROOT/web/build/$SUBPROJECT_NAME" -builder_run_action build compile $SUBPROJECT_NAME - -# No headless tests for this child project. Currently, DOM-based unit & -# integrated tests are run solely by the top-level $KEYMAN_ROOT/web project. \ No newline at end of file diff --git a/web/src/engine/dom-utils/src/index.ts b/web/src/engine/dom-utils/src/index.ts deleted file mode 100644 index ad667ea341e..00000000000 --- a/web/src/engine/dom-utils/src/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { arrayFromNodeList } from './arrayFromNodeList.js'; -export { default as createUnselectableElement } from './createUnselectableElement.js'; -export { createStyleSheet, StylesheetManager } from './stylesheets.js'; -export { default as landscapeView } from './landscapeView.js'; -export { default as CookieSerializer } from './cookieSerializer.js'; -export { getAbsoluteX, getAbsoluteY } from './getAbsolute.js'; diff --git a/web/src/engine/dom-utils/tsconfig.json b/web/src/engine/dom-utils/tsconfig.json deleted file mode 100644 index aab3cabf873..00000000000 --- a/web/src/engine/dom-utils/tsconfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "extends": "../../tsconfig.dom.json", - - "compilerOptions": { - "baseUrl": "./", - "outDir": "../../../build/engine/dom-utils/obj/", - "tsBuildInfoFile": "../../../build/engine/dom-utils/obj/tsconfig.tsbuildinfo", - "rootDir": "./src" - }, - - "include": [ "src/**/*.ts" ], - - "references": [ - { "path": "../keyboard" }, - { "path": "../common/web-utils" } - ] -} diff --git a/web/src/engine/element-wrappers/build.sh b/web/src/engine/element-wrappers/build.sh deleted file mode 100755 index 18d7f2c0edc..00000000000 --- a/web/src/engine/element-wrappers/build.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/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-full.inc.sh" -## END STANDARD BUILD SCRIPT INCLUDE - -SUBPROJECT_NAME=engine/element-wrappers -. "$KEYMAN_ROOT/web/common.inc.sh" -. "$KEYMAN_ROOT/resources/build/utils.inc.sh" -. "$KEYMAN_ROOT/resources/build/node.inc.sh" - -# ################################ Main script ################################ - -builder_describe "Builds DOM-based OutputTarget subclasses used by the Keyman Engine for Web (KMW)." \ - "@/web/src/engine/js-processor" \ - "clean" \ - "configure" \ - "build" \ - "test" - -# Possible TODO? -# "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ - -builder_describe_outputs \ - configure /node_modules \ - build /web/build/$SUBPROJECT_NAME/lib/index.mjs - -builder_parse "$@" - -#### Build action definitions #### - -do_build () { - compile $SUBPROJECT_NAME - - node "${LIB_BUNDLER}" "${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 node_select_version_and_npm_ci -builder_run_action clean rm -rf "$KEYMAN_ROOT/web/build/$SUBPROJECT_NAME" -builder_run_action build do_build - -# No headless tests for this child project. Currently, DOM-based unit & -# integrated tests are run solely by the top-level $KEYMAN_ROOT/web project. \ No newline at end of file diff --git a/web/src/engine/element-wrappers/readme.md b/web/src/engine/element-wrappers/readme.md deleted file mode 100644 index 2a7685edbcb..00000000000 --- a/web/src/engine/element-wrappers/readme.md +++ /dev/null @@ -1,4 +0,0 @@ -## 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` submodule. \ No newline at end of file diff --git a/web/src/engine/element-wrappers/src/index.ts b/web/src/engine/element-wrappers/src/index.ts deleted file mode 100644 index 06971bdeff9..00000000000 --- a/web/src/engine/element-wrappers/src/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export { default as wrapElement } from './wrapElement.js'; -export { default as ContentEditable } from './contentEditable.js'; -export { default as DesignIFrame } from './designIFrame.js'; -export { default as Input } from './input.js'; -export { default as OutputTarget } from './outputTarget.js'; -export { default as TextArea } from './textarea.js'; -export { nestedInstanceOf } from './utils.js'; \ No newline at end of file diff --git a/web/src/engine/element-wrappers/src/wrapElement.ts b/web/src/engine/element-wrappers/src/wrapElement.ts deleted file mode 100644 index 91d482e16e1..00000000000 --- a/web/src/engine/element-wrappers/src/wrapElement.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type OutputTarget from './outputTarget.js'; -import Input from './input.js'; -import TextArea from './textarea.js'; -import DesignIFrame from './designIFrame.js'; -import ContentEditable from './contentEditable.js'; -import { nestedInstanceOf } from './utils.js'; - -export default function wrapElement(e: HTMLElement): OutputTarget { - // Complex type scoping is implemented here so that kmwutils.ts is not a dependency for test compilations. - - if(nestedInstanceOf(e, "HTMLInputElement")) { - return new Input( e); - } else if(nestedInstanceOf(e, "HTMLTextAreaElement")) { - return new TextArea( e); - } else if(nestedInstanceOf(e, "HTMLIFrameElement")) { - const iframe = e; - - if(iframe.contentWindow && iframe.contentWindow.document && iframe.contentWindow.document.designMode == "on") { - return new DesignIFrame(iframe); - } else if (e.isContentEditable) { - // Do content-editable