diff --git a/.github/workflows/core-arm64-windows-test.yml b/.github/workflows/core-arm64-windows-test.yml index 0eb4e8f8f6..76d273de22 100644 --- a/.github/workflows/core-arm64-windows-test.yml +++ b/.github/workflows/core-arm64-windows-test.yml @@ -119,7 +119,7 @@ jobs: - name: Install meson shell: bash run: | - pip3 install --user meson==1.10.1 + pip3 install --user meson==1.11.0 - name: Run test shell: bash diff --git a/.github/workflows/deb-packaging.yml b/.github/workflows/deb-packaging.yml index 6e7fe54cb3..9a990634b2 100644 --- a/.github/workflows/deb-packaging.yml +++ b/.github/workflows/deb-packaging.yml @@ -29,6 +29,7 @@ env: COLOR_GREEN: "\e[32m" GH_TOKEN: ${{ github.token }} STATUS_CONTEXT: 'Ubuntu Packaging' + STATUS_CONTEXT_SOURCE_VERIFICATION: 'Linux source verification' DEBFULLNAME: 'Keyman GHA packager' DEBEMAIL: 'support@keyman.com' _builder_timings: false @@ -403,3 +404,112 @@ jobs: -f target_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" \ -f description="$MSG" \ -f context="$STATUS_CONTEXT" + + #--------------------------------------------------------------------------------------------- + source_verification: + name: Verify source tarball and Linux source package + if: github.repository == 'keymanapp/keyman' || github.event.client_payload.force + needs: sourcepackage + runs-on: ubuntu-latest + outputs: + KEYMAN_VERSION: ${{ needs.sourcepackage.outputs.KEYMAN_VERSION }} + HAS_VERIFY_SOURCE: ${{ steps.check_requirements.outputs.HAS_VERIFY_SOURCE }} + + steps: + - name: Set pending status on PR builds + id: set_status + if: github.event.client_payload.isTestBuild == 'true' + shell: bash + run: | + gh api \ + --method POST \ + -H "Accept: application/vnd.github+json" \ + /repos/$GITHUB_REPOSITORY/statuses/${{ github.event.client_payload.buildSha }} \ + -f state='pending' \ + -f target_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" \ + -f description='Linux source verification started' \ + -f context="$STATUS_CONTEXT_SOURCE_VERIFICATION" + + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: '${{ github.event.client_payload.buildSha }}' + fetch-depth: 0 + clean: false + path: ${{ github.workspace }}/keyman/ + + # TODO: Remove after release of Keyman 19 + - name: Check requirements + id: check_requirements + shell: bash + run: | + if [[ -f "${GITHUB_WORKSPACE}/keyman/linux/scripts/verify_source.sh" ]]; then + echo "HAS_VERIFY_SOURCE=true" >> $GITHUB_OUTPUT + fi + + - name: Install devscripts + if: steps.check_requirements.outputs.HAS_VERIFY_SOURCE == 'true' + uses: ./keyman/.github/actions/apt-install + with: + packages: devscripts equivs + + - name: Install dependencies + if: steps.check_requirements.outputs.HAS_VERIFY_SOURCE == 'true' + run: | + cd ${{ github.workspace }}/keyman/linux + ./scripts/deb-packaging.sh --gha dependencies + + - name: Verify source tarball + if: steps.check_requirements.outputs.HAS_VERIFY_SOURCE == 'true' + shell: bash + run: | + cd ${{ github.workspace }}/keyman/linux + ./scripts/verify_source.sh --source-only --target-dir "${{ github.workspace }}/keyman-${{ needs.sourcepackage.outputs.KEYMAN_VERSION }}" + + - name: Verify Ubuntu source package + if: steps.check_requirements.outputs.HAS_VERIFY_SOURCE == 'true' + shell: bash + run: | + cd ${{ github.workspace }}/keyman/linux + ./scripts/verify_source.sh --no-create-tarball --launchpad-only --target-dir "${{ github.workspace }}/keyman-${{ needs.sourcepackage.outputs.KEYMAN_VERSION }}" + + set_status_source_verification: + name: Set result status of source verification on PR builds + needs: [source_verification] + runs-on: ubuntu-latest + if: ${{ always() && github.event.client_payload.isTestBuild == 'true' && (github.repository == 'keymanapp/keyman' || github.event.client_payload.force) }} + steps: + - name: Requirements not met + if: needs.source_verification.result == 'success' && needs.source_verification.outputs.HAS_VERIFY_SOURCE != 'true' + run: | + echo "RESULT=success" >> $GITHUB_ENV + echo "MSG=Linux source verification requirements not met" >> $GITHUB_ENV + + - name: Set success + if: needs.source_verification.result == 'success' && needs.source_verification.outputs.HAS_VERIFY_SOURCE == 'true' + run: | + echo "RESULT=success" >> $GITHUB_ENV + echo "MSG=Linux source verification succeeded" >> $GITHUB_ENV + + - name: Set cancelled + if: needs.source_verification.result == 'cancelled' + run: | + echo "RESULT=error" >> $GITHUB_ENV + echo "MSG=Linux source verification cancelled" >> $GITHUB_ENV + + - name: Set failure + if: needs.source_verification.result == 'failure' + run: | + echo "RESULT=failure" >> $GITHUB_ENV + echo "MSG=Linux source verification failed" >> $GITHUB_ENV + + - name: Set final status + run: | + gh api \ + --method POST \ + -H "Accept: application/vnd.github+json" \ + /repos/$GITHUB_REPOSITORY/statuses/${{ github.event.client_payload.buildSha }} \ + -f state="$RESULT" \ + -f target_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" \ + -f description="$MSG" \ + -f context="$STATUS_CONTEXT_SOURCE_VERIFICATION" diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index ee7fe7d03d..9eb25a49e7 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -8,12 +8,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Update labels based on changed files - uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1 + uses: actions/labeler@f27b608878404679385c85cfa523b85ccb86e213 # v6.1.0 with: repo-token: "${{ secrets.GITHUB_TOKEN }}" - name: Update labels based on PR title id: labeler - uses: fuxingloh/multi-labeler@f5bd7323b53b0833c1e4ed8d7b797ae995ef75b4 # v2.0.1 + uses: fuxingloh/multi-labeler@bcd50af464202999e57f556b4aefcf05a34abf85 # v5.0.0 with: github-token: ${{secrets.GITHUB_TOKEN}} config-path: .github/multi-labeler.yml diff --git a/.github/workflows/pr-build-status.yml b/.github/workflows/pr-build-status.yml index bd5fe2f46a..51571b33ef 100644 --- a/.github/workflows/pr-build-status.yml +++ b/.github/workflows/pr-build-status.yml @@ -80,6 +80,10 @@ jobs: summary += addStatus(o, 'check', status.context, status.state); } else if(status.context == 'Ubuntu Packaging') { summary += addStatus(o, 'build', status.context, status.state); + } else if(status.context == 'Linux source verification') { + // Ignore Linux source verification -- we won't block automerge + // for this at this point + summary += addLog(`Skipping ${status.context}`); } else if(status.context == 'npm pack/publish') { summary += addStatus(o, 'build', status.context, status.state); } else if(status.context == 'Keyman Core - ARM64 test') { diff --git a/HISTORY.md b/HISTORY.md index 7909ef0351..f2d3cab56b 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,115 @@ # Keyman Version History +## 19.0.247 alpha 2026-06-16 + +* chore: update multi-labeler to 5.0.0 (#16100) + +## 19.0.246 alpha 2026-06-15 + +* feat(developer): run project validation from IDE (#16076) +* fix(core): use meson subsystem and needs_exe_wrapper for cross builds on Windows (#16088) +* docs(windows): add context documentation for additional Advanced options (#16089) + +## 19.0.245 alpha 2026-06-10 + +* chore(web): hide KMX keyboard test page (#16083) +* docs(web): remove unnecessary mentioning of Keyman 17 from docs (#16085) +* chore(web): remove outdated `*_load.js` files (#16086) +* fix(web): fix `KeyboardStub.validateForCustomKeyboard` (#16067) + +## 19.0.244 alpha 2026-06-09 + +* refactor(web): extract function, rename variables (#16063) +* refactor(web): reformatting of files (#16066) +* chore(web): improve the KeymanWeb integration documentation (#16064) +* chore(web): more improvements to documentation (#16070) + +## 19.0.243 alpha 2026-06-08 + +* fix(developer): reduce km_core_keyboard_attrs size to 12 (#16075) +* chore(deps): bump minimatch in /core/tests/unit/wasm (#16045) +* chore(deps): bump glob from 10.4.5 to 10.5.0 in /core/tests/unit/wasm (#16046) +* chore(deps-dev): bump js-yaml from 4.1.0 to 4.2.0 in /core/tests/unit/wasm (#16047) +* chore(deps-dev): bump picomatch from 2.3.1 to 2.3.2 in /core/tests/unit/wasm (#16048) +* chore(deps): bump qs and express (#16009) + +## 19.0.242 alpha 2026-06-03 + +* fix(web): fix displaying of keyboard menu (#16061) + +## 19.0.241 alpha 2026-06-02 + +* chore(web): web-core preflight - strip core references (#16040) +* docs: add note on how to use composer on dockerized websites (#16029) +* fix(web): fix race displaying active keyboard in menu (#16042) + +## 19.0.240 alpha 2026-05-28 + +* chore(web): add filename to link text of manual web tests (#16019) +* docs(web): reformat and small fixes (#16021) + +## 19.0.239 alpha 2026-05-27 + +* chore(web): remove obsolete file (#16013) + +## 19.0.238 alpha 2026-05-26 + +* maint(linux): Don't block merge if source verification check fails (#16010) +* maint(linux): fix Linux source tarball (#16011) + +## 19.0.237 alpha 2026-05-22 + +* fix(windows): Ensure default locale always appears in list of locales (#15984) +* chore(ios): update First Voices distribution certificate (#15993) + +## 19.0.236 alpha 2026-05-21 + +* docs(developer): write up basic internal docs on kmc modules (#15982) +* chore(common): move common cpp files and remove unused files (#15981) +* docs(developer): update links to lexical model distribution (#15974) + +## 19.0.235 alpha 2026-05-20 + +* fix(linux): fix source tarball verification (#15975) +* fix(windows): add apply actions call to core_event (#15867) +* chore(ios): add extra logging to xcodebuild (#15964) +* maint(linux): skip source verification if script is missing (#15979) + +## 19.0.234 alpha 2026-05-19 + +* chore(deps): bump brace-expansion from 5.0.5 to 5.0.6 in /developer/src/server/src/win32/trayicon/addon-src (#15969) +* chore(deps): bump ws from 8.18.1 to 8.20.1 (#15971) +* chore: move to .localhost for local server URLs (#15963) + +## 19.0.233 alpha 2026-05-18 + +* chore(deps): bump path-to-regexp and express (#15902) +* chore(deps): bump ip-address and socks (#15918) +* chore(deps): bump fast-uri from 3.1.0 to 3.1.2 (#15932) +* chore(deps): bump fast-xml-parser from 5.3.8 to 5.7.1 (#15868) +* chore(deps): bump ip-address from 10.1.0 to 10.2.0 in /developer/src/server/src/win32/trayicon/addon-src (#15921) +* fix(linux): add dependency on `procps` (#15967) +* maint(linux): fix source tarball verification (#15966) + +## 19.0.232 alpha 2026-05-15 + +* docs: clarify Build-bot test build trigger (#15958) + +## 19.0.231 alpha 2026-05-13 + +* chore(deps): bump lodash and @microsoft/api-extractor (#15829) +* chore(deps-dev): bump basic-ftp from 5.0.5 to 5.2.2 (#15848) +* chore(deps): bump uuid and @actions/core (#15866) + +## 19.0.230 alpha 2026-05-11 + +* chore(linux): add verification for source tarball and source package (#15916) +* chore(linux): make `debian.sh` a builder script (#15924) +* chore(linux): remove `--project` parameter (#15925) +* maint(core): exclude `.configured` files from source tarball (#15928) +* maint(core): retry upload to launchpad on network failures (#15930) +* maint(linux): fix uploading to ppa (#15944) + ## 19.0.229 alpha 2026-05-08 * maint(linux): fix source tarball used for packaging (#15926) diff --git a/VERSION.md b/VERSION.md index ad55e04523..a0b5f4d5f2 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -19.0.230 \ No newline at end of file +19.0.248 \ No newline at end of file diff --git a/android/KMEA/app/src/main/assets/android-host.js b/android/KMEA/app/src/main/assets/android-host.js index ad440d493a..48672c0572 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 f4d7705815..28d9877285 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/windows/cpp/src/vkeys.cpp b/common/cpp/vkeys.cpp similarity index 99% rename from common/windows/cpp/src/vkeys.cpp rename to common/cpp/vkeys.cpp index 5bf249b3dd..e1de19b5e1 100644 --- a/common/windows/cpp/src/vkeys.cpp +++ b/common/cpp/vkeys.cpp @@ -16,9 +16,12 @@ History: 22 Mar 2010 - mcdurdin - Compiler fixup - tidy up */ -#include "pch.h" #include "../include/vkeys.h" +#ifndef USE_CHAR16_T +#define lpuch(x) x +#endif + const VKEY_CHAR* VKeyNames[256] = { // Key Codes lpuch("K_?00"), // &H0 diff --git a/common/windows/cpp/include/keymanversion.h b/common/include/keymanversion.h similarity index 94% rename from common/windows/cpp/include/keymanversion.h rename to common/include/keymanversion.h index e9d39defba..bf7ae35e84 100644 --- a/common/windows/cpp/include/keymanversion.h +++ b/common/include/keymanversion.h @@ -1,7 +1,7 @@ #ifndef _KEYMANVERSION_H #define _KEYMANVERSION_H -#include "../../../include/keymanversion_build.h" +#include "./keymanversion_build.h" // We should not need to add to these hard-coded version numbers for future versions, unless // we have a back-compat need to refer to a specific version. diff --git a/common/include/km_types.h b/common/include/km_types.h index 05bc0aa432..cd0ca7f8d0 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/windows/cpp/include/vkeys.h b/common/include/vkeys.h similarity index 79% rename from common/windows/cpp/include/vkeys.h rename to common/include/vkeys.h index 6aa71cc497..494f1d1b7f 100644 --- a/common/windows/cpp/include/vkeys.h +++ b/common/include/vkeys.h @@ -4,8 +4,7 @@ #include #define VKEY_CHAR KMX_UCHAR #else -#define VKEY_CHAR WCHAR -#define lpuch(x) L ## x +#define VKEY_CHAR char #endif extern const VKEY_CHAR* VKeyNames[256]; diff --git a/common/test/keyboards/baseline/README.md b/common/test/keyboards/baseline/README.md index cede107085..28106b6f1d 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 3ce7e9b83c..5e7c461aac 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 1428b5e0c4..3a1e8d9f1e 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 0000000000..076ec597c4 --- /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 ecae49acde..57321e6d63 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 0000000000..dfc85b5e2a 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 0000000000..d33ee337cf --- /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 32f6e84839..44d92b628c 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 0000000000..6795c349f5 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 0000000000..ca42f2a1f3 --- /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 f59016cbe1..4ae05e6ba4 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 0000000000..3d89b790f5 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 0000000000..330a614dba --- /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 20da4d4af7..87fc78f86f 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 0000000000..e30ca2494d 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 0000000000..a4ee094cb5 --- /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 07e37ee681..2660d114d4 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 0000000000..b256ace536 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 0000000000..e0d19f0651 --- /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 65e650ee44..b9b9fcab8c 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 0000000000..c491183f26 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 2ac1a0f65f..0000000000 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 82f60cd001..0000000000 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 5f1497a29e..0000000000 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 9a5e835e04..0000000000 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 c465d596d5..0000000000 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 53f9889b32..0000000000 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 6651a91b19..0000000000 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 3000af8a80..0000000000 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 b12a0f15c8..0000000000 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 0000000000..86e960301a --- /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 446c0e8f1d..da80e98ca7 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 0000000000..b31daddd07 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 0000000000..74dc5e3ddb --- /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 04c6df9f4a..a14821c8b6 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 0000000000..acf956d6b4 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 0000000000..a7ce73ed87 --- /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 d878214427..0b072799ac 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 0000000000..2e431a12ef 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 0000000000..0775346e75 --- /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 9a966aa651..c9947cfcc5 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 0000000000..9a9747c33d 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 0000000000..ee6e25596f --- /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 3c2eb42bfe..a7e7b60810 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 0000000000..ae53a86547 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 0000000000..2a6c8c0d02 --- /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 d1660c40f2..6baa092327 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 0000000000..6f88e25389 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 0000000000..e7c75e32d7 --- /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 7c1eaaba96..3ce026ca4c 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 0000000000..cfbb429d0b 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 0000000000..a5455156e9 --- /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 33f9c05297..86edfb9dc6 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 0000000000..d55d4d2c97 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 3ac57c165b..0000000000 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 7f93d7d9ae..0000000000 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 03bb1508a5..0000000000 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 631bea8d8d..0000000000 --- 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 0a5e1bbf43..0000000000 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 ffb5e1ac09..0000000000 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 7c54781918..0000000000 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 fe22a2819a..0000000000 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 0000000000..1e4672f568 --- /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 8e041ad99e..5dd8e09ab1 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 0000000000..6fd03a1b6c 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 0000000000..b4504c909d --- /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 0000000000..d22af03e74 --- /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 0000000000..79ead9aea3 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 0000000000..c0643cfca4 --- /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 0000000000..3c5415f729 --- /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 0000000000..14a61fc01b 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 0000000000..de496127b2 --- /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 1bbb1de661..8221e7d62c 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 0000000000..c2ac5c2f2f 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 f35da34878..0000000000 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 e681df8339..0000000000 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 3668b7a066..0000000000 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 1fecdfac21..0000000000 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 028f81cb5f..0000000000 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 bb918cf142..0000000000 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 dac90ab985..0000000000 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 f343f969e9..0000000000 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 abf8b89983..0000000000 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 0000000000..0ceda69824 --- /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 d0f4876455..528a0929a0 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 0000000000..a575f19954 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 0000000000..67b3f4987c --- /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 e70b30f08c..ea7b853581 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 0000000000..68804c91dd 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 0000000000..2322275bdd --- /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 af7c80f21d..8049e44a86 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 6827116073..71e4f50f3e 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 5fe3e4fbd7..0000000000 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 1914d1954b..0000000000 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 cb9a71a046..0000000000 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 df8eb8062a..0000000000 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 e112a0740f..0000000000 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 eed688349c..0000000000 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 8166409f5f..0000000000 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 1bf180a31c..0000000000 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 0000000000..32aebaea24 --- /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 0e32c432eb..67e63340a1 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 0000000000..c0ab17f657 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 0000000000..12bc00f9e6 --- /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 b9148827bc..87097387aa 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 e27ee4dd08..415a932ccb 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 0000000000..aa1e890329 --- /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 4c6409c1c7..dd8df42184 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 0000000000..a6a883d2fd 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 55a88a77ab..0000000000 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 de2b1d5020..0000000000 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 fbe552d53b..0000000000 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 a25aae26a6..0000000000 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 60c0c6300a..0000000000 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 4b1e3bfb2a..0000000000 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 618eefbf27..0000000000 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 301fcddc04..0000000000 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 98ca5a6dbe..0000000000 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 916a4a4662..0000000000 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 0000000000..a9eb29cc71 --- /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 3851896b84..428168cadb 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 0000000000..df17de841b 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 0000000000..bf48622b98 --- /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 dbaad6e63c..98184fca34 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 0000000000..0ed8c43f5e 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 0000000000..26c4fa041b --- /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 913bea076f..987b30055c 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 0000000000..5277a9c6e3 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 0000000000..0ce89bd875 --- /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 0c3004c3e3..9688ed8e61 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 0000000000..49b55208b6 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 0000000000..5cb7dc19ae --- /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 13a0d69283..caeb29c25d 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 0000000000..413060deca 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 0000000000..7e89315cda --- /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 3fe9225eca..e91f95e26b 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 0000000000..f44ef699c0 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 0000000000..d0e5bb58ff --- /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 75d1b81b89..c78bee2fcf 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 0000000000..c6f03efa7c 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 0000000000..754fd8ae65 --- /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 53157b487d..e250695af1 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 ccb05e04c1..2aba8f9cdb 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 0000000000..9f208eaaaf --- /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 05e5fe7b02..766cf5f87c 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 0000000000..f34e800c02 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 a777f48e2c..0000000000 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 facfe91859..0000000000 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 7e533db791..0000000000 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 ee42613034..0000000000 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 3c75d606f4..0000000000 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 551a263920..0000000000 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 0000000000..b72c56cc1c --- /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 0538c51364..9b63ffb576 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 0000000000..54c86383bc 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 0000000000..2a2d14135e --- /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 95457c8463..3e30cbf5e5 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 0000000000..f19063be7d 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 0000000000..a89cef36e4 --- /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 d14b8ad56b..27fc5b6b73 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 0000000000..072520eb51 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 0000000000..0b4ee57e6d --- /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 884fb41a6d..13c9aa29a0 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 0000000000..c9f04435d2 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 0000000000..48455fb1a9 --- /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 912f2c5ac0..fb2099bbe9 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 0000000000..f8d6c0c9df 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 0000000000..a482844bec --- /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 4c0b691365..140a3167e0 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 0000000000..bd9c41c9dc 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 0000000000..9870e97456 --- /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 f570d25710..b14373ae3d 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 0000000000..7ff3b9dc82 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 0000000000..01f5f0f0d2 --- /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 455fa1c41c..29fea90590 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 0000000000..ff8c7a55ba 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 0000000000..467eb87472 --- /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 ce31d18e28..a6d883886a 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 0000000000..f26e1e4386 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 0000000000..68ac3f6dcf --- /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 352490325c..e19a96c17a 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 0000000000..17e648142b 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 0000000000..0b233bdc24 --- /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 c79953a05b..3c6522d470 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 0000000000..c0a8199fa5 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 0000000000..b58f22a223 --- /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 48ad796c3e..f120a98252 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 0000000000..73811a388a 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 0000000000..afb8164dee --- /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 bb0cfc4df5..97cce24a6b 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 0000000000..fcf3ca65c5 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 0000000000..90948d0648 --- /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 78363865ef..c66f2fccf0 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 0000000000..863379d98c 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 0000000000..cca0be5e35 --- /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 206777b7f0..fabac4155c 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 0000000000..2304b23fe7 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 0000000000..a2e3ecd035 --- /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 7a6a3e3f63..29c7c48ddb 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 0000000000..ac1e467c9c 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 0000000000..1f86fe5ac0 --- /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 c56c411c07..91940d089c 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 0000000000..ea1a20064e 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 0000000000..68205a31e7 --- /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 86479a8e88..b019ffcc2b 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 0000000000..3313e890f9 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 39ef0d4534..ae57598e1c 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 0000000000..ae1dd8d8f8 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 0000000000..3991bda76c --- /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 b84e9a4ab7..f52c747f36 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 0000000000..526c9300b5 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 8252b51660..aa8507e073 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.html b/common/test/resources/keyboards/test_8568_deadkeys.html index 1b4cf31424..054f19b4f8 100644 --- a/common/test/resources/keyboards/test_8568_deadkeys.html +++ b/common/test/resources/keyboards/test_8568_deadkeys.html @@ -36,22 +36,20 @@ + }); + diff --git a/common/test/resources/keyboards/test_8568_deadkeys.kmn b/common/test/resources/keyboards/test_8568_deadkeys.kmn index 4cf7cc799d..f7f3067daa 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 0000000000..9ec0d156a3 --- /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 0000000000..52efb684c5 --- /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 0000000000..3571b6aa43 Binary files /dev/null and b/common/test/resources/keyboards/test_rtl.kmx differ diff --git a/common/test/resources/mocha-teamcity-reporter/teamcity.cjs b/common/test/resources/mocha-teamcity-reporter/teamcity.cjs index 24c76a5f2b..fd901faaa1 100644 --- a/common/test/resources/mocha-teamcity-reporter/teamcity.cjs +++ b/common/test/resources/mocha-teamcity-reporter/teamcity.cjs @@ -135,6 +135,8 @@ function Teamcity(runner, options) { const ignoredTests = {}; const testState = { pending: 0 }; + log('Initializing Mocha TeamCity Reporter'); + runner.on(EVENT_SUITE_BEGIN, function (suite) { handleFlow(true, hasParentFlowId); if (suite.root) { diff --git a/common/test/resources/playwright-TC-reporter.ts b/common/test/resources/playwright-TC-reporter.ts new file mode 100644 index 0000000000..20d6ac39d4 --- /dev/null +++ b/common/test/resources/playwright-TC-reporter.ts @@ -0,0 +1,200 @@ +/* + * 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 | null; + 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): void { + 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); + } + + 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`); + } + 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); + if (!node) { + console.error(`Node for '${id}' not found in Nodes map, removing from OpenNodes`); + TestNode.OpenNodes.pop(); + continue; + } + + 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; + + public constructor(options: { parentFlow?: string } = {}) { + console.log('Initializing Playwright TeamCity Reporter'); + 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/test/resources/test-runner-TC-reporter.mjs b/common/test/resources/test-runner-TC-reporter.mjs index 8a6aeaccf2..33198592af 100644 --- a/common/test/resources/test-runner-TC-reporter.mjs +++ b/common/test/resources/test-runner-TC-reporter.mjs @@ -94,14 +94,16 @@ export default function teamcityReporter({ name="Web Test Runner JavaScript test /** @type {import('@web/test-runner').Reporter} */ const reporter = { - start({config, sessions}) { + start({ config, sessions }) { + logger = config.logger; + logger.log('Initializing Web Test Runner TeamCity Reporter'); + rootDir = config.rootDir; for(const session of sessions.all()) { testDefMap.set(buildSessionName(session), new Map()); } - logger = config.logger; logger.log(`##teamcity[blockOpened name='${e(name)}']`); }, stop(args) { diff --git a/common/tools/es-bundling/.gitignore b/common/tools/es-bundling/.gitignore new file mode 100644 index 0000000000..07ed7069a2 --- /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 3a05714120..8ff7f035f4 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 1c317aabec..5870280035 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/build.sh b/common/web/build.sh index 182de85d62..052061946f 100755 --- a/common/web/build.sh +++ b/common/web/build.sh @@ -11,6 +11,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" builder_describe "Keyman common web modules" \ :keyman-version \ :langtags \ + :sentry-manager \ :types \ clean \ configure \ diff --git a/common/web/sentry-manager/build.sh b/common/web/sentry-manager/build.sh new file mode 100755 index 0000000000..b2bcea8d94 --- /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 0000000000..0967154d90 --- /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 dc22aa5605..304269dbb6 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 ca1719f280..67dfbcb523 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 afd0029af0..3ce697ef4b 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 4f53e29fde..651a6db0d1 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/common/windows/cpp/include/ConvertUTF.h b/common/windows/cpp/include/ConvertUTF.h deleted file mode 100644 index c39871e362..0000000000 --- a/common/windows/cpp/include/ConvertUTF.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2001 Unicode, Inc. - * - * Disclaimer - * - * This source code is provided as is by Unicode, Inc. No claims are - * made as to fitness for any particular purpose. No warranties of any - * kind are expressed or implied. The recipient agrees to determine - * applicability of information provided. If this file has been - * purchased on magnetic or optical media from Unicode, Inc., the - * sole remedy for any claim will be exchange of defective media - * within 90 days of receipt. - * - * Limitations on Rights to Redistribute This Code - * - * Unicode, Inc. hereby grants the right to freely use the information - * supplied in this file in the creation of products supporting the - * Unicode Standard, and to make copies of this file in any form - * for internal or external distribution as long as this notice - * remains attached. - */ - -/* --------------------------------------------------------------------- - - Conversions between UTF32, UTF-16, and UTF-8. Header file. - - Several funtions are included here, forming a complete set of - conversions between the three formats. UTF-7 is not included - here, but is handled in a separate source file. - - Each of these routines takes pointers to input buffers and output - buffers. The input buffers are const. - - Each routine converts the text between *sourceStart and sourceEnd, - putting the result into the buffer between *targetStart and - targetEnd. Note: the end pointers are *after* the last item: e.g. - *(sourceEnd - 1) is the last item. - - The return result indicates whether the conversion was successful, - and if not, whether the problem was in the source or target buffers. - (Only the first encountered problem is indicated.) - - After the conversion, *sourceStart and *targetStart are both - updated to point to the end of last text successfully converted in - the respective buffers. - - Input parameters: - sourceStart - pointer to a pointer to the source buffer. - The contents of this are modified on return so that - it points at the next thing to be converted. - targetStart - similarly, pointer to pointer to the target buffer. - sourceEnd, targetEnd - respectively pointers to the ends of the - two buffers, for overflow checking only. - - These conversion functions take a ConversionFlags argument. When this - flag is set to strict, both irregular sequences and isolated surrogates - will cause an error. When the flag is set to lenient, both irregular - sequences and isolated surrogates are converted. - - Whether the flag is strict or lenient, all illegal sequences will cause - an error return. This includes sequences such as: , , - or in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code - must check for illegal sequences. - - When the flag is set to lenient, characters over 0x10FFFF are converted - to the replacement character; otherwise (when the flag is set to strict) - they constitute an error. - - Output parameters: - The value "sourceIllegal" is returned from some routines if the input - sequence is malformed. When "sourceIllegal" is returned, the source - value will point to the illegal value that caused the problem. E.g., - in UTF-8 when a sequence is malformed, it points to the start of the - malformed sequence. - - Author: Mark E. Davis, 1994. - Rev History: Rick McGowan, fixes & updates May 2001. - ------------------------------------------------------------------------- */ - -/* --------------------------------------------------------------------- - The following 4 definitions are compiler-specific. - The C standard does not guarantee that wchar_t has at least - 16 bits, so wchar_t is no less portable than unsigned short! - All should be unsigned values to avoid sign extension during - bit mask & shift operations. ------------------------------------------------------------------------- */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef unsigned long UTF32; /* at least 32 bits */ -typedef unsigned short UTF16; /* at least 16 bits */ -typedef unsigned char UTF8; /* typically 8 bits */ -typedef unsigned char Boolean; /* 0 or 1 */ - -/* Some fundamental constants */ -#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD -#define UNI_MAX_BMP (UTF32)0x0000FFFF -#define UNI_MAX_UTF16 (UTF32)0x0010FFFF -#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF - -#define UTF8Sig "\xEF\xBB\xBF" -#define UTF16Sig "\xFF\xFE" - -typedef enum { - conversionOK, /* conversion successful */ - sourceExhausted, /* partial character in source, but hit end */ - targetExhausted, /* insuff. room in target for conversion */ - sourceIllegal /* source sequence is illegal/malformed */ -} ConversionResult; - -typedef enum { - strictConversion = 0, - lenientConversion -} ConversionFlags; - -ConversionResult ConvertUTF32toUTF16 ( - UTF32** sourceStart, const UTF32* sourceEnd, - UTF16** targetStart, const UTF16* targetEnd, const ConversionFlags flags); - -ConversionResult ConvertUTF16toUTF32 ( - UTF16** sourceStart, UTF16* sourceEnd, - UTF32** targetStart, const UTF32* targetEnd, const ConversionFlags flags); - -ConversionResult ConvertUTF16toUTF8 ( - UTF16** sourceStart, const UTF16* sourceEnd, - UTF8** targetStart, const UTF8* targetEnd, const ConversionFlags flags); - -ConversionResult ConvertUTF8toUTF16 ( - UTF8** sourceStart, UTF8* sourceEnd, - UTF16** targetStart, const UTF16* targetEnd, const ConversionFlags flags); - -ConversionResult ConvertUTF32toUTF8 ( - UTF32** sourceStart, const UTF32* sourceEnd, - UTF8** targetStart, const UTF8* targetEnd, const ConversionFlags flags); - -ConversionResult ConvertUTF8toUTF32 ( - UTF8** sourceStart, UTF8* sourceEnd, - UTF32** targetStart, const UTF32* targetEnd, const ConversionFlags flags); - -Boolean isLegalUTF8Sequence(UTF8 *source, UTF8 *sourceEnd); - -#ifdef __cplusplus -} -#endif - -/* --------------------------------------------------------------------- */ diff --git a/common/windows/cpp/src/ConvertUTF.c b/common/windows/cpp/src/ConvertUTF.c deleted file mode 100644 index f331202620..0000000000 --- a/common/windows/cpp/src/ConvertUTF.c +++ /dev/null @@ -1,467 +0,0 @@ -/* - * Copyright 2001 Unicode, Inc. - * - * Disclaimer - * - * This source code is provided as is by Unicode, Inc. No claims are - * made as to fitness for any particular purpose. No warranties of any - * kind are expressed or implied. The recipient agrees to determine - * applicability of information provided. If this file has been - * purchased on magnetic or optical media from Unicode, Inc., the - * sole remedy for any claim will be exchange of defective media - * within 90 days of receipt. - * - * Limitations on Rights to Redistribute This Code - * - * Unicode, Inc. hereby grants the right to freely use the information - * supplied in this file in the creation of products supporting the - * Unicode Standard, and to make copies of this file in any form - * for internal or external distribution as long as this notice - * remains attached. - */ - -/* --------------------------------------------------------------------- - - Conversions between UTF32, UTF-16, and UTF-8. Source code file. - Author: Mark E. Davis, 1994. - Rev History: Rick McGowan, fixes & updates May 2001. - - See the header file "ConvertUTF.h" for complete documentation. - ------------------------------------------------------------------------- */ - -#include "../include/ConvertUTF.h" -#ifdef CVTUTF_DEBUG -#include -#endif - -static const int halfShift = 10; /* used for shifting by 10 bits */ - -static const UTF32 halfBase = 0x0010000UL; -static const UTF32 halfMask = 0x3FFUL; - -#define UNI_SUR_HIGH_START (UTF32)0xD800 -#define UNI_SUR_HIGH_END (UTF32)0xDBFF -#define UNI_SUR_LOW_START (UTF32)0xDC00 -#define UNI_SUR_LOW_END (UTF32)0xDFFF -#define false 0 -#define true 1 - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF32toUTF16 ( - UTF32** sourceStart, const UTF32* sourceEnd, - UTF16** targetStart, const UTF16* targetEnd, const ConversionFlags flags) { - ConversionResult result = conversionOK; - UTF32* source = *sourceStart; - UTF16* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch; - if (target >= targetEnd) { - result = targetExhausted; break; - } - ch = *source++; - if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ - if ((flags == strictConversion) && (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END)) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = (UTF16) ch; /* normal case */ - } - } else if (ch > UNI_MAX_UTF16) { - if (flags == strictConversion) { - result = sourceIllegal; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - /* target is a character in range 0xFFFF - 0x10FFFF. */ - if (target + 1 >= targetEnd) { - result = targetExhausted; break; - } - ch -= halfBase; - *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); - *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); - } - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF16toUTF32 ( - UTF16** sourceStart, UTF16* sourceEnd, - UTF32** targetStart, const UTF32* targetEnd, const ConversionFlags flags) { - ConversionResult result = conversionOK; - UTF16* source = *sourceStart; - UTF32* target = *targetStart; - UTF32 ch, ch2; - while (source < sourceEnd) { - ch = *source++; - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END && source < sourceEnd) { - ch2 = *source; - if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { - ch = ((ch - UNI_SUR_HIGH_START) << halfShift) - + (ch2 - UNI_SUR_LOW_START) + halfBase; - ++source; - } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } else if ((flags == strictConversion) && (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END)) { - /* an unpaired low surrogate */ - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - if (target >= targetEnd) { - result = targetExhausted; break; - } - *target++ = ch; - } - *sourceStart = source; - *targetStart = target; -#ifdef CVTUTF_DEBUG -if (result == sourceIllegal) { - fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2); - fflush(stderr); -} -#endif - return result; -} - -/* --------------------------------------------------------------------- */ - -/* - * Index into the table below with the first byte of a UTF-8 sequence to - * get the number of trailing bytes that are supposed to follow it. - */ -static const char trailingBytesForUTF8[256] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 -}; - -/* - * Magic values subtracted from a buffer value during UTF8 conversion. - * This table contains as many values as there might be trailing bytes - * in a UTF-8 sequence. - */ -static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, - 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; - -/* - * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed - * into the first byte, depending on how many bytes follow. There are - * as many entries in this table as there are UTF-8 sequence types. - * (I.e., one byte sequence, two byte... six byte sequence.) - */ -static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - -/* --------------------------------------------------------------------- */ - -/* The interface converts a whole buffer to avoid function-call overhead. - * Constants have been gathered. Loops & conditionals have been removed as - * much as possible for efficiency, in favor of drop-through switches. - * (See "Note A" at the bottom of the file for equivalent code.) - * If your compiler supports it, the "isLegalUTF8" call can be turned - * into an inline function. - */ - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF16toUTF8 ( - UTF16** sourceStart, const UTF16* sourceEnd, - UTF8** targetStart, const UTF8* targetEnd, const ConversionFlags flags) { - ConversionResult result = conversionOK; - UTF16* source = *sourceStart; - UTF8* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch; - unsigned short bytesToWrite = 0; - const UTF32 byteMask = 0xBF; - const UTF32 byteMark = 0x80; - ch = *source++; - /* If we have a surrogate pair, convert to UTF32 first. */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END && source < sourceEnd) { - UTF32 ch2 = *source; - if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { - ch = ((ch - UNI_SUR_HIGH_START) << halfShift) - + (ch2 - UNI_SUR_LOW_START) + halfBase; - ++source; - } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } else if ((flags == strictConversion) && (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END)) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - /* Figure out how many bytes the result will require */ - if (ch < (UTF32)0x80) { bytesToWrite = 1; - } else if (ch < (UTF32)0x800) { bytesToWrite = 2; - } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; - } else if (ch < (UTF32)0x200000) { bytesToWrite = 4; - } else { bytesToWrite = 2; - ch = UNI_REPLACEMENT_CHAR; - } - - target += bytesToWrite; - if (target > targetEnd) { - target -= bytesToWrite; result = targetExhausted; break; - } - switch (bytesToWrite) { /* note: everything falls through. */ - case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); - } - target += bytesToWrite; - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- */ - -/* - * Utility routine to tell whether a sequence of bytes is legal UTF-8. - * This must be called with the length pre-determined by the first byte. - * If not calling this from ConvertUTF8to*, then the length can be set by: - * length = trailingBytesForUTF8[*source]+1; - * and the sequence is illegal right away if there aren't that many bytes - * available. - * If presented with a length > 4, this returns false. The Unicode - * definition of UTF-8 goes up to 4-byte sequences. - */ - -static Boolean isLegalUTF8(UTF8 *source, int length) { - UTF8 a; - UTF8 *srcptr = source+length; - switch (length) { - default: return false; - /* Everything else falls through when "true"... */ - case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; - case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; - case 2: if ((a = (*--srcptr)) > 0xBF) return false; - switch (*source) { - /* no fall-through in this inner switch */ - case 0xE0: if (a < 0xA0) return false; break; - case 0xF0: if (a < 0x90) return false; break; - case 0xF4: if (a > 0x8F) return false; break; - default: if (a < 0x80) return false; - } - case 1: if (*source >= 0x80 && *source < 0xC2) return false; - if (*source > 0xF4) return false; - } - return true; -} - -/* --------------------------------------------------------------------- */ - -/* - * Exported function to return whether a UTF-8 sequence is legal or not. - * This is not used here; it's just exported. - */ -Boolean isLegalUTF8Sequence(UTF8 *source, UTF8 *sourceEnd) { - int length = trailingBytesForUTF8[*source]+1; - if (source+length > sourceEnd) { - return false; - } - return isLegalUTF8(source, length); -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF8toUTF16 ( - UTF8** sourceStart, UTF8* sourceEnd, - UTF16** targetStart, const UTF16* targetEnd, const ConversionFlags flags) { - ConversionResult result = conversionOK; - UTF8* source = *sourceStart; - UTF16* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch = 0; - unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; - if (source + extraBytesToRead >= sourceEnd) { - result = sourceExhausted; break; - } - /* Do this check whether lenient or strict */ - if (! isLegalUTF8(source, extraBytesToRead+1)) { - result = sourceIllegal; - break; - } - /* - * The cases all fall through. See "Note A" below. - */ - switch (extraBytesToRead) { - case 3: ch += *source++; ch <<= 6; - case 2: ch += *source++; ch <<= 6; - case 1: ch += *source++; ch <<= 6; - case 0: ch += *source++; - } - ch -= offsetsFromUTF8[extraBytesToRead]; - - if (target >= targetEnd) { - result = targetExhausted; break; - } - if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ - if ((flags == strictConversion) && (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END)) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = (UTF16) ch; /* normal case */ - } - } else if (ch > UNI_MAX_UTF16) { - if (flags == strictConversion) { - result = sourceIllegal; - source -= extraBytesToRead; /* return to the start */ - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - /* target is a character in range 0xFFFF - 0x10FFFF. */ - if (target + 1 >= targetEnd) { - result = targetExhausted; break; - } - ch -= halfBase; - *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); - *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); - } - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF32toUTF8 ( - UTF32** sourceStart, const UTF32* sourceEnd, - UTF8** targetStart, const UTF8* targetEnd, const ConversionFlags flags) { - ConversionResult result = conversionOK; - UTF32* source = *sourceStart; - UTF8* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch; - unsigned short bytesToWrite = 0; - const UTF32 byteMask = 0xBF; - const UTF32 byteMark = 0x80; - ch = *source++; - /* surrogates of any stripe are not legal UTF32 characters */ - if (flags == strictConversion ) { - if ((ch >= UNI_SUR_HIGH_START) && (ch <= UNI_SUR_LOW_END)) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - /* Figure out how many bytes the result will require */ - if (ch < (UTF32)0x80) { bytesToWrite = 1; - } else if (ch < (UTF32)0x800) { bytesToWrite = 2; - } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; - } else if (ch < (UTF32)0x200000) { bytesToWrite = 4; - } else { bytesToWrite = 2; - ch = UNI_REPLACEMENT_CHAR; - } - - target += bytesToWrite; - if (target > targetEnd) { - target -= bytesToWrite; result = targetExhausted; break; - } - switch (bytesToWrite) { /* note: everything falls through. */ - case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 1: *--target = (UTF8)( ch | firstByteMark[bytesToWrite]); - } - target += bytesToWrite; - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF8toUTF32 ( - UTF8** sourceStart, UTF8* sourceEnd, - UTF32** targetStart, const UTF32* targetEnd, const ConversionFlags flags) { - ConversionResult result = conversionOK; - UTF8* source = *sourceStart; - UTF32* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch = 0; - unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; - if (source + extraBytesToRead >= sourceEnd) { - result = sourceExhausted; break; - } - /* Do this check whether lenient or strict */ - if (! isLegalUTF8(source, extraBytesToRead+1)) { - result = sourceIllegal; - break; - } - /* - * The cases all fall through. See "Note A" below. - */ - switch (extraBytesToRead) { - case 3: ch += *source++; ch <<= 6; - case 2: ch += *source++; ch <<= 6; - case 1: ch += *source++; ch <<= 6; - case 0: ch += *source++; - } - ch -= offsetsFromUTF8[extraBytesToRead]; - - if (target >= targetEnd) { - result = targetExhausted; break; - } - if (ch <= UNI_MAX_UTF32) { - *target++ = ch; - } else if (ch > UNI_MAX_UTF32) { - *target++ = UNI_REPLACEMENT_CHAR; - } else { - if (target + 1 >= targetEnd) { - result = targetExhausted; break; - } - ch -= halfBase; - *target++ = (ch >> halfShift) + UNI_SUR_HIGH_START; - *target++ = (ch & halfMask) + UNI_SUR_LOW_START; - } - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- - - Note A. - The fall-through switches in UTF-8 reading code save a - temp variable, some decrements & conditionals. The switches - are equivalent to the following loop: - { - int tmpBytesToRead = extraBytesToRead+1; - do { - ch += *source++; - --tmpBytesToRead; - if (tmpBytesToRead) ch <<= 6; - } while (tmpBytesToRead > 0); - } - In UTF-8 writing code, the switches on "bytesToWrite" are - similarly unrolled loops. - - --------------------------------------------------------------------- */ - - diff --git a/common/windows/cpp/src/keymansentry.cpp b/common/windows/cpp/src/keymansentry.cpp index 71f640a4a5..9caa9ed499 100644 --- a/common/windows/cpp/src/keymansentry.cpp +++ b/common/windows/cpp/src/keymansentry.cpp @@ -1,7 +1,7 @@ #include #include "../include/keymansentry.h" -#include "../include/keymanversion.h" +#include "../../../include/keymanversion.h" #include #include "../include/registry.h" #include diff --git a/common/windows/delphi/general/KeymanPaths.pas b/common/windows/delphi/general/KeymanPaths.pas index a0cc07d5b4..2e5bff0aab 100644 --- a/common/windows/delphi/general/KeymanPaths.pas +++ b/common/windows/delphi/general/KeymanPaths.pas @@ -44,6 +44,7 @@ type class function KeyboardsInstallDir: string; static; class function KeymanConfigStaticHttpFilesPath(const filename: string = ''): string; static; class function KeymanCustomisationPath: string; static; + class function KeymanLocalePath: string; static; class function KeymanCoreLibraryPath(const Filename: string): string; static; class function CEFPath: string; static; // Chromium Embedded Framework class function CEFDataPath(const mode: string): string; static; @@ -389,6 +390,20 @@ begin Result := Result + filename; end; +class function TKeymanPaths.KeymanLocalePath: string; +var + keyman_root: string; +begin + // Look up KEYMAN_ROOT development variable -- if found and executable + // within that path then use that as source path + if TKeymanPaths.RunningFromSource(keyman_root) then + begin + Exit(keyman_root + 'windows\src\desktop\kmshell\locale\'); + end; + + Result := TKeymanPaths.KeymanDesktopInstallPath('locale\'); +end; + class function TKeymanPaths.KeymanCustomisationPath: string; var keyman_root: string; diff --git a/common/windows/delphi/general/KeymanVersion.pas b/common/windows/delphi/general/KeymanVersion.pas index 524973e025..5979485423 100644 --- a/common/windows/delphi/general/KeymanVersion.pas +++ b/common/windows/delphi/general/KeymanVersion.pas @@ -30,6 +30,17 @@ const TIER_STABLE = 'stable'; const + ENVIRONMENT_TEST = 'test'; + ENVIRONMENT_LOCAL = 'local'; + ENVIRONMENT_ALPHA = 'alpha'; + ENVIRONMENT_BETA = 'beta'; + ENVIRONMENT_STABLE = 'stable'; + +const + SKeymanVersion190 = '19.0'; + SKeymanVersion180 = '18.0'; + SKeymanVersion170 = '17.0'; + SKeymanVersion160 = '16.0'; SKeymanVersion150 = '15.0'; SKeymanVersion140 = '14.0'; SKeymanVersion130 = '13.0'; diff --git a/common/windows/delphi/general/Upload_Settings.pas b/common/windows/delphi/general/Upload_Settings.pas index e1e8ce4294..8811ec6f10 100644 --- a/common/windows/delphi/general/Upload_Settings.pas +++ b/common/windows/delphi/general/Upload_Settings.pas @@ -66,11 +66,11 @@ const URLPath_Community = '/go/'+SKeymanVersion+'/community'; // Keyboard download and installation - URLPath_RegEx_MatchKeyboardsInstall = '^http(?:s)?://keyman(?:-staging)?\.com(?:\.local)?/keyboards/install/([^?/]+)(?:\?(.+))?$'; + URLPath_RegEx_MatchKeyboardsInstall = '^http(?:s)?://keyman(?:-staging)?\.com(?:\.localhost)?/keyboards/install/([^?/]+)(?:\?(.+))?$'; // e.g. https://keyman.com/keyboards/install/foo - UrlPath_RegEx_MatchKeyboardsRoot = '^http(?:s)?://keyman(?:-staging)?\.com(?:\.local)?/keyboards([/?].*)?$'; - // e.g. http://keyman.com.local/keyboards/foo - UrlPath_RegEx_MatchKeyboardsGo = '^http(?:s)?://keyman(?:-staging)?\.com(?:\.local)?/go/windows/[^/]+/download-keyboards'; + UrlPath_RegEx_MatchKeyboardsRoot = '^http(?:s)?://keyman(?:-staging)?\.com(?:\.localhost)?/keyboards([/?].*)?$'; + // e.g. http://keyman.com.localhost/keyboards/foo + UrlPath_RegEx_MatchKeyboardsGo = '^http(?:s)?://keyman(?:-staging)?\.com(?:\.localhost)?/go/windows/[^/]+/download-keyboards'; // e.g. https://keyman-staging.com/go/windows/14.0/download-keyboards?version=14.0.146.0 // Cloning keyboards - Keyman Developer diff --git a/core/cross-arm64.build b/core/cross-arm64.build index 9fd7cc6d14..7bea64992e 100644 --- a/core/cross-arm64.build +++ b/core/cross-arm64.build @@ -1,5 +1,6 @@ [host_machine] system = 'windows' +subsystem = 'windows' cpu_family = 'aarch64' cpu = 'arm64' endian = 'little' diff --git a/core/cross-x64.build b/core/cross-x64.build index df3ab0b5dc..ecc0486e08 100644 --- a/core/cross-x64.build +++ b/core/cross-x64.build @@ -1,5 +1,6 @@ [host_machine] system = 'windows' +subsystem = 'windows' cpu_family = 'x86_64' cpu = 'x86_64' endian = 'little' @@ -11,3 +12,6 @@ ar = 'lib' ld = 'link' strip = 'llvm-strip' pkgconfig = 'pkg-config' + +[properties] +needs_exe_wrapper = false diff --git a/core/docs/api/changes.md b/core/docs/api/changes.md index e5736494ab..f7f250f337 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 3439e20722..07a30921c9 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 c26cbdf9ff..981aa59d11 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) + en - - - - en - diff --git a/package-lock.json b/package-lock.json index db123f1822..8975f8c522 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,11 +28,11 @@ "common/test/resources", "common/web/keyman-version", "common/web/langtags", + "common/web/sentry-manager", "common/web/types", "common/tools/sourcemap-path-remapper", "common/tools/hextobin", "web", - "web/src/engine/osk/gesture-processor", "web/src/engine/predictive-text/*" ], "dependencies": { @@ -46,7 +46,7 @@ }, "devDependencies": { "@microsoft/api-documenter": "^7.28.0", - "@microsoft/api-extractor": "^7.57.6", + "@microsoft/api-extractor": "^7.58.1", "@types/chai": "^4.3.14", "@types/mocha": "^10.0.10", "@types/node": "^20.4.1", @@ -66,7 +66,7 @@ "eslint-plugin-n": "^15.7.0", "eslint-plugin-promise": "^6.1.1", "mocha": "^11.2.2", - "playwright": "^1.46.1", + "playwright": "1.46.1", "sinon": "^17.0.1", "source-map-support": "^0.5.21", "tslib": "^2.5.2", @@ -142,6 +142,17 @@ "typescript": "^5.4.5" } }, + "common/web/sentry-manager": { + "name": "@keymanapp/web-sentry-manager", + "license": "MIT", + "dependencies": { + "@keymanapp/keyman-version": "*", + "@sentry/browser": "^8.55.0" + }, + "devDependencies": { + "typescript": "^5.4.5" + } + }, "common/web/types": { "name": "@keymanapp/common-types", "license": "MIT", @@ -238,7 +249,7 @@ "dependencies": { "@keymanapp/common-types": "*", "eventemitter3": "^5.0.0", - "fast-xml-parser": "^5.3.8", + "fast-xml-parser": "5.8.0", "path-browserify": "^1.0.1", "restructure": "^3.0.1", "sax": ">=0.6.0", @@ -255,6 +266,56 @@ "typescript": "^5.4.5" } }, + "developer/src/common/web/utils/node_modules/fast-xml-builder": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz", + "integrity": "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "path-expression-matcher": "^1.5.0", + "xml-naming": "^0.1.0" + } + }, + "developer/src/common/web/utils/node_modules/fast-xml-parser": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.8.0.tgz", + "integrity": "sha512-6bIM7fsJxeo3uXv7OncQYsBAMPJ7V16Slahl/6M98C/i2q+vB1+4a0MtrvYwDFEUrwDSbAmeLDRXsOBwrL7yAg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "@nodable/entities": "^2.1.0", + "fast-xml-builder": "^1.2.0", + "path-expression-matcher": "^1.5.0", + "strnum": "^2.3.0", + "xml-naming": "^0.1.0" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "developer/src/common/web/utils/node_modules/strnum": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.3.0.tgz", + "integrity": "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, "developer/src/kmc": { "name": "@keymanapp/kmc", "license": "MIT", @@ -1171,13 +1232,13 @@ "@ngrok/ngrok": "^1.7.0", "@sentry/node": "^7.57.0", "chalk": "^4.1.2", - "express": "^4.20.0", + "express": "^4.22.2", "multer": "^2.1.1", "open": "^8.4.0", "restructure": "^3.0.1", "sax": ">=0.6.0", "semver": "^7.5.4", - "ws": "^8.17.1", + "ws": "^8.20.1", "xmlbuilder": "~11.0.0" }, "devDependencies": { @@ -1224,6 +1285,27 @@ "url": "https://opencollective.com/express" } }, + "developer/src/server/node_modules/ws": { + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", + "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/@75lb/deep-merge": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@75lb/deep-merge/-/deep-merge-1.1.2.tgz", @@ -1247,11 +1329,22 @@ } }, "node_modules/@actions/core": { - "version": "1.9.1", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", + "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==", "license": "MIT", "dependencies": { - "@actions/http-client": "^2.0.1", - "uuid": "^8.3.2" + "@actions/exec": "^1.1.1", + "@actions/http-client": "^2.0.1" + } + }, + "node_modules/@actions/exec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", + "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", + "license": "MIT", + "dependencies": { + "@actions/io": "^1.0.1" } }, "node_modules/@actions/github": { @@ -1279,6 +1372,12 @@ "undici": "^5.25.4" } }, + "node_modules/@actions/io": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", + "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==", + "license": "MIT" + }, "node_modules/@babel/code-frame": { "version": "7.24.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", @@ -1686,10 +1785,6 @@ "resolved": "developer/src/common/web/utils", "link": true }, - "node_modules/@keymanapp/gesture-recognizer": { - "resolved": "web/src/engine/osk/gesture-processor", - "link": true - }, "node_modules/@keymanapp/hextobin": { "resolved": "common/tools/hextobin", "link": true @@ -1783,7 +1878,7 @@ "link": true }, "node_modules/@keymanapp/web-sentry-manager": { - "resolved": "web/src/engine/sentry-manager", + "resolved": "common/web/sentry-manager", "link": true }, "node_modules/@keymanapp/web-utils": { @@ -1816,26 +1911,26 @@ } }, "node_modules/@microsoft/api-extractor": { - "version": "7.57.6", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.57.6.tgz", - "integrity": "sha512-0rFv/D8Grzw1Mjs2+8NGUR+o4h9LVm5zKRtMeWnpdB5IMJF4TeHCL1zR5LMCIudkOvyvjbhMG5Wjs0B5nqsrRQ==", + "version": "7.58.1", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.58.1.tgz", + "integrity": "sha512-kF3GFME4lN22O5zbnXk2RP4y/4PDQdps0xKiYTipMYprkwCmmpsWLZt/N2Fkbil540cSLfJX0BW7LkHzgMVUYg==", "dev": true, "license": "MIT", "dependencies": { - "@microsoft/api-extractor-model": "7.33.4", + "@microsoft/api-extractor-model": "7.33.5", "@microsoft/tsdoc": "~0.16.0", "@microsoft/tsdoc-config": "~0.18.1", - "@rushstack/node-core-library": "5.20.3", + "@rushstack/node-core-library": "5.21.0", "@rushstack/rig-package": "0.7.2", - "@rushstack/terminal": "0.22.3", - "@rushstack/ts-command-line": "5.3.3", + "@rushstack/terminal": "0.22.4", + "@rushstack/ts-command-line": "5.3.4", "diff": "~8.0.2", - "lodash": "~4.17.23", - "minimatch": "10.2.1", + "lodash": "~4.18.1", + "minimatch": "10.2.3", "resolve": "~1.22.1", "semver": "~7.5.4", "source-map": "~0.6.1", - "typescript": "5.8.2" + "typescript": "5.9.3" }, "bin": { "api-extractor": "bin/api-extractor" @@ -1854,21 +1949,21 @@ } }, "node_modules/@microsoft/api-extractor/node_modules/@microsoft/api-extractor-model": { - "version": "7.33.4", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.33.4.tgz", - "integrity": "sha512-u1LTaNTikZAQ9uK6KG1Ms7nvNedsnODnspq/gH2dcyETWvH4hVNGNDvRAEutH66kAmxA4/necElqGNs1FggC8w==", + "version": "7.33.5", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.33.5.tgz", + "integrity": "sha512-Xh4dXuusndVQqVz4nEN9xOp0DyzsKxeD2FFJkSPg4arAjDSKPcy6cAc7CaeBPA7kF2wV1fuDlo2p/bNMpVr8yg==", "dev": true, "license": "MIT", "dependencies": { "@microsoft/tsdoc": "~0.16.0", "@microsoft/tsdoc-config": "~0.18.1", - "@rushstack/node-core-library": "5.20.3" + "@rushstack/node-core-library": "5.21.0" } }, "node_modules/@microsoft/api-extractor/node_modules/@rushstack/node-core-library": { - "version": "5.20.3", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.20.3.tgz", - "integrity": "sha512-95JgEPq2k7tHxhF9/OJnnyHDXfC9cLhhta0An/6MlkDsX2A6dTzDrTUG18vx4vjc280V0fi0xDH9iQczpSuWsw==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.21.0.tgz", + "integrity": "sha512-LFzN+1lyWROit/P8Md6yxAth7lLYKn37oCKJHirEE2TQB25NDUM7bALf0ar+JAtwFfRCH+D+DGOA7DAzIi2r+g==", "dev": true, "license": "MIT", "dependencies": { @@ -1906,13 +2001,13 @@ } }, "node_modules/@microsoft/api-extractor/node_modules/@rushstack/terminal": { - "version": "0.22.3", - "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.22.3.tgz", - "integrity": "sha512-gHC9pIMrUPzAbBiI4VZMU7Q+rsCzb8hJl36lFIulIzoceKotyKL3Rd76AZ2CryCTKEg+0bnTj406HE5YY5OQvw==", + "version": "0.22.4", + "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.22.4.tgz", + "integrity": "sha512-fhtLjnXCc/4WleVbVl6aoc7jcWnU6yqjS1S8WoaNREG3ycu/viZ9R/9QM7Y/b4CDvcXoiDyMNIay7JMwBptM3g==", "dev": true, "license": "MIT", "dependencies": { - "@rushstack/node-core-library": "5.20.3", + "@rushstack/node-core-library": "5.21.0", "@rushstack/problem-matcher": "0.2.1", "supports-color": "~8.1.1" }, @@ -1926,13 +2021,13 @@ } }, "node_modules/@microsoft/api-extractor/node_modules/@rushstack/ts-command-line": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-5.3.3.tgz", - "integrity": "sha512-c+ltdcvC7ym+10lhwR/vWiOhsrm/bP3By2VsFcs5qTKv+6tTmxgbVrtJ5NdNjANiV5TcmOZgUN+5KYQ4llsvEw==", + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-5.3.4.tgz", + "integrity": "sha512-MLkVKVEN6/2clKTrjN2B2KqKCuPxRwnNsWY7a+FCAq2EMdkj10cM8YgiBSMeGFfzM0mDMzargpHNnNzaBi9Whg==", "dev": true, "license": "MIT", "dependencies": { - "@rushstack/terminal": "0.22.3", + "@rushstack/terminal": "0.22.4", "@types/argparse": "1.0.38", "argparse": "~1.0.9", "string-argv": "~0.3.1" @@ -1994,9 +2089,9 @@ } }, "node_modules/@microsoft/api-extractor/node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2017,16 +2112,16 @@ } }, "node_modules/@microsoft/api-extractor/node_modules/minimatch": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.1.tgz", - "integrity": "sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A==", + "version": "10.2.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.3.tgz", + "integrity": "sha512-Rwi3pnapEqirPSbWbrZaa6N3nmqq4Xer/2XooiOKyV3q12ML06f7MOuc5DVH8ONZIFhwIYQ3yzPH4nt7iWHaTg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "brace-expansion": "^5.0.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -2059,9 +2154,9 @@ } }, "node_modules/@microsoft/api-extractor/node_modules/typescript": { - "version": "5.8.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", - "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -2321,6 +2416,18 @@ "node": ">= 10" } }, + "node_modules/@nodable/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nodable" + } + ], + "license": "MIT" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3191,7 +3298,6 @@ "version": "8.55.0", "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.55.0.tgz", "integrity": "sha512-ROgqtQfpH/82AQIpESPqPQe0UyWywKJsmVIqi3c5Fh+zkds5LUxnssTj3yNd1x+kxaPDVB023jAP+3ibNgeNDw==", - "dev": true, "license": "MIT", "dependencies": { "@sentry/core": "8.55.0" @@ -3200,21 +3306,10 @@ "node": ">=14.18" } }, - "node_modules/@sentry-internal/browser-utils/node_modules/@sentry/core": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.55.0.tgz", - "integrity": "sha512-6g7jpbefjHYs821Z+EBJ8r4Z7LT5h80YSWRJaylGS4nW5W5Z2KXzpdnyFarv37O7QjauzVC2E+PABmpkw5/JGA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.18" - } - }, "node_modules/@sentry-internal/feedback": { "version": "8.55.0", "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.55.0.tgz", "integrity": "sha512-cP3BD/Q6pquVQ+YL+rwCnorKuTXiS9KXW8HNKu4nmmBAyf7urjs+F6Hr1k9MXP5yQ8W3yK7jRWd09Yu6DHWOiw==", - "dev": true, "license": "MIT", "dependencies": { "@sentry/core": "8.55.0" @@ -3223,21 +3318,10 @@ "node": ">=14.18" } }, - "node_modules/@sentry-internal/feedback/node_modules/@sentry/core": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.55.0.tgz", - "integrity": "sha512-6g7jpbefjHYs821Z+EBJ8r4Z7LT5h80YSWRJaylGS4nW5W5Z2KXzpdnyFarv37O7QjauzVC2E+PABmpkw5/JGA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.18" - } - }, "node_modules/@sentry-internal/replay": { "version": "8.55.0", "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.55.0.tgz", "integrity": "sha512-roCDEGkORwolxBn8xAKedybY+Jlefq3xYmgN2fr3BTnsXjSYOPC7D1/mYqINBat99nDtvgFvNfRcZPiwwZ1hSw==", - "dev": true, "license": "MIT", "dependencies": { "@sentry-internal/browser-utils": "8.55.0", @@ -3251,7 +3335,6 @@ "version": "8.55.0", "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.55.0.tgz", "integrity": "sha512-nIkfgRWk1091zHdu4NbocQsxZF1rv1f7bbp3tTIlZYbrH62XVZosx5iHAuZG0Zc48AETLE7K4AX9VGjvQj8i9w==", - "dev": true, "license": "MIT", "dependencies": { "@sentry-internal/replay": "8.55.0", @@ -3261,26 +3344,6 @@ "node": ">=14.18" } }, - "node_modules/@sentry-internal/replay-canvas/node_modules/@sentry/core": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.55.0.tgz", - "integrity": "sha512-6g7jpbefjHYs821Z+EBJ8r4Z7LT5h80YSWRJaylGS4nW5W5Z2KXzpdnyFarv37O7QjauzVC2E+PABmpkw5/JGA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.18" - } - }, - "node_modules/@sentry-internal/replay/node_modules/@sentry/core": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.55.0.tgz", - "integrity": "sha512-6g7jpbefjHYs821Z+EBJ8r4Z7LT5h80YSWRJaylGS4nW5W5Z2KXzpdnyFarv37O7QjauzVC2E+PABmpkw5/JGA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.18" - } - }, "node_modules/@sentry-internal/tracing": { "version": "7.108.0", "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.108.0.tgz", @@ -3325,6 +3388,22 @@ "node": ">=8" } }, + "node_modules/@sentry/browser": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.55.0.tgz", + "integrity": "sha512-1A31mCEWCjaMxJt6qGUK+aDnLDcK6AwLAZnqpSchNysGni1pSn1RWSmk9TBF8qyTds5FH8B31H480uxMPUJ7Cw==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "8.55.0", + "@sentry-internal/feedback": "8.55.0", + "@sentry-internal/replay": "8.55.0", + "@sentry-internal/replay-canvas": "8.55.0", + "@sentry/core": "8.55.0" + }, + "engines": { + "node": ">=14.18" + } + }, "node_modules/@sentry/cli": { "version": "2.31.0", "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.31.0.tgz", @@ -3469,6 +3548,15 @@ "node": ">=10" } }, + "node_modules/@sentry/core": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.55.0.tgz", + "integrity": "sha512-6g7jpbefjHYs821Z+EBJ8r4Z7LT5h80YSWRJaylGS4nW5W5Z2KXzpdnyFarv37O7QjauzVC2E+PABmpkw5/JGA==", + "license": "MIT", + "engines": { + "node": ">=14.18" + } + }, "node_modules/@sentry/node": { "version": "7.108.0", "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.108.0.tgz", @@ -5197,9 +5285,9 @@ "license": "MIT" }, "node_modules/basic-ftp": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", - "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.2.2.tgz", + "integrity": "sha512-1tDrzKsdCg70WGvbFss/ulVAxupNauGnOlgpyjKzeQxzyllBLS0CGLV7tjIXTK3ZQA9/FBEm9qyFFN1bciA6pw==", "dev": true, "license": "MIT", "engines": { @@ -5213,22 +5301,23 @@ "license": "Apache-2.0" }, "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", + "license": "MIT", "dependencies": { - "bytes": "3.1.2", + "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", "type-is": "~1.6.18", - "unpipe": "1.0.0" + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8", @@ -5239,6 +5328,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -5247,14 +5337,60 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, + "node_modules/body-parser/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/body-parser/node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, "node_modules/brace-expansion": { "version": "1.1.12", @@ -5512,6 +5648,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -5539,6 +5676,22 @@ "node": ">= 0.4" } }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -6268,6 +6421,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -7728,39 +7882,39 @@ "dev": true }, "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", + "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", + "body-parser": "~1.20.5", + "content-disposition": "~0.5.4", "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", + "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.13.0", + "qs": "~6.15.1", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", + "send": "~0.19.0", + "serve-static": "~1.16.2", "setprototypeof": "1.2.0", - "statuses": "2.0.1", + "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -7879,9 +8033,9 @@ "dev": true }, "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", "dev": true, "funding": [ { @@ -7895,24 +8049,6 @@ ], "license": "BSD-3-Clause" }, - "node_modules/fast-xml-parser": { - "version": "5.3.8", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.3.8.tgz", - "integrity": "sha512-53jIF4N6u/pxvaL1eb/hEZts/cFLWZ92eCfLrNyCI0k38lettCG/Bs40W9pPwoPXyHQlKu2OUbQtiEIZK/J6Vw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT", - "dependencies": { - "strnum": "^2.1.2" - }, - "bin": { - "fxparser": "src/cli/cli.js" - } - }, "node_modules/fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -8546,6 +8682,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, "dependencies": { "es-define-property": "^1.0.0" }, @@ -8941,24 +9078,15 @@ } }, "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", + "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", "dev": true, - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, + "license": "MIT", "engines": { "node": ">= 12" } }, - "node_modules/ip-address/node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true - }, "node_modules/ip-regex": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", @@ -9404,12 +9532,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "dev": true - }, "node_modules/jsdom": { "version": "23.0.1", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-23.0.1.tgz", @@ -9823,9 +9945,9 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "dev": true, "license": "MIT" }, @@ -10907,9 +11029,10 @@ "dev": true }, "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -11262,6 +11385,21 @@ "node": ">=8" } }, + "node_modules/path-expression-matcher": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz", + "integrity": "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "dev": true, @@ -11663,12 +11801,12 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -11723,6 +11861,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -12151,6 +12290,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -12218,14 +12358,69 @@ } }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -12360,12 +12555,13 @@ } }, "node_modules/socks": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", - "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.8.tgz", + "integrity": "sha512-NlGELfPrgX2f1TAAcz0WawlLn+0r3FyhhCRpFFK2CemXenPYvzMWWZINv3eDNo9ucdwme7oCHRY0Jnbs4aIkog==", "dev": true, + "license": "MIT", "dependencies": { - "ip-address": "^9.0.5", + "ip-address": "^10.1.1", "smart-buffer": "^4.2.0" }, "engines": { @@ -12698,18 +12894,6 @@ "resolved": "resources/tools/strip-emoji", "link": true }, - "node_modules/strnum": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.0.tgz", - "integrity": "sha512-Y7Bj8XyJxnPAORMZj/xltsfo55uOiyHcU2tnAVzHUnSJR/KsEX+9RoDeXEnsXtl/CX4fAcrt64gZ13aGaWPeBg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT" - }, "node_modules/supports-color": { "version": "7.2.0", "license": "MIT", @@ -13356,13 +13540,6 @@ "node": ">= 0.4.0" } }, - "node_modules/uuid": { - "version": "8.3.2", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/v8-to-istanbul": { "version": "9.0.1", "dev": true, @@ -13640,6 +13817,7 @@ "version": "8.18.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", + "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -13666,6 +13844,21 @@ "node": ">=18" } }, + "node_modules/xml-naming": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.1.0.tgz", + "integrity": "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/xmlbuilder": { "version": "11.0.1", "license": "MIT", @@ -13839,18 +14032,29 @@ "name": "@keymanapp/auto-history-action", "license": "MIT", "dependencies": { - "@actions/core": "^1.9.1", + "@actions/core": "^1.11.1", "@actions/github": "^6.0.1", "emoji-regex": "^10.3.0", "typescript": "^5.4.5", "yargs": "^17.7.2" }, "devDependencies": { + "@types/node": "^25.7.0", "@types/semver": "^7.1.0", "@types/yargs": "^17.0.26", "semver": "^7.5.4" } }, + "resources/build/version/node_modules/@types/node": { + "version": "25.7.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.7.0.tgz", + "integrity": "sha512-z+pdZyxE+RTQE9AcboAZCb4otwcrvgHD+GlBpPgn0emDVt0ohrTMhAwlr2Wd9nZ+nihhYFxO2pThz3C5qSu2Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.21.0" + } + }, "resources/build/version/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -13914,6 +14118,13 @@ "node": ">=8" } }, + "resources/build/version/node_modules/undici-types": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.21.0.tgz", + "integrity": "sha512-w9IMgQrz4O0YN1LtB7K5P63vhlIOvC7opSmouCJ+ZywlPAlO9gIkJ+otk6LvGpAs2wg4econaCz3TvQ9xPoyuQ==", + "dev": true, + "license": "MIT" + }, "resources/build/version/node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -14056,50 +14267,41 @@ "@keymanapp/keyman-version": "*", "@keymanapp/lexical-model-layer": "*", "@keymanapp/recorder-core": "*", - "@keymanapp/web-utils": "*", "core-js": "^3.34.0", "eventemitter3": "^5.0.0", "tslib": "^2.5.2" }, "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.22.2", "jsdom": "^23.0.1", + "promise-status-async": "^1.2.10", "tsx": "^4.19.0" } }, - "web/node_modules/@sentry/browser": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.55.0.tgz", - "integrity": "sha512-1A31mCEWCjaMxJt6qGUK+aDnLDcK6AwLAZnqpSchNysGni1pSn1RWSmk9TBF8qyTds5FH8B31H480uxMPUJ7Cw==", + "web/node_modules/@playwright/test": { + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.46.1.tgz", + "integrity": "sha512-Fq6SwLujA/DOIvNC2EL/SojJnkKf/rAwJ//APpJJHRyMi1PdKrY3Az+4XNQ51N4RTbItbIByQ0jgd1tayq1aeA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "@sentry-internal/browser-utils": "8.55.0", - "@sentry-internal/feedback": "8.55.0", - "@sentry-internal/replay": "8.55.0", - "@sentry-internal/replay-canvas": "8.55.0", - "@sentry/core": "8.55.0" + "playwright": "1.46.1" + }, + "bin": { + "playwright": "cli.js" }, "engines": { - "node": ">=14.18" - } - }, - "web/node_modules/@sentry/core": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.55.0.tgz", - "integrity": "sha512-6g7jpbefjHYs821Z+EBJ8r4Z7LT5h80YSWRJaylGS4nW5W5Z2KXzpdnyFarv37O7QjauzVC2E+PABmpkw5/JGA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.18" + "node": ">=18" } }, "web/src/engine/common/web-utils": { "name": "@keymanapp/web-utils", + "dev": true, "license": "MIT", "devDependencies": { "@keymanapp/keyman-version": "*", @@ -14110,6 +14312,7 @@ }, "web/src/engine/osk/gesture-processor": { "name": "@keymanapp/gesture-recognizer", + "extraneous": true, "dependencies": { "@keymanapp/web-utils": "*", "eventemitter3": "^5.0.0" @@ -14125,7 +14328,6 @@ "license": "MIT", "dependencies": { "@keymanapp/common-types": "*", - "@keymanapp/keyman-version": "*", "@keymanapp/models-wordbreakers": "*", "@keymanapp/resources-gosh": "*" }, @@ -14160,7 +14362,6 @@ "@keymanapp/keyman-version": "*", "@keymanapp/models-templates": "*", "@keymanapp/models-wordbreakers": "*", - "@keymanapp/web-utils": "*", "es6-shim": "^0.35.5", "string.prototype.codepointat": "^0.2.1" }, @@ -14177,7 +14378,6 @@ "@keymanapp/keyman-version": "*", "@keymanapp/models-templates": "*", "@keymanapp/models-wordbreakers": "*", - "@keymanapp/web-utils": "*", "es6-shim": "^0.35.5", "string.prototype.codepointat": "^0.2.1", "string.prototype.startswith": "^0.2.0" @@ -14193,7 +14393,7 @@ }, "web/src/engine/sentry-manager": { "name": "@keymanapp/web-sentry-manager", - "dev": true, + "extraneous": true, "license": "MIT", "dependencies": { "@keymanapp/keyman-version": "*", @@ -14206,11 +14406,6 @@ "web/src/tools/testing/recorder-core": { "name": "@keymanapp/recorder-core", "license": "MIT", - "dependencies": { - "@keymanapp/common-types": "*", - "@keymanapp/keyman-version": "*", - "@keymanapp/web-utils": "*" - }, "devDependencies": { "typescript": "^5.4.5" } diff --git a/package.json b/package.json index 697bf312e1..7999772548 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "private": true, "devDependencies": { "@microsoft/api-documenter": "^7.28.0", - "@microsoft/api-extractor": "^7.57.6", + "@microsoft/api-extractor": "^7.58.1", "@types/chai": "^4.3.14", "@types/mocha": "^10.0.10", "@types/node": "^20.4.1", @@ -23,7 +23,7 @@ "eslint-plugin-n": "^15.7.0", "eslint-plugin-promise": "^6.1.1", "mocha": "^11.2.2", - "playwright": "^1.46.1", + "playwright": "1.46.1", "sinon": "^17.0.1", "source-map-support": "^0.5.21", "tslib": "^2.5.2", @@ -53,11 +53,11 @@ "common/test/resources", "common/web/keyman-version", "common/web/langtags", + "common/web/sentry-manager", "common/web/types", "common/tools/sourcemap-path-remapper", "common/tools/hextobin", "web", - "web/src/engine/osk/gesture-processor", "web/src/engine/predictive-text/*" ], "dependencies": { diff --git a/resources/build/builder-full.inc.sh b/resources/build/builder-full.inc.sh index e937582565..ca4d7c38ac 100644 --- a/resources/build/builder-full.inc.sh +++ b/resources/build/builder-full.inc.sh @@ -14,7 +14,7 @@ set -eu # Prevents 'clear' on exit of mingw64 bash shell SHLVL=0 -function _builder_full_not_a_builder_script() { +function __builder_full_not_a_builder_script() { if ! _builder_has_function_been_called builder_describe; then builder_echo warning "builder_describe was never called; script is not a valid builder script" exit 1 @@ -25,7 +25,7 @@ function _builder_full_not_a_builder_script() { fi } -trap _builder_full_not_a_builder_script exit +trap __builder_full_not_a_builder_script exit # This will also import /resources/builder.inc.sh . "${BASH_SOURCE[0]%/*}/builder-basic.inc.sh" diff --git a/resources/build/ci/npm-publish.sh b/resources/build/ci/npm-publish.sh index e9b522e2aa..1e32e2e43a 100755 --- a/resources/build/ci/npm-publish.sh +++ b/resources/build/ci/npm-publish.sh @@ -24,6 +24,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" . "$KEYMAN_ROOT/resources/build/ci/ci-publish.inc.sh" . "$KEYMAN_ROOT/resources/build/ci/npm-packages.inc.sh" . "$KEYMAN_ROOT/resources/build/minimum-versions.inc.sh" +. "$KEYMAN_ROOT/resources/locate_emscripten.inc.sh" builder_describe \ "Publish @keymanapp packages to NPM" \ @@ -107,17 +108,10 @@ function install_emscripten() { local EMSDK_TEMP EMSDK_TEMP=$(mktemp -d) - pushd "${EMSDK_TEMP}" - git clone https://github.com/emscripten-core/emsdk.git - cd emsdk - ./emsdk install "${KEYMAN_MIN_VERSION_EMSCRIPTEN}" - ./emsdk activate "${KEYMAN_MIN_VERSION_EMSCRIPTEN}" - cd upstream/emscripten - npm install - echo "EMSCRIPTEN_BASE=$(pwd)" >> $GITHUB_ENV - EMSCRIPTEN_BASE="$(pwd)" + install_emscripten_into "${EMSDK_TEMP}" + EMSCRIPTEN_BASE="${EMSDK_TEMP}/upstream/emscripten" export EMSCRIPTEN_BASE - popd + echo "EMSCRIPTEN_BASE=${EMSCRIPTEN_BASE}" >> "${GITHUB_ENV}" } function install_meson() { diff --git a/resources/build/mac/mac.inc.sh b/resources/build/mac/mac.inc.sh index 5a00793fa1..ffe10f8574 100644 --- a/resources/build/mac/mac.inc.sh +++ b/resources/build/mac/mac.inc.sh @@ -117,13 +117,16 @@ function _mac_generate_xcode_environment_definition_script() { # If there is no logfile, then this function will not emit anything. # mac_print_xcode_build_script_logs() { + local ret_code="$1" local SCRIPT_LOG="$KEYMAN_ROOT/xcodebuild-scripts.log" if [ -f "$SCRIPT_LOG" ]; then - builder_echo "mac_print_xcode_build_script_logs: reporting script results from previous xcode build" + builder_echo "mac_print_xcode_build_script_logs: reporting script results from previous xcode build (exit code $ret_code)" cat "$SCRIPT_LOG" rm "$SCRIPT_LOG" builder_echo "mac_print_xcode_build_script_logs: done" echo + elif [[ $1 != 0 ]]; then + builder_echo error "mac_print_xcode_build_script_logs: build failed with $ret_code; expected $SCRIPT_LOG to exist" fi } @@ -133,6 +136,9 @@ mac_print_xcode_build_script_logs() { mac_xcodebuild() { typeset cmnd="$*" typeset ret_code + + builder_echo "mac_xcodebuild: start xcodebuild $cmnd" + local hasSetErrExit=false if [ -o errexit ]; then hasSetErrExit=true @@ -144,7 +150,10 @@ mac_xcodebuild() { set -e fi - mac_print_xcode_build_script_logs + mac_print_xcode_build_script_logs $ret_code + + builder_echo "mac_xcodebuild: finish xcodebuild $cmnd" + if [ $ret_code != 0 ]; then builder_die "Build failed! Error: [$ret_code] when executing command: 'xcodebuild $cmnd'" fi diff --git a/resources/build/mac/xcode-utils.inc.sh b/resources/build/mac/xcode-utils.inc.sh index df4bd7d5a2..db1e3b1fda 100644 --- a/resources/build/mac/xcode-utils.inc.sh +++ b/resources/build/mac/xcode-utils.inc.sh @@ -174,6 +174,7 @@ function phaseSentryDsymUpload() { function logScriptsToFile() { local SCRIPT_LOG="$KEYMAN_ROOT/xcodebuild-scripts.log" exec >> "$SCRIPT_LOG" 2>&1 + echo "Logging xcode build phase script to $KEYMAN_ROOT/xcodebuild-scripts.log" } logScriptsToFile diff --git a/resources/build/minimum-versions.inc.sh b/resources/build/minimum-versions.inc.sh index f4645ecdf8..5ff9e32b46 100644 --- a/resources/build/minimum-versions.inc.sh +++ b/resources/build/minimum-versions.inc.sh @@ -28,7 +28,7 @@ KEYMAN_MIN_TARGET_VERSION_WEB_SAFARI=13.0 # iOS 13.0, macOS 10.13.6+ # Dependency minimum versions KEYMAN_MIN_VERSION_NODE_MAJOR=20 # node version source of truth is /package.json:/engines/node; use KEYMAN_USE_NVM to automatically update KEYMAN_MIN_VERSION_NPM=10.5.1 # 10.5.0 has bug, discussed in #10350 -KEYMAN_MIN_VERSION_EMSCRIPTEN=3.1.58 # Use KEYMAN_USE_EMSDK to automatically update to this version +KEYMAN_MIN_VERSION_EMSCRIPTEN=3.1.64 # Use KEYMAN_USE_EMSDK to automatically update to this version KEYMAN_MIN_VERSION_VISUAL_STUDIO=2022 # Visual Studio 2022, see /docs/build/windows.md for workloads and components KEYMAN_MIN_VERSION_MESON=1.0.0 # TODO: rename meson_options.txt to meson.options when updating to >= 1.1, see #15127. diff --git a/resources/build/node.inc.sh b/resources/build/node.inc.sh index 013020dbb3..88cf3de205 100644 --- a/resources/build/node.inc.sh +++ b/resources/build/node.inc.sh @@ -86,3 +86,7 @@ _node_select_version_with_nvm() { builder_die "Attempted to select node.js version $REQUIRED_NODE_VERSION but found $CURRENT_NODE_VERSION instead" fi } + +node_es_bundle() { + node "${KEYMAN_ROOT}/common/tools/es-bundling/build/common-bundle.mjs" "$@" +} \ No newline at end of file diff --git a/resources/build/version/package.json b/resources/build/version/package.json index 7eaf125cdc..db75014787 100644 --- a/resources/build/version/package.json +++ b/resources/build/version/package.json @@ -2,13 +2,14 @@ "description": "Automatically updates HISTORY.md based on pull requests", "type": "module", "dependencies": { - "@actions/core": "^1.9.1", + "@actions/core": "^1.11.1", "@actions/github": "^6.0.1", "emoji-regex": "^10.3.0", "typescript": "^5.4.5", "yargs": "^17.7.2" }, "devDependencies": { + "@types/node": "^25.7.0", "@types/semver": "^7.1.0", "@types/yargs": "^17.0.26", "semver": "^7.5.4" diff --git a/resources/build/zip.inc.sh b/resources/build/zip.inc.sh index 8ab4aa77fc..5748bc6ab2 100644 --- a/resources/build/zip.inc.sh +++ b/resources/build/zip.inc.sh @@ -124,7 +124,12 @@ function add_zip_files() { if [[ -z "${SEVENZ+x}" ]]; then if builder_is_windows; then if [[ -z "${SEVENZ_HOME+x}" ]]; then - SEVENZ="$(command -v 7z.exe)" + SEVENZ="$(command -v 7z.exe || true)" + if [[ -z "${SEVENZ}" ]]; then + builder_die "7z.exe not found on path. Please install 7-Zip " \ + "and ensure 7z.exe is on the path or set SEVENZ_HOME " \ + "environment variable to the folder containing 7z.exe." + fi else SEVENZ="${SEVENZ_HOME}/7z.exe" fi diff --git a/resources/docker-images/README.md b/resources/docker-images/README.md index 2406ba7dee..51de3ff72d 100644 --- a/resources/docker-images/README.md +++ b/resources/docker-images/README.md @@ -154,7 +154,7 @@ For example to debug the integration tests in Docker: ```bash resources/docker-images/run.sh --remote-debug :linux -- linux/ibus-keyman/tests/scripts/run-tests.sh \ - --no-x11 --remote-debug -- --directory /home/build/.local/share/keyman/test_kmx k_001___basic_input_unicodei + --no-x11 --remote-debug -- --directory /home/build/.local/share/keyman/test_kmx k_0100___basic_input_unicodei ``` * then attach debugger in vscode diff --git a/resources/locate_emscripten.inc.sh b/resources/locate_emscripten.inc.sh index 50c8534ef4..d212b7a427 100644 --- a/resources/locate_emscripten.inc.sh +++ b/resources/locate_emscripten.inc.sh @@ -38,7 +38,7 @@ locate_emscripten() { if [[ -z "${EMSCRIPTEN_BASE:-}" ]]; then if [[ -z "${EMCC:-}" ]]; then local EMCC - EMCC="$(command -v "${EMCC_EXECUTABLE}")" + EMCC="$(command -v "${EMCC_EXECUTABLE}" || true)" [[ -z "${EMCC}" ]] && builder_die "locate_emscripten: Could not locate emscripten (${EMCC_EXECUTABLE}) on the path or with \$EMCC or \$EMSCRIPTEN_BASE" fi [[ -f "${EMCC}" && ! -x "${EMCC}" ]] && builder_die "locate_emscripten: Variable EMCC (${EMCC}) points to ${EMCC_EXECUTABLE} but it is not executable" @@ -117,3 +117,22 @@ _select_emscripten_version_with_emsdk() { fi ) } + +install_emscripten_into() { + if [[ -z "${1:-}" ]]; then + builder_die "${FUNCNAME[0]} requires a directory argument" + fi + + local EMSDK_DIR=$1 + builder_heading "Installing emscripten into ${EMSDK_DIR}" + + mkdir -p "${EMSDK_DIR}" + ( + cd "${EMSDK_DIR}" + git clone https://github.com/emscripten-core/emsdk.git . + ./emsdk install "${KEYMAN_MIN_VERSION_EMSCRIPTEN}" + ./emsdk activate "${KEYMAN_MIN_VERSION_EMSCRIPTEN}" + cd upstream/emscripten + npm install + ) +} diff --git a/resources/teamcity/linux/keyman-linux-release.sh b/resources/teamcity/linux/keyman-linux-release.sh index 61c5d93cf4..9cc1b76a1b 100755 --- a/resources/teamcity/linux/keyman-linux-release.sh +++ b/resources/teamcity/linux/keyman-linux-release.sh @@ -61,15 +61,11 @@ function _make_release_source_tarball() { ./scripts/reconf.sh PKG_CONFIG_PATH="${KEYMAN_ROOT}/core/build/arch/release/meson-private" ./scripts/dist.sh mv dist/*.tar.xz "upload/${KEYMAN_VERSION}/" - builder_echo heading "Make source for packaging" - PKG_CONFIG_PATH="${KEYMAN_ROOT}/core/build/arch/release/meson-private" ./scripts/dist.sh origdist - mv "dist/keyman_${KEYMAN_VERSION}.orig.tar.xz" "dist/keyman_${KEYMAN_VERSION}.pkg.tar.xz" - mv dist/*.tar.xz "upload/${KEYMAN_VERSION}/" ( cd "upload/${KEYMAN_VERSION}" sha256sum ./*.tar.xz > SHA256SUMS - builder_echo end "make source tarball" success "Make source tarball" ) + builder_echo end "make source tarball" success "Make source tarball" } function _sign_source_tarball() { @@ -100,7 +96,6 @@ function _publish_to_downloads() { chmod a+r "${UPLOAD_DIR}"/* write_download_info "${UPLOAD_DIR}" "keyman-${KEYMAN_VERSION}.tar.xz" "Keyman for Linux source tarball" tar.xz linux - write_download_info "${UPLOAD_DIR}" "keyman_${KEYMAN_VERSION}.pkg.tar.xz" "Keyman for Linux source for packaging" tar.xz linux tc_rsync_upload "${UPLOAD_DIR}" "linux/${KEYMAN_TIER}" builder_echo end "publish to downloads" success "Publish to downloads.keyman.com" @@ -112,7 +107,7 @@ function _publish_to_launchpad() { git reset --hard /usr/lib/gnupg/gpg-preset-passphrase --passphrase "${GPGKEYPW}" --preset "${GPGKEYGRIP}" - UPLOAD=yes "${KEYMAN_ROOT}/linux/scripts/launchpad.sh" + "${KEYMAN_ROOT}/linux/scripts/launchpad.sh" --upload /usr/lib/gnupg/gpg-preset-passphrase --forget "${GPGKEYGRIP}" || true builder_echo end "upload to launchpad" success "Upload to launchpad" diff --git a/resources/tools/check-markdown/build.sh b/resources/tools/check-markdown/build.sh index 01dd9d81c9..c6fb2bd35c 100755 --- a/resources/tools/check-markdown/build.sh +++ b/resources/tools/check-markdown/build.sh @@ -16,7 +16,7 @@ builder_describe "Check markdown internal links" \ "build" builder_describe_outputs \ - configure "${THIS_SCRIPT_PATH}/node_modules" \ + configure /node_modules \ build build/index.js builder_parse "$@" diff --git a/tsconfig.base.json b/tsconfig.base.json index 6880709c17..4ee9ff4832 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -22,7 +22,7 @@ "declaration": true, "declarationMap": true, - "baseUrl": ".", + "baseUrl": "./", "paths": { "@keymanapp/common-types": ["./common/web/types/src/main"], @@ -30,7 +30,6 @@ "@keymanapp/keyman": ["./web" ], "@keymanapp/models-templates": ["./web/src/engine/predictive-text/templates/"], "@keymanapp/models-wordbreakers": ["./web/src/engine/predictive-text/wordbreakers"], - "@keymanapp/web-utils": ["./web/src/engine/common/web-utils"], "@keymanapp/lm-message-types": ["./web/src/engine/predictive-text/types"], "@keymanapp/keyman-version": ["./common/web/keyman-version"], "@keymanapp/ldml-keyboard-constants": [ "./core/include/ldml" ], diff --git a/tsconfig.json b/tsconfig.json index e7d0db1776..b5586ec174 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,6 +4,7 @@ { "path": "./common/tools/hextobin/" }, + { "path": "./common/web/sentry-manager" }, { "path": "./common/web/keyman-version" }, { "path": "./common/web/langtags" }, { "path": "./common/web/types" }, @@ -39,18 +40,5 @@ { "path": "./resources/build/version/" }, { "path": "./web/src/tsconfig.all.json" }, - { "path": "./web/src/engine/common/web-utils" }, - { "path": "./web/src/engine/predictive-text/types/" }, - { "path": "./web/src/engine/predictive-text/templates" }, - { "path": "./web/src/engine/predictive-text/wordbreakers" }, - { "path": "./web/src/engine/predictive-text/worker-main/tsconfig.all.json" }, - { "path": "./web/src/engine/predictive-text/worker-thread" }, - { "path": "./web/src/engine/osk/gesture-processor/tsconfig.json" }, - { "path": "./web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/tsconfig.json" }, - { "path": "./web/src/engine/sentry-manager/src" }, - - { "path": "./web/src/tools/testing/recorder" }, - // { "path": "./web/tools/recorder/tsconfig.json" }, - // { "path": "./web/tools/sourcemap-root/tsconfig.json" }, ] } diff --git a/web/.gitignore b/web/.gitignore index d7d1e04036..7e33d0cd87 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -11,4 +11,8 @@ node_modules/ source/environment.inc.ts **/.idea/**/*.xml **/*.iml -**/*.kpj.user \ No newline at end of file +**/*.kpj.user + +# Playwright +playwright-report/ +test-results/ diff --git a/web/.mocharc.json b/web/.mocharc.json deleted file mode 100644 index e8ecf2c60f..0000000000 --- a/web/.mocharc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/mocharc.json", - "require": "tsx" -} diff --git a/web/NOTICE b/web/NOTICE deleted file mode 100644 index 116bef6767..0000000000 --- a/web/NOTICE +++ /dev/null @@ -1,5 +0,0 @@ - Tavultesoft KeymanWeb 2.0 - Copyright 2005-2014 Tavultesoft Pty Ltd - - This product includes software developed at - Tavultesoft (http://www.tavultesoft.com/). diff --git a/web/README.md b/web/README.md index 7f7415c698..de8f638e5f 100644 --- a/web/README.md +++ b/web/README.md @@ -29,8 +29,9 @@ src/test/auto A Node-driven test suite for automated testing of Key ## Usage -Open **index.html** or **samples/index.html** in your browser. Be sure to -compile Keyman Engine for Web before viewing the pages. +Start the test server by running `./build.sh start`, then open +your browser to http://localhost:3000. Be sure to compile Keyman Engine +for Web before viewing the pages. Refer to the samples for usage details. @@ -84,7 +85,7 @@ graph TD; KeyboardSpec["/web/src/engine/keyboard"]; JSProc["/web/src/engine/js-processor"]; OSK-->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 cbbaaca183..ca253ab82c 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:tools/building -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:common/web-utils -# Uses engine/dom-utils and engine/interfaces -builder_run_child_actions build:engine/osk +builder_run_child_actions build:engine +# builder_run_child_actions build:engine/predictive-text -# Uses engine/element-wrappers -builder_run_child_actions build:engine/attachment - -# 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,67 @@ 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 + builder_echo "Running browser-based tests..." + 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 + builder_echo "Running integration tests..." + 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 + builder_echo "Running end-to-end tests..." + 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 +229,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 9008d56a50..f9c4e4263d 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 c88c081900..2d222bc34c 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/guide/adding-keyboards.md b/web/docs/engine/guide/adding-keyboards.md index 221f495de1..957df80270 100644 --- a/web/docs/engine/guide/adding-keyboards.md +++ b/web/docs/engine/guide/adding-keyboards.md @@ -8,8 +8,8 @@ There are multiple ways to add and install keyboards into your KeymanWeb install The most efficient way to utilize a keyboard is to obtain a local copy of it and place this copy in a static location on your website. Once this is done, it can be directly linked into KeymanWeb as follows. -```c -keyman.addKeyboards({ +```typescript +await keyman.addKeyboards({ id:'us', // The keyboard's unique identification code. name:'English', // The keyboard's user-readable name. language:{ @@ -22,7 +22,7 @@ keyman.addKeyboards({ Custom fonts may also be utilized via the `language.font` property. For example: -```c +```typescript font:{ family:'LaoWeb', source:['../font/saysettha_web.ttf','../font/saysettha_web.woff','../font/saysettha_web.eot'] @@ -33,16 +33,16 @@ font:{ To obtain the default Keyman keyboard for a given language, call the following function. -```c -keyman.addKeyboardsForLanguage('Dzongkha'); +```typescript +await keyman.addKeyboardsForLanguage('Dzongkha'); ``` This example would find the default keyboard for the Dzongkha language. This method will fail if the name doesn't perfectly match any language found in the CDN's repository. Alternatively, languages may be looked up via their BCP 47 language code as follows: -```c -keyman.addKeyboards('@he') +```typescript +await keyman.addKeyboards('@he'); ``` The `@` prefix indicates the use of the BCP 47 language code, which in this case corresponds with Hebrew. @@ -51,8 +51,8 @@ The `@` prefix indicates the use of the BCP 47 language code, which in this case To obtain a specific keyboard by name or by keyboard name and language code as a pair, see the following: -```c -keyman.addKeyboards('french','sil_euro_latin@sv','sil_euro_latin@no') +```typescript +await keyman.addKeyboards('french', 'sil_euro_latin@sv', 'sil_euro_latin@no'); ``` This will install three keyboards - one for French (named, quite simply, "French") and two copies of the EuroLatin keyboard - one for Swedish and one for Norwegian. diff --git a/web/docs/engine/guide/examples/__auto-control.html b/web/docs/engine/guide/examples/__auto-control.html index 050e03a9f0..c2a8b472b0 100644 --- a/web/docs/engine/guide/examples/__auto-control.html +++ b/web/docs/engine/guide/examples/__auto-control.html @@ -1,20 +1,17 @@ + - - @@ -28,4 +25,4 @@ Back to Document - \ No newline at end of file + diff --git a/web/docs/engine/guide/examples/__control-by-control.html b/web/docs/engine/guide/examples/__control-by-control.html index 93a481a75f..f694b582ec 100644 --- a/web/docs/engine/guide/examples/__control-by-control.html +++ b/web/docs/engine/guide/examples/__control-by-control.html @@ -1,35 +1,33 @@ + - @@ -38,7 +36,7 @@

Email to (KeymanWeb not enabled)

-

Subject (Defaults to 'English' or 'off' unless on a touch-based device)

+

Subject (Defaults to '(System keyboard)' or 'off' unless on a touch-based device)

Message body (Defaults to 'LaoKeys')

@@ -46,4 +44,4 @@ Back to Document - \ No newline at end of file + diff --git a/web/docs/engine/guide/examples/__first-example.html b/web/docs/engine/guide/examples/__first-example.html index feb96f4daa..24a58c4891 100644 --- a/web/docs/engine/guide/examples/__first-example.html +++ b/web/docs/engine/guide/examples/__first-example.html @@ -6,15 +6,14 @@ - @@ -23,4 +22,4 @@ Back to Document - \ No newline at end of file + diff --git a/web/docs/engine/guide/examples/__full-manual-control.html b/web/docs/engine/guide/examples/__full-manual-control.html index 5a70c7183f..6313c13518 100644 --- a/web/docs/engine/guide/examples/__full-manual-control.html +++ b/web/docs/engine/guide/examples/__full-manual-control.html @@ -1,45 +1,39 @@ + - diff --git a/web/docs/engine/guide/examples/__manual-control.html b/web/docs/engine/guide/examples/__manual-control.html index 4680400e4d..a1cfa72c83 100644 --- a/web/docs/engine/guide/examples/__manual-control.html +++ b/web/docs/engine/guide/examples/__manual-control.html @@ -1,29 +1,27 @@ + - - - @@ -38,4 +36,4 @@ Back to Document - \ No newline at end of file + diff --git a/web/docs/engine/guide/examples/automatic-control.md b/web/docs/engine/guide/examples/automatic-control.md index c804556e18..d21946aa53 100644 --- a/web/docs/engine/guide/examples/automatic-control.md +++ b/web/docs/engine/guide/examples/automatic-control.md @@ -2,28 +2,28 @@ title: Automatic Mode Example --- -This page shows how to include a local keyboard from an arbitrary location in your website's file structure. +This page shows how to include a local keyboard from an arbitrary location +in your website's file structure. -In this example, we use only the LaoKey keyboard. Please click [this link](./__auto-control.html) to open the test page. +In this example, we use only the LaoKey keyboard. Please click +[this link](./__auto-control.html) to open the test page. ## Code Walkthrough ```html - + @@ -31,8 +31,6 @@ In this example, we use only the LaoKey keyboard. Please click [this link](./__a ``` -As you can see above, the second line in the code snippet above references the LaoKey keyboard loader JavaScript file. This is a small stub file, typically less than 200 bytes, that defines the name and actual location of the real keyboard file (in this case, **laokeys.js**). When a page may reference many keyboards, this saves downloading potentially hundreds of kilobytes of unused Javascript keyboards - the keyboard is downloaded when it is first selected by the user. - ## API References On initialization: [`keyman.init()`](../../reference/core/init). diff --git a/web/docs/engine/guide/examples/control-by-control.md b/web/docs/engine/guide/examples/control-by-control.md index 974338ef1f..b3b0b9b3a5 100644 --- a/web/docs/engine/guide/examples/control-by-control.md +++ b/web/docs/engine/guide/examples/control-by-control.md @@ -2,7 +2,10 @@ title: Control-by-Control Example --- -In this example, a simulated webmail form, the default and permissible keyboard for each control is managed by the web page. We use the automatic mode for simplicity of demonstration. We also link to the CDN for KeymanWeb in this example. Please click [this link](__control-by-control.html) to open the test page. +In this example, a simulated webmail form, the default and permissible keyboard for each control +is managed by the web page. We use the automatic mode for simplicity of demonstration. We also +link to the CDN for KeymanWeb in this example. Please click [this link](__control-by-control.html) +to open the test page. ## Code Walkthrough @@ -10,28 +13,23 @@ Include the following script in the HEAD of your page: ```js ``` @@ -40,18 +38,18 @@ Also include the following HTML code: ```html - - + + - - - - ``` + --- -**Note:** In this example we disabled the first element (`document.f.address`) by API call. A later API call can re-enable KeymanWeb for this control should it fit the page's design. Alternatively, this can be done by instead adding the class `'kmw-disabled'` to the control. This will permanently block KeymanWeb from handling its input. +**Note:** In this example we disabled the first element (`document.f.address`) by API call. A +later API call can re-enable KeymanWeb for this control should it fit the page's design. +Alternatively, this can be done by instead adding the class `'kmw-disabled'` to the control. This +will permanently block KeymanWeb from handling its input. --- diff --git a/web/docs/engine/guide/examples/full-manual-control.md b/web/docs/engine/guide/examples/full-manual-control.md index e9e8d2908a..39be4d34b3 100644 --- a/web/docs/engine/guide/examples/full-manual-control.md +++ b/web/docs/engine/guide/examples/full-manual-control.md @@ -2,7 +2,9 @@ title: Manual Control - Custom Interface --- -In this example, the web page designer has opted for their own user interface instead of the KeymanWeb interface. The keyboards in the selector are populated from the KeymanWeb list of keyboards. Please click [this link](__full-manual-control.html) to open the test page. +In this example, the web page designer has opted for their own user interface instead of the +KeymanWeb interface. The keyboards in the selector are populated from the KeymanWeb list of +keyboards. Please click [this link](__full-manual-control.html) to open the test page. ## Code Walkthrough @@ -12,31 +14,25 @@ Include the following script in the HEAD of your page: + - - - ``` - File: [unified_loader.js](js/unified_loader.js) diff --git a/web/docs/engine/guide/examples/js/devanagari_inscript_load.js b/web/docs/engine/guide/examples/js/devanagari_inscript_load.js deleted file mode 100644 index c2fd4d90fe..0000000000 --- a/web/docs/engine/guide/examples/js/devanagari_inscript_load.js +++ /dev/null @@ -1,2 +0,0 @@ -/*(C) Copyright 1994-2006 Tavultesoft Pty Ltd. All Rights Reserved. Details: keymanweb.com*/ -KeymanWeb.KRS(new Stub_Keyboard_devanagari_inscript()); function Stub_Keyboard_devanagari_inscript() {this.KF="devanagari_inscript.js";this.KI="Keyboard_devanagari_inscript";this.KN="Devanagari (INSCRIPT)";} diff --git a/web/docs/engine/guide/examples/js/european2_load.js b/web/docs/engine/guide/examples/js/european2_load.js deleted file mode 100644 index 96ecc9a9be..0000000000 --- a/web/docs/engine/guide/examples/js/european2_load.js +++ /dev/null @@ -1 +0,0 @@ -KeymanWeb.KRS(new Stub_Keyboard_european2()); function Stub_Keyboard_european2() {this.KF="european2-1.6.js";this.KI="Keyboard_european2";this.KN="EuroLatin2 Keyboard";} \ No newline at end of file diff --git a/web/docs/engine/guide/examples/js/hebrew_load.js b/web/docs/engine/guide/examples/js/hebrew_load.js deleted file mode 100644 index ebcd50e4d0..0000000000 --- a/web/docs/engine/guide/examples/js/hebrew_load.js +++ /dev/null @@ -1,2 +0,0 @@ -/*(C) Copyright 1994-2006 Tavultesoft Pty Ltd. All Rights Reserved. Details: keymanweb.com*/ -KeymanWeb.KRS(new Stub_Keyboard_hebrew()); function Stub_Keyboard_hebrew() {this.KF="hebrew.js";this.KI="Keyboard_hebrew";this.KN="Hebrew";} diff --git a/web/docs/engine/guide/examples/js/keymanwebtest_load.js b/web/docs/engine/guide/examples/js/keymanwebtest_load.js deleted file mode 100644 index c06cbba38e..0000000000 --- a/web/docs/engine/guide/examples/js/keymanwebtest_load.js +++ /dev/null @@ -1,2 +0,0 @@ -/*(C) Copyright 1994-2006 Tavultesoft Pty Ltd. All Rights Reserved. Details: keymanweb.com*/ -KeymanWeb.KRS(new Stub_Keyboard_keymanwebtest()); function Stub_Keyboard_keymanwebtest() {this.KF="keymanwebtest.js";this.KI="Keyboard_keymanwebtest";this.KN="KeymanWeb Test";} diff --git a/web/docs/engine/guide/examples/js/korean_korda_load.js b/web/docs/engine/guide/examples/js/korean_korda_load.js deleted file mode 100644 index 7fa96e4bc0..0000000000 --- a/web/docs/engine/guide/examples/js/korean_korda_load.js +++ /dev/null @@ -1,2 +0,0 @@ -/*(C) Copyright 1994-2006 Tavultesoft Pty Ltd. All Rights Reserved. Details: keymanweb.com*/ -KeymanWeb.KRS(new Stub_Keyboard_korean_korda()); function Stub_Keyboard_korean_korda() {this.KF="korean_korda.js";this.KI="Keyboard_korean_korda";this.KN="Korean (KORDA) - 30 Day Evaluation";} diff --git a/web/docs/engine/guide/examples/js/korean_morse_load.js b/web/docs/engine/guide/examples/js/korean_morse_load.js deleted file mode 100644 index fb7abbdb91..0000000000 --- a/web/docs/engine/guide/examples/js/korean_morse_load.js +++ /dev/null @@ -1,2 +0,0 @@ -/*(C) Copyright 1994-2006 Tavultesoft Pty Ltd. All Rights Reserved. Details: keymanweb.com*/ -KeymanWeb.KRS(new Stub_Keyboard_korean_morse()); function Stub_Keyboard_korean_morse() {this.KF="korean_morse.js";this.KI="Keyboard_korean_morse";this.KN="Korean (Morse) - 30 Day Evaluation";} diff --git a/web/docs/engine/guide/examples/js/laokeys_load.js b/web/docs/engine/guide/examples/js/laokeys_load.js deleted file mode 100644 index 522e21fd5a..0000000000 --- a/web/docs/engine/guide/examples/js/laokeys_load.js +++ /dev/null @@ -1,7 +0,0 @@ -/*(C) Copyright 1994-2021 SIL International. All Rights Reserved. Details: keymanweb.com*/ -keyman.addKeyboards({ - id: "laokeys", - name: "Lao (Phonetic)", - languages:{id:'lo',name:'Lao'}, - filename: "./js/laokeys.js" -}); \ No newline at end of file diff --git a/web/docs/engine/guide/examples/js/unified_loader.js b/web/docs/engine/guide/examples/js/unified_loader.js index 2987ce3413..f4a695d24a 100644 --- a/web/docs/engine/guide/examples/js/unified_loader.js +++ b/web/docs/engine/guide/examples/js/unified_loader.js @@ -1,16 +1,18 @@ -/*(C) Copyright 2021 SIL International. All Rights Reserved. Details: keymanweb.com*/ -function loadKeyboards() { - // Uses an older type of keyboard stub definition. - var KWK={ - "devanagari_inscript":{KN:"Devanagari (INSCRIPT)", KLC:"hi", KL:"Hindi"}, - "european2":{KN:"EuroLatin2", KLC:"en", KL:"English"}, - "hebrew":{KN:"Hebrew", KLC:"he", KL:"Hebrew"}, - "korean_korda":{KN:"Korean (KORDA) - 30 Day Evaluation", KLC:"ko", KL:"Korean"}, - "korean_morse":{KN:"Korean (Morse) - 30 Day Evaluation", KLC:"ko", KL:"Korean"}, - "laokeys":{KN:"Lao (Phonetic)", KLC:"lo", KL:"Lao"} - }; +/* + * Keyman is copyright (C) SIL Global. MIT License. + */ +async function loadKeyboards() { + const keyboardList = [ + { id: 'devanagari_inscript', name: 'Devanagari (INSCRIPT)', languages: { id: 'hi', name: 'Hindi' }, filename: './js/devanagari_inscript.js' }, + { id: 'european2', name: 'EuroLatin2', languages: { id: 'en', name: 'English' }, filename: './js/european2.js' }, + { id: 'hebrew', name: 'Hebrew', languages: { id: 'he', name: 'Hebrew' }, filename: './js/hebrew.js' }, + { id: 'korean_korda', name: 'Korean (KORDA)', languages: { id: 'ko', name: 'Korean' }, filename: './js/korean_korda.js' }, + { id: 'korean_morse', name: 'Korean (Morse)', languages: { id: 'ko', name: 'Korean' }, filename: './js/korean_morse.js' }, + // using a KeyboardStub would allow to customize e.g. which font the keyboard uses + { KF: "./js/laokeys.js", KI: "Keyboard_laokeys", KN: "Lao (Phonetic)", KL: "Lao", KLC: "lo" } + ]; - for(var n in KWK) { - KeymanWeb.registerStub({KF:"./js/" + n+".js", KI:"Keyboard_"+n, KN:KWK[n].KN, KL:KWK[n].KL, KLC:KWK[n].KLC}); - } + return keyman.addKeyboards(keyboardList).catch(function(err) { + console.error('keyman.addKeyboards failed with '+errToString(err)+' for '+JSON.stringify(keyboardList)); + }); } diff --git a/web/docs/engine/guide/examples/manual-control.md b/web/docs/engine/guide/examples/manual-control.md index 1087c518c8..d67db736e9 100644 --- a/web/docs/engine/guide/examples/manual-control.md +++ b/web/docs/engine/guide/examples/manual-control.md @@ -10,21 +10,19 @@ Include the following script in the HEAD of your page: ```js - - + - - - ``` -- File: [laokeys_load.js](js/laokeys_load.js) - And finally, include the control img for KeymanWeb: ```html @@ -61,9 +52,11 @@ And finally, include the control img for KeymanWeb: ## API References On programmatically setting the keyboard: + - [`keyman.setActiveKeyboard()`](../../reference/core/setActiveKeyboard). On managing the visibility of the OSK: + - [`keyman.osk.hide()`](../../reference/osk/hide) - [`keyman.osk.show()`](../../reference/osk/show). diff --git a/web/docs/engine/guide/get-started.md b/web/docs/engine/guide/get-started.md index 8d3cd1baa4..96e7a699f4 100644 --- a/web/docs/engine/guide/get-started.md +++ b/web/docs/engine/guide/get-started.md @@ -22,12 +22,10 @@ The source code for the page may be seen below. diff --git a/web/docs/engine/reference/core/addKeyboards.md b/web/docs/engine/reference/core/addKeyboards.md index 4a2dc77f5d..e5f48680a7 100644 --- a/web/docs/engine/reference/core/addKeyboards.md +++ b/web/docs/engine/reference/core/addKeyboards.md @@ -9,7 +9,7 @@ Adds keyboards to KeymanWeb. ## Syntax ```js -keyman.addKeyboards(spec[, spec...]) +await keyman.addKeyboards([spec...]) ``` ### Parameters @@ -26,7 +26,9 @@ keyman.addKeyboards(spec[, spec...]) fulfilled upon adding keyboards. The promise is an array containing a combination of the following: -* successfully registered keyboard objects which define some or all of these [properties](../keyboard_properties) + +* successfully registered keyboard objects which define some or all of these + [properties](../keyboard_properties) * [ErrorStub](../keyboard_registration_errors) objects for keyboards that failed to register ## Description @@ -35,7 +37,8 @@ The keyboard spec can be a string or an object. Multiple keyboard specs can be specified in a single call, which can reduce the round-trip cost of multiple calls to Keyman Cloud servers (when using Keyman Cloud). -For general information and example uses of this method, please see the [Adding Keyboards](../../guide/adding-keyboards) page from the guide section. +For general information and example uses of this method, please see the +[Adding Keyboards](../../guide/adding-keyboards) page from the guide section. ### Using a `string` @@ -48,7 +51,7 @@ The string format is one of the following: * `'keyboardID@languageID'`: Loads a specific keyboard + language combination The keyboard catalogue is online at -[http://keyman.com/developer/keymanweb/keyboards](http://keyman.com/developer/keymanweb/keyboards). +[https://keyman.com/developer/keymanweb/keyboards](https://keyman.com/developer/keymanweb/keyboards). ### Using an `object` @@ -59,7 +62,6 @@ known as KeymanWeb Server Data API): The `spec` object contains the following members: - `name` : `string` @@ -143,7 +145,7 @@ The `spec.languages` object contains the following members: : `array|object` optional - An array of Font objects (see definition below) or single object describing + An array of Font objects (see `font` definition below) or single object describing fonts for input fields and the OSK (if `oskFont` is not present.) `oskFont` @@ -177,3 +179,7 @@ The `spec.languages.font` object contains the following members: : `string` optional Font size (in CSS dimensions). If not specified, then `1em` is used. + +### Not passing any parameter + +Not passing any parameter will obtain all Keyman keyboards from the CDN. \ No newline at end of file diff --git a/web/docs/engine/reference/core/addKeyboardsForLanguage.md b/web/docs/engine/reference/core/addKeyboardsForLanguage.md index d06ce2ede2..e3a1e553c7 100644 --- a/web/docs/engine/reference/core/addKeyboardsForLanguage.md +++ b/web/docs/engine/reference/core/addKeyboardsForLanguage.md @@ -9,7 +9,7 @@ Add default or all keyboards for a given language to KeymanWeb. ## Syntax ```js -keyman.addKeyboardsForLanguage(spec[, spec...]) +await keyman.addKeyboardsForLanguage(spec[, spec...]) ``` ### Parameters @@ -18,7 +18,8 @@ keyman.addKeyboardsForLanguage(spec[, spec...]) : Type: `string` - Language name string. Appending `$` to the language name will cause all available keyboards for that language to be loaded rather than the default keyboard. + Language name string. Appending `$` to the language name will cause all available keyboards for + that language to be loaded rather than only the default keyboard. ### Return Value @@ -26,7 +27,9 @@ keyman.addKeyboardsForLanguage(spec[, spec...]) fulfilled upon adding keyboards. The promise is an array containing the following: -* successfully registered keyboard objects which define some or all of these [properties](../keyboard_properties) + +* successfully registered keyboard objects which define some or all of these + [properties](../keyboard_properties) ## Description @@ -34,9 +37,12 @@ The language spec is a string. Multiple language specs can also be specified in a single call, which can reduce the round-trip cost of multiple calls to Keyman Cloud servers (when using Keyman Cloud). -The first call to `addKeyboardsForLanguage()` makes an additional call to the Keyman API to load the current list of keyboard/language associations. This determines the default keyboards that are added for the language. +The first call to `addKeyboardsForLanguage()` makes an additional call to the Keyman API to load +the current list of keyboard/language associations. This determines the default keyboards that +are added for the language. -For general information and example uses of this method, please see the [Adding Keyboards](../../guide/adding-keyboards) page from the guide section. +For general information and example uses of this method, please see the +[Adding Keyboards](../../guide/adding-keyboards) page from the guide section. ### Using a `string` diff --git a/web/docs/engine/reference/core/getKeyboard.md b/web/docs/engine/reference/core/getKeyboard.md index 0d6f8eb52e..9b728995d0 100644 --- a/web/docs/engine/reference/core/getKeyboard.md +++ b/web/docs/engine/reference/core/getKeyboard.md @@ -8,7 +8,7 @@ Get keyboard meta data for the selected keyboard and language. ## Syntax -```c +```js keyman.getKeyboard(keyboardName, languageCode) ``` @@ -75,5 +75,5 @@ The `keyboard` object contains the following members: : `string` *optional* : The font packaged with the keyboard to properly display specialized OSK characters. -## See also +## See also - [keyman.addKeyboards()](addKeyboards) and its documentation about keyboard specification objects. diff --git a/web/docs/engine/reference/core/getKeyboards.md b/web/docs/engine/reference/core/getKeyboards.md index 8d84521b31..cd8b0f2d9c 100644 --- a/web/docs/engine/reference/core/getKeyboards.md +++ b/web/docs/engine/reference/core/getKeyboards.md @@ -8,7 +8,7 @@ Get details of currently installed keyboards. ## Syntax -```c +```js keyman.getKeyboards() ``` @@ -25,5 +25,5 @@ None. See [keyman.getKeyboard()](getKeyboard) for detail on the returned keyboard specification objects. -## See also +## See also - [keyman.addKeyboards()](addKeyboards) diff --git a/web/docs/engine/reference/interface/contextExOutput.md b/web/docs/engine/reference/interface/contextExOutput.md index 35a1801088..73a1a97c8a 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/engine/reference/interface/registerStub.md b/web/docs/engine/reference/interface/registerStub.md index 2d9c8ef5a8..9dc8e10c34 100644 --- a/web/docs/engine/reference/interface/registerStub.md +++ b/web/docs/engine/reference/interface/registerStub.md @@ -8,13 +8,13 @@ Registers the keyboard stub or returns true if already registered. ## Syntax -```c +```js keyman.interface.registerStub(Pstub); ``` or -```c +```js KeymanWeb.KRS(Pstub); // Shorthand ``` diff --git a/web/docs/engine/reference/layouts.md b/web/docs/engine/reference/layouts.md index df3e3b50c7..56d1e40d62 100644 --- a/web/docs/engine/reference/layouts.md +++ b/web/docs/engine/reference/layouts.md @@ -2,4 +2,6 @@ title: Layout Designer --- -One of the main features of *KeymanWeb 17* is its ability to support distinct, user-customizable layouts for touch-screen keyboards on phones and tablets. *Keyman Developer 17* includes a layout designer to simplify the process of creating custom layouts for any keyboard. +One of the main features of *KeymanWeb* is its ability to support distinct, user-customizable +layouts for touch-screen keyboards on phones and tablets. *Keyman Developer* includes a layout +designer to simplify the process of creating custom layouts for any keyboard. diff --git a/web/docs/engine/reference/layoutspec.md b/web/docs/engine/reference/layoutspec.md index 2cdaec1fff..b9d2353901 100644 --- a/web/docs/engine/reference/layoutspec.md +++ b/web/docs/engine/reference/layoutspec.md @@ -2,13 +2,19 @@ title: Layout Specifications --- -Touch-screen layouts for *KeymanWeb 17* are specified as JSON objects containing a member object for each specified device type. Currently supported device types are *tablet* and *phone*. Layouts for *desktop* computers may also be specified but desktop on-screen keyboard design is normally managed by the -standard *Keyman Developer* on-screen keyboard tool rather than the keyboard layout designer. If the same -layout is appropriate for both *tablet* and *phone* devices only one need be specified, and will be used for either type of device. +Touch-screen layouts for *KeymanWeb* are specified as JSON objects containing a member object for +each specified device type. Currently supported device types are *tablet* and *phone*. Layouts +for *desktop* computers may also be specified but desktop on-screen keyboard design is normally +managed by the standard *Keyman Developer* on-screen keyboard tool rather than the keyboard +layout designer. If the same layout is appropriate for both *tablet* and *phone* devices only one +need be specified, and will be used for either type of device. -File encoding for manually-created layout files may use either UTF-8 or 7-bit ANSI coding, but must not include a BOM. For easier editing and management without requiring special fonts, embedded Unicode characters with values above 127 may use the *\uXXXX* notation. +File encoding for manually-created layout files may use either UTF-8 or 7-bit ANSI coding, but +must not include a BOM. For easier editing and management without requiring special fonts, +embedded Unicode characters with values above 127 may use the *\uXXXX* notation. -For details of the JSON specification, see [The JSON Data Interchange Format(ECMA-404)](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). +For details of the JSON specification, see [The JSON Data Interchange +Format(ECMA-404)](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). @@ -249,7 +255,7 @@ Details of key member specifications are given below: - + @@ -330,7 +336,11 @@ Details of key member specifications are given below:
id Each key id must start with >K_ , for keys mapped to standard Keyman virtual key names, e.g. K_HYPHEN , or either U_ or T_ for user-defined names. Keys identified as U_xxxx[_xxxx...] specify one or more Unicode characters in hex format, e.g. U_1363 for the Ethiopic Comma character, and will insert those characters if the key id is not matched by a rule. Other user-defined keys, such as T_ZZZ , will be ignored unless matched by a rule. The key id is required except for key styles 9 or 10 (blank or spacer keys).
-For many keyboards, it is helpful to associate some keyboard layers with physical keyboard modifier states. This is reflected in the layer name, where a layer name of *shift* means that when a key in that layer is touched, the keystroke will be processed as if the keyboard Shift key is held. +For many keyboards, it is helpful to associate some keyboard layers with physical keyboard +modifier states. This is reflected in the layer name, where a layer name of *shift* means that +when a key in that layer is touched, the keystroke will be processed as if the keyboard Shift key +is held. + The special layer names of:   *leftalt* , @@ -364,7 +374,9 @@ The following special key identifiers have been added to simplify layer selectio | K_SHIFTED | 264 | | K_ALTGR | 265 | -A special font is used to provide easily recognizable key graphics for various special purpose keys. The following key text strings will be recognized and cause the appropriate graphic to be used for the key cap instead of the actual text: +A special font is used to provide easily recognizable key graphics for various special purpose +keys. The following key text strings will be recognized and cause the appropriate graphic to be +used for the key cap instead of the actual text: | Text string | Key purpose | |:------------------|:--------------------------------------------------------| diff --git a/web/docs/engine/reference/overview.md b/web/docs/engine/reference/overview.md index 574e704abf..712a20640b 100644 --- a/web/docs/engine/reference/overview.md +++ b/web/docs/engine/reference/overview.md @@ -4,11 +4,14 @@ title: Overview *KeymanWeb* is a cross-browser JavaScript input method solution. -The *KeymanWeb 17 API* provides JavaScript functions to allow a website developer to integrate the use of -*KeymanWeb* multi-lingual keyboard mapping into a website, using either a standard or a custom-designed user-interface. The functions are exposed as API calls to the *KeymanWeb* core, the -*On-Screen Keyboard* module, a *Utility function* library, or one of the standard *User Interface* modules. +The *KeymanWeb API* provides JavaScript functions to allow a website developer to integrate the +use of *KeymanWeb* multi-lingual keyboard mapping into a website, using either a standard or a +custom-designed user-interface. The functions are exposed as API calls to the *KeymanWeb* core, +the *On-Screen Keyboard* module, a *Utility function* library, or one of the standard *User +Interface* modules. -A *KeymanWeb* instance is automatically constructed when you include the compiled KeymanWeb script (kmw-release.js) in your web page source. +A *KeymanWeb* instance is automatically constructed when you include the compiled KeymanWeb +script (kmw-release.js) in your web page source. The *KeymanWeb API* comprises the following objects: diff --git a/web/docs/internal/context-state-management.md b/web/docs/internal/context-state-management.md index 4c049a9092..9c25186f7b 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 `TextStore` 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. +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. -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 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. -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 +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). +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. +- `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. -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`)). +This type may then be used as an argument to `TextStore.apply()` +(defined on `TextStore`) to update any context source accordingly. -### The `Mock` - representing context-state +It is possible to determine the `Transform` needed to transition from +one `TextStore` to another using `TextStore.buildTransformFrom` +(defined on `TextStore`). -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. +### The `SyntheticTextStore` - representing context-state -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. +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. -`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. +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`. +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. +`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` + +- `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. + - This uses a specialized variant that also notes if the transition + destroyed previously-existing selected text. -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. +- `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`. +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 `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. +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 c2e401b008..68dfc14d02 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 8606d18cba..ca44e59783 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 cfbab0fcbf..5ec0135add 100644 --- a/web/package.json +++ b/web/package.json @@ -3,88 +3,86 @@ "description": "Facilitates text input in any language.", "exports": { "./app/browser": { - "es6-bundling": "./src/app/browser/src/test-index.ts", - "types": "./build/app/browser/obj/test-index.d.js", - "import": "./build/app/browser/obj/test-index.js" + "es6-bundling": "./src/app/browser/src/index.ts", + "types": "./build/app/browser/obj/index.d.ts", + "import": "./build/app/browser/obj/index.js" + }, + "./common/web-utils": { + "es6-bundling": "./src/common/web-utils/src/index.ts", + "types": "./build/common/web-utils/obj/index.d.ts", + "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" - }, - "./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" + "es6-bundling": "./src/engine/src/attachment/index.ts", + "types": "./build/engine/obj/attachment/index.d.ts", + "import": "./build/engine/obj/attachment/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/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/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/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" + "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": { - "es6-bundling": "./src/engine/keyboard/src/index.ts", - "types": "./build/engine/keyboard/obj/index.d.ts", - "import": "./build/engine/keyboard/obj/index.js" - }, - "./engine/keyboard/node-keyboard-loader": { - "es6-bundling": "./src/engine/keyboard/src/keyboards/loaders/node-keyboard-loader.ts", - "types": "./build/engine/keyboard/obj/keyboards/loaders/node-keyboard-loader.d.ts", - "import": "./build/engine/keyboard/obj/keyboards/loaders/node-keyboard-loader.js" - }, - "./engine/keyboard/dom-keyboard-loader": { - "es6-bundling": "./src/engine/keyboard/src/keyboards/loaders/dom-keyboard-loader.ts", - "types": "./build/engine/keyboard/obj/keyboards/loaders/dom-keyboard-loader.d.ts", - "import": "./build/engine/keyboard/obj/keyboards/loaders/dom-keyboard-loader.js" + "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" }, - "./engine/osk/internals": { - "types": "./build/engine/osk/obj/test-index.d.ts", - "import": "./build/engine/osk/obj/test-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" + }, + "./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 +103,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.22.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/.editorconfig b/web/src/.editorconfig deleted file mode 100644 index 34f03b7b15..0000000000 --- a/web/src/.editorconfig +++ /dev/null @@ -1,10 +0,0 @@ -# top-most EditorConfig file -root = true - -; applies to all files -[*] -indent_style = space - -[*.{java, js, ts, sh, css, html, xml}] -indent_size = 2 - diff --git a/web/src/app/browser/build.sh b/web/src/app/browser/build.sh index 7a168a5d46..41fc9c5230 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,25 +49,25 @@ 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_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 "${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_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 "${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 "${BUILD_ROOT}/obj/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/" diff --git a/web/src/app/browser/src/beepHandler.ts b/web/src/app/browser/src/beepHandler.ts index 6e23c09464..b520c709ce 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'); } @@ -149,7 +149,7 @@ export class FocusAssistant extends EventEmitter { * @param {(boolean|number)} state Activate (true,false) */ setMaintainingFocus(state: boolean) { - this.maintainingFocus = state ? true : false; + this.maintainingFocus = !!state; } setFocusTimer(): void { diff --git a/web/src/app/browser/src/context/pageIntegrationHandlers.ts b/web/src/app/browser/src/context/pageIntegrationHandlers.ts index 3a997d9392..eebf0ebde5 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 c898544fb8..33e58f4889 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 349fe4fed6..75c1850868 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 ae5fa680a3..b64fd760e1 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/index.ts b/web/src/app/browser/src/index.ts new file mode 100644 index 0000000000..786f004de5 --- /dev/null +++ b/web/src/app/browser/src/index.ts @@ -0,0 +1,22 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + */ + +export { ContextManager, KeyboardCookie } from "./contextManager.js"; +export { KeyboardDetails } from './keyboardDetails.js'; +export { KeymanEngine } from './keymanEngine.js'; +export { UIModule } from './uiModuleInterface.js'; + +//---------------------------------------------------------------------- +// Exports for unit testing only + +/** @internal */ +export { type BrowserInitOptionSpec } from './configuration.js'; +/** @internal */ +export { type KeyboardInterface } from './keyboardInterface.js'; + +import { preprocessKeyboardEvent } from './hardwareEventKeyboard.js'; +/** @internal */ +export const unitTestEndPoints = { + preprocessKeyboardEvent +} diff --git a/web/src/app/browser/src/keyboardDetails.ts b/web/src/app/browser/src/keyboardDetails.ts new file mode 100644 index 0000000000..a410800fbd --- /dev/null +++ b/web/src/app/browser/src/keyboardDetails.ts @@ -0,0 +1,66 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + */ + +import { InternalKeyboardFont } from 'keyman/engine/keyboard'; + +/** + * Defines keyboard metadata + */ +export interface KeyboardDetails { + /** + * true if the keyboard has been loaded, false otherwise + */ + HasLoaded: boolean, + /** + * User-friendly name of the keyboard. + */ + Name: string, + /** + * Internal name of the keyboard. + */ + InternalName: string, + /** + * User-friendly name of the language actively tied to the keyboard. + */ + LanguageName: string, + /** + * The three-letter code used to internally represent the language. + */ + LanguageCode: string, + /** + * The user-friendly name of the region of the world within which + * the language is predominantly found. + */ + RegionName: string, + /** + * The three-letter code representing the region. + */ + RegionCode: string, + /** + * The user-friendly name of the country in which the language is spoken. (Optional) + */ + CountryName?: string, + /** + * A three-letter code corresponding to the country. (Optional) + */ + CountryCode?: string, + /** + * Deprecated. A unique identifier for the keyboard. (Use 'InternalName' instead.) + */ + KeyboardID?: string, + /** + * The font packaged with the keyboard to support its use. (Optional) + */ + Font?: InternalKeyboardFont, + /** + * The font packaged with the keyboard to properly display specialized + * OSK characters. (Optional) + */ + OskFont?: InternalKeyboardFont, + /** + * Indicates whether the keyboard is designed for right-to-left scripts, + * null if the keyboard hasn't been loaded yet (and thus the value is unknown). + */ + IsRTL: boolean | null +}; diff --git a/web/src/app/browser/src/keyboardInterface.ts b/web/src/app/browser/src/keyboardInterface.ts index e9b0bda379..4da0579a00 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 59987035cc..af3bae2d20 100644 --- a/web/src/app/browser/src/keymanEngine.ts +++ b/web/src/app/browser/src/keymanEngine.ts @@ -1,33 +1,35 @@ 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 { ErrorStub, KeyboardStub, CloudQueryResult, toPrefixedKeyboardId } from 'keyman/engine/keyboard-storage'; +import { DeviceSpec } from 'keyman/common/web-utils'; +import { JSKeyboard, Keyboard } 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'; +import { KeyboardDetails } from './keyboardDetails.js'; export class KeymanEngine extends KeymanEngineBase { touchLanguageMenu?: LanguageMenu; @@ -42,8 +44,8 @@ export class KeymanEngine extends KeymanEngineBase number = null; - getOskWidth?: () => number = null; + public getOskHeight?: () => number = null; + public getOskWidth?: () => number = null; /** * Provides a quick link to the base help page for Keyman keyboards. @@ -52,8 +54,8 @@ export class KeymanEngine extends KeymanEngineBase { - this.contextManager.restoreLastActiveTarget(); + public keyEventRefocus = () => { + this.contextManager.restoreLastActiveTextStore(); } constructor(workerFactory: WorkerFactory, sourceUri: string) { @@ -61,8 +63,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,24 +71,24 @@ 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); } }); } - public ensureElementVisibility(e: HTMLElement) { + public ensureElementVisibility(e: HTMLElement): void { if(!e || !this.osk) { return; } @@ -108,7 +109,7 @@ export class KeymanEngine extends KeymanEngineBase) { + public async init(options: Required): Promise { const deviceDetector = new DeviceDetector(); const device = deviceDetector.detect(); @@ -192,11 +193,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('', ''); } }); @@ -256,7 +257,7 @@ export class KeymanEngine extends KeymanEngineBase /* [b/c Toolbar UI]*/) { + public isCJK(k0?: KeyboardObject | KeyboardDetails /* [b/c Toolbar UI]*/) { let kbd: Keyboard; if(k0) { - const kbdDetail = k0 as ReturnType; + const kbdDetail = k0 as KeyboardDetails; if(kbdDetail.KeyboardID){ kbd = this.keyboardRequisitioner.cache.getKeyboard(kbdDetail.KeyboardID); } else { - kbd = new Keyboard(k0); + kbd = new JSKeyboard(k0); } } else { kbd = this.core.activeKeyboard; } - return kbd && kbd.isCJK; + // We only support isCJK on legacy .js keyboards; see #7928 + return kbd && kbd instanceof JSKeyboard && kbd.isCJK; } /** * Get keyboard meta data for the selected keyboard and language * - * @param {string} PInternalName Internal name of keyboard - * @param {string=} PlgCode language code - * @return {Object} Details of named keyboard + * @param {string} id Internal name of keyboard + * @param {string?} langCode language code + * @return {KeyboardDetails} Details of named keyboard * * See https://help.keyman.com/developer/engine/web/current-version/reference/core/getKeyboard **/ - public getKeyboard(PInternalName: string, PlgCode?: string) { - const stub = this.keyboardRequisitioner.cache.getStub(PInternalName, PlgCode); + public getKeyboard(id: string, langCode?: string): KeyboardDetails { + const stub = this.keyboardRequisitioner.cache.getStub(id, langCode); const keyboard = this.keyboardRequisitioner.cache.getKeyboardForStub(stub); - return stub && this._GetKeyboardDetail(stub, keyboard); + return this._GetKeyboardDetail(stub, keyboard); } /** - * Get API-friendly array of available keyboard stubs + * Get API-friendly array of available keyboard metadata * - * Refer to https://help.keyman.com/developer/engine/web/current-version/reference/core/getKeyboards. - * - * The type of each entry of the array corresponds to that of `getKeyboard`. - * - * @return {Array} Array of available keyboards + * @return {KeyboardDetails[]} Array of available keyboards * * See https://help.keyman.com/developer/engine/web/current-version/reference/core/getKeyboards */ - public getKeyboards(): ReturnType[] { - const Lr: ReturnType[] = []; + public getKeyboards(): KeyboardDetails[] { + const detailsForAllKeyboards: KeyboardDetails[] = []; const cache = this.keyboardRequisitioner.cache; const keyboardStubs = cache.getStubList() - for(let Ln=0; Ln < keyboardStubs.length; Ln++) { // I1511 - array prototype extended - const Lstub = keyboardStubs[Ln]; - - // In Chrome, (including on Android), Array.prototype.find() requires Chrome 45. - // This is a later version than the default on our oldest-supported Android devices. - const Lkbd = cache.getKeyboardForStub(Lstub); - const Lrn = this._GetKeyboardDetail(Lstub, Lkbd); // I2078 - Full keyboard detail - Lr.push(Lrn); + for (const stub of keyboardStubs) { + const keyboard = cache.getKeyboardForStub(stub); + const keyboardDetails = this._GetKeyboardDetail(stub, keyboard); + if (keyboardDetails) { + detailsForAllKeyboards.push(keyboardDetails); + } } - return Lr; + return detailsForAllKeyboards; } /** @@ -497,13 +499,13 @@ export class KeymanEngine extends KeymanEngineBase void) { + public addHotKey(keyCode: number, shiftState: number, handler: () => void): void { this.hotkeyManager.addHotKey(keyCode, shiftState, handler); } @@ -605,7 +607,7 @@ 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 da6b5be109..3e3a168ccd 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 deleted file mode 100644 index 408b47cba6..0000000000 --- a/web/src/app/browser/src/test-index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export { BrowserConfiguration, BrowserInitOptionSpec } from './configuration.js'; -export { default as ContextManager, KeyboardCookie } from "./contextManager.js"; -export { preprocessKeyboardEvent, default as HardwareEventKeyboard } from './hardwareEventKeyboard.js'; - -export { KeymanEngine } from './keymanEngine.js'; -export { default as 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 07e1c1b202..c6854aa8c0 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 4aeb519f29..de34dea8d7 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 145cea8e4b..bdb40f9ba6 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,16 +48,16 @@ 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 diff --git a/web/src/app/ui/kmwuifloat.ts b/web/src/app/ui/kmwuifloat.ts index f67463cf48..7154ec85de 100644 --- a/web/src/app/ui/kmwuifloat.ts +++ b/web/src/app/ui/kmwuifloat.ts @@ -261,12 +261,19 @@ if(!keymanweb) { } this.updateList = false; - // Set the menu selector to the currently saved keyboard - const sk = keymanweb.getSavedKeyboard().split(':'); - if(sk.length < 2) { - sk[1] = ''; + // Set the menu selector to the last active keyboard + let activeKeyboard = keymanweb.getActiveKeyboard(); + let activeLanguage = ''; + if (activeKeyboard) { + activeLanguage = keymanweb.getActiveLanguage(); + } else { + // savedKeyboard is only correct if we use global keyboard settings, + // otherwise it's set to the first keyboard in the list + const savedKeyboard = keymanweb.getSavedKeyboard().split(':'); + activeKeyboard = savedKeyboard[0]; + activeLanguage = savedKeyboard.length < 2 ? '' : savedKeyboard[1]; } - this.updateMenu(sk[0],sk[1]); + this.updateMenu(activeKeyboard, activeLanguage); // Redisplay the UI to correct width for any new language entries if(keymanweb.getLastActiveElement()) { @@ -450,7 +457,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/kmwuitoggle.ts b/web/src/app/ui/kmwuitoggle.ts index 1aa4561465..79b7829322 100644 --- a/web/src/app/ui/kmwuitoggle.ts +++ b/web/src/app/ui/kmwuitoggle.ts @@ -152,12 +152,12 @@ if(!keymanweb) { } osk.addEventListener('show', (oskPosition) => { - // Ensure that the ui.controller is visible if help is displayed - this.controller.style.display = 'block'; - this.oskButton._setSelected(true); + // Ensure that the ui.controller is visible if help is displayed + this.controller.style.display = 'block'; + this.oskButton._setSelected(true); - return oskPosition; - }); + return oskPosition; + }); osk.addEventListener('hide', (byUser) => { if(byUser['HiddenByUser']) { @@ -542,8 +542,18 @@ if(!keymanweb) { } // Highlight the last active keyboard - const sk=keymanweb.getSavedKeyboard().split(':'); - this.updateMenu(sk[0],sk[1]); + let activeKeyboard = keymanweb.getActiveKeyboard(); + let activeLanguage = ''; + if (activeKeyboard) { + activeLanguage = keymanweb.getActiveLanguage(); + } else { + // savedKeyboard is only correct if we use global keyboard settings, + // otherwise it's set to the first keyboard in the list + const savedKeyboard = keymanweb.getSavedKeyboard().split(':'); + activeKeyboard = savedKeyboard[0]; + activeLanguage = savedKeyboard[1]; + } + this.updateMenu(activeKeyboard, activeLanguage); } /* ---------------------------------------- @@ -555,24 +565,24 @@ if(!keymanweb) { /** * Function selecKbd * Scope Private - * @param {number} _kbd + * @param {number} kbdIndex * Description Select a keyboard from the drop down menu **/ - private async selectKbd(_kbd: number): Promise { - let _name,_lgCode; - if(_kbd < 0) { - _name = ''; - _lgCode=''; + private async selectKbd(kbdIndex: number): Promise { + let name: string, languageCode: string; + if (kbdIndex < 0) { + name = ''; + languageCode = ''; } else { - _name = this.keyboards[_kbd]._InternalName; - _lgCode = this.keyboards[_kbd]._LanguageCode; + name = this.keyboards[kbdIndex]._InternalName; + languageCode = this.keyboards[kbdIndex]._LanguageCode; } - await keymanweb.setActiveKeyboard(_name,_lgCode); + await keymanweb.setActiveKeyboard(name, languageCode); keymanweb.focusLastActiveElement(); - this.kbdButton._setSelected(_name != ''); - if(_kbd >= 0) { - this.lastActiveKeyboard = _kbd; + this.kbdButton._setSelected(name != ''); + if (kbdIndex >= 0) { + this.lastActiveKeyboard = kbdIndex; } return false; @@ -687,6 +697,22 @@ if(!keymanweb) { `; } + private createMenuItem(index: number, id: string, name: string, isSelected: boolean): { li: HTMLLIElement, a: HTMLAnchorElement } { + const li = util.createElement('li'); + const a = util.createElement('a'); + a.innerHTML = name; + a.href = "#"; + a.onclick = ((x) => { + return () => this.selectKbd(x); + })(index); + a.id = id; + if (isSelected) { + a.className = 'selected'; + } + li.appendChild(a); + return { li, a }; + } + /** * Function createMenu * Scope Private @@ -701,38 +727,29 @@ if(!keymanweb) { this.keyboardMenu.innerHTML = ''; // I2403 - Allow toggle design to be loaded twice } - const _li = util.createElement('li'); - const _a = util.createElement('a'); - _a.innerHTML='(System keyboard)'; - _a.href="#"; - _a.onclick = () => { - return this.selectKbd(-1); - }; - _a.id='KMWSel_$'; - _a.className='selected'; - _li.appendChild(_a); + // Add the default (system) keyboard as the first entry in the menu + const { li, a } = this.createMenuItem(-1, 'KMWSel_$', '(System keyboard)', true); + this.selectedMenuItem = a; + this.keyboardMenu.appendChild(li); - this.selectedMenuItem=_a; - this.keyboardMenu.appendChild(_li); - - const _kbds=keymanweb.getKeyboards(), _added: Record = {}; + // Add loaded keyboards to the menu this.keyboards = []; - for(let _kbd = 0; _kbd < _kbds.length; _kbd++) { - const _li1=util.createElement('li'); - const _a1=util.createElement('a'); - _a1.innerHTML=_kbds[_kbd].LanguageName + ' - ' + _kbds[_kbd].Name; - if(!_added[_kbds[_kbd].InternalName]) _added[_kbds[_kbd].InternalName]=0; - _added[_kbds[_kbd].InternalName]++; + const keyboards = keymanweb.getKeyboards(); + const added: Record = {}; + for (let kbdIndex = 0; kbdIndex < keyboards.length; kbdIndex++) { + if (!added[keyboards[kbdIndex].InternalName]) { + added[keyboards[kbdIndex].InternalName] = 0; + } + added[keyboards[kbdIndex].InternalName]++; - const _n=_added[_kbds[_kbd].InternalName]; - this.keyboards.push({_InternalName: _kbds[_kbd].InternalName, _LanguageCode:_kbds[_kbd].LanguageCode, _Index: _n}); + const kbdInstanceCount = added[keyboards[kbdIndex].InternalName]; + this.keyboards.push({ _InternalName: keyboards[kbdIndex].InternalName, _LanguageCode: keyboards[kbdIndex].LanguageCode, _Index: kbdInstanceCount }); - _a1.href="#"; - _a1.onclick = ((x) => { return () => this.selectKbd(x); })(this.keyboards.length-1); - _a1.id='KMWSel_'+_kbds[_kbd].InternalName+'$'+_n; - - _li1.appendChild(_a1); - this.keyboardMenu.appendChild(_li1); + const { li } = this.createMenuItem(this.keyboards.length - 1, + `KMWSel_${keyboards[kbdIndex].InternalName}\$${kbdInstanceCount}`, + `${keyboards[kbdIndex].LanguageName} - ${keyboards[kbdIndex].Name}`, + false); + this.keyboardMenu.appendChild(li); } //if(!ui.initialized) // I2403 - Allow toggle design to be loaded twice @@ -740,7 +757,6 @@ if(!keymanweb) { this.kbdButton.getElem().appendChild(this.keyboardMenu); } }; - } @@ -795,4 +811,4 @@ if(!keymanweb) { ui.initialize(); } catch(ex){} -} \ No newline at end of file +} diff --git a/web/src/app/ui/kmwuitoolbar.ts b/web/src/app/ui/kmwuitoolbar.ts index daf1adf8ca..6ed8d82e23 100644 --- a/web/src/app/ui/kmwuitoolbar.ts +++ b/web/src/app/ui/kmwuitoolbar.ts @@ -3,7 +3,7 @@ Copyright 2019-2023 SIL International ***/ -import type { KeymanEngine, KeyboardCookie, UIModule } from 'keyman/app/browser'; +import type { KeymanEngine, KeyboardCookie, KeyboardDetails, UIModule } from 'keyman/app/browser'; declare global { interface Window { @@ -31,8 +31,6 @@ type ToolbarCookie = { maxrecent: number; } & Record<`recent${number}`, string>; -type KeyboardDetail = ReturnType; - type LanguageEntry = { /** Language id */ id: string; @@ -43,13 +41,13 @@ type LanguageEntry = { /** * A rich list of keyboard metadata for keyboards matching this language's language code (`id`). */ - keyboards: KeyboardDetail[]; + keyboards: KeyboardDetails[]; } interface ListedKeyboard { priority: number; lang: LanguageEntry, - keyboard: KeyboardDetail; + keyboard: KeyboardDetails; buttonNode: HTMLDivElement; aNode: HTMLAnchorElement; } @@ -128,7 +126,7 @@ if(!keymanweb) { */ maxListedKeyboards = 1; lastActiveControl: HTMLElement = null; - selectedKeyboard: KeyboardDetail = null; + selectedKeyboard: KeyboardDetails = null; selectedLanguage = ''; helpOffsetX = 0; helpOffsetY = 0; @@ -563,7 +561,7 @@ if(!keymanweb) { * @param {Object} b * @return {number} **/ - readonly sortKeyboards = function(a: KeyboardDetail, b: KeyboardDetail) { + readonly sortKeyboards = function(a: KeyboardDetails, b: KeyboardDetails) { if(a.RegionCode < b.RegionCode) { return -2; } @@ -611,7 +609,7 @@ if(!keymanweb) { * @param {Object} lang * @param {Object} kbd **/ - addKeyboardToList(lang: LanguageEntry, kbd: KeyboardDetail) { + addKeyboardToList(lang: LanguageEntry, kbd: KeyboardDetails) { const found = this.findListedKeyboard(lang); if(found == null) { // Add the button @@ -795,7 +793,7 @@ if(!keymanweb) { **/ selectLanguage(event: Event, lang: LanguageEntry) { const found = this.findListedKeyboard(lang); - let kbd: KeyboardDetail = null; + let kbd: KeyboardDetails = null; if(found == null) { kbd = lang.keyboards[0]; @@ -820,7 +818,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: KeyboardDetails, updateKeyman: boolean): Promise { keymanweb.activatingUI(true); if(this.selectedLanguage) { @@ -943,7 +941,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) { @@ -1152,8 +1150,8 @@ if(!keymanweb) { internalName: string, languageCode: string }) => { // Uses a different format than .getKeyboards(), b/c why not? - // https://help.keyman.com/developer/engine/web/16.0/reference/core/getKeyboards vs - // https://help.keyman.com/developer/engine/web/16.0/reference/events/kmw.keyboardchange + // https://help.keyman.com/developer/engine/web/current-version/reference/core/getKeyboards vs + // https://help.keyman.com/developer/engine/web/current-version/reference/events/kmw.keyboardchange this.lastSelectedKeyboard = null; const kbName=p.internalName, lgName=keymanweb.util.getLanguageCodes(p.languageCode)[0]; diff --git a/web/src/app/ui/tsconfig.json b/web/src/app/ui/tsconfig.json index 8d6da3884a..b37d8bd681 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 72708eabea..cce218ba6d 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,29 @@ 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/" # 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 +75,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 72b7a83243..257f897e70 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 da441de3ff..971c207a50 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 cd0bdd9b4f..e71c6bab7f 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 c036119508..293be9883b 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 da6b5be109..3e3a168ccd 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 b595456aba..06f6e0064a 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 4c652ff892..1b73d94074 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 8be7be6df3..d74c1f2663 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 c88f255660..db0eb49834 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 3ab0352fc4..f993f94b82 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 b268687216..c6c0af33e5 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 30f4821590..f471946d71 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 0000000000..82832d1fdd --- /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 5288531902..4319575709 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 66867f37ad..2d75d62a92 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 90e809dc11..5b2d8eb0ce 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 6b7fe72205..2c2b0f5a56 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 0aa4c50b96..2394718aec 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 e22ef633d1..be93a45c8b 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 337cf286e2..e8a14afbec 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 36ed51cbac..aa4c67c454 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 4b6fb3a7d6..0f48d09671 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 145b336106..61b94147b8 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 1747a62274..0e866bd4cc 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 65dd2858d4..dd274be940 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 eea63036d2..0000000000 --- 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 0c37fb62c1..0000000000 --- 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 02a8111402..0000000000 --- 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 8e75e7645f..0000000000 --- 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 3ce6a07308..0000000000 --- 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 0000000000..115792926e --- /dev/null +++ b/web/src/engine/build.sh @@ -0,0 +1,89 @@ +#!/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() { + 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 56baafc822..0000000000 --- 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 557878d43e..0000000000 --- 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 df6180e2ed..0000000000 --- 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 ad667ea341..0000000000 --- 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 aab3cabf87..0000000000 --- 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 18d7f2c0ed..0000000000 --- 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 2a7685edbc..0000000000 --- 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 06971bdeff..0000000000 --- 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 91d482e16e..0000000000 --- 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 --> -
-
- -

Return to testing home page

- - - +

This test page exists for testing KMW's keyboard-documentation rendering system.

+ +
+
+ +

Return to testing home page

@@ -51,7 +50,7 @@ - +

KeymanWeb Sample Page - Chirality Testing

This page is designed to stress-test the new support for chiral modifiers and state keys.

Be sure to reference the developer console for additional feedback.

diff --git a/web/src/test/manual/web/chirality/utilities.js b/web/src/test/manual/web/chirality/utilities.js index 16c9caaf02..7aea2825dd 100644 --- a/web/src/test/manual/web/chirality/utilities.js +++ b/web/src/test/manual/web/chirality/utilities.js @@ -1,19 +1,17 @@ -function loadKeyboards() -{ - var kmw=keyman; - +async function loadKeyboards() +{ // A testing keyboard handwritten with chirality information. - kmw.addKeyboards({id:'chirality',name:'Chirality Testing', + await keyman.addKeyboards({id:'chirality',name:'Chirality Testing', languages:{ id:'en',name:'English',region:'North America' }, filename:'../../../../../build/test-resources/keyboards/chirality.js' }); - + // A testing keyboard using 10.0 format and the KLS layout specifier // without the 'shift' layer properly defined. - // Add a fully-specified, locally-sourced, keyboard with custom font - kmw.addKeyboards({id:'halfDefined',name:'Undefined Shift Layer Keyboard', + // Add a fully-specified, locally-sourced, keyboard with custom font + await keyman.addKeyboards({id:'halfDefined',name:'Undefined Shift Layer Keyboard', languages:{ id:'en',name:'English',region:'North America' }, diff --git a/web/src/test/manual/web/ckeditor/index.html b/web/src/test/manual/web/ckeditor/index.html index 950f8bcb9b..16de19ba02 100644 --- a/web/src/test/manual/web/ckeditor/index.html +++ b/web/src/test/manual/web/ckeditor/index.html @@ -30,10 +30,9 @@ @@ -44,7 +43,7 @@ - +

KeymanWeb Sample Page - Test CKEditor Integration

Test CKEditor Integration

diff --git a/web/src/test/manual/web/ckeditor/inline.html b/web/src/test/manual/web/ckeditor/inline.html index 463ebf2138..06ec8ca0e5 100644 --- a/web/src/test/manual/web/ckeditor/inline.html +++ b/web/src/test/manual/web/ckeditor/inline.html @@ -30,10 +30,9 @@ @@ -44,7 +43,7 @@ - +

KeymanWeb Sample Page - Test CKEditor Integration

Test CKEditor Integration

diff --git a/web/src/test/manual/web/ckeditor/utilities.js b/web/src/test/manual/web/ckeditor/utilities.js index 2ca0fd324c..8c281e2223 100644 --- a/web/src/test/manual/web/ckeditor/utilities.js +++ b/web/src/test/manual/web/ckeditor/utilities.js @@ -1,15 +1,13 @@ -function loadKeyboards() +async function loadKeyboards() { - var kmw=keyman; - // Add more keyboards to the language menu, by keyboard name, // keyboard name and language code, or just the BCP-47 language code. // We use a different loading pattern here than in the samples version to provide a slightly different set of test cases. - kmw.addKeyboards('french','@he'); - kmw.addKeyboards({id:'sil_euro_latin', name:'SIL EuroLatin', languages: [{id:'no'}, {id:'sv'}]}); // Loads from partial stub instead of the compact string. + await keyman.addKeyboards('french', '@he', + { id: 'sil_euro_latin', name: 'SIL EuroLatin', languages: [{ id: 'no' }, { id: 'sv' }] }); // Loads from partial stub instead of the compact string. // Add a keyboard by language name. Note that the name must be spelled // correctly, or the keyboard will not be found. (Using BCP-47 codes is // usually easier.) - kmw.addKeyboardsForLanguage('Dzongkha'); + await keyman.addKeyboardsForLanguage('Dzongkha'); } \ No newline at end of file diff --git a/web/src/test/manual/web/commonHeader.js b/web/src/test/manual/web/commonHeader.js index 74cb22e1cd..e80368b556 100644 --- a/web/src/test/manual/web/commonHeader.js +++ b/web/src/test/manual/web/commonHeader.js @@ -1,172 +1,122 @@ -// JavaScript Document samplehdr.js: Keyboard management for KeymanWeb demonstration pages - /* - The keyboard name and/or BCP-47 language code must be specified for each keyboard that is to be available. - If the same keyboard is used for several languages, it must be listed for each - language, but the keyboard itself will only be loaded once. - If two (or more) keyboards are to be available for a given language, both must be listed. - Any number of keyboards may be specified in one or more calls. - Keyboard paths may be absolute (with respect to the server root) or relative to the keyboards option path. - The actual keyboard object will be downloaded asynchronously when first selected for use. + * Keyman is copyright (C) SIL Global. MIT License. + */ - Each argument to addKeyboards() is a string, for example: - european2 loads the current version of the Eurolatin 2 keyboard (for its default language) - european2@fr loads the current version of the Eurolatin 2 keyboard for French - european2@fr@1.2 loads version 1.2 of the Eurolatin 2 keyboard for French - - Argument syntax also supports the following extensions: - @fr load the current version of the default keyboard for French - @fr$ load all available keyboards (current version) for French - - Each call to addKeyboards() requires a single call to the remote server, - (unless all keyboards listed are local and fully specified) so it is better - to use multiple arguments rather than separate function calls. - - Calling addKeyboards() with no arguments returns a list of *all* available keyboards. - The Toolbar (desktop browser) UI is best suited for allowing users to select - the appropriate language and keyboard in this case. - - Keyboards may also be specified by language name using addKeyboardsForLanguage() - for example: - keymanweb.addKeyboardsForLanguage('Burmese'); - - Appending $ to the language name will again cause all available keyboards for that - language to be loaded rather than the default keyboard. - - The first call to addKeyboardsForLanguage() makes an additional call to the - keyman API to load the current list of keyboard/language associations. - - In this example, the following function loads the indicated keyboards, - and is called when the page loads. -*/ - - function errToString(err) { - // Painful? Kinda. But needed on un-updated Android API 21! - if(Array.isArray(err)) { - var result = ''; - for(var i = 0; i < err.length; i++) { - var e = err[i]; - if(e.error instanceof Error) { - result += e.error.message + '\n'; - } else { - result += JSON.stringify(e) + '\n'; - } - } - return result; - } - if(err instanceof Error) { - return err.message; - } - return JSON.stringify(err); - } - - function doAddKeyboards(data) { - return keyman.addKeyboards(data).catch(function(err) { - console.error('keyman.addKeyboards failed with '+errToString(err)+' for '+JSON.stringify(data)); - }); - } - - function doAddKeyboardsForLanguage(data) { - return keyman.addKeyboardsForLanguage(data).catch(function(err) { - console.error('keyman.addKeyboardsForLanguage failed with '+errToString(err)+' for '+JSON.stringify(data)); - }); - } - - function loadKeyboards(nestLevel) - { - var kmw=keyman; - - var base_prefix = '../'; - var prefix = './'; // The default - when prefix == 0. - - if(nestLevel !== undefined && nestLevel > 0) { - prefix = ''; - for(var i=0; i < nestLevel; i++) { - prefix = prefix + base_prefix; +function errToString(err) { + // Painful? Kinda. But needed on un-updated Android API 21! + if(Array.isArray(err)) { + let result = ''; + for(let i = 0; i < err.length; i++) { + const e = err[i]; + if(e.error instanceof Error) { + result += e.error.message + '\n'; + } else { + result += JSON.stringify(e) + '\n'; } } - - // The first keyboard added will be the default keyboard for touch devices. - // For faster loading, it may be best for the default keyboard to be - // locally sourced. - doAddKeyboards({id:'us',name:'English',languages:{id:'en',name:'English'}, - filename:(prefix + 'us-1.0.js')}); - - doAddKeyboards({id:'web_context_tests',name:'Web Context Tests',languages:{id:'en',name:'English'}, - filename:(prefix + 'web_context_tests.js')}); - - doAddKeyboards({id:'test_chirality',name:'test_chirality',languages:{id:'en',name:'English'}, - filename:(prefix + 'test_chirality.js')}); - - doAddKeyboards({id:'obolo_chwerty_6351',name:'obolo_chwerty_6351',languages:{id:'en',name:'English'}, - filename:(prefix + 'obolo_chwerty_6351.js')}); - - doAddKeyboards({id:'gesture_prototyping',name:'Gesture Prototyping',languages:{id:'en',name:'English'}, - filename:(prefix + 'keyboards/gesture_prototyping/build/gesture_prototyping.js')}); - - doAddKeyboards({id:'diacritic_rota',name:'Diacritic 10-key Rota',languages:{id:'en',name:'English'}, - filename:(prefix + 'keyboards/diacritic_rota/build/diacritic_rota.js')}); - - doAddKeyboards({id:'ye_old_ten_key',name:'Classic 10-key',languages:{id:'en',name:'English'}, - filename:(prefix + 'keyboards/ye_old_ten_key/build/ye_old_ten_key.js')}); - - // Add more keyboards to the language menu, by keyboard name, - // keyboard name and language code, or just the BCP-47 language code. - // We use a different loading pattern here than in the samples version to provide a slightly different set of test cases. - doAddKeyboards('french','@he'); - doAddKeyboards('khmer_angkor','@km'); - doAddKeyboards({id:'sil_euro_latin', name:'SIL EuroLatin', languages: [{id:'no'}, {id:'sv'}]}); // Loads from partial stub instead of the compact string. - - // Add a keyboard by language name. Note that the name must be spelled - // correctly, or the keyboard will not be found. (Using BCP-47 codes is - // usually easier.) - doAddKeyboardsForLanguage('Dzongkha'); - - // Add a fully-specified, locally-sourced, keyboard with custom font - doAddKeyboards({id:'lao_2008_basic',name:'Lao Basic', - languages: { - id:'lo',name:'Lao',region:'Asia', - }, - filename:(prefix + 'lao_2008_basic-1.2.js') - }); - - // The following two optional calls should be delayed until language menus are fully loaded: - // (a) a specific mapped input element input is focused, to ensure that the OSK appears - // (b) a specific keyboard is loaded, rather than the keyboard last used. - //window.setTimeout(function(){kmw.setActiveElement('ta1',true);},2500); - //window.setTimeout(function(){kmw.setActiveKeyboard('Keyboard_french','fr');},3000); - - // Note that locally specified keyboards will be listed before keyboards - // requested from the remote server by user interfaces that do not order - // keyboards alphabetically by language. + return result; } + if(err instanceof Error) { + return err.message; + } + return JSON.stringify(err); +} - // Script to allow a user to add any keyboard to the keyboard menu - function addKeyboard(n) - { - var sKbd,kmw=keyman; - switch(n) - { - case 1: - sKbd=document.getElementById('kbd_id1').value; - doAddKeyboards(sKbd); - break; - case 2: - sKbd=document.getElementById('kbd_id2').value.toLowerCase(); - doAddKeyboards('@'+sKbd); - break; - case 3: - // Add keyboard for comma-separated language name(s) - sKbd=document.getElementById('kbd_id3').value; - doAddKeyboardsForLanguage(sKbd); - break; +function doAddKeyboards(data) { + return keyman.addKeyboards(data).catch(function(err) { + console.error('keyman.addKeyboards failed with '+errToString(err)+' for '+JSON.stringify(data)); + }); +} + +function doAddKeyboardsForLanguage(data) { + return keyman.addKeyboardsForLanguage(data).catch(function(err) { + console.error('keyman.addKeyboardsForLanguage failed with '+errToString(err)+' for '+JSON.stringify(data)); + }); +} + +async function loadKeyboards(nestLevel) { + const base_prefix = '../'; + let prefix = './'; // The default - when prefix == 0. + + if(nestLevel !== undefined && nestLevel > 0) { + prefix = ''; + for(let i=0; i < nestLevel; i++) { + prefix += base_prefix; } } - // Add keyboard on Enter (as well as pressing button) - function clickOnEnter(e,id) - { - e = e || window.event; - if(e.keyCode == 13) addKeyboard(id); - } + // The first keyboard added will be the default keyboard for touch devices. + // For faster loading, it may be best for the default keyboard to be + // locally sourced. + await doAddKeyboards({id:'us',name:'English',languages:{id:'en',name:'English'}, + filename:(prefix + 'us-1.0.js')}); + + await doAddKeyboards({id:'web_context_tests',name:'Web Context Tests',languages:{id:'en',name:'English'}, + filename:(prefix + 'web_context_tests.js')}); + + await doAddKeyboards({id:'test_chirality',name:'test_chirality',languages:{id:'en',name:'English'}, + filename:(prefix + 'test_chirality.js')}); + + await doAddKeyboards({id:'obolo_chwerty_6351',name:'obolo_chwerty_6351',languages:{id:'en',name:'English'}, + filename:(prefix + 'obolo_chwerty_6351.js')}); + + await doAddKeyboards({id:'gesture_prototyping',name:'Gesture Prototyping',languages:{id:'en',name:'English'}, + filename:(prefix + 'keyboards/gesture_prototyping/build/gesture_prototyping.js')}); + + await doAddKeyboards({id:'diacritic_rota',name:'Diacritic 10-key Rota',languages:{id:'en',name:'English'}, + filename:(prefix + 'keyboards/diacritic_rota/build/diacritic_rota.js')}); + + await doAddKeyboards({id:'ye_old_ten_key',name:'Classic 10-key',languages:{id:'en',name:'English'}, + filename:(prefix + 'keyboards/ye_old_ten_key/build/ye_old_ten_key.js')}); + + // Add more keyboards to the language menu, by keyboard name, + // keyboard name and language code, or just the BCP-47 language code. + // We use a different loading pattern here than in the samples version to provide a slightly different set of test cases. + await doAddKeyboards('french','@he'); + await doAddKeyboards('khmer_angkor','@km'); + await doAddKeyboards({id:'sil_euro_latin', name:'SIL EuroLatin', languages: [{id:'no'}, {id:'sv'}]}); // Loads from partial stub instead of the compact string. + + // Add a keyboard by language name. Note that the name must be spelled + // correctly, or the keyboard will not be found. (Using BCP-47 codes is + // usually easier.) + await doAddKeyboardsForLanguage('Dzongkha'); + + // Add a fully-specified, locally-sourced, keyboard with custom font + await doAddKeyboards({ + id: 'lao_2008_basic', + name: 'Lao Basic', + languages: { + id: 'lo', name: 'Lao', region: 'Asia' + }, + filename: (prefix + 'lao_2008_basic-1.2.js') + }); +} + +// Script to allow a user to add any keyboard to the keyboard menu +async function addKeyboard(n) { + let sKbd; + switch(n) { + case 1: + sKbd=document.getElementById('kbd_id1').value; + await doAddKeyboards(sKbd); + break; + case 2: + sKbd=document.getElementById('kbd_id2').value.toLowerCase(); + await doAddKeyboards('@'+sKbd); + break; + case 3: + // Add keyboard for comma-separated language name(s) + sKbd=document.getElementById('kbd_id3').value; + await doAddKeyboardsForLanguage(sKbd); + break; + } +} + +// Add keyboard on Enter (as well as pressing button) +async function clickOnEnter(e,id) { + e = e || window.event; + if (e.keyCode == 13) { + await addKeyboard(id); + } +} diff --git a/web/src/test/manual/web/core/load-keyboard-blob.js b/web/src/test/manual/web/core/load-keyboard-blob.js new file mode 100644 index 0000000000..527f0e7203 --- /dev/null +++ b/web/src/test/manual/web/core/load-keyboard-blob.js @@ -0,0 +1,9 @@ +export async function loadKeyboardBlob(uri) { + const response = await fetch(uri); + if (!response.ok) { + throw new Error(`HTTP ${response.status} ${response.statusText}`); + } + + const buffer = await response.arrayBuffer(); + return new Uint8Array(buffer); +} diff --git a/web/src/test/manual/web/core/paths.js b/web/src/test/manual/web/core/paths.js new file mode 100644 index 0000000000..9803ea624b --- /dev/null +++ b/web/src/test/manual/web/core/paths.js @@ -0,0 +1 @@ +export const CORE_WASM = '../../../../../build/engine/core-adapter/obj/import/core'; diff --git a/web/src/test/manual/web/core/stress.html b/web/src/test/manual/web/core/stress.html new file mode 100644 index 0000000000..e78facdb9f --- /dev/null +++ b/web/src/test/manual/web/core/stress.html @@ -0,0 +1,65 @@ + + + + + + + + + + KeymanWeb Core Stress Test + + + + + + + + +

KeymanWeb Sample Page - Core Testing

+

This page is designed to stress-test the loading a KMX keyboard from blob. It will repeatedly load a .kmx using the KM_Core loader.

+

Be sure to reference the developer console for additional feedback.

+ +
+

Return to testing home page

+ + + \ No newline at end of file diff --git a/web/src/test/manual/web/core/test_8568_deadkeys.kmx b/web/src/test/manual/web/core/test_8568_deadkeys.kmx new file mode 100644 index 0000000000..88f00e8baf Binary files /dev/null and b/web/src/test/manual/web/core/test_8568_deadkeys.kmx differ diff --git a/web/src/test/manual/web/default-subkey/index.html b/web/src/test/manual/web/default-subkey/index.html index 728355c43b..22f00ef3fe 100644 --- a/web/src/test/manual/web/default-subkey/index.html +++ b/web/src/test/manual/web/default-subkey/index.html @@ -36,11 +36,10 @@ - +

KeymanWeb Testing Page - Desktop UI module Testing

This page is designed to facilitate testing of various aspects of the Toolbar UI for KeymanWeb. Originally developed to help address issue #1275. diff --git a/web/src/test/manual/web/empty-row/index.html b/web/src/test/manual/web/empty-row/index.html index 02953493e9..ee6da66cca 100644 --- a/web/src/test/manual/web/empty-row/index.html +++ b/web/src/test/manual/web/empty-row/index.html @@ -36,18 +36,16 @@ - - + + @@ -47,7 +49,7 @@ - +

KeymanWeb: 'Test case' for proper implementation of the removeKeyboards API function

diff --git a/web/src/test/manual/web/issue103/index.html b/web/src/test/manual/web/issue103/index.html index 35b006e347..53c0447cbd 100644 --- a/web/src/test/manual/web/issue103/index.html +++ b/web/src/test/manual/web/issue103/index.html @@ -36,10 +36,11 @@ @@ -48,7 +49,7 @@ - +

KeymanWeb Sample Page - Keyboard Registration Check

This page is designed to test KeymanWeb's behavior when being told to load a keyboard multiple times, both via diff --git a/web/src/test/manual/web/issue103/samplehdr.js b/web/src/test/manual/web/issue103/samplehdr.js index 36b08861c1..e689bf4b3b 100644 --- a/web/src/test/manual/web/issue103/samplehdr.js +++ b/web/src/test/manual/web/issue103/samplehdr.js @@ -1,70 +1,64 @@ -// Modified version of commonHeader - contains repeated requests for the same language. +/* + * Keyman is copyright (C) SIL Global. MIT License. + * + * Modified version of commonHeader.js - contains repeated requests for the same language. + */ - function loadKeyboards() - { - var kmw=keyman; - - // The first keyboard added will be the default keyboard for touch devices. - // For faster loading, it may be best for the default keyboard to be - // locally sourced. - kmw.addKeyboards({id:'us',name:'English',languages:{id:'en',name:'English'}, - filename:'../us-1.0.js'}); - - // Add more keyboards to the language menu, by keyboard name, - // keyboard name and language code, or just the BCP-47 language code. - kmw.addKeyboards('french','european2@sv','european2@sv','european2@sv','european2@sv','european2@sv','european2@sv','european2@no','@he'); - kmw.addKeyboards('@he'); - kmw.addKeyboards('@he'); - - // Add a keyboard by language name. Note that the name must be spelled - // correctly, or the keyboard will not be found. (Using BCP-47 codes is - // usually easier.) - kmw.addKeyboardsForLanguage('Dzongkha'); - - // Add a fully-specified, locally-sourced, keyboard with custom font - kmw.addKeyboards({id:'lao_2008_basic',name:'Lao Basic', - languages:{ - id:'lo',name:'Lao',region:'Asia' - }, - filename:'../lao_2008_basic.js' - }); +async function loadKeyboards() { + await keyman.addKeyboards({id:'us',name:'English',languages:{id:'en',name:'English'}, + filename:'../us-1.0.js'}); - // The following two optional calls should be delayed until language menus are fully loaded: - // (a) a specific mapped input element input is focused, to ensure that the OSK appears - // (b) a specific keyboard is loaded, rather than the keyboard last used. - //window.setTimeout(function(){kmw.setActiveElement('ta1',true);},2500); - //window.setTimeout(function(){kmw.setActiveKeyboard('Keyboard_french','fr');},3000); - - // Note that locally specified keyboards will be listed before keyboards - // requested from the remote server by user interfaces that do not order - // keyboards alphabetically by language. - } - - // Script to allow a user to add any keyboard to the keyboard menu - function addKeyboard(n) - { - var sKbd,kmw=keyman; - switch(n) - { - case 1: - sKbd=document.getElementById('kbd_id1').value; - kmw.addKeyboards(sKbd); - break; - case 2: - sKbd=document.getElementById('kbd_id2').value.toLowerCase(); - kmw.addKeyboards('@'+sKbd); - break; - case 3: - sKbd=document.getElementById('kbd_id3').value; - kmw.addKeyboardsForLanguage(sKbd); - break; - } - } - - // Add keyboard on Enter (as well as pressing button) - function clickOnEnter(e,id) - { - e = e || window.event; - if(e.keyCode == 13) addKeyboard(id); - } + // Intentionally request the same keyboard multiple times to test that it + // is not added multiple times and doesn't cause an error. + await keyman.addKeyboards('french', 'european2@sv', 'european2@sv', 'european2@sv', + 'european2@sv', 'european2@sv', 'european2@sv', 'european2@no', '@he'); + await keyman.addKeyboards('@he'); + await keyman.addKeyboards('@he'); // intentional duplicate + + // Add a keyboard by language name. Note that the name must be spelled + // correctly, or the keyboard will not be found. (Using BCP-47 codes is + // usually easier.) + await keyman.addKeyboardsForLanguage('Dzongkha'); + + // Add a fully-specified, locally-sourced, keyboard with custom font + await keyman.addKeyboards({ + id: 'lao_2008_basic', + name: 'Lao Basic', + languages:{ + id: 'lo', + name: 'Lao', + region: 'Asia' + }, + filename: '../lao_2008_basic.js' + }); +} + +// Script to allow a user to add any keyboard to the keyboard menu +async function addKeyboard(n) +{ + let sKbd; + switch(n) + { + case 1: + sKbd=document.getElementById('kbd_id1').value; + await keyman.addKeyboards(sKbd); + break; + case 2: + sKbd=document.getElementById('kbd_id2').value.toLowerCase(); + await keyman.addKeyboards('@'+sKbd); + break; + case 3: + sKbd=document.getElementById('kbd_id3').value; + await keyman.addKeyboardsForLanguage(sKbd); + break; + } +} + +// Add keyboard on Enter (as well as pressing button) +async function clickOnEnter(e,id) { + e = e || window.event; + if (e.keyCode == 13) { + await addKeyboard(id); + } +} diff --git a/web/src/test/manual/web/issue115/index.html b/web/src/test/manual/web/issue115/index.html index cd9afcb8fa..f55d98d382 100644 --- a/web/src/test/manual/web/issue115/index.html +++ b/web/src/test/manual/web/issue115/index.html @@ -36,11 +36,10 @@ diff --git a/web/src/test/manual/web/issue116/index.html b/web/src/test/manual/web/issue116/index.html index d81fb947c0..d8f64d9f74 100644 --- a/web/src/test/manual/web/issue116/index.html +++ b/web/src/test/manual/web/issue116/index.html @@ -36,12 +36,12 @@ diff --git a/web/src/test/manual/web/issue11785/index.html b/web/src/test/manual/web/issue11785/index.html index 5df453aab9..fb51a97bcf 100644 --- a/web/src/test/manual/web/issue11785/index.html +++ b/web/src/test/manual/web/issue11785/index.html @@ -40,9 +40,8 @@ @@ -49,7 +50,7 @@ - +

KeymanWeb Sample Page - Mixed Case of TTF font files

Previously, KMW was not applying .TTF fonts on mobile devices.

See issue #1332 diff --git a/web/src/test/manual/web/issue160/index.html b/web/src/test/manual/web/issue160/index.html index 33219e7fdf..3808341b7d 100644 --- a/web/src/test/manual/web/issue160/index.html +++ b/web/src/test/manual/web/issue160/index.html @@ -36,12 +36,12 @@ diff --git a/web/src/test/manual/web/issue266/index.html b/web/src/test/manual/web/issue266/index.html index 56e52016d7..adf03ffe70 100644 --- a/web/src/test/manual/web/issue266/index.html +++ b/web/src/test/manual/web/issue266/index.html @@ -36,12 +36,12 @@ diff --git a/web/src/test/manual/web/issue271/header.js b/web/src/test/manual/web/issue271/header.js index b0d52effe9..6fd6bec984 100644 --- a/web/src/test/manual/web/issue271/header.js +++ b/web/src/test/manual/web/issue271/header.js @@ -1,7 +1,5 @@ function setActiveKeyboard() { - var kmw=window['keyman'] ? keyman : tavultesoft.keymanweb; - var sKbd = document.getElementById('kbd_id4').value; var sLng = document.getElementById('lang_id4').value; - var result = kmw.setActiveKeyboard("Keyboard_" + sKbd, sLng); + var result = keyman.setActiveKeyboard("Keyboard_" + sKbd, sLng); } \ No newline at end of file diff --git a/web/src/test/manual/web/issue271/index.html b/web/src/test/manual/web/issue271/index.html index fa969195a1..0bf9624779 100644 --- a/web/src/test/manual/web/issue271/index.html +++ b/web/src/test/manual/web/issue271/index.html @@ -36,9 +36,10 @@ @@ -49,7 +50,7 @@ - +

KeymanWeb: Test page for interactions between setActiveKeyboard and the toolbar UI

This version is used to test the interactions of SetActiveKeyboard with the Toolbar UI.

diff --git a/web/src/test/manual/web/issue29/index.html b/web/src/test/manual/web/issue29/index.html index 24a226326c..3f007c9cb4 100644 --- a/web/src/test/manual/web/issue29/index.html +++ b/web/src/test/manual/web/issue29/index.html @@ -36,8 +36,9 @@ @@ -47,7 +48,7 @@ - +

KeymanWeb: Test desktop MutationObserver functionality

diff --git a/web/src/test/manual/web/issue3701/index.html b/web/src/test/manual/web/issue3701/index.html index c27bba6c81..6393f5fe7c 100644 --- a/web/src/test/manual/web/issue3701/index.html +++ b/web/src/test/manual/web/issue3701/index.html @@ -36,11 +36,10 @@ diff --git a/web/src/test/manual/web/issue53/index.html b/web/src/test/manual/web/issue53/index.html index 4c730a3f39..d58dbcfdf4 100644 --- a/web/src/test/manual/web/issue53/index.html +++ b/web/src/test/manual/web/issue53/index.html @@ -36,9 +36,10 @@ @@ -48,7 +49,7 @@ - +

KeymanWeb: Tests layering transitions for keyboards with variable layer sizes.

This test should be run from mobile devices or with Chrome's mobile device emulation settings available within Developer Mode.

diff --git a/web/src/test/manual/web/issue53/issue53.js b/web/src/test/manual/web/issue53/issue53.js index 03d1175866..4cef9371cd 100644 --- a/web/src/test/manual/web/issue53/issue53.js +++ b/web/src/test/manual/web/issue53/issue53.js @@ -1,9 +1,7 @@ function loadKeyboards() { - var kmw=keyman; - // Add a fully-specified, locally-sourced, keyboard. - kmw.addKeyboards({id:'layered_debug_keyboard',name:'Web_Layer_Debugging', + keyman.addKeyboards({id:'layered_debug_keyboard',name:'Web_Layer_Debugging', languages:{ id:'dbg',name:'Debug',region:'North America' }, @@ -14,28 +12,28 @@ function loadKeyboards() // Script to allow a user to add any keyboard to the keyboard menu function addKeyboard(n) { - var sKbd,kmw=keyman; + var sKbd; switch(n) { case 1: sKbd=document.getElementById('kbd_id1').value; - kmw.addKeyboards(sKbd); + keyman.addKeyboards(sKbd); break; case 2: sKbd=document.getElementById('kbd_id2').value.toLowerCase(); - kmw.addKeyboards('@'+sKbd); + keyman.addKeyboards('@'+sKbd); break; case 3: sKbd=document.getElementById('kbd_id3').value; - kmw.addKeyboardsForLanguage(sKbd); + keyman.addKeyboardsForLanguage(sKbd); break; } } function removeKeyboard(n) { - var sKbd=document.getElementById('kbd_id4').value, kmw=keyman; - kmw["removeKeyboards"](sKbd); + var sKbd=document.getElementById('kbd_id4').value; + keyman.removeKeyboards(sKbd); } // Add keyboard on Enter (as well as pressing button) diff --git a/web/src/test/manual/web/issue6005/index.html b/web/src/test/manual/web/issue6005/index.html index 7326f99c7d..9410bed564 100644 --- a/web/src/test/manual/web/issue6005/index.html +++ b/web/src/test/manual/web/issue6005/index.html @@ -40,13 +40,11 @@ const alertType = (new URLSearchParams(window.location.search)).get("useAlerts") != "false"; var alertText = alertType ? 'enabled(default)' : 'disabled'; - var kmw=window.keyman; - - kmw.init({ + keyman.init({ 'attachType': 'auto' }).then(function() { // if mobile device, activate pred text. - if(kmw.util.isTouchDevice()) { + if(keyman.util.isTouchDevice()) { var pageRef = (window.location.protocol == 'file:') ? window.location.href.substr(0, window.location.href.lastIndexOf('/')+1) : window.location.href; @@ -60,24 +58,25 @@ languages: ['en'], path: (pageRef + "prediction-mtnt/nrc.en.mtnt.model.js") }; - kmw.addModel(modelStub1); + keyman.addModel(modelStub1); var modelStub2 = {'id': 'nrc.en.mtnt', languages: ['pny-latn'], // yep. Total cheat for the sake of testing. path: (pageRef + "prediction-mtnt/nrc.en.mtnt.model.js") }; - kmw.addModel(modelStub2); + keyman.addModel(modelStub2); } - }); - kmw.addKeyboards('sil_euro_latin@en', - 'galaxie_hebrew_positional@he', - 'sil_cameroon_qwerty@pny-latn'); - kmw.addKeyboards({ - id:'unmatched_final_group_model_interactions_6005', - name:'"Unmatched Vowel Rule"', - languages:{id:'en',name:'English'}, - filename:('unmatched_final_group_model_interactions_6005.js') - }); + keyman.addKeyboards('sil_euro_latin@en', + 'galaxie_hebrew_positional@he', + 'sil_cameroon_qwerty@pny-latn'); + + keyman.addKeyboards({ + id:'unmatched_final_group_model_interactions_6005', + name:'"Unmatched Vowel Rule"', + languages:{id:'en',name:'English'}, + filename:('unmatched_final_group_model_interactions_6005.js') + }); + }); diff --git a/web/src/test/manual/web/issue62/index.html b/web/src/test/manual/web/issue62/index.html index 23ac9889df..c647b03e88 100644 --- a/web/src/test/manual/web/issue62/index.html +++ b/web/src/test/manual/web/issue62/index.html @@ -36,9 +36,10 @@ @@ -49,7 +50,7 @@ - +

KeymanWeb: Light test for touch-based MutationObserver functionality

diff --git a/web/src/test/manual/web/issue63/index.html b/web/src/test/manual/web/issue63/index.html index 55cee63c97..acb2cdd40f 100644 --- a/web/src/test/manual/web/issue63/index.html +++ b/web/src/test/manual/web/issue63/index.html @@ -36,9 +36,10 @@ @@ -49,7 +50,7 @@ - +

KeymanWeb: Test/stress-test touch-based MutationObserver functionality

diff --git a/web/src/test/manual/web/issue917-context-and-notany/index.html b/web/src/test/manual/web/issue917-context-and-notany/index.html index 251edb9142..f7941b8a0d 100644 --- a/web/src/test/manual/web/issue917-context-and-notany/index.html +++ b/web/src/test/manual/web/issue917-context-and-notany/index.html @@ -36,11 +36,10 @@ diff --git a/web/src/test/manual/web/issue920/index.html b/web/src/test/manual/web/issue920/index.html index b20f536906..03265f30bf 100644 --- a/web/src/test/manual/web/issue920/index.html +++ b/web/src/test/manual/web/issue920/index.html @@ -36,15 +36,10 @@ - +

KeymanWeb Sample Page - deadkeys and multiple groups Testing

See issue #920 for details on what this test is all about. Both ;e and .e should produce ə but ;e uses a deadkey and fails.

diff --git a/web/src/test/manual/web/issue9469/index.html b/web/src/test/manual/web/issue9469/index.html index 78c3a15f95..5c7e33daa3 100644 --- a/web/src/test/manual/web/issue9469/index.html +++ b/web/src/test/manual/web/issue9469/index.html @@ -36,11 +36,10 @@ @@ -48,7 +49,7 @@ - +

KeymanWeb Sample Page - Error Testing page

Pick one of the 'debugging' keyboards to test whether the represented error is handled correctly.

@@ -65,9 +66,32 @@

or in this input field:

+

Expected error messages:

+
    +
  • wrong-filename keyboard: "Unable to download wrong-filename keyboard for debugging"
  • +
  • non-parsable keyboard: "Error registering the non-parsable keyboard for debugging; keyboard script at ./unparsable.js may contain an error."
  • +
  • timeout keyboard: "Sorry, the timeout keyboard for debugging is not currently available."
  • +
+

Return to testing home page

+ + + + + + + + + + + KeymanWeb Khmer KMX/JS test page + + + + + + + + + + + + + + + + + + + + +

KeymanWeb Sample Page - Khmer Angkor KMX and JS Keyboards

+ +
+ +
+ +

This page allows to use either the .kmx or the .js version of the Khmer Angkor + keyboard (or whatever .kmx keyboard specified by the keyboard query + parameter). + Which one can be selected by the type query parameter: + append ?type=kmx or ?type=js to the URL. + The default is to use the .kmx version. +

+

Type Khmer in this text area:

+ + +

Return to testing home page

+
+ + +
+

--End of Document--

+ + + + + diff --git a/web/src/test/manual/web/mnemonic/index.html b/web/src/test/manual/web/mnemonic/index.html index e0b0f0de79..a77c862219 100644 --- a/web/src/test/manual/web/mnemonic/index.html +++ b/web/src/test/manual/web/mnemonic/index.html @@ -33,24 +33,21 @@ - - diff --git a/web/src/test/manual/web/options-with-save/index.html b/web/src/test/manual/web/options-with-save/index.html index 9f607fd11f..2e69318bbc 100644 --- a/web/src/test/manual/web/options-with-save/index.html +++ b/web/src/test/manual/web/options-with-save/index.html @@ -33,24 +33,21 @@ - - diff --git a/web/src/test/manual/web/osk-event-buttons/index.html b/web/src/test/manual/web/osk-event-buttons/index.html index 92dafcdb4a..95ce7c7707 100644 --- a/web/src/test/manual/web/osk-event-buttons/index.html +++ b/web/src/test/manual/web/osk-event-buttons/index.html @@ -36,8 +36,7 @@ @@ -51,7 +52,7 @@ - +

KeymanWeb Sample Page - Platform Testing

This page is designed to test the Platform statement for consistency. Refer to PR #969.
diff --git a/web/src/test/manual/web/platform/utilities.js b/web/src/test/manual/web/platform/utilities.js index 5c351e0317..bb02bdd6a1 100644 --- a/web/src/test/manual/web/platform/utilities.js +++ b/web/src/test/manual/web/platform/utilities.js @@ -1,8 +1,6 @@ -function loadKeyboards() -{ - var kmw=keyman; - - kmw.addKeyboards({id:'platformtest',name:'Platform Testing', +function loadKeyboards() +{ + keyman.addKeyboards({id:'platformtest',name:'Platform Testing', languages:{ id:'en',name:'English',region:'North America' }, diff --git a/web/src/test/manual/web/pr10506/header.js b/web/src/test/manual/web/pr10506/header.js index 0107af3525..986cc00433 100644 --- a/web/src/test/manual/web/pr10506/header.js +++ b/web/src/test/manual/web/pr10506/header.js @@ -1,11 +1,10 @@ function loadKeyboards() { - var kmw=keyman; - kmw.addKeyboards({id:'us',name:'English',languages:{id:'en',name:'English'}, + keyman.addKeyboards({id:'us',name:'English',languages:{id:'en',name:'English'}, filename:('../us-1.0.js')}); // Add a fully-specified, locally-sourced, keyboard with custom font - kmw.addKeyboards({id:'dotty_keys',name:'Dotty Keys', + keyman.addKeyboards({id:'dotty_keys',name:'Dotty Keys', languages:{ id:'und',name:'Special',region:'World', font:{family:'DejaVu Dots',source:['./DejaVu-Dots.ttf']} diff --git a/web/src/test/manual/web/pr10506/index.html b/web/src/test/manual/web/pr10506/index.html index 06eae11362..84ff48f868 100644 --- a/web/src/test/manual/web/pr10506/index.html +++ b/web/src/test/manual/web/pr10506/index.html @@ -36,9 +36,10 @@ @@ -49,7 +50,7 @@ - +

KeymanWeb Test Page - Key-cap scaling / font-load delay interactions

To run the test, simply change from the default (English) keyboard to the "Special" keyboard.

When things are working properly, the base keys on the "Special" keyboard should contain diff --git a/web/src/test/manual/web/prediction-mtnt/index.html b/web/src/test/manual/web/prediction-mtnt/index.html index 34f43f3c5b..0e41b5b63a 100644 --- a/web/src/test/manual/web/prediction-mtnt/index.html +++ b/web/src/test/manual/web/prediction-mtnt/index.html @@ -36,16 +36,15 @@ - +

@@ -72,8 +73,8 @@ e.value = e.value + event + ': w.iw='+window.innerWidth+' w.ih='+window.innerHeight+orientText+orient+'\n'; - if(event == 'kmw.ri' || event == 'kmw.rh' || event == 'kmw.re') { - e.value = e.value + ' osk.w=' + keyman.osk.computedWidth + ' osk.h=' + keyman.osk.computedHeight + ' kmw.vs=' + keyman.util.getViewportScale() + '\n'; + if(event == 'keyman.ri' || event == 'keyman.rh' || event == 'keyman.re') { + e.value = e.value + ' osk.w=' + keyman.osk.computedWidth + ' osk.h=' + keyman.osk.computedHeight + ' keyman.vs=' + keyman.util.getViewportScale() + '\n'; } e.scrollTop = e.scrollHeight; @@ -89,22 +90,22 @@ window.addEventListener('orientationchange', function() { doLog('orientationchange-b', false) }, false); window.addEventListener('orientationchange', function() { doLog('orientationchange-c', false) }, true); - var kmw_ri = com.keyman.RotationManager.prototype.initNewRotation; + var keyman_ri = com.keyman.RotationManager.prototype.initNewRotation; com.keyman.RotationManager.prototype.initNewRotation = function() { - doLog('kmw.ri'); - kmw_ri.call(this); + doLog('keyman.ri'); + keyman_ri.call(this); } - var kmw_rh = com.keyman.RotationManager.prototype.iOSEventHandler; + var keyman_rh = com.keyman.RotationManager.prototype.iOSEventHandler; com.keyman.RotationManager.prototype.iOSEventHandler = function() { - doLog('kmw.rh'); - kmw_rh.call(this); + doLog('keyman.rh'); + keyman_rh.call(this); } - var kmw_irh = com.keyman.RotationManager.prototype.resolve; + var keyman_irh = com.keyman.RotationManager.prototype.resolve; com.keyman.RotationManager.prototype.resolve = function() { - doLog('kmw.re'); - kmw_irh.call(this); + doLog('keyman.re'); + keyman_irh.call(this); }

Return to main index. diff --git a/web/src/test/manual/web/sentry-integration/errorhdr.js b/web/src/test/manual/web/sentry-integration/errorhdr.js index f5e4ec283f..27b8869504 100644 --- a/web/src/test/manual/web/sentry-integration/errorhdr.js +++ b/web/src/test/manual/web/sentry-integration/errorhdr.js @@ -1,27 +1,25 @@ -// JavaScript Document samplehdr.js: Keyboard management for KeymanWeb demonstration pages - -/* - This script is designed to test KeymanWeb error message handling. +/* + * Keyman is copyright (C) SIL Global. MIT License. + * + * This script is designed to test KeymanWeb error message handling. */ -function loadKeyboards() { - var kmw=keyman; - +async function loadKeyboards() { // We start by adding a keyboard correctly. It's best to include a 'control' in our experiment. - kmw.addKeyboards({id:'us',name:'English',languages:{id:'en',name:'English'}, + await keyman.addKeyboards({id:'us',name:'English',languages:{id:'en',name:'English'}, filename:'../us-1.0.js'}); - + // Insert a keyboard that cannot be found. - kmw.addKeyboards({id:'lao_2008_basic',name:'wrong-filename', + await keyman.addKeyboards({id:'lao_2008_basic',name:'wrong-filename', languages:{ id:'lo',name:'debugging',region:'Asia', font:{family:'LaoWeb',source:['../font/saysettha_web.ttf','../font/saysettha_web.woff','../font/saysettha_web.eot']} }, filename:'./missing_file.js' // Intentional error - the file doesn't exist, so the @@ -51,7 +52,7 @@ - +

KeymanWeb Sample Page - Shift Testing

See issue #978 for details on what this test is all about.

diff --git a/web/src/test/manual/web/test-updateLayer/utilities.js b/web/src/test/manual/web/test-updateLayer/utilities.js index 41704fa0da..378f44c87e 100644 --- a/web/src/test/manual/web/test-updateLayer/utilities.js +++ b/web/src/test/manual/web/test-updateLayer/utilities.js @@ -1,8 +1,6 @@ -function loadKeyboards() -{ - var kmw=keyman; - - kmw.addKeyboards({id:'rac_balti',name:'RAC Balti', +function loadKeyboards() +{ + keyman.addKeyboards({id:'rac_balti',name:'RAC Balti', languages:{ id:'en',name:'English',region:'North America' }, diff --git a/web/src/test/manual/web/text_selection_tests_9073/index.html b/web/src/test/manual/web/text_selection_tests_9073/index.html index 20bd3cda68..7851186892 100644 --- a/web/src/test/manual/web/text_selection_tests_9073/index.html +++ b/web/src/test/manual/web/text_selection_tests_9073/index.html @@ -20,23 +20,21 @@ + }); + diff --git a/web/src/test/manual/web/unminified - manual.html b/web/src/test/manual/web/unminified - manual.html index dbe7cdae48..5ff0c686e3 100644 --- a/web/src/test/manual/web/unminified - manual.html +++ b/web/src/test/manual/web/unminified - manual.html @@ -36,8 +36,7 @@ diff --git a/web/src/tools/testing/bulk_rendering/renderer_core.ts b/web/src/tools/testing/bulk_rendering/renderer_core.ts index 50c5ca2494..597ef36950 100644 --- a/web/src/tools/testing/bulk_rendering/renderer_core.ts +++ b/web/src/tools/testing/bulk_rendering/renderer_core.ts @@ -1,11 +1,14 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + */ // Includes KeymanWeb's Device class, as it's quite a useful resource for KMW-related projects. import { DeviceDetector } from 'keyman/engine/main'; -import { type DeviceSpec } from '@keymanapp/web-utils'; +import { type DeviceSpec } from 'keyman/common/web-utils'; import type { KeymanEngine } from 'keyman/app/browser'; -import type { FloatingOSKView } from 'keyman/engine/osk'; +import { JSKeyboard, type FloatingOSKView } from 'keyman/engine/osk'; -declare var keyman: KeymanEngine; +declare const keyman: KeymanEngine; type KeyboardData = ReturnType; type KeyboardMap = {[id: string]: KeyboardData}; @@ -53,12 +56,12 @@ export class BatchRenderer { // Filters the keyboard array to ensure only a single entry remains, rather than an entry per language. private filterKeyboards(): KeyboardMap { - let kbds = keyman.getKeyboards(); + const kbds = keyman.getKeyboards(); - let keyboardMap: Record[0]> = {}; + const keyboardMap: Record[0]> = {}; - for(var i = 0; i < kbds.length; i++) { - let id: string = kbds[i].InternalName; + for(let i = 0; i < kbds.length; i++) { + const id: string = kbds[i].InternalName; if(!id.match(BatchRenderer.keyboardMatch)) continue; if(id.match(/^Keyboard_bod/)) continue; // bod keyboards currently don't load on Chrome and break the test run; they need rebuild. if(keyboardMap[id]) { @@ -73,7 +76,7 @@ export class BatchRenderer { private render(ele: HTMLElement, isMobile?: boolean): Promise { const capture = async () => { - const result = await new Promise((resolve, reject) => { + return await new Promise((resolve, reject) => { // from: https://github.com/kasprownik/electron-screencapture/blob/master/index.js const canvas = document.createElement('canvas'); canvas.width = BatchRenderer.boundingRect.width; @@ -87,26 +90,24 @@ export class BatchRenderer { 0, 0, canvas.width, canvas.height); const frame = canvas.toDataURL("image/png"); - let imgOut = document.createElement('img'); + const imgOut = document.createElement('img'); imgOut.src = frame; resolve(imgOut); }); - - return result; } return capture(); } createKeyboardHeader(kbd: KeyboardData, formFactor: DeviceSpec.FormFactor, loaded: boolean): HTMLDivElement { - let divHeader = document.createElement('div'); - let eleName = document.createElement('h2'); + const divHeader = document.createElement('div'); + const eleName = document.createElement('h2'); eleName.textContent = 'ID: ' + kbd.InternalName; divHeader.appendChild(eleName); - let eleDescription = document.createElement('p'); + const eleDescription = document.createElement('p'); if(loaded) { @@ -114,19 +115,23 @@ export class BatchRenderer { eleDescription.appendChild(document.createElement('br')); const keyboard = keyman.core.activeKeyboard; - // Some keyboards, such as sil_euro_latin and sil_ipa, no longer specify this property. - if(keyboard['_legacyLayoutSpec']) { - eleDescription.appendChild(document.createTextNode('Font: ' + keyboard['_legacyLayoutSpec'].F)); - } else { - // They instead specify only the post-KMW-10 touch-layout format. - const layout = keyboard.layout(formFactor); - if(!layout) { - eleDescription.appendChild(document.createTextNode('Keyboard is help-text based')); + if (keyboard instanceof JSKeyboard) { + // Some keyboards, such as sil_euro_latin and sil_ipa, no longer specify this property. + if (keyboard['_legacyLayoutSpec']) { + eleDescription.appendChild(document.createTextNode('Font: ' + keyboard['_legacyLayoutSpec'].F)); } else { - eleDescription.appendChild(document.createTextNode('Font: ' + layout.font)); + // They instead specify only the post-KMW-10 touch-layout format. + const layout = keyboard.layout(formFactor); + if (!layout) { + eleDescription.appendChild(document.createTextNode('Keyboard is help-text based')); + } else { + eleDescription.appendChild(document.createTextNode('Font: ' + layout.font)); + } } + } else { + // TODO-web-core: implement for KMX keyboards + eleDescription.appendChild(document.createTextNode('Keyboard is help-text based')); } - } else { eleDescription.appendChild(document.createTextNode('Unable to load this keyboard!')); } @@ -137,22 +142,22 @@ export class BatchRenderer { } private processKeyboard(kbd: KeyboardData) { - let p: Promise = keyman.setActiveKeyboard(kbd.InternalName); + const p: Promise = keyman.setActiveKeyboard(kbd.InternalName); const formFactor = keyman.config.hostDevice.formFactor; - let isMobile = formFactor != 'desktop'; + const isMobile = formFactor != 'desktop'; // Establish common keyboard header info. - let divSummary = document.createElement('div'); + const divSummary = document.createElement('div'); // Establishes a linkable target for this keyboard's data. divSummary.id = "summary-" + kbd.InternalName; BatchRenderer.divMaster.insertAdjacentElement('afterbegin', divSummary); // A nice, closure-friendly reference for use in our callbacks. - let renderer = this; + const renderer = this; // Once the keyboard's loaded, we can really get started. return p.then(function() { - let box: HTMLDivElement = keyman.osk._Box; + const box: HTMLDivElement = keyman.osk._Box; BatchRenderer.boundingRect = box.getBoundingClientRect(); @@ -163,12 +168,12 @@ export class BatchRenderer { divSummary.appendChild(renderer.createKeyboardHeader(kbd, formFactor, true)); - let divRenders = document.createElement('div'); + const divRenders = document.createElement('div'); divSummary.appendChild(divRenders); // Uses 'private' APIs that may be subject to change in the future. Keep it updated! let layers: string[]; - if(!isMobile) { + if(!isMobile && keyman.core.activeKeyboard instanceof JSKeyboard) { // The desktop OSK will be overpopulated, with a number of blank layers to display in most cases. // We instead rely upon the KLS definition to ensure we keep the renders sparse. // @@ -180,7 +185,7 @@ export class BatchRenderer { // Note: vkbd will be null for keyboards with desktop help-text, such as sil_euro_latin. layers = layers || Object.keys(keyman.osk.vkbd?.layerGroup.layers); - let renderLayer = function(i: number) { + const renderLayer = function(i: number) { return new Promise(function(resolve) { // (Private API) Directly sets the keyboard layer within KMW, then uses .show to force-display it. if(keyman.osk.vkbd) { @@ -198,8 +203,8 @@ export class BatchRenderer { (document as any).fonts.ready.then(function() { window.setTimeout(function() { renderer.render(box, isMobile).then(function(imgEle: HTMLImageElement) { - let eleLayer = document.createElement('div'); - let eleLayerId = document.createElement('p'); + const eleLayer = document.createElement('div'); + const eleLayerId = document.createElement('p'); eleLayerId.textContent = 'Layer ID: ' + Object.keys(layers)[i]; eleLayer.appendChild(eleLayerId); @@ -227,9 +232,9 @@ export class BatchRenderer { // Synchronously performs asynchronous operations across a loop, one at a time. // Necessary due to the nature of KMW OSK rendering. private arrayPromiseIteration(promiseGenerator: (i: number) => Promise, length: number): Promise { - let iteration = function(index: number): Promise { + const iteration = function(index: number): Promise { if(index < length) { - var promise = promiseGenerator(index); + const promise = promiseGenerator(index); return promise.then(function(index: number) { return iteration(++index); }) @@ -242,8 +247,8 @@ export class BatchRenderer { } fillDeviceNotes() { - let description = document.createElement('p'); - let device = new DeviceDetector(); + const description = document.createElement('p'); + const device = new DeviceDetector(); device.detect(); description.appendChild(document.createTextNode('Browser: ' + device.browser)); @@ -266,7 +271,7 @@ export class BatchRenderer { BatchRenderer.keyboardMatch = new RegExp('^Keyboard_('+filter+')', 'i'); if(keyman) { - let cc = await this.startCapture(); + const cc = await this.startCapture(); BatchRenderer.captureStream = cc.captureStream; BatchRenderer.video = cc.video; @@ -288,13 +293,13 @@ export class BatchRenderer { } // Assumes that the keyboards have been preloaded for us. - let kbds = this.filterKeyboards(); + const kbds = this.filterKeyboards(); console.log("Unique keyboard ids detected: " + Object.keys(kbds).length); - let renderer = this; + const renderer = this; - let keyboardIterator = function(i: number) { + const keyboardIterator = function(i: number) { return new Promise(function(resolve) { renderer.processKeyboard(kbds[Object.keys(kbds)[i]]).then(function () { //console.log("Keyboard " + i + " processed!"); @@ -321,5 +326,5 @@ export class BatchRenderer { // BatchRenderer's internal state stuff is static on the class and is not exposed with // the line below. // @ts-ignore - window['kmw_renderer'] = new BatchRenderer(); + window['keyman_renderer'] = new BatchRenderer(); })(); \ No newline at end of file diff --git a/web/src/tools/testing/bulk_rendering/tsconfig.json b/web/src/tools/testing/bulk_rendering/tsconfig.json index 8256bda7b9..dc736a02b8 100644 --- a/web/src/tools/testing/bulk_rendering/tsconfig.json +++ b/web/src/tools/testing/bulk_rendering/tsconfig.json @@ -2,10 +2,9 @@ "extends": "../../../tsconfig.dom.json", "compilerOptions": { - "baseUrl": "./", "outDir": "../../../../build/tools/testing/bulk_rendering/obj/", "tsBuildInfoFile": "../../../../build/tools/testing/bulk_rendering/obj/tsconfig.tsbuildinfo", - "rootDir": "." + "rootDir": ".", }, "files": [ @@ -13,7 +12,8 @@ ], "references": [ + { "path": "../../../common/web-utils" }, { "path": "../../../app/browser" }, - { "path": "../../../engine/main" } + { "path": "../../../engine" } ] } diff --git a/web/src/engine/osk/gesture-processor/src/tools/build.sh b/web/src/tools/testing/gesture-processor/build.sh similarity index 62% rename from web/src/engine/osk/gesture-processor/src/tools/build.sh rename to web/src/tools/testing/gesture-processor/build.sh index 0fe33fe784..b596089914 100755 --- a/web/src/engine/osk/gesture-processor/src/tools/build.sh +++ b/web/src/tools/testing/gesture-processor/build.sh @@ -3,18 +3,20 @@ ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" -. "$(dirname "$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" -BASE_DIR="/web/src/engine/osk/gesture-processor" -BUILD_DIR="${BASE_DIR}/build" +# BASE_DIR="/web/src/engine/osk/gesture-processor" +BUILD_DIR=/web/build/tools/testing/gesture-processor ################################ Main script ################################ builder_describe "Testing-oriented tools for the Gesture Processor module of web-based Keyman OSKs" \ + "@/common/tools/es-bundling build" \ "clean" \ "build" \ ":fixture The HTML-element fixture and CSS fixture used for both user-testing and unit-testing" \ @@ -25,21 +27,21 @@ builder_parse "$@" builder_describe_outputs \ configure /node_modules \ - build:fixture "${BUILD_DIR}/tools/host-fixture.html" \ - build:recorder "${BASE_DIR}/src/tools/recorder/build/recorder.mjs" \ - build:test-module "${BUILD_DIR}/tools/lib/index.mjs" + build:fixture "${BUILD_DIR}/unit-test-resources/host-fixture.html" \ + build:recorder "/web/tools/testing/gesture-processor/recorder/build/recorder.mjs" \ + build:test-module "${BUILD_DIR}/unit-test-resources/lib/index.mjs" # TODO: build if out-of-date if test is specified # TODO: configure if npm has not been run, and build is specified function do_clean_fixture() { - rm -f ../../build/tools/host-fixture.html - rm -f ../../build/tools/gestureHost.css + rm -f "${KEYMAN_ROOT}/${BUILD_DIR}/unit-test-resources/host-fixture.html" + rm -f "${KEYMAN_ROOT}/${BUILD_DIR}/unit-test-resources/gestureHost.css" } function do_clean_testmodule() { - rm -rf ../../build/tools/*.ts* - rm -rf ../../build/tools/*.js* + rm -rf "${KEYMAN_ROOT}/${BUILD_DIR}/unit-test-resources/*.ts*" + rm -rf "${KEYMAN_ROOT}/${BUILD_DIR}/unit-test-resources/*.js*" } function do_build_recorder() { @@ -59,18 +61,16 @@ function do_build_recorder() { } function do_build_fixture() { - if [[ ! -d ../../build/tools ]]; then - mkdir -p ../../build/tools - fi - ./host-fixture/extract-fixture.sh > ../../build/tools/host-fixture.html - cp ./host-fixture/gestureHost.css ../../build/tools/gestureHost.css + mkdir -p "${KEYMAN_ROOT}/${BUILD_DIR}/unit-test-resources" + ./host-fixture/extract-fixture.sh > "${KEYMAN_ROOT}/${BUILD_DIR}/unit-test-resources/host-fixture.html" + cp ./host-fixture/gestureHost.css "${KEYMAN_ROOT}/${BUILD_DIR}/unit-test-resources/gestureHost.css" } function do_build_testmodule() { - compile "" "${THIS_SCRIPT_PATH}/unit-test-resources" "${KEYMAN_ROOT}/${BUILD_DIR}/tools" + compile "" "${THIS_SCRIPT_PATH}/unit-test-resources" "${KEYMAN_ROOT}/${BUILD_DIR}/unit-test-resources" - node "$LIB_BUNDLER" "${KEYMAN_ROOT}/${BUILD_DIR}/tools/obj/index.js" \ - --out "${KEYMAN_ROOT}/${BUILD_DIR}/tools/lib/index.mjs" \ + node_es_bundle "${KEYMAN_ROOT}/${BUILD_DIR}/unit-test-resources/obj/index.js" \ + --out "${KEYMAN_ROOT}/${BUILD_DIR}/unit-test-resources/lib/index.mjs" \ --format "esm" } diff --git a/web/src/engine/osk/gesture-processor/src/tools/host-fixture/extract-fixture.sh b/web/src/tools/testing/gesture-processor/host-fixture/extract-fixture.sh similarity index 100% rename from web/src/engine/osk/gesture-processor/src/tools/host-fixture/extract-fixture.sh rename to web/src/tools/testing/gesture-processor/host-fixture/extract-fixture.sh diff --git a/web/src/engine/osk/gesture-processor/src/tools/host-fixture/extractor.cjs b/web/src/tools/testing/gesture-processor/host-fixture/extractor.cjs similarity index 100% rename from web/src/engine/osk/gesture-processor/src/tools/host-fixture/extractor.cjs rename to web/src/tools/testing/gesture-processor/host-fixture/extractor.cjs diff --git a/web/src/engine/osk/gesture-processor/src/tools/host-fixture/gestureHost.css b/web/src/tools/testing/gesture-processor/host-fixture/gestureHost.css similarity index 100% rename from web/src/engine/osk/gesture-processor/src/tools/host-fixture/gestureHost.css rename to web/src/tools/testing/gesture-processor/host-fixture/gestureHost.css diff --git a/web/src/engine/osk/gesture-processor/src/tools/host-fixture/host-fixture.html b/web/src/tools/testing/gesture-processor/host-fixture/host-fixture.html similarity index 100% rename from web/src/engine/osk/gesture-processor/src/tools/host-fixture/host-fixture.html rename to web/src/tools/testing/gesture-processor/host-fixture/host-fixture.html diff --git a/web/src/engine/osk/gesture-processor/src/tools/recorder/src/index.html b/web/src/tools/testing/gesture-processor/recorder/src/index.html similarity index 100% rename from web/src/engine/osk/gesture-processor/src/tools/recorder/src/index.html rename to web/src/tools/testing/gesture-processor/recorder/src/index.html diff --git a/web/src/engine/osk/gesture-processor/src/tools/recorder/src/pageStyle.css b/web/src/tools/testing/gesture-processor/recorder/src/pageStyle.css similarity index 100% rename from web/src/engine/osk/gesture-processor/src/tools/recorder/src/pageStyle.css rename to web/src/tools/testing/gesture-processor/recorder/src/pageStyle.css diff --git a/web/src/engine/osk/gesture-processor/src/tools/recorder/src/recorder.mjs b/web/src/tools/testing/gesture-processor/recorder/src/recorder.mjs similarity index 100% rename from web/src/engine/osk/gesture-processor/src/tools/recorder/src/recorder.mjs rename to web/src/tools/testing/gesture-processor/recorder/src/recorder.mjs diff --git a/web/src/engine/osk/gesture-processor/src/tools/recorder/update-index.cjs b/web/src/tools/testing/gesture-processor/recorder/update-index.cjs similarity index 100% rename from web/src/engine/osk/gesture-processor/src/tools/recorder/update-index.cjs rename to web/src/tools/testing/gesture-processor/recorder/update-index.cjs diff --git a/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/fixtureLayoutConfiguration.ts b/web/src/tools/testing/gesture-processor/unit-test-resources/src/fixtureLayoutConfiguration.ts similarity index 100% rename from web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/fixtureLayoutConfiguration.ts rename to web/src/tools/testing/gesture-processor/unit-test-resources/src/fixtureLayoutConfiguration.ts diff --git a/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/headlessInputEngine.ts b/web/src/tools/testing/gesture-processor/unit-test-resources/src/headlessInputEngine.ts similarity index 97% rename from web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/headlessInputEngine.ts rename to web/src/tools/testing/gesture-processor/unit-test-resources/src/headlessInputEngine.ts index beb37d0755..adec117ec1 100644 --- a/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/headlessInputEngine.ts +++ b/web/src/tools/testing/gesture-processor/unit-test-resources/src/headlessInputEngine.ts @@ -2,10 +2,10 @@ import { InputEngineBase, SerializedGestureSource, GestureSource -} from '@keymanapp/gesture-recognizer'; +} from 'keyman/engine/gesture-processor'; import { RecordedCoordSequenceSet } from './inputRecording.js'; -import { timedPromise } from '@keymanapp/web-utils'; +import { timedPromise } from 'keyman/common/web-utils'; export class HeadlessInputEngine extends InputEngineBase { private PATH_ID_SEED = 1; diff --git a/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/hostFixtureLayoutController.ts b/web/src/tools/testing/gesture-processor/unit-test-resources/src/hostFixtureLayoutController.ts similarity index 98% rename from web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/hostFixtureLayoutController.ts rename to web/src/tools/testing/gesture-processor/unit-test-resources/src/hostFixtureLayoutController.ts index 7930368442..a0d191f580 100644 --- a/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/hostFixtureLayoutController.ts +++ b/web/src/tools/testing/gesture-processor/unit-test-resources/src/hostFixtureLayoutController.ts @@ -1,5 +1,5 @@ import { EventEmitter } from 'eventemitter3'; -import { GestureRecognizer, GestureRecognizerConfiguration } from '@keymanapp/gesture-recognizer'; +import { GestureRecognizer, GestureRecognizerConfiguration } from 'keyman/engine/gesture-processor'; import { FixtureLayoutConfiguration } from './fixtureLayoutConfiguration.js'; diff --git a/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/index.ts b/web/src/tools/testing/gesture-processor/unit-test-resources/src/index.ts similarity index 100% rename from web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/index.ts rename to web/src/tools/testing/gesture-processor/unit-test-resources/src/index.ts diff --git a/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/inputRecording.ts b/web/src/tools/testing/gesture-processor/unit-test-resources/src/inputRecording.ts similarity index 81% rename from web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/inputRecording.ts rename to web/src/tools/testing/gesture-processor/unit-test-resources/src/inputRecording.ts index 2784dfdedc..c055a70db5 100644 --- a/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/inputRecording.ts +++ b/web/src/tools/testing/gesture-processor/unit-test-resources/src/inputRecording.ts @@ -1,4 +1,4 @@ -import { type SerializedGestureSource } from "@keymanapp/gesture-recognizer"; +import { type SerializedGestureSource } from "keyman/engine/gesture-processor"; import { type FixtureLayoutConfiguration } from "./fixtureLayoutConfiguration.js"; import { type JSONObject } from "./jsonObject.js"; diff --git a/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/inputSequenceSimulator.ts b/web/src/tools/testing/gesture-processor/unit-test-resources/src/inputSequenceSimulator.ts similarity index 99% rename from web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/inputSequenceSimulator.ts rename to web/src/tools/testing/gesture-processor/unit-test-resources/src/inputSequenceSimulator.ts index c6f9a89ba2..04a6059aaf 100644 --- a/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/inputSequenceSimulator.ts +++ b/web/src/tools/testing/gesture-processor/unit-test-resources/src/inputSequenceSimulator.ts @@ -2,7 +2,7 @@ import { GestureDebugPath, GestureDebugSource, type InputSample -} from "@keymanapp/gesture-recognizer"; +} from "keyman/engine/gesture-processor"; import { type HostFixtureLayoutController } from "./hostFixtureLayoutController.js"; import { type JSONObject } from "./jsonObject.js"; diff --git a/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/jsonObject.ts b/web/src/tools/testing/gesture-processor/unit-test-resources/src/jsonObject.ts similarity index 100% rename from web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/jsonObject.ts rename to web/src/tools/testing/gesture-processor/unit-test-resources/src/jsonObject.ts diff --git a/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/sequenceRecorder.ts b/web/src/tools/testing/gesture-processor/unit-test-resources/src/sequenceRecorder.ts similarity index 95% rename from web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/sequenceRecorder.ts rename to web/src/tools/testing/gesture-processor/unit-test-resources/src/sequenceRecorder.ts index b0451375d4..5b125e6b93 100644 --- a/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/sequenceRecorder.ts +++ b/web/src/tools/testing/gesture-processor/unit-test-resources/src/sequenceRecorder.ts @@ -1,4 +1,4 @@ -import { GestureDebugSource, GestureSource } from "@keymanapp/gesture-recognizer"; +import { GestureDebugSource, GestureSource } from "keyman/engine/gesture-processor"; import { HostFixtureLayoutController } from "./hostFixtureLayoutController.js"; import { RecordedCoordSequenceSet } from "./inputRecording.js"; diff --git a/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/touchpathTurtle.ts b/web/src/tools/testing/gesture-processor/unit-test-resources/src/touchpathTurtle.ts similarity index 99% rename from web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/touchpathTurtle.ts rename to web/src/tools/testing/gesture-processor/unit-test-resources/src/touchpathTurtle.ts index 524fe0de4b..df4f15b184 100644 --- a/web/src/engine/osk/gesture-processor/src/tools/unit-test-resources/src/touchpathTurtle.ts +++ b/web/src/tools/testing/gesture-processor/unit-test-resources/src/touchpathTurtle.ts @@ -2,7 +2,7 @@ import { EventEmitter } from "eventemitter3"; import { type InputSample -} from "@keymanapp/gesture-recognizer" +} from "keyman/engine/gesture-processor" interface EventMap { /** diff --git a/web/src/tools/testing/gesture-processor/unit-test-resources/tsconfig.json b/web/src/tools/testing/gesture-processor/unit-test-resources/tsconfig.json new file mode 100644 index 0000000000..ad1b766227 --- /dev/null +++ b/web/src/tools/testing/gesture-processor/unit-test-resources/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../../../../../tsconfig.base.json", + "compilerOptions": { + "lib": [ "dom", "es6" ], + "outDir": "../../../../../build/tools/testing/gesture-processor/unit-test-resources/obj", + "rootDir": "./src", + "tsBuildInfoFile": "../../../../../build/tools/testing/gesture-processor/unit-test-resources/tsconfig.tsbuildinfo", + }, + "references": [ + { "path": "../../../../engine/" } + ], + "include": ["./src/**/*.ts"] +} diff --git a/web/src/tools/testing/recorder-core/build.sh b/web/src/tools/testing/recorder-core/build.sh index 4bd56ee2b8..4075ce26f7 100755 --- a/web/src/tools/testing/recorder-core/build.sh +++ b/web/src/tools/testing/recorder-core/build.sh @@ -18,7 +18,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" builder_describe \ "Compiles the web-oriented utility function module." \ - "@/common/web/keyman-version" \ + "@/common/web/keyman-version build" \ configure \ clean \ build diff --git a/web/src/tools/testing/recorder-core/package.json b/web/src/tools/testing/recorder-core/package.json index 6bec4354ae..5bbe584e7e 100644 --- a/web/src/tools/testing/recorder-core/package.json +++ b/web/src/tools/testing/recorder-core/package.json @@ -18,11 +18,6 @@ "url": "https://github.com/keymanapp/keyman/issues" }, "homepage": "https://github.com/keymanapp/keyman#readme", - "dependencies": { - "@keymanapp/common-types": "*", - "@keymanapp/keyman-version": "*", - "@keymanapp/web-utils": "*" - }, "devDependencies": { "typescript": "^5.4.5" } diff --git a/web/src/tools/testing/recorder-core/src/index.ts b/web/src/tools/testing/recorder-core/src/index.ts index 2a73971023..e1d3d913ce 100644 --- a/web/src/tools/testing/recorder-core/src/index.ts +++ b/web/src/tools/testing/recorder-core/src/index.ts @@ -1,12 +1,11 @@ -import { Mock, type OutputTarget } from "keyman/engine/js-processor"; -import { KeyDistribution, KeyEvent } from "keyman/engine/keyboard"; +import { KeyDistribution, KeyEvent, type TextStore, SyntheticTextStore } from "keyman/engine/keyboard"; -import Proctor from "./proctor.js"; +import { Proctor } from "./proctor.js"; -export { default as Proctor } from "./proctor.js"; -export { default as NodeProctor } from "./nodeProctor.js"; +export { Proctor } from "./proctor.js"; +export { NodeProctor } from "./nodeProctor.js"; -import * as utils from "@keymanapp/web-utils"; +import * as utils from "keyman/common/web-utils"; type EventTypeTag = 'key' | 'osk'; type TaggedEventObject = { type: EventTypeTag } @@ -217,15 +216,15 @@ export abstract class TestSequence { - // Start with an empty OutputTarget and a fresh KeyboardProcessor. - if(!target) { - target = new Mock(); + async test(proctor: Proctor, textStore?: TextStore): Promise<{success: boolean, result: string}> { + // Start with an empty TextStore and a fresh KeyboardProcessor. + if(!textStore) { + textStore = new SyntheticTextStore(); } proctor.before(); - let result = await proctor.simulateSequence(this, target); + const result = await proctor.simulateSequence(this, textStore); proctor.assertEquals(result, this.output, this.msg); return {success: (result == this.output), result: result}; diff --git a/web/src/tools/testing/recorder-core/src/nodeProctor.ts b/web/src/tools/testing/recorder-core/src/nodeProctor.ts index 204ef21939..10f30a4990 100644 --- a/web/src/tools/testing/recorder-core/src/nodeProctor.ts +++ b/web/src/tools/testing/recorder-core/src/nodeProctor.ts @@ -1,4 +1,4 @@ -import Proctor, { AssertCallback } from "./proctor.js"; +import { Proctor, AssertCallback } from "./proctor.js"; import { KeyboardTest, TestSet, @@ -8,12 +8,11 @@ import { RecordedSyntheticKeystroke } from "./index.js"; -import { KeyEvent, KeyEventSpec, KeyboardHarness } from "keyman/engine/keyboard"; -import { Mock, type OutputTarget } from "keyman/engine/js-processor"; -import { DeviceSpec } from "@keymanapp/web-utils"; -import { KeyboardInterface, KeyboardProcessor } from 'keyman/engine/js-processor'; +import { DefaultOutputRules, KeyEvent, KeyEventSpec, KeyboardHarness, SyntheticTextStore, TextStore } from "keyman/engine/keyboard"; +import { DeviceSpec } from "keyman/common/web-utils"; +import { JSKeyboardInterface, JSKeyboardProcessor } from 'keyman/engine/js-processor'; -export default class NodeProctor extends Proctor { +export class NodeProctor extends Proctor { private keyboardWithHarness: KeyboardHarness; public __debug = false; @@ -49,19 +48,22 @@ export default class NodeProctor extends Proctor { return true; } - async simulateSequence(sequence: TestSequence, target?: OutputTarget): Promise { - // Start with an empty OutputTarget and a fresh KeyboardProcessor. - if(!target) { - target = new Mock(); + async simulateSequence(sequence: TestSequence, textStore?: TextStore): Promise { + // Start with an empty TextStore and a fresh KeyboardProcessor. + if(!textStore) { + textStore = new SyntheticTextStore(); } // Establish a fresh processor, setting its keyboard appropriately for the test. - let processor = new KeyboardProcessor(this.device); - processor.keyboardInterface = this.keyboardWithHarness as KeyboardInterface; + const processor = new JSKeyboardProcessor(this.device, { + baseLayout: 'us', + keyboardInterface: this.keyboardWithHarness as JSKeyboardInterface, + defaultOutputRules: new DefaultOutputRules() + }); const keyboard = processor.activeKeyboard; if(sequence instanceof RecordedKeystrokeSequence) { - for(let keystroke of sequence.inputs) { + for(const keystroke of sequence.inputs) { let keyEvent: KeyEventSpec; if(keystroke instanceof RecordedPhysicalKeystroke) { // Use the keystroke's stored data to reconstruct the KeyEvent. @@ -77,7 +79,7 @@ export default class NodeProctor extends Proctor { LisVirtualKey: keyboard.definesPositionalOrMnemonic // Only false for 1.0 keyboards. } } else if(keystroke instanceof RecordedSyntheticKeystroke) { - let key = keyboard.layout(this.device.formFactor).getLayer(keystroke.layer).getKey(keystroke.keyName); + const key = keyboard.layout(this.device.formFactor).getLayer(keystroke.layer).getKey(keystroke.keyName); keyEvent = keyboard.constructKeyEvent(key, this.device, processor.stateKeys); } @@ -88,17 +90,17 @@ export default class NodeProctor extends Proctor { // We don't care too much about particularities of per-keystroke behavior yet. // ... we _could_ if we wanted to, though. The framework is mostly in place; // it's a matter of actually adding the feature. - let ruleBehavior = processor.processKeystroke(new KeyEvent(keyEvent), target); + const ruleBehavior = processor.processKeystroke(new KeyEvent(keyEvent), textStore); if (this.debugMode) { console.log("Processing %d:", keyEvent.Lcode); - console.log("target=%s", JSON.stringify(target, null, ' ')); + console.log("textStore=%s", JSON.stringify(textStore, null, ' ')); console.log("ruleBehavior=%s", JSON.stringify(ruleBehavior, null, ' ')); } } } else { throw new Error("NodeProctor only supports RecordedKeystrokeSequences for testing at present."); } - return target.getText(); + return textStore.getText(); } } diff --git a/web/src/tools/testing/recorder-core/src/proctor.ts b/web/src/tools/testing/recorder-core/src/proctor.ts index ec4f584b04..52db386818 100644 --- a/web/src/tools/testing/recorder-core/src/proctor.ts +++ b/web/src/tools/testing/recorder-core/src/proctor.ts @@ -1,5 +1,5 @@ -import { type DeviceSpec } from "@keymanapp/web-utils"; -import { type OutputTarget } from "keyman/engine/js-processor"; +import { type DeviceSpec } from "keyman/common/web-utils"; +import { type TextStore } from "keyman/engine/keyboard"; import type { KeyboardTest, TestSet, TestSequence } from "./index.js"; @@ -11,7 +11,7 @@ export type AssertCallback = (s1: any, s2: any, msg?: string) => void; * Note that DOM-aware KeymanWeb will implement a Browser-based version, while * keyboard and input-processor will use a Node-based version instead. */ -export default abstract class Proctor { +export abstract class Proctor { device: DeviceSpec; _assert: AssertCallback; @@ -49,5 +49,5 @@ export default abstract class Proctor { * Simulates the specified test sequence for use in testing. * @param sequence The recorded sequence, generally provided by a test set. */ - abstract simulateSequence(sequence: TestSequence, target?: OutputTarget): Promise; + abstract simulateSequence(sequence: TestSequence, textStore?: TextStore): Promise; } \ No newline at end of file diff --git a/web/src/tools/testing/recorder-core/tsconfig.json b/web/src/tools/testing/recorder-core/tsconfig.json index 67affcca5e..9bed116df2 100644 --- a/web/src/tools/testing/recorder-core/tsconfig.json +++ b/web/src/tools/testing/recorder-core/tsconfig.json @@ -3,10 +3,9 @@ "compilerOptions": { "types": ["node"], - "baseUrl": "./", "outDir": "./build/obj/", "tsBuildInfoFile": "./build/obj/tsconfig.tsbuildinfo", - "rootDir": "./src" + "rootDir": "./src", }, "include": [ @@ -14,10 +13,7 @@ ], "references": [ - { "path": "../../../../../common/web/keyman-version" }, - { "path": "../../../engine/common/web-utils/" }, - { "path": "../../../engine/predictive-text/types" }, - { "path": "../../../engine/js-processor" }, - { "path": "../../../engine/keyboard" }, + { "path": "../../../common/web-utils/" }, + { "path": "../../../engine" }, ], } diff --git a/web/src/tools/testing/recorder/browserDriver.ts b/web/src/tools/testing/recorder/browserDriver.ts index a0255ae0e0..7be0caed6d 100644 --- a/web/src/tools/testing/recorder/browserDriver.ts +++ b/web/src/tools/testing/recorder/browserDriver.ts @@ -4,7 +4,7 @@ import { OSKInputEventSpec, PhysicalInputEventSpec } from "@keymanapp/recorder-core"; -import { ManagedPromise, timedPromise } from "@keymanapp/web-utils"; +import { ManagedPromise, timedPromise } from "keyman/common/web-utils"; import { type KeymanEngine } from 'keyman/app/browser'; diff --git a/web/src/tools/testing/recorder/browserProctor.ts b/web/src/tools/testing/recorder/browserProctor.ts index f0e486d035..f0b09e9b50 100644 --- a/web/src/tools/testing/recorder/browserProctor.ts +++ b/web/src/tools/testing/recorder/browserProctor.ts @@ -2,9 +2,9 @@ // Only BrowserDriver.ts and its prerequisites are needed during actual integrated unit testing. /// -import { type DeviceSpec } from "@keymanapp/web-utils"; +import { type DeviceSpec } from "keyman/common/web-utils"; -import { type OutputTarget } from "keyman/engine/js-processor"; +import { type TextStore } from "keyman/engine/keyboard"; import { type KeymanEngine } from 'keyman/app/browser'; @@ -81,7 +81,7 @@ export class BrowserProctor extends Proctor { // Execution of a test sequence depends on the testing environment; this handles // the browser-specific aspects. - async simulateSequence(sequence: TestSequence, outputTarget?: OutputTarget): Promise { + async simulateSequence(sequence: TestSequence, textStore?: TextStore): Promise { const driver = new BrowserDriver(this.target); // For the version 10.0 spec diff --git a/web/src/tools/testing/recorder/build.sh b/web/src/tools/testing/recorder/build.sh index ab8f3c6471..edada7aeee 100755 --- a/web/src/tools/testing/recorder/build.sh +++ b/web/src/tools/testing/recorder/build.sh @@ -16,9 +16,10 @@ SUBPROJECT_NAME=tools/testing/recorder ################################ Main script ################################ builder_describe "Builds the Keyman Engine for Web's test-sequence recording tool" \ - "@/common/web/keyman-version" \ - "@/web/src/engine/keyboard" \ - "@../recorder-core" \ + "@/common/tools/es-bundling build" \ + "@/common/web/keyman-version build" \ + "@/web/src/engine build" \ + "@../recorder-core build" \ "clean" \ "configure" \ "build" @@ -33,8 +34,8 @@ do_build ( ) { compile $SUBPROJECT_NAME # Base product - the main keyboard processor - node "${LIB_BUNDLER}" "${KEYMAN_ROOT}/web/build/$SUBPROJECT_NAME/obj/index.js" \ - --out "${KEYMAN_ROOT}/web/build/$SUBPROJECT_NAME/lib/index.mjs" \ + node_es_bundle "${KEYMAN_ROOT}/web/build/$SUBPROJECT_NAME/obj/index.js" \ + --out "${KEYMAN_ROOT}/web/build/$SUBPROJECT_NAME/lib/index.mjs" \ --format esm } diff --git a/web/src/tools/testing/recorder/index.html b/web/src/tools/testing/recorder/index.html index f4a68ba769..a9af8e2029 100644 --- a/web/src/tools/testing/recorder/index.html +++ b/web/src/tools/testing/recorder/index.html @@ -57,6 +57,8 @@ keyman.init({ attachType: 'auto', keyboards: '' + }).then(function () { + loadKeyboards(); }); document.getElementById("body").focus(); @@ -67,7 +69,7 @@ - +
diff --git a/web/src/tools/testing/recorder/scribe.ts b/web/src/tools/testing/recorder/scribe.ts index 83179e76de..1b37610d05 100644 --- a/web/src/tools/testing/recorder/scribe.ts +++ b/web/src/tools/testing/recorder/scribe.ts @@ -17,7 +17,7 @@ import { RecordedSyntheticKeystroke } from "@keymanapp/recorder-core"; -import { outputTargetForElement } from 'keyman/engine/attachment'; +import { textStoreForElement } from 'keyman/engine/attachment'; import { type KeymanEngine } from 'keyman/app/browser'; @@ -28,7 +28,7 @@ declare let keyman: KeymanEngine; // export namespace dom { // export declare var DOMEventHandlers: any; // export declare class Utils { -// static getOutputTarget(elem: HTMLElement): any; // text.OutputTarget; +// static getTextStore(elem: HTMLElement): any; // text.TextStore; // } // } @@ -183,8 +183,8 @@ export class Scribe extends EventEmitter { const recorderScribe = this; keyman.hardKeyboard.on('keyevent', (e) => { - const in_output = outputTargetForElement(recordingElement); - if(!in_output || keyman.contextManager.activeTarget != in_output) { + const in_output = textStoreForElement(recordingElement); + if(!in_output || keyman.contextManager.activeTextStore != in_output) { return; } @@ -199,8 +199,8 @@ export class Scribe extends EventEmitter { }); keyman.osk.on('keyevent', (e) => { - const in_output = outputTargetForElement(recordingElement); - if(!in_output || keyman.contextManager.activeTarget != in_output) { + const in_output = textStoreForElement(recordingElement); + if(!in_output || keyman.contextManager.activeTextStore != in_output) { return; } @@ -212,7 +212,7 @@ export class Scribe extends EventEmitter { }); keyman.contextManager.on('keyboardchange', (kbdTuple) => { - const in_output = outputTargetForElement(recordingElement); + const in_output = textStoreForElement(recordingElement); // If it's not on our recording control, ignore the change and do nothing special. if(!in_output || document.activeElement != in_output.getElement()) { return; @@ -230,7 +230,7 @@ export class Scribe extends EventEmitter { // What's the active stub immediately after our _SetActiveKeyboard call? const internalStub = kbdTuple.metadata; - if(internalStub && (keyman.contextManager.activeTarget == in_output)) { + if(internalStub && (keyman.contextManager.activeTextStore == in_output)) { const kbdRecord = Scribe.recordKeyboardStub(internalStub, 'resources/keyboards'); recorderScribe.emit('stub-changed', JSON.stringify(kbdRecord)); diff --git a/web/src/tools/testing/recorder/tsconfig.json b/web/src/tools/testing/recorder/tsconfig.json index a33d2ee5eb..0d3d3e5bc6 100644 --- a/web/src/tools/testing/recorder/tsconfig.json +++ b/web/src/tools/testing/recorder/tsconfig.json @@ -1,20 +1,17 @@ { "extends": "../../../tsconfig.dom.json", "compilerOptions": { - "baseUrl": "./", "outDir": "../../../../build/tools/testing/recorder/obj/", "rootDir": ".", - "tsBuildInfoFile": "../../../../build/tools/testing/recorder/obj/tsconfig.tsbuildinfo" + "tsBuildInfoFile": "../../../../build/tools/testing/recorder/obj/tsconfig.tsbuildinfo", }, "include": [ "*.ts" ], "references": [ - { "path": "../../../../../common/web/keyman-version" }, - { "path": "../../../engine/common/web-utils" }, - { "path": "../../../engine/predictive-text/types" }, + { "path": "../../../common/web-utils" }, { "path": "../../../app/browser" }, { "path": "../recorder-core" }, - { "path": "../../../engine/keyboard" }, + { "path": "../../../engine" }, ] } diff --git a/web/src/tools/testing/test-server/index.cjs b/web/src/tools/testing/test-server/index.cjs new file mode 100644 index 0000000000..119a18f5c7 --- /dev/null +++ b/web/src/tools/testing/test-server/index.cjs @@ -0,0 +1,27 @@ +const express = require('express') +const path = require('path') +const app = express() +const port = 3000 + +app.use(express.static(path.join(__dirname, '../../../../'))) +// Also serve /common for shared test resources +app.use('/common', express.static(path.join(__dirname, '../../../../../common/'))) + +// for testing timeout error in web/src/test/manual/web/keyboard-errors +const router = express.Router() +router.get('/src/test/manual/web/keyboard-errors/timeout.js', async (req, res, next) => { + console.log('timeout.js requested') + return new Promise(() => { + setTimeout(() => { + res.set('Content-Type', 'application/json'); + res.status(200); + + next(); + }, 10500); // > ContextManagerBase.TIMEOUT_THRESHOLD (10 seconds) + }); +}) +app.use(router) + +app.listen(port, () => { + console.log(`Keyman test app listening on port ${port}: http://localhost:${port}`) +}) diff --git a/web/src/tools/testing/test-utils/build.sh b/web/src/tools/testing/test-utils/build.sh new file mode 100755 index 0000000000..d31795b07e --- /dev/null +++ b/web/src/tools/testing/test-utils/build.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# +# Compile KeymanWeb's automated js/ts test utilities + +## 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=tools/testing/test-utils +. "$KEYMAN_ROOT/resources/build/utils.inc.sh" +. "$KEYMAN_ROOT/resources/build/node.inc.sh" +. "$KEYMAN_ROOT/web/common.inc.sh" + +################################ Main script ################################ + +builder_describe "Automated js/ts test utilities for KeymanWeb" \ + "clean" \ + "configure" \ + "build" + +builder_describe_outputs \ + configure /node_modules \ + build "/web/build/${SUBPROJECT_NAME}/obj/index.js" + +builder_parse "$@" + +do_build ( ) { + compile "${SUBPROJECT_NAME}" +} + +builder_run_action configure node_select_version_and_npm_ci +builder_run_action clean rm -rf "../../../../build/${SUBPROJECT_NAME}/" +builder_run_action build do_build \ No newline at end of file diff --git a/web/src/tools/testing/test-utils/index.ts b/web/src/tools/testing/test-utils/index.ts new file mode 100644 index 0000000000..79f98d1a3b --- /dev/null +++ b/web/src/tools/testing/test-utils/index.ts @@ -0,0 +1,31 @@ +import { assert } from 'chai'; + +// export async function assertThrowsAsync(fn: () => Promise, message?: string): Promise; +export async function assertThrowsAsync(fn: () => Promise, type?: any, message?: string): Promise { + assert(!!type || !!message, 'at least one of type or message must be specified'); + if (typeof(type) === 'string') { + message = type; + type = undefined; + } + try { + await fn(); + assert.fail('Expected function to throw an error, but it did not.'); + } catch (err) { + if (type) { + assert.isTrue(err instanceof type, `Expected error to be of type ${type.name}, but got ${err.constructor.name}`); + } + if (message) { + assert.equal((err as Error).message, message); + } + } +} + +export function assertThrows(fn: () => any, message?: string): void; +export function assertThrows(fn: () => any, type?: any, message?: string): void { + assert(!!type || !!message, 'at least one of type or message must be specified'); + if (typeof(type) === 'string') { + message = type; + type = undefined; + } + assert.throws(fn, type, message); +} diff --git a/web/src/tools/testing/test-utils/tsconfig.json b/web/src/tools/testing/test-utils/tsconfig.json new file mode 100644 index 0000000000..190dfc710c --- /dev/null +++ b/web/src/tools/testing/test-utils/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../../tsconfig.dom.json", + "compilerOptions": { + "outDir": "../../../../build/tools/testing/test-utils/obj/", + "rootDir": ".", + "tsBuildInfoFile": "../../../../build/tools/testing/test-utils/obj/tsconfig.tsbuildinfo" + }, + + "include": [ "*.ts" ], +} diff --git a/web/src/tsconfig.all.json b/web/src/tsconfig.all.json index 0a9ab828dd..5c67a919c4 100644 --- a/web/src/tsconfig.all.json +++ b/web/src/tsconfig.all.json @@ -1,18 +1,22 @@ -// Is not `extend`ed by any tsconfigs; this is solely to build all app/ targets. -// Doesn't bundle them, though, so there are limits to the usefulness of this file. +// This file lists all the child modules, for completeness. However, there are +// steps like bundling and sourcing external resources that are not performed by +// tsc, so there are limits to the usefulness of this file. { - "extends": "../tsconfig.base.json", - - "compilerOptions": { - "baseUrl": "./", - "outDir": "../build", - "tsBuildInfoFile": "../build/tsconfig.all.tsbuildinfo", - "rootDir": "./" - }, - "files": [], "references": [ { "path": "app/browser" }, { "path": "app/webview" }, - { "path": "app/ui" } + { "path": "app/ui" }, + + { "path": "common/web-utils" }, + { "path": "engine/" }, + { "path": "engine/predictive-text/types/" }, + { "path": "engine/predictive-text/templates" }, + { "path": "engine/predictive-text/wordbreakers" }, + { "path": "engine/predictive-text/worker-main/tsconfig.all.json" }, + { "path": "engine/predictive-text/worker-thread" }, + { "path": "tools/testing/gesture-processor/unit-test-resources" }, + + { "path": "tools/testing/recorder" }, + // { "path": "tools/sourcemap-root/tsconfig.json" }, ], } \ No newline at end of file diff --git a/web/test.sh b/web/test.sh index b65af498df..103cb1d7fc 100755 --- a/web/test.sh +++ b/web/test.sh @@ -20,6 +20,7 @@ builder_describe "Runs the Keyman Engine for Web unit-testing suites" \ "test+" \ ":dom Runs DOM-oriented unit tests (reduced footprint, nothing browser-specific)" \ ":integrated Runs KMW's integration test suite" \ + ":e2e Runs KMW's end-to-end test suite" \ "--inspect Runs browser-based unit tests in an inspectable mode" builder_parse "$@" @@ -30,6 +31,7 @@ builder_parse "$@" 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. @@ -40,6 +42,10 @@ fi # End common configs. -builder_run_action test:dom web-test-runner --config "src/test/auto/dom/web-test-runner${WTR_CONFIG}.config.mjs" ${WTR_INSPECT} +cd "${KEYMAN_ROOT}" -builder_run_action test:integrated web-test-runner --config "src/test/auto/integrated/web-test-runner${WTR_CONFIG}.config.mjs" ${WTR_INSPECT} +builder_run_action test:dom web-test-runner --config "web/src/test/auto/dom/web-test-runner${WTR_CONFIG}.config.mjs" ${WTR_INSPECT} + +builder_run_action test:integrated web-test-runner --config "web/src/test/auto/integrated/web-test-runner${WTR_CONFIG}.config.mjs" ${WTR_INSPECT} + +builder_run_action test:e2e npx playwright test --config "web/src/test/auto/e2e/playwright.config.ts" diff --git a/web/tsconfig.base.json b/web/tsconfig.base.json index d1deafecb6..95acf6658a 100644 --- a/web/tsconfig.base.json +++ b/web/tsconfig.base.json @@ -16,5 +16,14 @@ "importHelpers": true, "inlineSources": true, "sourceMap": true, + + "baseUrl": "./", + + "paths": { + // Note: this overrides paths in ../tsconfig.base.json + "keyman/common/web-utils": ["./src/common/web-utils/src/index.js"], + "keyman/engine/*": ["./src/engine/src/*/index.js"], + }, + } } diff --git a/windows/docs/help/advanced/locale_edit.md b/windows/docs/help/advanced/locale_edit.md index 1db621bebf..d37c12d6ce 100644 --- a/windows/docs/help/advanced/locale_edit.md +++ b/windows/docs/help/advanced/locale_edit.md @@ -43,12 +43,7 @@ messages (these mostly start with SK) and with the Menu strings. First, edit the translation's language information - SKUILanguageName, SKUILanguageNameWithEnglish, and SKLanguageCode. The SKLanguageCode -should be the same as the language code you chose earlier. You will also -see a String with id SKDefaultLanguageCode. For Keyman for Windows, this -should remain "en" for all translations. When developing a custom -product using the Keyman Engine for Windows, you may change your -product's default language, and this would then entail changing -SKDefaultLanguageCode. +should be the same as the language code you chose earlier. **Note:** Any entries missing from the translation will be retrieved from the default file. diff --git a/windows/docs/help/basic/config/options.md b/windows/docs/help/basic/config/options.md index 3b4bbd86b0..f4084f6465 100644 --- a/windows/docs/help/basic/config/options.md +++ b/windows/docs/help/basic/config/options.md @@ -180,6 +180,28 @@ To open the Options tab of Keyman Configuration: log on for short and isolated tests as specifically requested by Keyman Technical Support. +- Proxy Settings + + In some environments, you may need to configure proxy settings in + order to download keyboards or updates for Keyman. Check with your + network administrator. More information is available in the + [Proxy Configuration](../../advanced/proxy_config) documentation. + +- Keyman System Settings + + The Keyman System Settings dialog provides access to various low-level + Keyman configuration settings. Generally, these settings do not need + to be changed, unless you instructed to do so by Keyman support staff. + +- Base Keyboard + + The Base Keyboard dialog allows you to select the physical Latin-script + layout of your keyboard, which will allow certain Keyman keyboards to remap + themselves dynamically to match your key caps. + + [Base Keyboard dialog](../../context/base-keyboard) + + ## Related Topics - [Keyman Configuration](../config/) diff --git a/windows/src/desktop/branding/messages.txt b/windows/src/desktop/branding/messages.txt index 9fa93cc6de..ac1ce1a5c9 100644 --- a/windows/src/desktop/branding/messages.txt +++ b/windows/src/desktop/branding/messages.txt @@ -40,14 +40,6 @@ object Messages: TStockMessages Comment = 'The language code for the current translation' Parameters = <> end - item - Name = 'SKDefaultLanguageCode' - DefStr = 'en' - Comment = - 'The default language code for this product. This should be the ' + - 'language that the product is created in' - Parameters = <> - end item Name = 'SKButtonUILanguageDownload' DefStr = 'More Languages Online...' diff --git a/windows/src/desktop/insthelp/version.rc b/windows/src/desktop/insthelp/version.rc index 41758886af..4106284426 100644 --- a/windows/src/desktop/insthelp/version.rc +++ b/windows/src/desktop/insthelp/version.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/desktop/kmbrowserhost/version.rc b/windows/src/desktop/kmbrowserhost/version.rc index a72b4392b5..36942b9e42 100644 --- a/windows/src/desktop/kmbrowserhost/version.rc +++ b/windows/src/desktop/kmbrowserhost/version.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/desktop/kmconfig/version.rc b/windows/src/desktop/kmconfig/version.rc index c6dd5399f8..7e61b179f4 100644 --- a/windows/src/desktop/kmconfig/version.rc +++ b/windows/src/desktop/kmconfig/version.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/desktop/kmshell/locale/am-ET/strings.xml b/windows/src/desktop/kmshell/locale/am-ET/strings.xml index 7f5f4f8ba7..2f23892343 100644 --- a/windows/src/desktop/kmshell/locale/am-ET/strings.xml +++ b/windows/src/desktop/kmshell/locale/am-ET/strings.xml @@ -647,10 +647,6 @@ am - - - - en diff --git a/windows/src/desktop/kmshell/locale/az-AZ/strings.xml b/windows/src/desktop/kmshell/locale/az-AZ/strings.xml index 404e51c51a..7e3b7d5691 100644 --- a/windows/src/desktop/kmshell/locale/az-AZ/strings.xml +++ b/windows/src/desktop/kmshell/locale/az-AZ/strings.xml @@ -626,10 +626,6 @@ az - - - - en diff --git a/windows/src/desktop/kmshell/locale/bwr-NG/strings.xml b/windows/src/desktop/kmshell/locale/bwr-NG/strings.xml index 28cdb065aa..503b941fde 100644 --- a/windows/src/desktop/kmshell/locale/bwr-NG/strings.xml +++ b/windows/src/desktop/kmshell/locale/bwr-NG/strings.xml @@ -627,10 +627,6 @@ Keyboard natǝ ga ana hara kǝthlǝr kari akwa Windows. Keyboardyeri ar Keyman a en - - - - en diff --git a/windows/src/desktop/kmshell/locale/ckl-NG/strings.xml b/windows/src/desktop/kmshell/locale/ckl-NG/strings.xml index dd994697df..779b0e0531 100644 --- a/windows/src/desktop/kmshell/locale/ckl-NG/strings.xml +++ b/windows/src/desktop/kmshell/locale/ckl-NG/strings.xml @@ -647,10 +647,6 @@ keyboard that you use in Windows. Keyman keyboards will adapt automatically to en - - - - en diff --git a/windows/src/desktop/kmshell/locale/cs-CZ/strings.xml b/windows/src/desktop/kmshell/locale/cs-CZ/strings.xml index 83adda0577..6e217e3b1f 100644 --- a/windows/src/desktop/kmshell/locale/cs-CZ/strings.xml +++ b/windows/src/desktop/kmshell/locale/cs-CZ/strings.xml @@ -714,10 +714,6 @@ klávesnici, kterou používáte v systému Windows. Klávesnice se automaticky cs-cs - - - - cs-cs diff --git a/windows/src/desktop/kmshell/locale/de/strings.xml b/windows/src/desktop/kmshell/locale/de/strings.xml index 9827426632..2e2d3bffd8 100644 --- a/windows/src/desktop/kmshell/locale/de/strings.xml +++ b/windows/src/desktop/kmshell/locale/de/strings.xml @@ -713,10 +713,6 @@ de - - - - en diff --git a/windows/src/desktop/kmshell/locale/el-polyton/strings.xml b/windows/src/desktop/kmshell/locale/el-polyton/strings.xml index f9699f61de..72d425903f 100644 --- a/windows/src/desktop/kmshell/locale/el-polyton/strings.xml +++ b/windows/src/desktop/kmshell/locale/el-polyton/strings.xml @@ -693,10 +693,6 @@ el - - - - en diff --git a/windows/src/desktop/kmshell/locale/es-419/strings.xml b/windows/src/desktop/kmshell/locale/es-419/strings.xml index 61cf66cb46..f09a4fd222 100644 --- a/windows/src/desktop/kmshell/locale/es-419/strings.xml +++ b/windows/src/desktop/kmshell/locale/es-419/strings.xml @@ -713,10 +713,6 @@ es-419 - - - - en diff --git a/windows/src/desktop/kmshell/locale/es-ES/strings.xml b/windows/src/desktop/kmshell/locale/es-ES/strings.xml index 639debd6fd..144777c605 100644 --- a/windows/src/desktop/kmshell/locale/es-ES/strings.xml +++ b/windows/src/desktop/kmshell/locale/es-ES/strings.xml @@ -713,10 +713,6 @@ en - - - - en diff --git a/windows/src/desktop/kmshell/locale/ff-NG/strings.xml b/windows/src/desktop/kmshell/locale/ff-NG/strings.xml index ccb18cebfe..9c15b5bf15 100644 --- a/windows/src/desktop/kmshell/locale/ff-NG/strings.xml +++ b/windows/src/desktop/kmshell/locale/ff-NG/strings.xml @@ -647,10 +647,6 @@ Kibod ko a` naftirta dow na`ura. Kibod Keyman koosan bee hoore mum yanayu mawnug en - - - - en diff --git a/windows/src/desktop/kmshell/locale/ff-ZA/strings.xml b/windows/src/desktop/kmshell/locale/ff-ZA/strings.xml index 119a12f37b..47b53ff10e 100644 --- a/windows/src/desktop/kmshell/locale/ff-ZA/strings.xml +++ b/windows/src/desktop/kmshell/locale/ff-ZA/strings.xml @@ -651,10 +651,6 @@ Jokku\? ful - - - - en diff --git a/windows/src/desktop/kmshell/locale/fr/strings.xml b/windows/src/desktop/kmshell/locale/fr/strings.xml index 2ed3f704bd..df1248f033 100644 --- a/windows/src/desktop/kmshell/locale/fr/strings.xml +++ b/windows/src/desktop/kmshell/locale/fr/strings.xml @@ -646,10 +646,6 @@ fr - - - - en diff --git a/windows/src/desktop/kmshell/locale/ha-HG/strings.xml b/windows/src/desktop/kmshell/locale/ha-HG/strings.xml index f65e132d35..91a118a878 100644 --- a/windows/src/desktop/kmshell/locale/ha-HG/strings.xml +++ b/windows/src/desktop/kmshell/locale/ha-HG/strings.xml @@ -626,10 +626,6 @@ en - - - - en diff --git a/windows/src/desktop/kmshell/locale/hia-NG/strings.xml b/windows/src/desktop/kmshell/locale/hia-NG/strings.xml index bb61880158..bb558c5b18 100644 --- a/windows/src/desktop/kmshell/locale/hia-NG/strings.xml +++ b/windows/src/desktop/kmshell/locale/hia-NG/strings.xml @@ -627,10 +627,6 @@ keyboard unda da mogka thlina nda Windows. Keyman keyboards na da spat sosaya t en - - - - en diff --git a/windows/src/desktop/kmshell/locale/id-ID/strings.xml b/windows/src/desktop/kmshell/locale/id-ID/strings.xml index b99c489289..bfc69558a3 100644 --- a/windows/src/desktop/kmshell/locale/id-ID/strings.xml +++ b/windows/src/desktop/kmshell/locale/id-ID/strings.xml @@ -626,10 +626,6 @@ id - - - - en diff --git a/windows/src/desktop/kmshell/locale/it-IT/strings.xml b/windows/src/desktop/kmshell/locale/it-IT/strings.xml index de66ee82e9..a89759327e 100644 --- a/windows/src/desktop/kmshell/locale/it-IT/strings.xml +++ b/windows/src/desktop/kmshell/locale/it-IT/strings.xml @@ -714,10 +714,6 @@ che usi in Windows. Le tastiere Keyman si adatteranno automaticamente al layout it - - - - it diff --git a/windows/src/desktop/kmshell/locale/km-KH/strings.xml b/windows/src/desktop/kmshell/locale/km-KH/strings.xml index 16deccb41d..4c32ffeb1b 100644 --- a/windows/src/desktop/kmshell/locale/km-KH/strings.xml +++ b/windows/src/desktop/kmshell/locale/km-KH/strings.xml @@ -713,10 +713,6 @@ km - - - - en diff --git a/windows/src/desktop/kmshell/locale/kn/strings.xml b/windows/src/desktop/kmshell/locale/kn/strings.xml index 0425ab7a58..4c985d98e0 100644 --- a/windows/src/desktop/kmshell/locale/kn/strings.xml +++ b/windows/src/desktop/kmshell/locale/kn/strings.xml @@ -646,10 +646,6 @@ kn - - - - en diff --git a/windows/src/desktop/kmshell/locale/kr-NG/strings.xml b/windows/src/desktop/kmshell/locale/kr-NG/strings.xml index ce4aee3edd..509f3e8544 100644 --- a/windows/src/desktop/kmshell/locale/kr-NG/strings.xml +++ b/windows/src/desktop/kmshell/locale/kr-NG/strings.xml @@ -627,10 +627,6 @@ keyboard do suro Windows ye dǝlan faidatǝmin ma. Keyman keyboards dǝye adai en - - - - en diff --git a/windows/src/desktop/kmshell/locale/mfi-NG/strings.xml b/windows/src/desktop/kmshell/locale/mfi-NG/strings.xml index 6f9c21529a..7f3788a37c 100644 --- a/windows/src/desktop/kmshell/locale/mfi-NG/strings.xml +++ b/windows/src/desktop/kmshell/locale/mfi-NG/strings.xml @@ -627,10 +627,6 @@ keyboard na ká ga slera anikwa na am Windows. Keyman keyboards anuga maga sler en - - - - en diff --git a/windows/src/desktop/kmshell/locale/mnw-MM/strings.xml b/windows/src/desktop/kmshell/locale/mnw-MM/strings.xml index a4c4ef6e92..63d921d4a9 100644 --- a/windows/src/desktop/kmshell/locale/mnw-MM/strings.xml +++ b/windows/src/desktop/kmshell/locale/mnw-MM/strings.xml @@ -693,10 +693,6 @@ mnw - - - - mnw diff --git a/windows/src/desktop/kmshell/locale/mrt-NG/strings.xml b/windows/src/desktop/kmshell/locale/mrt-NG/strings.xml index 72b2a4f362..896f67ddcb 100644 --- a/windows/src/desktop/kmshell/locale/mrt-NG/strings.xml +++ b/windows/src/desktop/kmshell/locale/mrt-NG/strings.xml @@ -626,10 +626,6 @@ en - - - - en diff --git a/windows/src/desktop/kmshell/locale/my/strings.xml b/windows/src/desktop/kmshell/locale/my/strings.xml index 7830d9473a..0e8576c65b 100644 --- a/windows/src/desktop/kmshell/locale/my/strings.xml +++ b/windows/src/desktop/kmshell/locale/my/strings.xml @@ -225,7 +225,6 @@ ကီးဘုတ်ို အောင်မြင်စွာ ပရင့် ထုတ်လို့မရပါ။ ဝက်ဘ်စာမျက်နှာမှာသိမ်းဆည်းပြီး ထုတ်ယူပါ <ကီးဘုတ်ထိခိုက်ခြင်း> Keyman debug information will be stored in a text file called keymanlog\system.log on your desktop. You should exit Keyman before reading or deleting this file. WARNING: This file can grow large very quickly. Enabling debugging will slow down your system and should only be done if advised by Tavultesoft support. PRIVACY WARNING: Please note that the debug logfile records all keystrokes that you type. You should only turn on the debug log for the duration of a debugging or diagnostic session, and delete the [desktop]\keymanlog\system.log file as soon as possible - en သုံးစွဲသူအတွက်ဘာသာစကားကို ရွေးချယ်ပါ အွန်လိုင်းဘာသာပြန်မှုအသစ်ကို ဖန်တီးပါ ဖိုင်ကိုဒေါင်းလုဒ်ဆွဲနေသည် diff --git a/windows/src/desktop/kmshell/locale/nl-NL/strings.xml b/windows/src/desktop/kmshell/locale/nl-NL/strings.xml index c6e48c924e..4edb9a4e6c 100644 --- a/windows/src/desktop/kmshell/locale/nl-NL/strings.xml +++ b/windows/src/desktop/kmshell/locale/nl-NL/strings.xml @@ -627,10 +627,6 @@ dat u in Windows gebruikt. Keyman toetsenborden worden automatisch aangepast aan nl - - - - en diff --git a/windows/src/desktop/kmshell/locale/pl-PL/strings.xml b/windows/src/desktop/kmshell/locale/pl-PL/strings.xml index d6a75be6e9..1702d5b4d1 100644 --- a/windows/src/desktop/kmshell/locale/pl-PL/strings.xml +++ b/windows/src/desktop/kmshell/locale/pl-PL/strings.xml @@ -627,10 +627,6 @@ której używasz w systemie Windows. Klawiatury Keyman automatycznie dostosują pl - - - - en diff --git a/windows/src/desktop/kmshell/locale/pt-BR/strings.xml b/windows/src/desktop/kmshell/locale/pt-BR/strings.xml index d3dd5437c8..d798b1b43d 100644 --- a/windows/src/desktop/kmshell/locale/pt-BR/strings.xml +++ b/windows/src/desktop/kmshell/locale/pt-BR/strings.xml @@ -647,10 +647,6 @@ keyboard that you use in Windows. Keyman keyboards will adapt automatically to en - - - - en diff --git a/windows/src/desktop/kmshell/locale/pt-PT/strings.xml b/windows/src/desktop/kmshell/locale/pt-PT/strings.xml index 906b23c858..6a1d0df5a4 100644 --- a/windows/src/desktop/kmshell/locale/pt-PT/strings.xml +++ b/windows/src/desktop/kmshell/locale/pt-PT/strings.xml @@ -542,7 +542,7 @@ - Selecione o teclado latino básico + Selecione o teclado latino básico que utiliza no Windows. O teclado Keyman irá se adaptar automaticamente ao seu layout preferido. @@ -714,10 +714,6 @@ por-PT - - - - por-PT diff --git a/windows/src/desktop/kmshell/locale/qqq/locale.xml b/windows/src/desktop/kmshell/locale/qqq/locale.xml deleted file mode 100644 index 0dfef8f9c7..0000000000 --- a/windows/src/desktop/kmshell/locale/qqq/locale.xml +++ /dev/null @@ -1,577 +0,0 @@ - - -]> - - - - -[!!Ķēɏmãŋ!!] - -Segoe UI -9 - - - - - - - -&Name; - - - - - -[!!Ÿĕŝ!!] -[!!Ňō!!] - -[!!&Ƴēš!!] -[!!&Ńŏ!!] - -[!!ƠĶ!!] -[!!Čãŋčȅļ!!] -[!!Ćļŏśȅ!!] -[!!Ãƥƥłƴ!!] -[!!Ʀȇmıŋď mĕ Ľàťēř!!] - -[!!ŐƘ!!] -[!!Ċāņċěł!!] - -[!!Ċłīċķ ţħĭš ĭċơŋ ťō şȇŀȅćţ ȁ ƙěɏƅŏáŗď!!] -&Name;[!! ıś ŝťıĺĺ ŕūʼnňīńġ. Ċŀĩćķ ţħıŝ įĉőň ťơ űśē ŷōūř ļāņğųãğě ƙȇƴƃŏǻřđ ąť āʼnɏ ŧĩmė!!] - - - - - -&Name;[!! Ćōʼnƒĩģųřȃţįőň!!] - - - 40 - 118 - 40 - - -[!!Ġĕţŧīńģ Ŝţářťěď!!] -[!!Ħēļƿ!!] - - - -[!!Ƙėƴɓŏäŗď Łǻŷơŭţš!!] [!!Ķ!!] -[!!Ōƿťĩőƞş!!] [!!Ŏ!!] -[!!Ĥōţƙȇȳş!!] [!!Ħ!!] -[!!Śűƥƥơřť!!] [!!Š!!] -[!!Ķēĕƥ īň Ťōŭċĥ!!] [!!Ŧ!!] - - - -[!!Ƒĭļėʼnȁmĕ:!!] - -[!!Ƥāčĸäġȅ vĕřšįơņ:!!] -[!!Ƙĕƴƅŏȃŕď vȇŕšįơņ:!!] -[!!Äųţĥōŗ:!!] -[!!Ŵēƀşīťę:!!] - -[!!Ƥáĉķąğȅ:!!] -[!!Ƒőƞţŝ:!!] -[!!Ƙěŷƀōäŗď Ĺāɏőūŧś:!!] - -[!!Ęńĉőďıʼnğś:!!] - -[!!Łáŷōũŧ Ŧŷƥȅ:!!] - [!!Ƒĭxěđ (Ƥőşıŧįơƞąŀ)!!] - [!!Mäƥƥȅď ŧơ Ŵıƞďőŵŝ ŀąƴőůŧ (Mƞēmŏʼnįč)!!] - -[!!Ɖȇŝĉřīƥťįơń:!!] - -[!!Įŋŝţăĺłȅđ ƒōŕ:!!] - [!!Āłĺ ŭšȇřş!!] - [!!Čūŕŗȅņţ űşęŗ!!] - -[!!Ĺǻƞĝůǻĝęŝ:!!] - [!!✕!!] - [!!Āđđ ļàʼnğũåĝē!!] - -[!!Őƞ Ŝĉŗȇȅň Ķȅƴƀŏȁřď:!!] - [!!Ĉŭŝťŏm!!] - [!!Įŋŝťăļļėđ!!] - [!!Ŋōŧ ĩņšťāłŀėđ!!] - -[!!Ďơĉũměŋťáťĩŏʼn:!!] - [!!İƞśţąļļĕď!!] - [!!Ɲőţ įńşťǻĺłȅđ!!] - -[!!Mȅşśäģę:!!] -[!!Čőƥȳŕīğĥť:!!] - - - -[!!Ƥąċƙäĝė ŏƿţīōʼnş!!] -[!!Őƥţĭơʼnş!!] -[!!Īňšŧąľľ ƙĕŷɓŏȃŕđ...!!] -[!!Ďŏŵƞļőȁđ ĸěƴɓōäŗď...!!] - - [!!Ƙēŷƀōăŕđ ōƿťĭőńš!!] -[!!Ūƞīŋšťāļŀ!!] -[!!Ŭňĭƞŝťąľĺ ƥåĉĸåĝĕ!!] -[!!Šħŏŵ ıʼnťŕơđūċŧŏŗŷ ĥȅłƥ!!] -[!!Čħąņģĕ ĥŏŧĸēƴ!!] -[!!Śęť ĥőťĸěɏ!!] -[!!Űńıňşťāľŀ Ơʼn Şčŗēȇń ƘȇƴƄơǻŕď!!] -[!!Īƞśŧăłŀ Ŏń Śċřęęŋ Ƙĕŷƀơáŗď...!!] - -[!!Ƴŏũ ďŏ ņōţ ħâvě àņƴ ķȅƴƀőāŗđś ĩņşŧăļłęď. Ćŀįĉķ ťĥē Ɗőŵńŀőȁď Ƙȅɏƀŏāřđ ƃŭţŧŏń ŧő ĭńŝţąĺĺ á ĸěƴƄŏąŗď ŀȃŷơŭŧ ƒŗōm ţħě Ƙěɏmăƞ ŵĕƀŝĩţȇ.!!] -[!!Ŷōų ĉáņ ŏƞľŷ ũʼnīňşŧȁĺŀ ŧħĕ ĸėɏƃōâŕđ '%0:s' ıƒ ŷőū ăŗę åŋ Âđmĩƞıśţřąţŏŗ!!] - - - -[!!Ğȅƞėřāĺ!!] -[!!Šťäřŧůƿ!!] -[!!Ŏń Śčŗȇĕň Ƙęŷƀơářď!!] -[!!Āďvăƞčĕď!!] - -[!!Ķĕɏɓơáŗď ħőţķȅŷş ŧōğģľė ƙēȳɓŏářđ áćŧīvǻŧĩōņ!!] -[!!Şīmũŀàťȇ ĄŀťĞř ŵīţĥ Ćţřľ+Āĺŧ!!] -[!!Ťŕėāţ ħȁŗđŵāřĕ ďěãđĸęŷş ǻş ƥľȃįŋ ĸēɏş!!] -[!!Ŝĥőŵ ĥĩʼnţ měššàĝȇś!!] -[!!Āűŧőmȁŧĩĉáĺłŷ ćħȅčķ ƒőŗ ūƿđȃťėŝ àńď đōŵʼnłőǻđ!!] - -[!!Šţářţ ŵĥēń Ŵīŋďơŵš ŝŧâřťš!!] -[!!Ŝĥơŵ ŝƥļąšħ šćŕęȅņ!!] -[!!Šħơŵ ŵěļĉōmė şĉŕĕěņ!!] -[!!Ţēśŧ ƒőŗ ćōńƒłĭćţıņġ ȃƥƿŀīčäťīōňş ŵĥēƞ !!]&Name;[!! şťǻřţš!!] - -[!!Ŕěŀęàšĕ Şĥıƒţ/Ĉţřŀ/Ȁľŧ ōň Őņ Ŝčŗėěń Ķēŷƃơâŕđ ȃƒţēŕ ćŀĭċĸīňģ å ĸȅȳ!!] -[!!Äľŵȁƴŝ ŝĥŏŵ Őƞ Šċŕėěń ĶĕƴƄōãřđ Ŵīƞďơŵ ŵĥėń Ķěɏmàƞ ķȇƴƃőáŗď ĩš śēļĕĉţěď!!] -[!!Šŵĭŧčĥ ŧơ āƥƿřőƥŕįáŧė Őŋ Šćŗěėń ƘȅƴƄőãŗđ/Ħȅĺƿ áųťơmăŧĭĉåłŀŷ ŵĥȅņ ȃ ķęȳƀōāŕđ ĭŝ śĕļȇćţȇđ!!] - -[!!ĎēƄŭģġįƞĝ!!] - -[!!Ůšēř ĩŋţĕŗƒāĉē łáņģůȃġė...!!] - -[!!Ɓâśȇ Ƙȇƴɓŏäŕđ...!!] - - - - - - - - - -[!!(ņōŋȅ)!!] -[!!Šŵĩťċĥ !!]&Name;[!! Ơƒƒ!!] -[!!Ōƥȇń Ķęƴɓőäŗď Měƞų!!] -[!!Śħōŵ Ŏƞ Ŝĉřęęƞ ĶėƴƂőäŗď Ƥâņȇ!!] -[!!Őƥȅņ Čŏƞƒıġŭřãŧĭőń!!] - -[!!Šĥōŵ Ƙȅɏƀŏâŗď Ũşāġė Ƥȁņě!!] -[!!Šħŏŵ Ƒơņŧ Ĥēľƿėř Ƥăňě!!] -[!!Šĥőŵ Ćħąŗâćţěŗ Mȁƥ Ƥȃņě!!] -[!!Ơƥĕʼn Ţěxţ Ęđĩţŏŕ!!] - -[!!Ŏƿĕʼn Łåƞġűãĝě Śŵīţċĥĕŕ!!] - -[!!Ğēņĕŕáŀ Ĥơťĸęŷŝ!!] -[!!Ƙȅŷƅŏȁřđ Łãƴơųţś!!] - - - -[!!Ĩňšťăłĺęđ Ŀāʼnĝŭāģė!!] -[!!Ŵıńďơŵš Ĺāɏőūŧ!!] -[!!Ƙěŷmąŋ ĶȅŷƄőāřď!!] - -[!!(ůšę Ŵīņđơŵş ĺáŷőůŧ)!!] - - - -[!!Ůƥģŗǻđȅ ňŏŵ!!!] -[!!Ŝēŋď Şūƥƿōŗŧ Ʀęǫűęšť!!] -[!!Ĉŏƞŧǻĉŧ Ķěɏmäń Şűƥƿŏřŧ!!] -[!!Ĭƒ ȳőŭ ĥȃvĕ ąŋɏ įśşųȅŝ űśĭňģ Ķėɏmāň, Ĵũšť ãšƙ ã ɋűȅšťıőƞ ŏņ ťħĕ Ķȇȳmȁń Ĉōmmūŋĭťŷ Ƒŏŗūm.!!] -[!!Ŏƿėŋ Ķȇȳmǻň Čőmmŭŋĭťɏ Ƒŏŕūm!!] -[!!Ĉōƿŷŕĭĝĥţ © ŜİĹ Īņţęřŋàťįơņåĺ. Ȃŀĺ Ŕĭğĥŧś Ŗěşĕŗvěď.!!] -[!!Vĕŕšĭōʼn!!] -[!!Ēƞģıňȅ Vęŗŝīőń!!] - -[!!Ũŝęƒųĺ Ľıŋķš!!] - -[!!Ơńŀĭŋě Ĥęĺƥ!!] -[!!Ɖĩȁģʼnőşťīċš!!] -[!!Čĥėĉķ ƒơŗ Ůƥđǻŧęŝ!!] -[!!Ƥŗŏxȳ Şęŧŧīʼnġŝ...!!] - -[!!Ďīāĝŋőşŧīĉş!!] -[!!Ĉħēĉĸ Ľȃŋĝūȃģȅ Śēţŧįŋġš!!] - -[!!Mīćřőŝơƒţ Ŵīňđőŵś ǻƥƿĕãŗś ťŏ Ƅĕ ćőŕŗēćţłŷ ċōŋƒįğűŗēđ ƒőř ɏőűř ľąŋğūȁģē(ś).!!] - - - - - - - 40 - - -[!!Đŏŵňľŏâď Ƙęŷƀőáŗđ Ƒŕŏm ƙėȳmâņ.čőm!!] -[!!Ɗōń'ŧ ĭʼnšŧȃļļ, Ĵūşť đōŵʼnłőǻđ!!] - - - - - - - - - -[!!Īňśťąľĺ Ķėȳƅőåřď/Ƥàčĸąĝė!!] - -[!!Ďȅťáıľś!!] -[!!Ŗěāďmē!!] - -[!!İňśťȁŀļ!!] -[!!Ĩŋšŧąĺŀ ƒŏŕ ãĺŀ űşęŗś!!] - - - - - - - -[!!Ƥřŏxɏ Śėŕvȅř Ĉőŋƒįğũŗåţįőň!!] - -[!!Šȇřvėŕ: !!] -[!!Ƥőŗŧ: !!] -[!!Űşēřńąmě: !!] -[!!Ƥàŝšŵōŗď: !!] - - - - - - - -[!!Šėţ ßǻśę Ķęȳɓơǻřđ!!] -[!!Ŝėłěċţ ťĥę Ƃãşȇ Ļǻťīʼn šċŗĭƥť -ƙėȳƄŏǻŗď ţħãţ ƴōű ůšę įŋ Ŵįŋďơŵŝ. Ķēŷmąň ĸēȳɓōȁřďś ŵĭŀļ ȁđǻƥť ǻųŧōmâŧĭĉäłļȳ ťō ȳőũŗ ƥŕĕƒėŗŕȅđ ŀàƴōũť.!!] - - - - - -[!!Ĉħåńğě Ħơťķėŷ!!] - -[!!&Ċłēǻŕ Ħŏťĸȅŷ!!] -[!!Šėľęćť ä šťȁňđáŕđ ħőŧƙȅƴ ơř ċĥơőşė 'Ćūşťōm' ăƞď ħŏļď Ćţŕŀ,Śĥįƒť åʼnđ/ōř Àļţ áƞđ ţŷƥė ŷőũŕ ďėšįŗěđ ĥőťĸēŷ ƒőŕ ĸęȳƄơȃŗď %0:s:!!] -[!!Ŝęļēċŧ à śŧáńďǻŗď ĥőţĸēɏ ōŕ ĉħőőšē 'Ćŭşţŏm' ǻňđ ħŏĺđ Ĉťŕŀ,Śħıƒŧ ȁʼnď/ŏŕ Àłţ åŋđ ťȳƿē ȳŏũŗ đĕŝĩŕęđ ĥōŧķęŷ ƒŏŗ ŀȃʼnğůăĝē %0:s:!!] -[!!Şēłēĉŧ ã šţàňđáŗď ħőţĸȇȳ ŏŗ ćħőőśȅ 'Ćűšťőm' ăńđ ĥōĺđ Čţŕł,Šħįƒť ăņđ/ơř Ȃŀŧ āʼnď ťȳƥȇ ŷơűŕ đęšĭŕěđ ħơţĸėɏ:!!] - -[!!Ţĥė ħŏţƙēȳ %0:s ŵįŀĺ čōńƒļĭċŧ ŵīŧħ ŋŏřmȁľ ĸęȳƅơǻřđ ŭşȇ. Ɏŏů śĥōųļđ ūşę áţ łėàŝţ Ĉţŕĺ ơŗ Áłť. Ɖő ɏőŭ ŵȁƞţ ţŏ čħäňğē ŧĥįş ńőŵ?!!] -[!!Ťĥē ħơťƙēɏ %0:s ċōŋƒŀĭćţş ŵĩŧĥ ťħę ĥőťĸěȳ şěłĕĉťěď ƒőŗ ƙȇɏƀōāŕď %1:s. Ĭƒ ŷōũ ĉőƞŧıʼnŭĕ, ťĥȇ ħŏŧƙęɏ ƒơŗ ƙȅƴƅōāŕď %1:s ŵīŀł ƃė ĉļēȁřěď. Čơʼnťįŋũę?!!] - - - - - -[!!Şȇłěčţ ƘęŷƂŏȁřďš ŧő Įňśţãļľ!!] -[!!Ÿőū ċȃƞņŏŧ įƞśťåłļ āŀŀ ŧħę ƙĕŷƂőǻŗďś įŋ ťħĩš ƥȁčķáĝē. Ƴŏũ ċãň īƞşťāĺľ à máxĩmūm őƒ %0:d àďđıŧıōʼnąļ ĸēɏƄōȃŕďš. Ƥļĕąšȇ šȅľĕċť ŧħē ĸȇƴƀơåŗđŝ ŷőū ŵįşħ ťő īʼnśŧăļĺ ƒŕŏm ťĥīś ƿàĉĸăģȅ.!!] - - - - - - - -[!!Ŭƥđăţĕď !!]&Name;[!! Ċơmƥơƞȅƞŧś Ãváīŀâɓļĕ!!] - -[!!Ůƥđäţęş ƒōŕ !!]&Name;[!! àŕė ŋơŵ ävàıłàƄľē!!] -[!!Ƥłęāşȅ šĕĺěčţ ŧħę űƥđáŧěš ȳőŭ ŵīŝħ ŧō ĭńšťąľŀ:!!] - -[!!Đō ȳőů ŵãʼnŧ ťŏ ďơŵńĺơăď ăńď ĭŋśţȁŀļ ťħīš ƿăŧċħ ƞōŵ?!!] -[!!Ŷŏů ċâƞ ďőŵŋłŏãđ ŧĥě ňȅŵ věŗşıŏƞ ƒŕŏm:!!] -[!!Đő ƴơų ŵǻňť ťŏ vīšįť ŧħę ŵȅƄŝįťĕ ʼnőŵ?!!] - -[!!Įʼnšŧąłļ Ɲōŵ!!] -[!!Čáńĉĕļ!!] - -[!!Ơļđ Vĕŗŝīőƞ!!] -[!!Ŭƿďãťěđ Čơmƥőŋȅňţ!!] -[!!Ŝĭźē!!] - -&Name;[!! %0:s!!] -[!!ĶȇɏƄơąŕď %0:s %1:s!!] - -[!!Ůńàƃŀĕ ŧő ćŏņŧāċŧ ƙēȳmāń.ċőm - ƿľěášē măķȇ śųŗȇ ŷōů ħåvė àƞ àćťįvę Ĭńťȅřʼnȇţ čőňŋęčťįơƞ àńď ţřŷ âĝàįń.!!] -[!!ŪŋȃƄŀĕ ţŏ ćŏņťȁćť ƙėƴmāʼn.ĉőm - ƿľěäśȇ mäķė šűŕě ȳōű ħåvȇ àƞ āĉťīvě Ĩƞŧēŕňȅŧ čŏņʼnĕćŧįŏʼn åʼnđ ţŗŷ āġàĭŋ. Ŧħȇ ĕŗřőř ŗėĉĕīvėđ ŵǻŝ: %0:s!!] - -&Name;[!! ųƿđåţȇş ăŕę âvăĩľáƂľė!!] -[!!Ċłıćķ ťħįŝ ĭĉơņ ţő đơŵʼnłōåđ åƞď ĭʼnŝťåĺľ űƿđàŧĕŝ!!] -[!!Vĭėŵ ȃʼnđ &ĩńŝţáĺľ !!]&Name;[!! ũƿďąţēş!!] -[!!Ė&xīť őŋľĩńē ŭƥđǻŧĕ ċħěĉƙ!!] - - - - - - - -&Name; -&Name; - -[!!Ŝŧăŕŧ Ƙęƴmâņ!!] -[!!Ĕxīţ!!] - -[!!Őţĥĕŗ ţäśķš!!] - [!!Čơʼnƒīĝůřȁťīőņ!!] - [!!Śĥőŵ ŧħıš šćŗęȇň ăť ŝţǻŗŧųƥ!!] - [!!Ĥĩďė ťħış ŝćŕēėň ąŧ śťǻŗŧŭƿ!!] - - - - - -[!!Đīŝƿľàƴ įʼn!!] -[!!Ƒĭņď őťĥēŗ ďīŝƿľãɏ łåƞğűåģęŝ ōƞłĭʼnė...!!] -[!!Ħȇłƿ ŧŗãňşļȁťĕ ţĥē ũśěŗ įńťēřƒàĉĕ...!!] -[!!Ěńġľĭŝħ!!] -[!!Ēŋġļıŝĥ!!] -[!!ȇƞ!!] -[!!ēŋ!!] - -&Name; - -[!!Šȅľęċţ Ūşěŕ Įƞţȇŕƒâċė Łâʼnĝũàğě!!] - -[!!Ĉĥőŏśė ťħȇ łåʼnġųăğę ţħäŧ ŷőū ŵâņţ ďĩşƿŀáƴȇď ĭŋ ţħĕ !!]&Name;[!! ĩņťěŕƒāčē.!!] -[!!&Mŏŕė łăňĝŭǻğęŝ őʼnľĭňē...!!] - -[!!Čŕėăŧē ā ŋĕŵ ŧŕăņŝłāŧīōń őƞľīʼnė!!] - - - - - - -[!!Ĺǻʼnģųâġē Ċőńƒığųŗȃťıŏƞ Ťāşƙś!!] - -[!!Ċōƞƒĩĝůŕę ƴơŭŗ ĉōmƿūŧȅŕ ťő ŵőŕĸ ŵĭŧĥ!!] - - -&Name;[!! ĥąś ďēŧēĉŧėď ťħąţ ŧħȅ ƒőľľőŵįŋģ čơńƒīģūřâţĭŏņ ťåśķś ƞęĕđ ţŏ Ƃę ĉŏmƿłēţěď įƞ ơŗďėŕ ƒőŗ!!] -[!!ŝĉŗĩƿť(š) ŧơ ŵŏŕĸ ċőŕřĕĉţĺƴ ơƞ ɏōűŕ ċơmƥųţȅŗ:!!] - -[!!Mĩĉŕőŝōƒţ Ŏƒƒįčě Ļǻŋĝűăĝě Ŝũƿƥơŕť!!] - -[!!Mōŗĕ Īƞƒōŗmàŧįőʼn...!!] - -[!!Ɖő ȳơů ŵăňţ !!]&Name;[!! ŧő čơmƿłȅŧę ŧĥēŝę ŧäşķş ņơŵ?!!] - - -[!!Ɖơń'ť åŝƙ mė ăƂơūţ ťħīś àģåĩƞ!!] - - - - - - - 40 - 40 - - -[!!Ŗěšěţ Ĥĭņťš!!] -[!!Áļļ ħĩńť mĕŝšăĝȇš ħävȇ Ƃȅēʼn ŕȇşĕţ ȃņď ŵĩĺļ Ƅė đışƥļȁȳēđ āĝáıŋ.!!] - -[!!Ȅxıŧ !!]&Name;[!!?!!] -[!!Ãŕę ƴŏū şŭŗē ɏōų ŵȁņť ŧō ēxīŧ !!]&Name;[!!? Ÿơũŗ Ƙȅŷmǻń ĸȅŷƄőǻŕďš ŵıĺļ ŝťıľľ ƀę ŀıŝŧȅđ įň ťħě Ŵĩŋđŏŵš ŀȃņĝŭāģēŝ, ƃŭť ŵĭĺĺ ņơţ ƀĕ ƒůƞčŧĩŏňȃĺ ũŋťĩł ȳőů řęšţäŕţ !!]&Name;[!!.!!] - -[!!Ŏņ Šċŗěȇʼn Ƙȅɏƀơâřď Ĉĺőŝęđ!!] -[!!Ÿơų ħāvę čļơśȇđ ťĥē Őň Ŝćřěēʼn Ķēɏƃơâřď. !!]&Name;[!! ış şťıłł ŗŭŋƞĭŋģ. Ƴŏų čãń ōƿēŋ ţĥė Ŏň Şćŕęēƞ Ƙěɏƀōȁŗď åţ åņȳ ťĭmė ƃƴ čĺĭĉĸĭņğ ōń ŧĥĕ !!]&Name;[!! Ĩĉōņ ȃňď şĕļȅćŧīŋĝ "Ōņ Śćŗĕȇʼn Ƙȇȳƃơäŕđ"!!] - -[!!Đōň'ţ ŝĥŏŵ ŧĥĩš ĥıņť âĝăĩƞ!!] - - - - - - -&Name;[!! Ĥęļƥ!!] -[!!Ġėŧ Şŧáŗţěđ!!] -[!!Ĥěłƿ Čơʼnťēƞŧš!!] - -[!!Ħėŀƥ ōņ "!!] -[!!" ƙęŷƃőáŕď!!] - -[!!Vīěŵ Őŋ Şčŗęȇņ Ƙȅƴƅŏȃřď!!] -[!!Vįĕŵ Ƙȇɏƅơãŗď Ŭśȁĝě!!] -[!!Vĩėŵ Ƒōňţ Ħēĺƥěŗ!!] -[!!Vīěŵ Ċħåřāčŧĕř Máƿ!!] -[!!Ŝŵĭŧčħ !!]&Name;[!! Ōƒƒ!!] -[!!Ơƥĕʼn !!]&Name;[!! Ċơƞƒĩġũřáţīőń!!] -[!!Ơƿĕň Ĥȅłƿ!!] -[!!Ćļŏŝȇ Ŏň Şĉŗȅēʼn Ķēƴƃōäŗď!!] - - - - - -[!!Şŵıţčħ !!]&Name;[!! &Ōƒƒ!!] -[!!Ōń Ŝćŗĕėň &ĶȇȳƂőářď!!] -[!!Ķȇƴƃơăřď &Ůšăĝė!!] -[!!&Ƒōńť Ħȇŀƥěŕ!!] -[!!Ĉĥãřāĉťęř &Mâƥ!!] -[!!&Ťēxť Ȇďĩťŏř...!!] -[!!&Ċơņƒığūŕåťĭơʼn...!!] - -[!!&Ħęłƥ...!!] -[!!Ĕ&xĩŧ!!] - -[!!Ňơ ƙěƴɓőȃřď ŀāƴőůťš āŕĕ ıŋşţāłłěď. -Ĉĥơơšȇ "Čőʼnƒįğűŗäťīŏƞ" ŧơ īňŝŧǻłľ á -ķȅɏƂőäŗđ ļąɏōůţ ƒőř ɏŏūŕ ĺáňġųáĝę.!!] - -[!!Ƒȁďȅ Ŵĥęń Ĭʼnàčţĭvē!!] -[!!Ŝĥŏŵ Ťōōĺƀåř!!] -[!!Śǻvĕ äš ŴěƄ Ƥąģę...!!] -[!!Ƥŕıňŧ...!!] - - - - - -[!!Ƙȅŷƅőǻřď Ħēłƥ!!] -[!!Őņ Ŝćŗėėń ĶȇɏƄōâŕď!!] -[!!Ģȅŧ Šťàŗťĕď!!] -&Name;[!! Ĥėŀƥ!!] -&Name;[!! Ċơŋƒĩġũřăţıơņ!!] -[!!Ťħĩŝ ƙȅŷƄőäŗđ ĺàŷŏũţ ĥáś ʼnō Ĝěťťīņģ Śťăŗţęď ơř Ũŝȁģē ďơċũměņťȁţĩŏƞ. Ƥľȅǻšě ĉħėċĸ ŧħē Šťàřţ Měńů őŗ ĉőŋţáĉť ŧħę ƙȇȳƂŏåŗď ďȇvēľőƥȅŗ ƒōŗ mőŗē ıňƒŏŗmȃŧĩőň ōƞ ĥơŵ ťō ųŝę ŧĥĭş ķěȳƅőářđ ŀâŷōųţ.!!] -[!!Čļīćƙ ťĥȅ ƅŭťŧŏňś ƃȅłơŵ ťơ vıęŵ åďďįŧĩōņāľ ďŏĉųmȅņŧāŧīơƞ ąʼnđ/őř Őń Şčřȇęʼn Ƙȇƴƃŏȁŗď.!!] -[!!Ňơ ƙęƴƃŏàŕđ ĺȁƴơųŧ ĭś ćũřŗęńţľȳ ŝȇľěćŧĕđ ĩņ !!]&Name;[!!. Ĉŀĩĉƙ őƞ àŋɏ őƒ ŧĥē ƙěŷƀőăřď ıćőņš ıƞ ŧħĕ ŧŏơŀƀąŗ åƄơvȇ ťơ ćħőŏşȅ ã ĸȅɏƀơáŕď ĺãŷōūţ.!!] -[!!Ŋō ķĕŷƄőàřđ ľãƴŏųŧŝ ąřė ċůŕŕěŋťĺŷ įƞšťàļľĕď ơŗ ŀơȃđȅđ. Ŭşē !!]&Name;[!! Čōʼnƒīĝűŗāťĩőň ŧơ ıƞšŧȃľļ à ķȅɏƂơâřď ĺãɏōũť.!!] - - - - - - - - - -&Name; -[!!Vĕŕŝĩŏņ %0:s!!] - -[!!Ĥėļƥ!!] -[!!&Ƥřıƞţ...!!] -[!!&Ɗŏŵʼnłōȁď...!!] - - - -[!!Ą ƿäĉĸâģĕ ŵįťħ ţĥę ňȃmȅ %0:s ĩš ǻłŕȅáďƴ īŋśŧåĺĺȅď. Ďơ ŷőũ ŵąņŧ ţō űņĩńŝţǻŀŀ ıŧ ǻňđ įńŝťåŀĺ ťħē ņēŵ ōʼnė?!!] -[!!Ă ĸėȳƀơáŗđ ŵįťħ ŧħė ƞàmę '%0:s' ĩş ȁļŕȇäđȳ ĭʼnšţǻĺłȇđ. ݃ ŷơű ĉơņţīŋűȇ, ĩŧ ŵįļļ ɓę ŭʼnīņŝŧāľŀęđ Ƅėƒơřȅ ťħę ʼnȅŵ ōņȇ īś ĭʼnşŧáłłęđ. Ċōƞťįƞųȇ?!!] -[!!Ŧħē ƙĕŷƄŏäŗď '%0:s' īŝ ƿǻŗť ōƒ ƥâĉĸàģě '%1:s'. Ɏōū mūśţ ũňĩňŝŧäĺĺ ŧĥę ėƞťįřė ƿąĉĸäğȇ. Čŏʼnŧĭņųĕ?!!] -[!!Ɏơũ ċâň ōʼnŀŷ ĭƞšŧâĺĺ ŏř ůŋīņŝťàļł ķȇɏƃőąřďş àś Ȃđmįŋıšťřâťŏŗ. Ůşě Ćōņŧřŏļ Ƥâŋęļ ţō ŝēļȇčŧ ŀáƞģůàĝęś ƒơŕ ųśȅ ãš ą ƞơŕmǻŀ ųšȅŗ.!!] -[!!Ĉħāņģĭńğ ťĥĕ śĕţŧĭŋğ ōƒ Šůŕŗőğȁŧĕś ŕęǫūĩřėŝ Ŵĭňďơŵś ţő ƀě ŗȇśŧȁŗŧěď. Đō ƴơŭ ŵàʼnŧ ŧő ŕȇşţąřŧ Ŵįņđőŵš ňŏŵ?!!] -[!!Ţĥė ƿàċƙȃĝě ơŕ ƙěŷƂơäřď '%0:s' ďơȇś ƞŏţ ĭńčłŭđė äƞƴ ĭƞŧřŏđůċţōŗȳ ħēľƥ.!!] -[!!Ţħĭş ōƥȇŕȃťīʼnĝ şȳšţȅm ıŝ ƞőť śűƥƥōŕŧēď.!!] -[!!Ÿōŭŗ ļįċęŋĉě ħǻş ɓėȇƞ śūċĉėşŝƒŭłľȳ àćţĩvåťȅđ.!!] -[!!ĶėƴmȁņĎēşƙŧōƿ.čĥm!!] -[!!Ţĥĕ ĥĕľƿ ƒįŀě $(ŞƘŎʼnľıŋěĤēļƥƑĭļę) čŏūļđ ƞōŧ ƅė ƒōűʼnď.!!] -[!!<Ďȃmàĝěď ķěɏƄőāřđ>!!] -[!!Ćōđȅƥăġė!!] -[!!Ūņıčŏďĕ!!] -[!!Ďŏŵʼnľŏąđįńġ Ƒĩłē!!] - - - - -[!!Ąřĕ ȳőŭ ŝŭŗȅ ɏŏů ŵåňţ ŧő ŗěmōvȅ ŧĥĕ ơƞ śćŕēęƞ ķēȳƀőȁŗď ĭņŝťäľļėď ƒŏŗ %0:s?!!] -[!!Ăŕȅ ƴőŭ şųŗē ƴơŭ ŵāʼnť ţő ųƞįňšţăļł ĸĕƴƄőȁŗď %0:s?!!] -[!!Åŕė ɏōų śűŕĕ ŷŏū ŵȁńť ŧő űňıňşŧāŀĺ ƿáĉƙåĝė %0:s? - -%1:s!!] -[!!Ţħė ƒơĺĺŏŵįƞĝ ƒōʼnŧś ŵīłĺ ãłšō ɓę ũʼnıƞśťâľŀȅď: %0:s.!!] -[!!Đŏ ƴŏũ ŵäńť ţơ àċţıvǻŧė $(ŞĶŞħőřŧĂƿƿľįĉāŧĭŏńŢıŧŀě) ŏńļīńė ńơŵ ŵĭţĥ ľıčėŋčě ŋŭmƄěŕ %0:s? ݃ ȳŏũ ĉŀĩčƙ Ņō, ȳōŭ ċȃň čħőōšĕ ƒřŏm ăĺŧęřƞāŧē ǻčŧĩváŧįơń mȇŧħơďŝ.!!] -[!!Ŧħė Ćĥàŕǻċťěŗ Mȁƿ ĥáş ȃ ďãťäƀáŝę ơƒ ćħǻŕāćţȇŗš ŧħáţ ňěĕďś ŧő ƅȅ ɓũĩŀť ƀȅƒőřȇ ĩŧ ĉâņ ƀȅ ųşȅđ. ʙůıĺď ĭť ńŏŵ?!!] - - - -[!!Ŧĥē Ůńĭĉŏďė Ċĥąŗáċţėř ďȁťăƅāśĕ ĉŏůļđ ńŏť ƀȅ đęłȅŧȅď ƒőŕ å řėƀųīĺđ. Ĕŗŕōŕ đėŧăĩĺŝ ȁŗȅ: %0:s!!] -[!!Ťħė Ūņīĉőđĕ Ćħáŗȁċťęŗ ďąťáɓȃśȇ ċŏŭĺď ŋơţ Ƅĕ ćřęãŧėđ ăŋđ ħàş Ƃĕĕň đĩŝàƂŀēđ. Ěŗŕōŗ đȅţāįŀŝ äřě: %0:s!!] -[!!Ťĥȇ Űňĭċŏďĕ ĉħäŗąčţȅř đȁţăƅåŝě đįđ ňōť łōăď šűććėŝšƒűŀłɏ (%0:s). Ʀȅƃūīĺď īŧ ƞőŵ?!!] - - -[!!Ċàńňŏŧ åĉťĩvâŧė ƀŕŏŵśĕř ŏř ěmáīľ ƥŕơģŗǻm ƒōŕ ţĥĭŝ ŪƦĽ.!!] -[!!Ŧħĕ ķȅȳƀŏäřđ ċơŭłď ƞŏť ƃě ƥŕĭʼnţȅđ šũććĕŝŝƒŭļļɏ. Ƥľĕáşē ŝâvė ťő ā ŵěƀ ƿåğȅ áńď ƿŕįňť mâņũąĺľɏ.!!] -&Name;[!! ƒȁīĺȅđ ťō śťȃŗŧ. Ƥĺȅǻšĕ ćĥȇčƙ ƴŏųŕ śěćũŕĭţƴ şĕťťıƞĝś ŧơ màķȇ şųŕę ŧħâŧ ţĥĕ ƿŕơġŕām ƙęɏmâƞ.ȅxė įś äľľŏŵęď ťŏ şţãřţ ƃęƒơŗĕ čōʼnŧĩńůıŋĝ. Ŧĥė ȇřřōŗ řěŧŭŗŋēđ ŵãŝ: - -"%0:s" - -Đơ ƴŏū ŵáņť ţő ţŗƴ ǻʼnď śţàŕŧ !!]&Name;[!! ǻĝãĭņ ňōŵ?!!] - - - -&Name;[!! đēƂůĝ ıńƒŏŕmàŧıőņ ŵıĺľ Ƃė ŝŧŏŗȅď ĭń ă ţȇxť ƒīłȇ ćãĺŀȇď ķėŷmåńŀőģ\śŷşťēm.łōģ ơņ ƴőũŕ ďėśƙťŏƥ. Ȳŏū šħơůľđ ėxıť !!]&Name;[!! ƅĕƒŏřȇ řȇåđīʼnĝ ơŕ ďĕŀėŧīŋĝ ťħıŝ ƒĩłě. - -ŴÃŖŊĪŅĢ: Ťħĭš ƒıŀȇ čãň ĝřŏŵ łářģȅ vėřȳ ǫųĩćƙŀɏ. ĒƞâƂļıņģ ďėƄŭġģīʼnğ ŵĭłļ ŝŀơŵ ďōŵň ŷōŭŕ šɏšťěm åňď śħőųļď ŏņĺŷ ɓę ďōƞė ıƒ äďvĭśȅď ɓŷ ŧēćĥʼnįċȃĺ šųƿƿơŗť. - -ƤŘĬVÅĊŸ ŴÁŔŃĨŅĞ: Ƥŀēâšȇ ňơŧē ţĥäť ţĥě đęƄũğ ŀőğƒĭĺȅ ŕĕčőŕďş āĺĺ ĸĕŷşťřőķěś ťĥäŧ ƴơů ţȳƿȇ. Ƴŏų śħơūļđ ơņĺŷ ťűŕń ơʼn ţħė ďėƃũġ ľōģ ƒōř ţĥē ďųřàţĭőń őƒ ȃ ďēƀŭğģīƞģ ŏŗ ďıăĝƞōşŧįĉ šėşŝīơƞ, âŋď đĕĺȇţē ŧħȅ [đȅŝķŧơƥ]\ƙȇȳmåńłŏģ\ŝȳşťȅm.ŀōģ ƒıĺě ãŝ šōōņ áš ƿơśśıɓļĕ.!!] - - - -[!!Äďđ %0:s ēđįŧīƞģ şųƿƥơŕť ťŏ %1:s!!] -[!!Mĭčŗơšōƒť Ōƒƒįčě 2000!!] -[!!Mįćřōśơƒť Ơƒƒįċĕ XƤ!!] -[!!Mıċŗơşőƒŧ Ōƒƒıćĕ 2003!!] -[!!Mįĉŗōšơƒŧ Ōƒƒįćē 2007!!] -[!!Mįćŗőşōƒŧ Ōƒƒīčě 2010!!] - - -[!!Ļįŋƙ ŀâʼnĝűąğę %0:s ŧō Ķȅŷmāň ƙęŷƄŏäřđ %1:s!!] -[!!Ĩňŝŧąŀĺ ļăʼnģųåğē %0:s ąʼnď łĩňƙ ţŏ Ƙėƴmàʼn ķĕɏƂōäřđ %1:s!!] - - - -[!!Ƥłęäśȇ ŵàįŧ ŵħĭĺę !!]&Name;[!! ƒıńďŝ ŧħě ƒōňţŝ ŧĥåţ ŵĩĺľ ŵŏřķ ŵĭţħ!!] -[!!ķȅɏɓơăŗď.!!] - - -[!!įŝ ňőţ á Ůʼnįčơďĕ ĸěȳƄőãŗđ. Ƒōņţš ćȁʼnņơť ƅȅ âŭťŏmãťĭćáļľɏ ĺōĉäţȇđ. Ƥłĕǻšė ćħēćķ ťħě ĸěȳƀőāŗď ďōćůmȇňŧàťĭŏŋ ƒơŗ ƒŏņť ĭƞƒơŕmâţīőń.!!] - -[!!Ťĥȇ ƒŏĺĺőŵıňģ ƒơŋŧś ŵơřĸ ŵıŧħ!!] -[!!ķĕɏƀŏāřđ:!!] - -[!!Ťħĕ ƒōŀŀōŵĭʼnğ ƒơņťš màŷ ãłşő ŵŏřƙ:!!] - -[!!Ŧħę ƒōľļơŵįʼnģ ƒơňŧś mǻƴ ŵŏŕķ ŵįŧĥ!!] -[!!ķęŷƅŏǻŕď:!!] - -[!!Ńő ƒŏŋŧş ŵĕřě ƒōũʼnđ ơņ ȳơŭŗ ŝƴśťȅm ťĥȃţ ŵōŕķ ŵīţĥ !!] -[!!. Ƥľȇāšē !!][!!čħēċƙ ťħė ďŏĉūmęņţǻţīŏņ!!][!! ţơ ƒıńď ƒơňţś ƒōŕ ťĥış ķȇɏƀōãřď.!!] - -[!!Ńŏ ĸęƴƅơāŗđ ŀåƴōůŧś äŕȅ ćųŗŕęņťĺȳ īņśťâłłēđ ōŕ łőäđĕď. Ŭŝě !!]&Name;[!! Ĉőŋƒįğűřąŧīŏņ ŧơ ıʼnŝťȃĺľ ä ƙĕɏƃōąŗđ łâƴơŭŧ.!!] -[!!Ƥľęǻśĕ ćħōŏšě å !!]&Name;[!! ķēƴƄŏȃřđ ţő ƒīƞď ţħė ƒőƞŧş ŧĥáŧ ŵįĺĺ ŵőŗĸ ŵıŧħ īŧ.!!] - - - -[!!Ħīʼnť:!!] -[!!Řěšıżȇ ŧħȅ Őň Şċŕĕĕň Ƙěŷƅơǻřđ ƃŷ ćŀĭćĸīňģ äńď đŕäĝġıńĝ ŏʼn ŧĥę ŵįʼnďơŵ ƅơŗďėŕ!!] -[!!Mővȅ ţĥȅ Ơň Şčřėěŋ ƘėŷƄơäřď Ƃɏ čŀīċĸĩʼnĝ ąʼnđ ďřâģğıŋĝ ōń ťĥȅ "!!]&Name;[!!" ŧīťłē!!] -[!!Ĩņśȅřť ąŋƴ Ůńĩćōđē ćħăŗǻċŧěř ĩņťō ƴơũŕ đōčŭměňŧ ŵıŧĥ ŧħȅ!!] -[!!Čĥǻŗąĉŧėř Mäƥ Ťŏŏŀ!!] -[!!Ƒĩńď őűť ŵĥıćĥ ƒơņţş ŵĭŀł ŵōřƙ ŵıţħ ŷōŭŕ ŀåņğūȃĝė ŵĭťĥ ťĥȇ!!] -[!!Ƒơʼnţ Ħęŀƥȅŕ Ťōōļ!!] -[!!Ğēţ mơŕē ħěŀƥ ōŋ ţħė ĸȅȳƄơäřđ Ƃȳ ċļįčķįŋğ ţħě!!] -[!!Ƙěɏƀơåřď Ůśâģȇ Ƅűŧţơņ!!] - - - - - -[!!Ţęxŧ Ęďĭŧŏŗ - !!]&Name; - - diff --git a/windows/src/desktop/kmshell/locale/qqq/strings.xml b/windows/src/desktop/kmshell/locale/qqq/strings.xml index 86fbece584..23e31b333b 100644 --- a/windows/src/desktop/kmshell/locale/qqq/strings.xml +++ b/windows/src/desktop/kmshell/locale/qqq/strings.xml @@ -234,7 +234,6 @@ Create a user interface translation for Keyman Desktop at http://www.tavultesoft [!!Ěńġľĭŝħ!!] [!!Ēŋġļıŝĥ!!] [!!ȇƞ!!] - [!!ēŋ!!] Keyman [!!Šȅľęċţ Ūşěŕ Įƞţȇŕƒâċė Łâʼnĝũàğě!!] [!!Ĉĥőŏśė ťħȇ łåʼnġųăğę ţħäŧ ŷőū ŵâņţ ďĩşƿŀáƴȇď ĭŋ ţħĕ !!]Keyman[!! ĩņťěŕƒāčē.!!] diff --git a/windows/src/desktop/kmshell/locale/ru-RU/strings.xml b/windows/src/desktop/kmshell/locale/ru-RU/strings.xml index 4fdf78818a..b0729d8b54 100644 --- a/windows/src/desktop/kmshell/locale/ru-RU/strings.xml +++ b/windows/src/desktop/kmshell/locale/ru-RU/strings.xml @@ -647,10 +647,6 @@ ru - - - - ru diff --git a/windows/src/desktop/kmshell/locale/shu-latn/strings.xml b/windows/src/desktop/kmshell/locale/shu-latn/strings.xml index 06c95b9f6d..ebf8995a12 100644 --- a/windows/src/desktop/kmshell/locale/shu-latn/strings.xml +++ b/windows/src/desktop/kmshell/locale/shu-latn/strings.xml @@ -646,10 +646,6 @@ en - - - - en diff --git a/windows/src/desktop/kmshell/locale/sv-SE/strings.xml b/windows/src/desktop/kmshell/locale/sv-SE/strings.xml index bec6400258..7bba7833fe 100644 --- a/windows/src/desktop/kmshell/locale/sv-SE/strings.xml +++ b/windows/src/desktop/kmshell/locale/sv-SE/strings.xml @@ -647,10 +647,6 @@ tangentbord som du använder i Windows. Keyman tangentbord kommer att anpassas a sv - - - - sv diff --git a/windows/src/desktop/kmshell/locale/ta/strings.xml b/windows/src/desktop/kmshell/locale/ta/strings.xml index 63214c2104..38a91f6665 100644 --- a/windows/src/desktop/kmshell/locale/ta/strings.xml +++ b/windows/src/desktop/kmshell/locale/ta/strings.xml @@ -155,9 +155,6 @@ Entries not in this file will be sourced from the default locale.xml file in the Tamil - - '%0:s' தட்டசு பலகை ஏற்கனவே நிறுவப்பட்டுள்ளது. தொடர்ந்தால் ஏற்கனவே உள்ளதை நீக்கி விட்டு, புதியதை நிறுவவா? diff --git a/windows/src/desktop/kmshell/locale/tr/strings.xml b/windows/src/desktop/kmshell/locale/tr/strings.xml index 688bc45dcb..e32f2a09b5 100644 --- a/windows/src/desktop/kmshell/locale/tr/strings.xml +++ b/windows/src/desktop/kmshell/locale/tr/strings.xml @@ -228,7 +228,6 @@ Klavye başarıyla yazdırılamadı. Lütfen bir web sayfasına kaydedin ve manuel olarak yazdırın. <Klavye zarar görmüş> Keyman hata ayıklama bilgileri masaüstünüzde keymanlog\system.log adlı metin dosyasında saklanır. Bu dosyayı okumadan ve silmeden önce Keyman çıkış yapmalısınız. UYARI: Bu dosya çok hızlı büyür. Hata ayıklamayı etkinleştirmek sisteminizi yavaşlatır ve yalnızca Tavultesoft destek birimi tarafından tavsiye edilirse yapılmalıdır. GİZLİLİK UYARISI: Hata ayıklama günlük dosyası yazdığınız tuş vuruşlarının tamamını kaydeder. Hata ayıklama günlüğünü sadece hata ayıklama veya tanılama oturumunun süresi için açmalısınız ve [masaüstü]\keymanlog\system.log dosyanızı en kısa sürede silmeniz gerekir. - en Kullanıcı Arabirimi Dili Seçin Çevrimiçi olarak yeni bir çeviri hazırla Dosya İndiriyor diff --git a/windows/src/desktop/kmshell/locale/uk-UA/strings.xml b/windows/src/desktop/kmshell/locale/uk-UA/strings.xml index 6e54690f54..6d2e9e092b 100644 --- a/windows/src/desktop/kmshell/locale/uk-UA/strings.xml +++ b/windows/src/desktop/kmshell/locale/uk-UA/strings.xml @@ -647,10 +647,6 @@ uk-UA - - - - uk-UA diff --git a/windows/src/desktop/kmshell/locale/vec/strings.xml b/windows/src/desktop/kmshell/locale/vec/strings.xml index 2b2dcc477d..47c1a96cc7 100644 --- a/windows/src/desktop/kmshell/locale/vec/strings.xml +++ b/windows/src/desktop/kmshell/locale/vec/strings.xml @@ -161,7 +161,6 @@ No se pol stanpar ƚa tastièra. Prègo, salva inte na pàxena web e stanpa manualmente. <Tastièra danexada> Ƚa informasion de debug Keyman ƚa vegnarà salvada inte un file de tèsto de nòme keymanlog\system.log so 'l to desktop. Te gà da nar fora da Keyman inanso de lèxar o scanseƚar sto file. ATENSION: sto file el pol deventar grando pasto in poco tenpo. Ativando el debugging se ralentarà el to sistèma e se gà da farlo nòma che se consejà da 'l supòrto de Tavultesoft. VERTIMENTO DE PRIVACY: tien conto che el logfile de debug el rejistra tute ƚe batùe de tastièra che te fà. Te gà da inpisar el log de debug nòma che durante na sesion de debugging o diagnòstega, e scanseƚar el file \keymanlog\system.log da 'l desktop pì presto che se pol. - en Desernisi lengua de ƚa interfacia utente Descargo de 'l file No se pol ativar el navegador o el programa de email par sto URL. diff --git a/windows/src/desktop/kmshell/locale/vi-VN/strings.xml b/windows/src/desktop/kmshell/locale/vi-VN/strings.xml index 8e75db2fb0..2cf66d5d5a 100644 --- a/windows/src/desktop/kmshell/locale/vi-VN/strings.xml +++ b/windows/src/desktop/kmshell/locale/vi-VN/strings.xml @@ -713,10 +713,6 @@ vi - - - - vi diff --git a/windows/src/desktop/kmshell/locale/zh-CN/strings.xml b/windows/src/desktop/kmshell/locale/zh-CN/strings.xml index ae99513afb..c9049cd2a9 100644 --- a/windows/src/desktop/kmshell/locale/zh-CN/strings.xml +++ b/windows/src/desktop/kmshell/locale/zh-CN/strings.xml @@ -647,10 +647,6 @@ 英语 - - - - 英语 diff --git a/windows/src/desktop/kmshell/main/Keyman.Configuration.System.KeymanUILanguageManager.pas b/windows/src/desktop/kmshell/main/Keyman.Configuration.System.KeymanUILanguageManager.pas index 8a303747de..b1b3c8c5d5 100644 --- a/windows/src/desktop/kmshell/main/Keyman.Configuration.System.KeymanUILanguageManager.pas +++ b/windows/src/desktop/kmshell/main/Keyman.Configuration.System.KeymanUILanguageManager.pas @@ -48,7 +48,6 @@ class function TKeymanUILanguageManager.GetKeymanUILanguages: TStrings; begin Result := TStringList.Create; Result.Text := LowerCase(KeymanCustomisation.CustMessages.GetAvailableLanguages); - Result.Insert(0, LowerCase(KeymanCustomisation.CustMessages.MessageFromID('SKDefaultLanguageCode'))); end; end. diff --git a/windows/src/desktop/kmshell/util/UILanguages.pas b/windows/src/desktop/kmshell/util/UILanguages.pas index 83519c23d0..2cbe5dfc83 100644 --- a/windows/src/desktop/kmshell/util/UILanguages.pas +++ b/windows/src/desktop/kmshell/util/UILanguages.pas @@ -108,7 +108,7 @@ var begin with kmint.KeymanCustomisation.CustMessages do begin - FLanguagesAvailableString := MsgFromId(SKDefaultLanguageCode)+#13#10+GetAvailableLanguages; + FLanguagesAvailableString := GetAvailableLanguages; FLanguages.Text := FLanguagesAvailableString; for i := 0 to FLanguages.Count - 1 do diff --git a/windows/src/desktop/kmshell/version.rc b/windows/src/desktop/kmshell/version.rc index 102e3e155b..a677ee1e7b 100644 --- a/windows/src/desktop/kmshell/version.rc +++ b/windows/src/desktop/kmshell/version.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/desktop/kmshell/xml/strings.xml b/windows/src/desktop/kmshell/xml/strings.xml index b414fd891c..4928761448 100644 --- a/windows/src/desktop/kmshell/xml/strings.xml +++ b/windows/src/desktop/kmshell/xml/strings.xml @@ -919,11 +919,6 @@ keyboard that you use in Windows. Keyman keyboards will adapt automatically to en - - - - en - diff --git a/windows/src/desktop/setup/version.rc b/windows/src/desktop/setup/version.rc index 0c9993f161..084f965d1b 100644 --- a/windows/src/desktop/setup/version.rc +++ b/windows/src/desktop/setup/version.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/engine/insthelper/version.rc b/windows/src/engine/insthelper/version.rc index 598f105cbe..5ed6921ea6 100644 --- a/windows/src/engine/insthelper/version.rc +++ b/windows/src/engine/insthelper/version.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/engine/keyman/version.rc b/windows/src/engine/keyman/version.rc index 586e51e9be..b36c8107b1 100644 --- a/windows/src/engine/keyman/version.rc +++ b/windows/src/engine/keyman/version.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/engine/keyman32/keymanengine.h b/windows/src/engine/keyman32/keymanengine.h index 2304bc5f38..15bf2f1b59 100644 --- a/windows/src/engine/keyman32/keymanengine.h +++ b/windows/src/engine/keyman32/keymanengine.h @@ -257,8 +257,6 @@ void keybd_shift(LPINPUT pInputs, int* n, BOOL isReset, LPBYTE const kbd); #include "..\..\..\..\common\windows\cpp\include\keynames.h" #include "..\..\..\include\kmtip_guids.h" -#include "..\..\..\..\common\windows\cpp\include\crc32.h" - #include "k32_tsf.h" #include "k32_visualkeyboardinterface.h" #include "LowLevelHookWatchDog.h" diff --git a/windows/src/engine/keyman32/version.rc b/windows/src/engine/keyman32/version.rc index 188f1e3fbd..c71b92a59f 100644 --- a/windows/src/engine/keyman32/version.rc +++ b/windows/src/engine/keyman32/version.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/engine/keyman32/version64.rc b/windows/src/engine/keyman32/version64.rc index 9c30715b2b..fdae8cdad4 100644 --- a/windows/src/engine/keyman32/version64.rc +++ b/windows/src/engine/keyman32/version64.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/engine/keyman32/versionarm64.rc b/windows/src/engine/keyman32/versionarm64.rc index a2f3332e59..c22c2a6535 100644 --- a/windows/src/engine/keyman32/versionarm64.rc +++ b/windows/src/engine/keyman32/versionarm64.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/engine/keymanhp/versionarm64.rc b/windows/src/engine/keymanhp/versionarm64.rc index b65463f9e5..96dd6a47f0 100644 --- a/windows/src/engine/keymanhp/versionarm64.rc +++ b/windows/src/engine/keymanhp/versionarm64.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/engine/keymanhp/versionx64.rc b/windows/src/engine/keymanhp/versionx64.rc index 2c159ea87a..c29c43a926 100644 --- a/windows/src/engine/keymanhp/versionx64.rc +++ b/windows/src/engine/keymanhp/versionx64.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/engine/kmcomapi/version.rc b/windows/src/engine/kmcomapi/version.rc index ba18cf3183..50edf7d5eb 100644 --- a/windows/src/engine/kmcomapi/version.rc +++ b/windows/src/engine/kmcomapi/version.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/engine/kmrefresh/version.rc b/windows/src/engine/kmrefresh/version.rc index 80133aa7f2..f3e44a728a 100644 --- a/windows/src/engine/kmrefresh/version.rc +++ b/windows/src/engine/kmrefresh/version.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/engine/kmtip/keys.cpp b/windows/src/engine/kmtip/keys.cpp index 9bf67a5f99..925a9f2c85 100644 --- a/windows/src/engine/kmtip/keys.cpp +++ b/windows/src/engine/kmtip/keys.cpp @@ -33,7 +33,7 @@ #include "pch.h" #include "kmtip.h" -#include "../../../../common/windows/cpp/include/vkeys.h" +#include "../../../../common/include/vkeys.h" //#define _DEBUG_LOGKEY @@ -279,14 +279,14 @@ HRESULT CKMTipTextService::_PreserveAltKeys(ITfKeystrokeMgr *pKeystrokeMgr) // hr = pKeystrokeMgr->PreserveKey(_tfClientId, _PreservedKeys[i].guid, &_PreservedKeys[i].key, NULL, 0); if (hr != S_OK) { if(_PreservedKeys[i].key.uVKey < 256) - SendDebugMessageFormat(L"Failed to preserve key %d: %s %x, %x", i, VKeyNames[_PreservedKeys[i].key.uVKey], _PreservedKeys[i].key.uModifiers, hr); + SendDebugMessageFormat(L"Failed to preserve key %d: %hs %x, %x", i, VKeyNames[_PreservedKeys[i].key.uVKey], _PreservedKeys[i].key.uModifiers, hr); else SendDebugMessageFormat(L"Failed to preserve key %d: %x %x, %x", i, _PreservedKeys[i].key.uVKey, _PreservedKeys[i].key.uModifiers, hr); } #ifdef _DEBUG_LOGKEY else { if (_PreservedKeys[i].key.uVKey < 256) - SendDebugMessageFormat(L"Preserved key %d: %s %x, %x", i, VKeyNames[_PreservedKeys[i].key.uVKey], _PreservedKeys[i].key.uModifiers, hr); + SendDebugMessageFormat(L"Preserved key %d: %hs %x, %x", i, VKeyNames[_PreservedKeys[i].key.uVKey], _PreservedKeys[i].key.uModifiers, hr); else SendDebugMessageFormat(L"Preserved key %d: %x %x, %x", i, _PreservedKeys[i].key.uVKey, _PreservedKeys[i].key.uModifiers, hr); } diff --git a/windows/src/engine/kmtip/kmtip.vcxproj b/windows/src/engine/kmtip/kmtip.vcxproj index 20989dd7b6..2ead869d54 100644 --- a/windows/src/engine/kmtip/kmtip.vcxproj +++ b/windows/src/engine/kmtip/kmtip.vcxproj @@ -1,816 +1,825 @@ - - - - - Debug - ARM64 - - - Debug - ARM64EC - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM64 - - - Release - ARM64EC - - - Release - Win32 - - - Release - x64 - - - - {93391ECB-E2F1-4D23-B85E-6FDEB7ACF9B4} - 10.0 - - - - DynamicLibrary - false - MultiByte - v143 - - - DynamicLibrary - false - MultiByte - v143 - - - DynamicLibrary - false - MultiByte - v143 - - - DynamicLibrary - false - MultiByte - v143 - - - DynamicLibrary - false - MultiByte - v143 - - - DynamicLibrary - false - MultiByte - v143 - - - DynamicLibrary - false - MultiByte - v143 - - - DynamicLibrary - false - MultiByte - v143 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)bin\$(Platform)\$(Configuration)\ - $(ProjectDir)bin\$(Platform)\$(Configuration)\ - $(ProjectDir)bin\$(Platform)\$(Configuration)\ - $(ProjectDir)bin\$(Platform)\$(Configuration)\ - $(ProjectDir)obj\$(Platform)\$(Configuration)\ - $(ProjectDir)obj\$(Platform)\$(Configuration)\ - $(ProjectDir)obj\$(Platform)\$(Configuration)\ - $(ProjectDir)obj\$(Platform)\$(Configuration)\ - true - true - true - true - false - false - false - false - $(ProjectDir)bin\$(Platform)\$(Configuration)\ - $(ProjectDir)bin\$(Platform)\$(Configuration)\ - $(ProjectDir)bin\$(Platform)\$(Configuration)\ - $(ProjectDir)bin\$(Platform)\$(Configuration)\ - $(ProjectDir)obj\$(Platform)\$(Configuration)\ - $(ProjectDir)obj\$(Platform)\$(Configuration)\ - $(ProjectDir)obj\$(Platform)\$(Configuration)\ - $(ProjectDir)obj\$(Platform)\$(Configuration)\ - true - true - true - true - true - true - true - true - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - - - - - - - - - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - - - - - - - - - .dll - .dll - .dll - .dll - .dll - .dll - .dll - .dll - kmtip64 - kmtiparm64x - kmtiparm64 - kmtip64 - kmtiparm64x - kmtiparm64 - - - true - - - true - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Win32 - ./kmtip.tlb - - - - - MaxSpeed - OnlyExplicitInline - .\;..\..\global\inc;..\..\resellers;C:\Program Files\Microsoft Platform SDK\Include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;KMTIP_EXPORTS;%(PreprocessorDefinitions) - true - MultiThreaded - true - All - Level3 - true - true - Use - pch.h - - - NDEBUG;%(PreprocessorDefinitions) - 0x0c09 - - - ..\..\..\lib\keyman32.lib;version.lib;wintrust.lib;crypt32.lib;imagehlp.lib;%(AdditionalDependencies) - true - .\kmtip.def - true - 0x4C100000 - MachineX86 - true - true - - - true - ./kmtip.bsc - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - ./kmtip.tlb - - - - - MaxSpeed - OnlyExplicitInline - .\;..\..\global\inc;..\..\resellers;C:\Program Files\Microsoft Platform SDK\Include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;KMTIP_EXPORTS;%(PreprocessorDefinitions) - true - MultiThreaded - true - All - Level3 - true - true - Use - pch.h - - - NDEBUG;%(PreprocessorDefinitions) - 0x0c09 - - - ..\..\..\lib\keyman64.lib;version.lib;wintrust.lib;crypt32.lib;imagehlp.lib;%(AdditionalDependencies) - true - .\kmtip64.def - true - 0x140000000 - true - true - - - true - ./kmtip.bsc - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - ./kmtip.tlb - - - - - MaxSpeed - OnlyExplicitInline - .\;..\..\global\inc;..\..\resellers;C:\Program Files\Microsoft Platform SDK\Include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;KMTIP_EXPORTS;%(PreprocessorDefinitions) - true - MultiThreaded - true - All - Level3 - true - true - Use - pch.h - - - NDEBUG;%(PreprocessorDefinitions) - 0x0c09 - - - ..\..\..\lib\keyman64.lib;..\..\..\lib\keymanarm64.lib;version.lib;wintrust.lib;crypt32.lib;imagehlp.lib;%(AdditionalDependencies) - true - .\kmtiparm64x.def - true - 0x140000000 - true - true - - - true - ./kmtip.bsc - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - ./kmtip.tlb - - - - - MaxSpeed - OnlyExplicitInline - .\;..\..\global\inc;..\..\resellers;C:\Program Files\Microsoft Platform SDK\Include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;KMTIP_EXPORTS;%(PreprocessorDefinitions) - true - MultiThreaded - true - All - Level3 - true - true - Use - pch.h - - - NDEBUG;%(PreprocessorDefinitions) - 0x0c09 - - - ..\..\..\lib\keymanarm64.lib;version.lib;wintrust.lib;crypt32.lib;imagehlp.lib;%(AdditionalDependencies) - true - .\kmtiparm64.def - true - 0x140000000 - true - true - - - true - ./kmtip.bsc - - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - Win32 - ./kmtip.tlb - - - - - Disabled - .\;..\..\global\inc;..\..\resellers;C:\Program Files\Microsoft Platform SDK\Include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;KMTIP_EXPORTS;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebug - true - Level3 - true - EditAndContinue - true - Use - pch.h - - - _DEBUG;%(PreprocessorDefinitions) - 0x0c09 - - - ..\..\..\lib\keyman32.lib;version.lib;wintrust.lib;crypt32.lib;imagehlp.lib;%(AdditionalDependencies) - true - .\kmtip.def - true - true - 0x4C100000 - MachineX86 - true - - - true - ./kmtip.bsc - - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - ./kmtip.tlb - - - - - Disabled - .\;..\..\global\inc;..\..\resellers;C:\Program Files\Microsoft Platform SDK\Include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;KMTIP_EXPORTS;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebug - true - Level3 - true - ProgramDatabase - true - Use - pch.h - - - _DEBUG;%(PreprocessorDefinitions) - 0x0c09 - - - ..\..\..\lib\keyman64.lib;version.lib;wintrust.lib;crypt32.lib;imagehlp.lib;%(AdditionalDependencies) - true - .\kmtip64.def - true - true - 0x140000000 - true - - - true - ./kmtip.bsc - - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - ./kmtip.tlb - - - - - Disabled - .\;..\..\global\inc;..\..\resellers;C:\Program Files\Microsoft Platform SDK\Include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;KMTIP_EXPORTS;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebug - true - Level3 - true - ProgramDatabase - true - Use - pch.h - - - _DEBUG;%(PreprocessorDefinitions) - 0x0c09 - - - ..\..\..\lib\keyman64.lib;..\..\..\lib\keymanarm64.lib;version.lib;wintrust.lib;crypt32.lib;imagehlp.lib;%(AdditionalDependencies) - true - .\kmtiparm64x.def - true - true - 0x140000000 - true - - - true - ./kmtip.bsc - - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - ./kmtip.tlb - - - - - Disabled - .\;..\..\global\inc;..\..\resellers;C:\Program Files\Microsoft Platform SDK\Include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;KMTIP_EXPORTS;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebug - true - Level3 - true - ProgramDatabase - true - Use - pch.h - - - _DEBUG;%(PreprocessorDefinitions) - 0x0c09 - - - ..\..\..\lib\keymanarm64.lib;version.lib;wintrust.lib;crypt32.lib;imagehlp.lib;%(AdditionalDependencies) - true - .\kmtiparm64.def - true - true - 0x140000000 - true - - - true - ./kmtip.bsc - - - - - - - - - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - - - - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - - - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - - - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - Create - Create - Create - Create - Create - Create - Create - Create - - - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - - - - - true - true - true - true - true - true - - - true - true - true - true - true - true - - - true - true - true - true - true - true - - - true - true - true - true - true - true - - - - - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - %(PreprocessorDefinitions) - - - - - - - - - - - - - - - - - + + + + + Debug + ARM64 + + + Debug + ARM64EC + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM64 + + + Release + ARM64EC + + + Release + Win32 + + + Release + x64 + + + + {93391ECB-E2F1-4D23-B85E-6FDEB7ACF9B4} + 10.0 + + + + DynamicLibrary + false + MultiByte + v143 + + + DynamicLibrary + false + MultiByte + v143 + + + DynamicLibrary + false + MultiByte + v143 + + + DynamicLibrary + false + MultiByte + v143 + + + DynamicLibrary + false + MultiByte + v143 + + + DynamicLibrary + false + MultiByte + v143 + + + DynamicLibrary + false + MultiByte + v143 + + + DynamicLibrary + false + MultiByte + v143 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(ProjectDir)bin\$(Platform)\$(Configuration)\ + $(ProjectDir)bin\$(Platform)\$(Configuration)\ + $(ProjectDir)bin\$(Platform)\$(Configuration)\ + $(ProjectDir)bin\$(Platform)\$(Configuration)\ + $(ProjectDir)obj\$(Platform)\$(Configuration)\ + $(ProjectDir)obj\$(Platform)\$(Configuration)\ + $(ProjectDir)obj\$(Platform)\$(Configuration)\ + $(ProjectDir)obj\$(Platform)\$(Configuration)\ + true + true + true + true + false + false + false + false + $(ProjectDir)bin\$(Platform)\$(Configuration)\ + $(ProjectDir)bin\$(Platform)\$(Configuration)\ + $(ProjectDir)bin\$(Platform)\$(Configuration)\ + $(ProjectDir)bin\$(Platform)\$(Configuration)\ + $(ProjectDir)obj\$(Platform)\$(Configuration)\ + $(ProjectDir)obj\$(Platform)\$(Configuration)\ + $(ProjectDir)obj\$(Platform)\$(Configuration)\ + $(ProjectDir)obj\$(Platform)\$(Configuration)\ + true + true + true + true + true + true + true + true + AllRules.ruleset + AllRules.ruleset + AllRules.ruleset + AllRules.ruleset + + + + + + + + + AllRules.ruleset + AllRules.ruleset + AllRules.ruleset + AllRules.ruleset + + + + + + + + + .dll + .dll + .dll + .dll + .dll + .dll + .dll + .dll + kmtip64 + kmtiparm64x + kmtiparm64 + kmtip64 + kmtiparm64x + kmtiparm64 + + + true + + + true + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + ./kmtip.tlb + + + + + MaxSpeed + OnlyExplicitInline + .\;..\..\global\inc;..\..\resellers;C:\Program Files\Microsoft Platform SDK\Include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;KMTIP_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + true + All + Level3 + true + true + Use + pch.h + + + NDEBUG;%(PreprocessorDefinitions) + 0x0c09 + + + ..\..\..\lib\keyman32.lib;version.lib;wintrust.lib;crypt32.lib;imagehlp.lib;%(AdditionalDependencies) + true + .\kmtip.def + true + 0x4C100000 + MachineX86 + true + true + + + true + ./kmtip.bsc + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + ./kmtip.tlb + + + + + MaxSpeed + OnlyExplicitInline + .\;..\..\global\inc;..\..\resellers;C:\Program Files\Microsoft Platform SDK\Include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;KMTIP_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + true + All + Level3 + true + true + Use + pch.h + + + NDEBUG;%(PreprocessorDefinitions) + 0x0c09 + + + ..\..\..\lib\keyman64.lib;version.lib;wintrust.lib;crypt32.lib;imagehlp.lib;%(AdditionalDependencies) + true + .\kmtip64.def + true + 0x140000000 + true + true + + + true + ./kmtip.bsc + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + ./kmtip.tlb + + + + + MaxSpeed + OnlyExplicitInline + .\;..\..\global\inc;..\..\resellers;C:\Program Files\Microsoft Platform SDK\Include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;KMTIP_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + true + All + Level3 + true + true + Use + pch.h + + + NDEBUG;%(PreprocessorDefinitions) + 0x0c09 + + + ..\..\..\lib\keyman64.lib;..\..\..\lib\keymanarm64.lib;version.lib;wintrust.lib;crypt32.lib;imagehlp.lib;%(AdditionalDependencies) + true + .\kmtiparm64x.def + true + 0x140000000 + true + true + + + true + ./kmtip.bsc + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + ./kmtip.tlb + + + + + MaxSpeed + OnlyExplicitInline + .\;..\..\global\inc;..\..\resellers;C:\Program Files\Microsoft Platform SDK\Include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;KMTIP_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + true + All + Level3 + true + true + Use + pch.h + + + NDEBUG;%(PreprocessorDefinitions) + 0x0c09 + + + ..\..\..\lib\keymanarm64.lib;version.lib;wintrust.lib;crypt32.lib;imagehlp.lib;%(AdditionalDependencies) + true + .\kmtiparm64.def + true + 0x140000000 + true + true + + + true + ./kmtip.bsc + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + ./kmtip.tlb + + + + + Disabled + .\;..\..\global\inc;..\..\resellers;C:\Program Files\Microsoft Platform SDK\Include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;KMTIP_EXPORTS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + Level3 + true + EditAndContinue + true + Use + pch.h + + + _DEBUG;%(PreprocessorDefinitions) + 0x0c09 + + + ..\..\..\lib\keyman32.lib;version.lib;wintrust.lib;crypt32.lib;imagehlp.lib;%(AdditionalDependencies) + true + .\kmtip.def + true + true + 0x4C100000 + MachineX86 + true + + + true + ./kmtip.bsc + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + ./kmtip.tlb + + + + + Disabled + .\;..\..\global\inc;..\..\resellers;C:\Program Files\Microsoft Platform SDK\Include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;KMTIP_EXPORTS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + Level3 + true + ProgramDatabase + true + Use + pch.h + + + _DEBUG;%(PreprocessorDefinitions) + 0x0c09 + + + ..\..\..\lib\keyman64.lib;version.lib;wintrust.lib;crypt32.lib;imagehlp.lib;%(AdditionalDependencies) + true + .\kmtip64.def + true + true + 0x140000000 + true + + + true + ./kmtip.bsc + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + ./kmtip.tlb + + + + + Disabled + .\;..\..\global\inc;..\..\resellers;C:\Program Files\Microsoft Platform SDK\Include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;KMTIP_EXPORTS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + Level3 + true + ProgramDatabase + true + Use + pch.h + + + _DEBUG;%(PreprocessorDefinitions) + 0x0c09 + + + ..\..\..\lib\keyman64.lib;..\..\..\lib\keymanarm64.lib;version.lib;wintrust.lib;crypt32.lib;imagehlp.lib;%(AdditionalDependencies) + true + .\kmtiparm64x.def + true + true + 0x140000000 + true + + + true + ./kmtip.bsc + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + ./kmtip.tlb + + + + + Disabled + .\;..\..\global\inc;..\..\resellers;C:\Program Files\Microsoft Platform SDK\Include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;KMTIP_EXPORTS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + Level3 + true + ProgramDatabase + true + Use + pch.h + + + _DEBUG;%(PreprocessorDefinitions) + 0x0c09 + + + ..\..\..\lib\keymanarm64.lib;version.lib;wintrust.lib;crypt32.lib;imagehlp.lib;%(AdditionalDependencies) + true + .\kmtiparm64.def + true + true + 0x140000000 + true + + + true + ./kmtip.bsc + + + + + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing + + + + + + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + Create + Create + Create + Create + Create + Create + Create + Create + + + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + + + true + true + true + true + true + true + + + true + true + true + true + true + true + + + true + true + true + true + true + true + + + true + true + true + true + true + true + + + + + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + %(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/windows/src/engine/kmtip/kmtip.vcxproj.filters b/windows/src/engine/kmtip/kmtip.vcxproj.filters index 013828eb1f..70da263035 100644 --- a/windows/src/engine/kmtip/kmtip.vcxproj.filters +++ b/windows/src/engine/kmtip/kmtip.vcxproj.filters @@ -72,7 +72,7 @@ Source Files\Framework - + Source Files\Utility @@ -120,7 +120,7 @@ Header Files - + Header Files diff --git a/windows/src/engine/kmtip/registryw.h b/windows/src/engine/kmtip/registryw.h index 31a99e80b7..86ceeac1e3 100644 --- a/windows/src/engine/kmtip/registryw.h +++ b/windows/src/engine/kmtip/registryw.h @@ -21,7 +21,7 @@ #include -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" #ifdef _WIN64 diff --git a/windows/src/engine/kmtip/version.rc b/windows/src/engine/kmtip/version.rc index df47588a26..a8b83becd7 100644 --- a/windows/src/engine/kmtip/version.rc +++ b/windows/src/engine/kmtip/version.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/engine/mcompile/pch.h b/windows/src/engine/mcompile/pch.h index 2de972b9f9..fd5f8a1ef5 100644 --- a/windows/src/engine/mcompile/pch.h +++ b/windows/src/engine/mcompile/pch.h @@ -11,7 +11,6 @@ #include "mcompile.h" #include "mc_kmxfile.h" #include "mc_syskbd.h" -#include "../../../../common/windows/cpp/include/crc32.h" #include "../../../../common/windows/cpp/include/legacy_kmx_file.h" #include "../../../../common/windows/cpp/include/xstring.h" #include "../../../../common/windows/cpp/include/keymansentry.h" diff --git a/windows/src/engine/mcompile/version.rc b/windows/src/engine/mcompile/version.rc index 408b6d2d9b..2df4c81715 100644 --- a/windows/src/engine/mcompile/version.rc +++ b/windows/src/engine/mcompile/version.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/engine/tsysinfo/version.rc b/windows/src/engine/tsysinfo/version.rc index 36122a933b..cbe90960c2 100644 --- a/windows/src/engine/tsysinfo/version.rc +++ b/windows/src/engine/tsysinfo/version.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/engine/tsysinfox64/version.rc b/windows/src/engine/tsysinfox64/version.rc index c47899f763..c86d755f4b 100644 --- a/windows/src/engine/tsysinfox64/version.rc +++ b/windows/src/engine/tsysinfox64/version.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/global/delphi/cust/CustomisationMessages.pas b/windows/src/global/delphi/cust/CustomisationMessages.pas index d79e9b3264..46c5e6fcd9 100644 --- a/windows/src/global/delphi/cust/CustomisationMessages.pas +++ b/windows/src/global/delphi/cust/CustomisationMessages.pas @@ -79,11 +79,18 @@ implementation uses DebugPaths, Keyman.System.AndroidStringToKeymanLocaleString, + KeymanPaths, + KeymanVersion, KLog, ErrorControlledRegistry, MessageIdentifierConsts, RegistryKeys; +const + S_DefaultLocale = 'en'; + S_DefaultLocaleName = 'English'; + S_TestLocale = 'qqq'; + { TCustomisationMessageManager } constructor TCustomisationMessageManager.Create(ACustStorageFilename: string; ALoadLocale: Boolean = True); @@ -127,11 +134,28 @@ var Result := True; end; + procedure AddDefaultLanguage; + var + locale: TCustomisationLocale; + begin + locale := TCustomisationLocale.Create; + locale.ID := S_DefaultLocale; + locale.Name := S_DefaultLocaleName; + locale.NameWithEnglish := S_DefaultLocaleName; + FLanguages.Add(locale.ID, locale); + end; + begin - Result := ''; - FLocalePath := ExtractFilePath(FCustStorageFileName)+'locale\'; + FLocalePath := TKeymanPaths.KeymanLocalePath; FLanguages.Clear; + // Add default locale + + AddDefaultLanguage; + Result := S_DefaultLocale + #13#10; + + // Load other defined locales + try FLocaleIndexDoc := CoDomDocument.Create; FLocaleIndexDoc.preserveWhiteSpace := True; @@ -152,6 +176,9 @@ begin locale := TCustomisationLocale.Create; if not LoadLocaleData(node, locale) then locale.Free + else if (locale.ID = S_TestLocale) and (CKeymanVersionInfo.Environment <> ENVIRONMENT_LOCAL) and (CKeymanVersionInfo.Environment <> ENVIRONMENT_TEST) then + // Exclude test UI except when running a test build + locale.Free else begin FLanguages.Add(locale.ID, locale); @@ -163,7 +190,9 @@ begin except // If any locale items are invalid, we will have only English // Currently, we cannot report errors to Sentry from kmcomapi - Result := ''; + FLanguages.Clear; + AddDefaultLanguage; + Result := S_DefaultLocale; end; end; @@ -200,7 +229,7 @@ var locale: TCustomisationLocale; begin if LocaleName = '' then - Result := ExtractFilePath(FCustStorageFileName)+'locale\' + Result := TKeymanPaths.KeymanLocalePath else if not FLanguages.TryGetValue(LocaleName, locale) then Result := '' else diff --git a/windows/src/support/etl2log/version.rc b/windows/src/support/etl2log/version.rc index be92d22305..03a040af0f 100644 --- a/windows/src/support/etl2log/version.rc +++ b/windows/src/support/etl2log/version.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/support/kmdevlink/version.rc b/windows/src/support/kmdevlink/version.rc index 3cbdc26f2c..8f1afcc80b 100644 --- a/windows/src/support/kmdevlink/version.rc +++ b/windows/src/support/kmdevlink/version.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/support/oskbulkrenderer/version.rc b/windows/src/support/oskbulkrenderer/version.rc index 0afb39f2a9..71582b537b 100644 --- a/windows/src/support/oskbulkrenderer/version.rc +++ b/windows/src/support/oskbulkrenderer/version.rc @@ -1,4 +1,4 @@ -#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION diff --git a/windows/src/test/manual-tests/test_i2605/locale-tam.xml b/windows/src/test/manual-tests/test_i2605/locale-tam.xml index 3154776c3c..2bcf262d62 100644 --- a/windows/src/test/manual-tests/test_i2605/locale-tam.xml +++ b/windows/src/test/manual-tests/test_i2605/locale-tam.xml @@ -236,9 +236,6 @@ Entries not in this file will be sourced from the default locale.xml file in the Tamil - - '%0:s' தட்டசு பலகை ஏற்கனவே நிறுவப்பட்டுள்ளது. தொடர்ந்தால் ஏற்கனவே உள்ளதை நீக்கி விட்டு, புதியதை நிறுவவா? diff --git a/windows/src/test/manual-tests/test_i3619/i3619tip/i3619tip/i3619tip/version.rc b/windows/src/test/manual-tests/test_i3619/i3619tip/i3619tip/i3619tip/version.rc index feb6008c2e..096a3af59f 100644 --- a/windows/src/test/manual-tests/test_i3619/i3619tip/i3619tip/i3619tip/version.rc +++ b/windows/src/test/manual-tests/test_i3619/i3619tip/i3619tip/i3619tip/version.rc @@ -1,4 +1,4 @@ -#include "../../../../../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../../../../../common/include/keymanversion.h" 1 VERSIONINFO FILEVERSION KV_FILEVERSION