Merge branch 'master' into feat/mac/mcompile_mac

This commit is contained in:
Marc Durdin 2024-08-14 22:21:33 +10:00 committed by GitHub
commit 684a2dfa2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
288 changed files with 7547 additions and 1590 deletions

View file

@ -1,5 +1,52 @@
# Keyman Version History
## 18.0.88 alpha 2024-08-13
* docs: add .kmx specification (#12163)
## 18.0.87 alpha 2024-08-12
* chore(web): drop flaky auto-test component (#12155)
* fix(common): show description even if child projects specifies path (#12145)
## 18.0.86 alpha 2024-08-09
* chore(android): Update splash screen with SIL Tai Heritage Pro logo (#12127)
* chore(common): Update localization for Greek Polytonic (#12112)
* chore(common): add support for build target platform exclusions (#12113)
* feat(common): add top-level build.sh (#12114)
* chore(developer): start building Developer on linux,mac (#12117)
* refactor(web): Move `common/web/recorder``web/src/tools/testing/recorder-core` (#12092)
## 18.0.85 alpha 2024-08-08
* fix(developer): update date for last git commit date fixture (#12122)
* refactor(android/engine): Parse keyboards.json for FirstVoices app (#11943)
## 18.0.84 alpha 2024-08-07
* refactor(common): move kpj-related files into developer-utils (#11531)
* refactor(common): move kps-file.ts to @keymanapp/developer-utils (#11763)
* refactor(common): move kvks-file to @keymanapp/developer-utils (#11764)
* refactor(common): move .keyman-touch-layout reader/writer to @keymanapp/developer-utils (#11765)
* refactor(common): move LDML keyboard .xml reader/writer and kmx-plus builder to @keymanapp/developer-utils (#12081)
* refactor(common): move compiler-interfaces to @keymanapp/developer-utils (#12088)
* refactor(common): move xml2js and related deps to @keymanapp/developer-utils (#12101)
## 18.0.83 alpha 2024-08-06
* chore(common): Update history from 17.0.328 (#12093)
* change(common/models): change model tokenization to also tokenize whitespace (#11975)
* feat(web): support transform tokenization when given a root context (#11998)
* change(web): track whitespace-aware tokenization for context + correction-search caching (#11979)
* change(web): leverage tokenization to preserve punctuation and whitespace when predicting (#11997)
* fix(web): patch up worker build to provide artifacts for its tests (#12082)
* chore(web): move `web/src/engine/paths/``web/src/engine/interfaces/` (#12064)
* chore(web): move `common/web/input-processor/``web/src/engine/main/` (#12066)
* refactor(web): refactor and harmonize constants (#12072)
* chore(common): add data versions to minimum-versions.inc.sh (#12103)
* fix(web): fix lm-worker test broken by botched merge conflict resolution (#12104)
## 18.0.82 alpha 2024-08-05
* chore(windows): remove QIT_VSHIFTDOWN QIT _VSHIFTUP (#11973)

View file

@ -1,6 +1,6 @@
# License
Copyright (c) 2017-2022 SIL International. All rights reserved.
Copyright (c) 2017-2024 SIL Global. All rights reserved.
Licensed under the MIT License.
@ -10,7 +10,7 @@ Licensed under the MIT License.
The MIT License
Copyright (c) 2017-2022 SIL International
Copyright (c) 2017-2024 SIL Global
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View file

@ -4,7 +4,7 @@
# License
Copyright (c) SIL International.
Copyright (c) SIL Global.
Keyman is an open source project distributed under the [MIT license](LICENSE.md).

View file

@ -1 +1 @@
18.0.83
18.0.89

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -15,7 +15,7 @@
<item>
<bitmap
android:src="@drawable/sil_logo_blue_2017_1"
android:src="@drawable/sil_logo_color_tai_heritage_pro"
android:gravity="center"/>
</item>

View file

@ -30,9 +30,9 @@
<!-- Context: Text Size dialog -->
<string name="text_size" comment="Current text size (number)">Μέγεθος κειμένου: %1$d</string>
<!-- Context: Text Size dialog -->
<string name="ic_text_size_up" comment="Make text bigger">Μεγαλῶστε τὸ κείμενο</string>
<string name="ic_text_size_up" comment="Make text bigger">Μεγαλῶστε τὴν γραμματοσειρά</string>
<!-- Context: Text Size dialog -->
<string name="ic_text_size_down" comment="Make text smaller">Μεγαλῶστε τὸ κείμενο</string>
<string name="ic_text_size_down" comment="Make text smaller">Μικρύνετε τὴν γραμματοσειρά</string>
<!-- Context: Text Size dialog -->
<string name="ic_text_size_slider" comment="Adjust text size">Ρύθμιση μεγέθους κειμένου</string>
<!-- Context: Clear Text dialog -->
@ -68,7 +68,7 @@
<!-- Context: Keyman Settings menu -->
<string name="adjust_keyboard_height" comment="Menu action to adjust keyboard height">Μεταβολὴ ὕψους πληκτρολογίου</string>
<!-- Context: Keyman Settings menu -->
<string name="spacebar_caption" comment="Menu action to set the spacebar caption">Spacebar caption</string>
<string name="spacebar_caption" comment="Menu action to set the spacebar caption">Λεζάντα πλήκτρου διαστήματος</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_keyboard" comment="Spacebar caption option - keyboard">Πληκτρολόγιο</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
@ -80,9 +80,9 @@
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_keyboard" comment="Spacebar caption hint - keyboard">\'Ονομα πληκτρολογίου στὸ πλῆκτρο διαστήματος</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_language" comment="Spacebar caption hint - language">\'Ονομα γλώσσας στὸ πλῆκτρο διαστήματος</string>
<string name="spacebar_caption_hint_language" comment="Spacebar caption hint - language">νομα γλώσσας στὸ πλῆκτρο διαστήματος</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_language_keyboard" comment="Spacebar caption hint - language + keyboard">\'Ονομα πληκτρολογίου καὶ γλώσσας στὸ πλῆκτρο διαστήματος</string>
<string name="spacebar_caption_hint_language_keyboard" comment="Spacebar caption hint - language + keyboard">νομα πληκτρολογίου καὶ γλώσσας στὸ πλῆκτρο διαστήματος</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_blank" comment="Spacebar caption hint - blank">Καμμία λεζάντα στὸ πλῆκτρο διαστήματος</string>
<!-- Context: Keyman Settings menu / Haptic feedback -->
@ -92,13 +92,13 @@
<!-- Context: Keyman Settings menu -->
<string name="show_banner_on" comment="Description when toggle is on">Πρὸς ὑλοποίησιν</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner_off" comment="Description when toggle is off">Ὅταν εἶναι off, ἐμφανίζεται μόνο ὅταν ἔχει ἐνεργοποιηθεῖ τὸ προγνωστικὸ κείμενο</string>
<string name="show_banner_off" comment="Description when toggle is off">OFF: ἐμφάνιση μόνον ὅταν ἔχει ἐνεργοποιηθεῖ ἡ πρόβλεψη κειμένου</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report" comment="permission for sending crash reports">Ἐπιτρέψτε τὴν ἀποστολὴ ἀναφορῶν κατάρρευσης μέσῳ δικτύου</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report_on" comment="Description when toggle is on">Ὅταν εἶναι ΟΝ, θὰ ἀποστέλλονται ἀναφορὲς κατάρρευσης</string>
<string name="show_send_crash_report_on" comment="Description when toggle is on">ON: Ἀποστολὴ ἀναφορῶν κατάρρευσης</string>
<!-- Context: Keyman Settings menu -->
<string name="show_send_crash_report_off" comment="Description when toggle is off">Ὅταν εἶναι off, δὲν θὰ ἀποστέλλονται ἀναφορὲς κατάρρευσης</string>
<string name="show_send_crash_report_off" comment="Description when toggle is off">OFF: Δὲν ἀποστέλλονται ἀναφορὲς κατάρρευσης</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
<string name="install_from_keyman_dot_com" comment="Install package from Keyman server">Ἐγκατάσταση ἀπὸ τὸ keyman.com</string>
<!-- Context: Keyman Settings "Install Keyboard or Dictionary" menu -->
@ -118,9 +118,9 @@
<!-- Context: Select Package and Select Languages menu -->
<string name="all_languages_installed" comment="Text when all languages from a keyboard package have been installed">Ὅλες οἱ γλῶσσες ἔχουν ἤδη ἐγκατασταθεῖ</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="drag_the_keyboard" comment="First line of adjusting keyboard height">Σύρετε τὸ πληκτρολόγιο γιὰ νὰ ἀλλάξετε τὸ ὕψος</string>
<string name="drag_the_keyboard" comment="First line of adjusting keyboard height">Σύρετε τὸ πληκτρολόγιο γιὰ νὰ ἀλλάξετε τὸ ὕψος του</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="rotate_the_device" comment="Second line of adjusting keyboard height">Περιστρέψτε τὴν συσκευὴ γιὰ λειτουργία πορτραίτου καὶ τοπίου</string>
<string name="rotate_the_device" comment="Second line of adjusting keyboard height">Περιστρέψτε τὴν συσκευὴ γιὰ προσαρμογὴ τοῦ ὕψους σὲ λειτουργία πορτραίτου καὶ τοπίου</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="reset_to_defaults" comment="Button to reset to default heights">Ἐπαναφέρετε τὶς προεπιλεγμένες ρυθμίσεις</string>
<!-- Context: Keyman Web Browser -->
@ -150,9 +150,9 @@
<!-- Context: KMP Package strings -->
<string name="no_new_touch_keyboards_to_install" comment="Notification when no touch-optimized keyboards can be installed">Τὸ πακέτο πληκτρολογίου δὲν ἔχει βελτιστοποιημένα πληκτρολόγια ἀφῆς πρὸς ἐγκατάστασιν</string>
<!-- Context: KMP Package strings -->
<string name="no_new_predictive_text_to_install" comment="Notification when no dictionaries can be installed">Δὲν ὑπάρχει νέο προγνωστικό κείμενο πρὸς ἐγκατάστασιν</string>
<string name="no_new_predictive_text_to_install" comment="Notification when no dictionaries can be installed">Δὲν ὑπάρχουν προγνώσεις κειμένων πρὸς ἐγκατάστασιν</string>
<!-- Context: KMP Package strings -->
<string name="no_targets_to_install" comment="Notification when a package doesn't contain keyboards or dictionaries">Δὲν ὑπάρχουν πληκτρολόγια ἢ προγνωστικό κείμενο πρὸς ἐγκατάστασιν</string>
<string name="no_targets_to_install" comment="Notification when a package doesn't contain keyboards or dictionaries">Δὲν ὑπάρχουν πληκτρολόγια ἢ προγνώσεις κειμένων πρὸς ἐγκατάστασιν</string>
<!-- Context: KMP Package strings -->
<string name="no_associated_languages" comment="Notification when a keyboard package doesn't contain languages">Τὸ πακέτο πληκτρολογίου δὲν ἔχει σχετικὲς μὲ αὐτὸ γλῶσσες πρὸς ἐγκατάστασιν</string>
<!-- Context: KMP Package strings -->

View file

@ -27,7 +27,7 @@
<!-- Context: Button label -->
<string name="label_close" comment="Close a dialog">Κλεῖστε</string>
<!-- Context: Button label. Removed in Keyman 15 -->
<string name="label_close_keyman" comment="Close the Keyman application">Κλεῖστε τὸ Κῆμαν</string>
<string name="label_close_keyman" comment="Close the Keyman application">Κλεῖστε τὸ Keyman</string>
<!-- Context: Button label -->
<string name="label_forward" comment="Button to go forward">Προχωρῆστε</string>
<!-- Context: Button label -->
@ -53,11 +53,11 @@
<!-- Context: Keyboard Updates -->
<string name="confirm_download_keyboard" comment="Confirmation to download a keyboard update">Θὰ θέλατε νὰ κατεβάσετε τὴν τελευταία ἔκδοση αὐτοῦ τοῦ πληκτρολογίου;</string>
<!-- Context: Keyboard Updates -->
<string name="confirm_update" comment="Confirmation to update several resources">Θά θέλατε νὰ ἐνημερώσετε τώρα πληκτρολόγια καὶ λεξικά;</string>
<string name="confirm_update" comment="Confirmation to update several resources">Θ θέλατε νὰ ἐνημερώσετε τώρα πληκτρολόγια καὶ λεξικά;</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_updates_channel">Ἐνημερώσεις Πόρων</string>
<string name="keyboard_updates_channel">Ἐνημερώσεις</string>
<!-- Context: Keyboard Updates -->
<string name="keyboard_updates_available" comment="Notification when resource updates are available">Διαθέσιμες Ἐνημερώσεις Πόρων</string>
<string name="keyboard_updates_available" comment="Notification when resource updates are available">Διαθέσιμες Ἐνημερώσεις</string>
<!-- Context: Keyboard Updates -->
<string name="update_available" comment="Currently installed version of a resource with an available update">%1$s (Διαθέσιμη Ἐνημέρωση)</string>
<!-- Context: Keyboard Updates -->
@ -67,13 +67,13 @@
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="keyboard_version" comment="Label for keyboard version">Ἔκδοση πληκτρολογίου</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="help_link" comment="Label for help link">Σύνδεσμος βοηθείας</string>
<string name="help_link" comment="Label for help link">Βοήθεια</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="uninstall_keyboard" comment="Label for uninstalling keyboard">Ἀπεγκαταστῆστε πληκτρολόγιο</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="keyboard_picker_new_keyboard" comment="Mark a language name that's newly installed in keyboard list">[νέο] %1$s</string>
<!-- Context: Keyboard Info and Keyboard Settings -->
<string name="keyboard_qr_code" comment="QR Code description">Σαρῶστε αὐτὸν τὸν κωδικό γιὰ νὰ φορτώσετε\nαὐτὸ τὸ πληκτρολόγιο σὲ ἄλλη συσκευή</string>
<string name="keyboard_qr_code" comment="QR Code description">Σαρῶστε αὐτὸν τὸν κωδικ γιὰ νὰ φορτώσετε\nαὐτὸ τὸ πληκτρολόγιο σὲ ἄλλη συσκευή</string>
<!-- Context: Keyboard Help welcome.htm title -->
<string name="welcome_package" comment="Title to welcome.htm page (name and version)">Καλωσορίσατε στὸ %1$s</string>
<!-- Context: Keyboard app doesn't include FileProvider library needed to view help file -->
@ -81,22 +81,22 @@
<!-- Context: Fatal keyboard error. Will load default keyboard -->
<string name="fatal_keyboard_error" comment="Fatal keyboard error (keyboard ID::packageID for language). Will load default keyboard">Μοιραῖο σφάλμα πληκτρολογίου στὸ %1$s:%2$s γιὰ τὴν %3$s γλῶσσα. Φορτώνεται προεπιλεγμένο πληκτρολόγιο.</string>
<!-- Context: Fatal keyboard error. -->
<string name="fatal_keyboard_error_short" comment="Error in keyboard (keyboard ID::packageID for language)."> Error in keyboard %1$s:%2$s for %3$s language.</string>
<string name="fatal_keyboard_error_short" comment="Error in keyboard (keyboard ID::packageID for language).">Σφάλμα στὸ πληκτρολόγιο %1$s:%2$s γιὰ τὴν γλῶσσα \"%3$s\".</string>
<!-- Context: Query for associated dictionary -->
<string name="query_associated_model" comment="Check if there's an available dictionary to download">Ἔλεγχος συσχετισμένου λεξικοῦ πρὸς λῆψιν</string>
<string name="cannot_query_associated_model" comment="Cannot reach server to check if there's an available dictionary to download">Ἀδυναμία συνδέσεως μὲ τὸν διακομιστὴ Κῆμαν γιὰ τὸν ἔλεγχο συσχετισμένου λεξικοῦ πρὸς λῆψιν</string>
<string name="query_associated_model" comment="Check if there's an available dictionary to download">Ἀναζήτηση σχετικοῦ λεξικοῦ πρὸς μεταφόρτωσιν</string>
<string name="cannot_query_associated_model" comment="Cannot reach server to check if there's an available dictionary to download">Ἀδυναμία συνδέσεως μὲ τὸν διακομιστὴ Keyman γιὰ τὴν εὕρεση σχετικοῦ λεξικοῦ πρὸς μεταφόρτωσιν</string>
<!-- Context: Model Updates -->
<string name="confirm_download_model" comment="Confirmation to download a dictionary update">Θὰ θέλατε νὰ κατεβάσετε τὴν τελευταία ἔκδοση αὐτοῦ τοῦ λεξικοῦ;</string>
<!-- Context: No associated dictionary found -->
<string name="no_associated_model" comment="Confirmation there's no available dictionary to download">Δὲν ὑπάρχει λεξικὸ πρὸς λῆψιν</string>
<string name="no_associated_model" comment="Confirmation there's no available dictionary to download">Δὲν ὑπάρχει λεξικὸ πρὸς μεταφόρτωσιν</string>
<!-- Context: Model Updates -->
<string name="catalog_unavailable" comment="Notification that the cloud resource catalog can't be updated">Μὴ διαθέσιμος κατάλογος πόρων</string>
<!-- Context: Background download messages-->
<string name="catalog_download_start_in_background" comment="Notification that the resource catalog update will begin">Ἔχει ξεκινήσει ἐνημέρωση καταλόγου στὸ παρασκήνιο</string>
<!-- Context: Background download messages-->
<string name="catalog_download_is_running_in_background" comment="Notification that the resource catalog update is still downloading">λήψη τοῦ καταλόγου συνεχίζεται· παρακαλοῦμε ξαναδοκιμάστε σὲ λίγο!</string>
<string name="catalog_download_is_running_in_background" comment="Notification that the resource catalog update is still downloading">μεταφόρτωση τοῦ καταλόγου συνεχίζεται· παρακαλοῦμε ξαναδοκιμάστε σὲ λίγο!</string>
<!-- Context: Background download messages-->
<string name="progress_message_checking_resource_is_running" comment="Progress notification that the check for a resource is still running ">Ἔλεγχος πόρου σὲ ἐξέλιξη</string>
<string name="progress_message_checking_resource_is_running" comment="Progress notification that the check for a resource is still running ">Ἀναζήτηση πόρου σὲ ἐξέλιξη</string>
<!-- Context: Background download messages-->
<string name="keyboard_download_start_in_background" comment="Notification that a keyboard download has started">Ἡ λήψη τοῦ πληκτρολογίου ἔχει ξεκινήσει στὸ παρασκήνιο</string>
<!-- Context: Background download messages-->
@ -112,7 +112,7 @@
<!-- Context: Background download messages -->
<string name="download_failed" comment="Notification that a download failed">Ἡ λήψη ἀπέτυχε</string>
<!-- Context: Background download messages -->
<string name="failed_to_retrieve_file" comment="Failed to retrieve downloaded file">Ἀποτυχία ἀνακτήσεως ληφθέντος ἀρχείου</string>
<string name="failed_to_retrieve_file" comment="Failed to retrieve downloaded file">Ἀποτυχία ἀνακλήσεως ληφθέντος ἀρχείου</string>
<!-- Context: General Updates -->
<string name="update_check_unavailable" comment="Error message when a Keyman server can't be reached">Ἀποτυχία προσβάσεως στὸν διακομιστή!</string>
<!-- Context: General Updates -->
@ -120,11 +120,11 @@
<!-- Context: General Updates -->
<string name="update_failed" comment="Notification that a resource update failed">Ἕνας ἢ περισσότεροι πόροι ἀπέτυχαν νὰ ἐνημερωθοῦν!</string>
<!-- Context: General Updates. Removed in Keyman 17 -->
<string name="update_success" comment="Notification that a resource update successfully updated">Οἱ πόροι ἐνημερώθηκαν ἐπιτυχῶς!</string>
<string name="update_success" comment="Notification that a resource update successfully updated">Ὅλες οἱ ἐνημερώσεις ὁλοκληρώθηκαν ἐπιτυχῶς!</string>
<!-- Context: Model Info -->
<string name="model_version" comment="Title for a dictionary version">Ἔκδοση λεξικοῦ</string>
<!-- Context: Model Info -->
<string name="uninstall_model" comment="Label to uninstall a dictionary">Ἀπεγκαταστῆτε λεξικό</string>
<string name="uninstall_model" comment="Label to uninstall a dictionary">Ἀπεγκαταστῆστε λεξικό</string>
<!-- Context: Model Info -->
<string name="confirm_delete_model" comment="Confirmation to delete a dictionary">Θὰ θέλατε νὰ διαγράψετε αὐτὸ τὸ λεξικό;</string>
<!-- Context: Model Deleted -->
@ -136,16 +136,16 @@
<!-- Context: Language Settings menu strings -->
<string name="enable_corrections" comment="Enable corrections from the suggestion banner">Ἐνεργοποιῆστε τὶς διορθώσεις</string>
<!-- Context: Language Settings menu strings -->
<string name="enable_predictions" comment="Enable predictions from the suggestion banner">Ἐνεργοποιῆστε προβλέψεις</string>
<string name="enable_predictions" comment="Enable predictions from the suggestion banner">Ἐνεργοποιῆστε προβλέψεις κειμένου</string>
<!-- Context: Language Settings menu strings -->
<string name="model_label">Λεξικά</string>
<string name="model_label">Λεξικό</string>
<plurals name="model_count">
<item quantity="one">Λεξικό</item>
<item quantity="other">Λεξικά</item>
</plurals>
<!-- Context: Language Settings menu substring - Check for available dictionary -->
<string name="check_available_model" comment="Check for available dictionary">Ἔλεγχος διαθεσίμου λεξικοῦ</string>
<string name="check_model_online" comment="Check for dictionaries online">Ἔλεγχος λεξικῶν ὀνλάϊν</string>
<string name="check_available_model" comment="Check for available dictionary">Ἀναζήτηση διαθεσίμου λεξικοῦ</string>
<string name="check_model_online" comment="Check for dictionaries online">Ἀναζήτηση λεξικῶν ὀνλάϊν</string>
<!-- Context: Language Settings menu strings -->
<string name="model_info_header" comment="Dictionary name">Λεξικό: %1$s</string>
<!-- Context: Language Settings menu strings -->

36
build.sh Executable file
View file

@ -0,0 +1,36 @@
#!/usr/bin/env bash
## START STANDARD BUILD SCRIPT INCLUDE
# adjust relative paths as necessary
THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
. "${THIS_SCRIPT%/*}/resources/build/builder.inc.sh"
## END STANDARD BUILD SCRIPT INCLUDE
builder_describe "Keyman -- all projects" \
":common" \
":core" \
":android" \
":ios" \
":linux" \
":mac" \
":web" \
":windows" \
":developer" \
clean \
configure \
build \
test \
install \
publish
builder_describe_platform \
:android android-studio \
:ios mac \
:linux linux \
:mac mac \
:windows win
builder_parse "$@"
#-------------------------------------------------------------------------------------------------------------------
builder_run_child_actions clean configure build test publish install

View file

@ -16,6 +16,11 @@ builder_describe "Keyman common and resources modules" \
build \
test
builder_describe_platform \
:linux linux \
:mac mac \
:windows win
builder_parse "$@"
#-------------------------------------------------------------------------------------------------------------------

389
common/cpp/km_u16.cpp Normal file
View file

@ -0,0 +1,389 @@
/*
* Keyman is copyright (C) SIL International. MIT License.
*
* std::u16string functions and string conversion utility functions
*/
#include <stdarg.h>
#include "utfcodec.hpp"
#include "km_u16.h"
/** string <- wstring
* @brief Obtain a std::string from a std::wstring
* @param wstr the std::wstring to be converted
* @return a std::string
*/
std::string string_from_wstring(std::wstring const wstr) {
return convert<wchar_t, char>((const std::wstring)wstr);
}
/** wstring <- string
* @brief Obtain a std::wstring from a std::string
* @param str the std::string to be converted
* @return a std::wstring
*/
std::wstring wstring_from_string(std::string const str) {
return convert<char, wchar_t>((const std::string)str);
}
/** u16string <- string
* @brief Obtain a std::u16string from a std::string
* @param str the std::string to be converted
* @return a std::u16string
*/
std::u16string u16string_from_string(std::string const str) {
return convert<char, char16_t>((const std::string)str);
}
/** string <- u16string
* @brief Obtain a std::string from a std::u16string
* @param str16 the std::u16string to be converted
* @return a std::string
*/
std::string string_from_u16string(std::u16string const str16) {
return convert<char16_t, char>((const std::u16string)str16);
}
/** wstring <- u16string
* @brief Obtain a std::wstring from a std::u16string
* @param str16 the std::u16string to be converted
* @return a std::wstring
*/
std::wstring wstring_from_u16string(std::u16string const str16) {
return convert<char16_t, wchar_t>((const std::u16string)str16);
}
/** u16string <- wstring
* @brief Obtain a std::u16string from a std::wstring
* @param wstr the std::wstring to be converted
* @return a std::u16string
*/
std::u16string u16string_from_wstring(std::wstring const wstr) {
return convert<wchar_t, char16_t>((const std::wstring)wstr);
}
/**
* @brief Convert pointer to wchar_t to pointer to char16_t and copy sz elements into dst
* @param dst destination
* @param sz nr of characters to be copied
* @param fmt source to convert and copy
*/
void u16sprintf(KMX_WCHAR* dst, const size_t sz, const wchar_t* fmt, ...) {
wchar_t* wbuf = new wchar_t[sz];
va_list args;
va_start(args, fmt);
vswprintf(wbuf, sz, fmt, args);
va_end(args);
std::u16string u16str = u16string_from_wstring(wbuf);
u16ncpy(dst, u16str.c_str(), sz);
delete[] wbuf;
}
/**
* @brief Convert u16string to long integer
* @param str u16string beginning with the representation of an integral number.
* @param endptr Reference to the next character in str
* @param base Numerical base (radix) that determines the valid characters and their interpretation
* @return a long
*/
long int u16tol(const KMX_WCHAR* str, KMX_WCHAR** endptr, int base) {
auto s = string_from_u16string(str);
char* t;
long int result = strtol(s.c_str(), &t, base);
if (endptr != nullptr)
*endptr = (KMX_WCHAR*)str + (t - s.c_str());
return result;
}
std::string toHex(int num1) {
if (num1 == 0)
return "0";
int num = num1;
std::string s = "";
while (num) {
int temp = num % 16;
if (temp <= 9)
s += (48 + temp);
else
s += (87 + temp);
num = num / 16;
}
std::reverse(s.begin(), s.end());
return s;
}
/**
* @brief Append max characters from u16string
* @param dst Pointer to the destination array
* @param src u16string to be appended
* @param max Maximum number of characters to be appended.
* @return Pointer to dst
*/
const KMX_WCHAR* u16ncat(KMX_WCHAR* dst, const KMX_WCHAR* src, size_t max) {
KMX_WCHAR* o = dst;
dst = (KMX_WCHAR*)u16chr(dst, 0);
// max -= (dst-o);
while (*src && max > 0) {
*dst++ = *src++;
max--;
}
if (max > 0)
*dst = 0;
return o;
}
/**
* @brief Find last '/' or '\\' in an array of char16_t
* @param name Pointer to the source
* @return Pointer to the last slash/backslash
*/
const KMX_WCHAR* u16rchr_slash(KMX_WCHAR const* name) {
const KMX_WCHAR* cp = NULL;
cp = u16rchr(name, '\\');
if (cp == NULL)
cp = u16rchr(name, '/');
return cp;
}
/**
* @brief Find last '/' or '\\' in an array of char
* @param name Pointer to the source
* @return Pointer to the last slash/backslash
*/
KMX_CHAR* strrchr_slash(KMX_CHAR* name) {
KMX_CHAR* cp = NULL;
cp = strrchr(name, '\\');
if (cp == NULL)
cp = strrchr(name, '/');
return cp;
}
/**
* @brief Locate last occurrence of character in u16string
* @param p Pointer to the source
* @param ch The character to be found
* @return A pointer to the last occurrence of character in u16str
*/
const KMX_WCHAR* u16rchr(const KMX_WCHAR* p, KMX_WCHAR ch) {
const KMX_WCHAR* p_end = p + u16len(p) - 1;
if (ch == '\0')
return p_end + 1;
while (p_end >= p) {
if (*p_end == ch)
return p_end;
p_end--;
}
return NULL;
}
/**
* @brief Locate first occurrence of character in u16string
* @param p Pointer to the source
* @param ch The character to be found
* @return A pointer to the first occurrence of character in u16str
*/
const KMX_WCHAR* u16chr(const KMX_WCHAR* p, KMX_WCHAR ch) {
while (*p) {
if (*p == ch)
return p;
p++;
}
return ch == 0 ? p : NULL;
}
/**
* @brief Copy the u16string pointed to by scr into the array pointed to by dst
* @param dst Pointer to the destination
* @param src Pointer to the source to be copied
* @return Pointer to dst
*/
const KMX_WCHAR* u16cpy(KMX_WCHAR* dst, const KMX_WCHAR* src) {
KMX_WCHAR* o = dst;
while (*src) {
*dst++ = *src++;
}
*dst = 0;
return o;
}
/**
* @brief Copy max characters of the u16string pointed to by src into the array pointed by dst
* @param dst Pointer to the destination
* @param src Pointer to the source to be copied
* @param max Maximum number of characters to be copied
* @return Pointer to dst
*/
const KMX_WCHAR* u16ncpy(KMX_WCHAR* dst, const KMX_WCHAR* src, size_t max) {
KMX_WCHAR* o = dst;
while (*src && max > 0) {
*dst++ = *src++;
max--;
}
if (max > 0) {
*dst = 0;
}
return o;
}
/**
* @brief Return the length of the u16string str
* @param p Pointer to the source
* @return The length of u16string
*/
size_t u16len(const KMX_WCHAR* p) {
int i = 0;
while (*p) {
p++;
i++;
}
return i;
}
/**
* @brief Compare two u16strings
* @param p Pointer one u16string
* @param q Pointer another u16string
* @return 0 if strings are equal
* ! = 0 if unequal
*/
int u16cmp(const KMX_WCHAR* p, const KMX_WCHAR* q) {
while (*p && *q) {
if (*p != *q)
return *p - *q;
p++;
q++;
}
return *p - *q;
}
/**
* @brief Case insensitive comparison of up to count characters in two strings
* @param p Pointer one u16string
* @param q Pointer another u16string
* @param count Maximum number of characters to compare
* @return 0 if strings are equal
* ! = 0 if unequal
*/
int u16nicmp(const KMX_WCHAR* p, const KMX_WCHAR* q, size_t count) {
while (*p && *q && count) {
if (toupper(*p) != toupper(*q))
return *p - *q;
p++;
q++;
count--;
}
if (count)
return *p - *q;
return 0;
}
/**
* @brief Case insensitive comparison of two strings
* @param p Pointer one u16string
* @param q Pointer another u16string
* @return 0 if strings are equal
* ! = 0 if unequal
*/
int u16icmp(const KMX_WCHAR* p, const KMX_WCHAR* q) {
while (*p && *q) {
if (toupper(*p) != toupper(*q))
return *p - *q;
p++;
q++;
}
return *p - *q;
}
/**
* @brief Comparison of up to count characters in two strings
* @param p Pointer one u16string
* @param q Pointer another u16string
* @param count Maximum number of characters to compare
* @return 0 if strings are equal
* ! = 0 if unequal
*/
int u16ncmp(const KMX_WCHAR* p, const KMX_WCHAR* q, size_t count) {
while (*p && *q && count) {
if (*p != *q)
return *p - *q;
p++;
q++;
count--;
}
if (count)
return *p - *q;
return 0;
}
/**
* @brief Split u16string into tokens
* @param p Pointer to u16string to parse.
* @param ch the delimiter character
* @param ctx the remaining string after the first delimiter
* @return Pointer to the first token in p
*/
KMX_WCHAR* u16tok(KMX_WCHAR* p, const KMX_WCHAR ch, KMX_WCHAR** ctx) {
if (!p) {
p = *ctx;
if (!p)
return NULL;
}
KMX_WCHAR* q = p;
while (*q && *q != ch) {
q++;
}
if (*q) {
*q = 0;
q++;
while (*q == ch)
q++;
*ctx = q;
} else {
*ctx = NULL;
}
return *p ? p : NULL;
}
/**
* @brief Split u16string into tokens
* @param p Pointer to u16string to parse.
* @param delimiters an array of delimiter characters
* @param ctx the remaining string after the first delimiter
* @return Pointer to the first token in p
*/
KMX_WCHAR* u16tok(KMX_WCHAR* p, const KMX_WCHAR* delimiters, KMX_WCHAR** ctx) {
if (!p) {
p = *ctx;
if (!p)
return NULL;
}
KMX_WCHAR* q = p;
while (*q && !u16chr(delimiters, *q)) {
q++;
}
if (*q) {
*q = 0;
q++;
while (*q && u16chr(delimiters, *q))
q++;
*ctx = q;
} else {
*ctx = NULL;
}
return *p ? p : NULL;
}
/**
* @brief Convert a u16string to a double
* @param str Pointer to u16string
* @return double value equivalent to the string
*/
double u16tof(KMX_WCHAR* str16) {
char* pEnd;
std::string str = string_from_u16string(str16);
return strtof(str.c_str(), &pEnd);
}

76
common/include/km_u16.h Normal file
View file

@ -0,0 +1,76 @@
#pragma once
#include <string>
#include <cstring>
#include <km_types.h>
/** @brief Obtain a std::string from a std::wstring */
std::string string_from_wstring(std::wstring const wstr);
/** @brief Obtain a std::wstring from a std::string */
std::wstring wstring_from_string(std::string const str);
/** @brief Obtain a std::u16string from a std::string */
std::u16string u16string_from_string(std::string const str);
/** @brief Obtain a std::string from a std::u16string */
std::string string_from_u16string(std::u16string const str16);
/** @brief Obtain a std::wstring from a std::u16string */
std::wstring wstring_from_u16string(std::u16string const str16);
/** @brief Obtain a std::u16string from a std::wstring */
std::u16string u16string_from_wstring(std::wstring const wstr);
/** @brief Convert pointer to wchar_t to pointer to char16_t and copy sz elements into dst */
void u16sprintf(KMX_WCHAR* dst, const size_t sz, const wchar_t* fmt, ...);
/** @brief Return the length of the u16string str */
size_t u16len(const KMX_WCHAR* p);
/** @brief Compare two u16strings */
int u16cmp(const KMX_WCHAR* p, const KMX_WCHAR* q);
/** @brief Case insensitive comparison of two strings */
int u16icmp(const KMX_WCHAR* p, const KMX_WCHAR* q);
/** @brief Comparison of up to count characters in two strings */
int u16ncmp(const KMX_WCHAR* p, const KMX_WCHAR* q, size_t count);
/** @brief Case insensitive comparison of up to count characters in two strings */
int u16nicmp(const KMX_WCHAR* p, const KMX_WCHAR* q, size_t count);
/** @brief Copy max characters of the u16string pointed to by src into the array pointed to by dst */
const KMX_WCHAR* u16ncpy(KMX_WCHAR* dst, const KMX_WCHAR* src, size_t max);
/** @brief Copy the u16string pointed to by src into the array pointed to by dst */
const KMX_WCHAR* u16cpy(KMX_WCHAR* dst, const KMX_WCHAR* src);
/** @brief Locate last occurrence of character in u16string */
const KMX_WCHAR* u16rchr(const KMX_WCHAR* p, KMX_WCHAR ch);
/** @brief Locate first occurrence of character in u16string */
const KMX_WCHAR* u16chr(const KMX_WCHAR* p, KMX_WCHAR ch);
/** @brief Append max characters from u16string */
const KMX_WCHAR* u16ncat(KMX_WCHAR* dst, const KMX_WCHAR* src, size_t max);
/** @brief Split u16string into tokens */
KMX_WCHAR* u16tok(KMX_WCHAR* p, const KMX_WCHAR ch, KMX_WCHAR** ctx);
/** @brief Split u16string into tokens */
KMX_WCHAR* u16tok(KMX_WCHAR* p, const KMX_WCHAR* delimiters, KMX_WCHAR** ctx);
/** @brief Convert a u16string to a double */
long int u16tol(const KMX_WCHAR* str, KMX_WCHAR** endptr, int base);
/** @brief Convert a u16string to a double */
double u16tof(KMX_WCHAR* str);
/** @brief find last '/' or '\\' in an array of char */
KMX_CHAR* strrchr_slash(KMX_CHAR* Name);
/** @brief find last '/' or '\\' in an array of char16_t */
const KMX_WCHAR* u16rchr_slash(KMX_WCHAR const* Name);
std::string toHex(int num1);

View file

@ -16,7 +16,7 @@ BUNDLE_CMD="node ${KEYMAN_ROOT}/common/web/es-bundling/build/common-bundle.mjs"
builder_describe \
"Compiles the web-oriented utility function module." \
"@/common/web/recorder test" \
"@/web/src/tools/testing/recorder-core test" \
"@/common/web/keyman-version" \
"@/common/web/es-bundling" \
"@/common/web/types" \

View file

@ -200,11 +200,9 @@ describe('ModelCompositor', function() {
// secondary corrections may be found
// - It's possible to interrupt "too late" if the correction search proceeds quickly,
// returning a standard full set.
const terminatedSuggestions = await firstPredict;
await firstPredict;
const finalSuggestions = await secondPredict;
if(terminatedSuggestions.length > 0) {
assert.isOk(terminatedSuggestions.find((entry) => entry.displayAs == 'a'));
}
assert.isOk(finalSuggestions.find((entry) => entry.displayAs == 'applied'));
});
});

View file

@ -1,22 +0,0 @@
{
"extends": "../tsconfig.kmw-main-base.json",
"compilerOptions": {
"types": ["node"],
"baseUrl": "./",
"outDir": "build/obj/",
"tsBuildInfoFile": "build/obj/tsconfig.tsbuildinfo",
"rootDir": "./src"
},
"include": [
"src/**/*.ts"
],
"references": [
{ "path": "../keyman-version" },
{ "path": "../utils/" },
{ "path": "../keyboard-processor/" },
{ "path": "../lm-message-types" }
],
}

View file

@ -73,40 +73,25 @@ function compile_schemas() {
node tools/schema-bundler.js
}
function copy_cldr_imports() {
# Store CLDR imports
# load all versions that have a cldr_info.json
for CLDR_INFO_PATH in "$KEYMAN_ROOT/resources/standards-data/ldml-keyboards/"*/cldr_info.json
do
# TODO-LDML: developer/src/inst/download.in.mak needs these also...
CLDR_PATH=$(dirname "$CLDR_INFO_PATH")
CLDR_VER=$(basename "$CLDR_PATH")
mkdir -p "$THIS_SCRIPT_PATH/build/src/import/$CLDR_VER"
# TODO-LDML: When these are copied, the DOCTYPE will break due to the wrong path. We don't use the DTD so it should be OK.
cp "$CLDR_INFO_PATH" "$CLDR_PATH/import/"*.xml "$THIS_SCRIPT_PATH/build/src/import/$CLDR_VER/"
done
}
function do_configure() {
compile_schemas
verify_npm_setup
}
function do_build() {
copy_cldr_imports
tsc --build
}
function do_test() {
eslint .
tsc --build test
c8 --skip-full --reporter=lcov --reporter=text mocha "${builder_extra_params[@]}"
readonly C8_THRESHOLD=50
c8 -skip-full --reporter=lcov --reporter=text --lines $C8_THRESHOLD --statements $C8_THRESHOLD --branches $C8_THRESHOLD --functions $C8_THRESHOLD mocha "${builder_extra_params[@]}"
builder_echo warning "Coverage thresholds are currently $C8_THRESHOLD%, which is lower than ideal."
builder_echo warning "Please increase threshold in build.sh as test coverage improves."
}
#-------------------------------------------------------------------------------------------------------------------
builder_run_action clean rm -rf ./build/ ./tsconfig.tsbuildinfo
builder_run_action configure do_configure
builder_run_action build do_build
builder_run_action build tsc --build
builder_run_action test do_test
builder_run_action publish builder_publish_npm

View file

@ -31,24 +31,17 @@
"dependencies": {
"@keymanapp/ldml-keyboard-constants": "*",
"@keymanapp/keyman-version": "*",
"restructure": "3.0.1",
"semver": "^7.5.2",
"sax": ">=0.6.0",
"xmlbuilder": "~11.0.0"
"restructure": "3.0.1"
},
"devDependencies": {
"@types/chai": "^4.1.7",
"@types/git-diff": "^2.0.3",
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"@types/semver": "^7.3.12",
"@types/xml2js": "^0.4.5",
"ajv": "^8.12.0",
"ajv-cli": "^5.0.0",
"ajv-formats": "^2.1.1",
"c8": "^7.12.0",
"chalk": "^2.4.2",
"git-diff": "^2.0.6",
"hexy": "^0.3.4",
"mocha": "^8.4.0",
"typescript": "^5.4.5"

View file

@ -1,8 +1,9 @@
import { constants } from '@keymanapp/ldml-keyboard-constants';
import { DependencySections, StrsItem, UsetItem } from './kmx-plus.js';
import { ElementParser, ElementSegment, ElementType } from '../ldml-keyboard/pattern-parser.js';
import { MATCH_HEX_ESCAPE } from '../util/consts.js';
import { unescapeOneQuadString } from '../util/util.js';
import { ElementParser, ElementSegment, ElementType } from '../../ldml-keyboard/pattern-parser.js';
import { util } from '@keymanapp/common-types';
import MATCH_HEX_ESCAPE = util.MATCH_HEX_ESCAPE;
import unescapeOneQuadString = util.unescapeOneQuadString;
export enum ElemElementFlags {
none = 0,

View file

@ -1,12 +1,18 @@
import { constants } from '@keymanapp/ldml-keyboard-constants';
import * as r from 'restructure';
import { ElementString } from './element-string.js';
import { ListItem } from './string-list.js';
import { isOneChar, toOneChar, unescapeString, escapeStringForRegex } from '../util/util.js';
import { KMXFile } from './kmx.js';
import { UnicodeSetParser, UnicodeSet } from '@keymanapp/common-types';
import { VariableParser } from '../ldml-keyboard/pattern-parser.js';
import { MarkerParser } from '../ldml-keyboard/pattern-parser.js';
import { ListItem } from '../../ldml-keyboard/string-list.js';
import { util } from '@keymanapp/common-types';
import { KMX } from '@keymanapp/common-types';
import { UnicodeSetParser, UnicodeSet } from '../../ldml-keyboard/unicodeset-parser-api.js';
import { VariableParser } from '../../ldml-keyboard/pattern-parser.js';
import { MarkerParser } from '../../ldml-keyboard/pattern-parser.js';
import isOneChar = util.isOneChar;
import toOneChar = util.toOneChar;
import unescapeString = util.unescapeString;
import escapeStringForRegex = util.escapeStringForRegex;
import KMXFile = KMX.KMXFile;
// Implementation of file structures from /core/src/ldml/C7043_ldml.md
// Writer in kmx-builder.ts

View file

@ -1,5 +1,5 @@
import { OrderedStringList } from '../ldml-keyboard/pattern-parser.js';
import { DependencySections, StrsItem, StrsOptions } from './kmx-plus.js';
import { OrderedStringList } from './pattern-parser.js';
import { DependencySections, StrsItem, StrsOptions } from '../kmx/kmx-plus/kmx-plus.js';
/**
* A single entry in a ListItem.

View file

@ -1,55 +1,19 @@
export * as KMX from './kmx/kmx.js';
export * as KMXPlus from './kmx/kmx-plus.js';
export { default as KMXBuilder } from './kmx/kmx-builder.js';
export { KmxFileReader, KmxFileReaderError } from './kmx/kmx-file-reader.js';
export * as KeymanTargets from './kmx/keyman-targets.js';
export * as VisualKeyboard from './kvk/visual-keyboard.js';
export { default as KMXPlusBuilder} from './kmx/kmx-plus-builder/kmx-plus-builder.js';
export { default as KvkFileReader } from './kvk/kvk-file-reader.js';
export { default as KvksFileReader } from './kvk/kvks-file-reader.js';
export { default as KvkFileWriter } from './kvk/kvk-file-writer.js';
export { default as KvksFileWriter } from './kvk/kvks-file-writer.js';
export * as KvkFile from './kvk/kvk-file.js';
export * as KvksFile from './kvk/kvks-file.js';
export * as LDMLKeyboard from './ldml-keyboard/ldml-keyboard-xml.js';
export { LDMLKeyboardTestDataXMLSourceFile } from './ldml-keyboard/ldml-keyboard-testdata-xml.js';
export { UnicodeSetParser, UnicodeSet } from './ldml-keyboard/unicodeset-parser-api.js';
export { VariableParser, MarkerParser } from './ldml-keyboard/pattern-parser.js';
export { LDMLKeyboardXMLSourceFileReader, LDMLKeyboardXMLSourceFileReaderOptions } from './ldml-keyboard/ldml-keyboard-xml-reader.js';
export { USVirtualKeyCodes } from './consts/virtual-key-constants.js';
export * as Constants from './consts/virtual-key-constants.js';
export { ModifierKeyConstants } from './consts/modifier-key-constants.js';
export { defaultCompilerOptions, CompilerBaseOptions, CompilerCallbacks, CompilerOptions, CompilerEvent, CompilerErrorNamespace,
CompilerErrorSeverity, CompilerPathCallbacks, CompilerFileSystemCallbacks, CompilerCallbackOptions,
CompilerError, CompilerMessageSpec, CompilerMessageSpecWithException, compilerErrorSeverity, CompilerErrorMask, CompilerFileCallbacks, compilerErrorSeverityName,
compilerErrorFormatCode, CompilerMessageDef,
compilerLogLevelToSeverity, CompilerLogLevel, compilerEventFormat, ALL_COMPILER_LOG_LEVELS,
ALL_COMPILER_LOG_FORMATS, CompilerLogFormat,
CompilerMessageOverride,
CompilerMessageOverrideMap,
KeymanCompilerArtifact,
KeymanCompilerArtifactOptional,
KeymanCompilerArtifacts,
KeymanCompilerResult,
KeymanCompiler
} from './util/compiler-interfaces.js';
export { CommonTypesMessages } from './util/common-events.js';
export * as TouchLayout from './keyman-touch-layout/keyman-touch-layout-file.js';
export { TouchLayoutFileReader } from './keyman-touch-layout/keyman-touch-layout-file-reader.js';
export { TouchLayoutFileWriter, TouchLayoutFileWriterOptions } from './keyman-touch-layout/keyman-touch-layout-file-writer.js';
export * as KPJ from './kpj/kpj-file.js';
export { KPJFileReader } from './kpj/kpj-file-reader.js';
export { KeymanDeveloperProject, KeymanDeveloperProjectFile, KeymanDeveloperProjectType, } from './kpj/keyman-developer-project.js';
export * as KpsFile from './package/kps-file.js';
export * as KmpJsonFile from './package/kmp-json-file.js';
export { Uni_IsSurrogate1, Uni_IsSurrogate2 } from './util/util.js';
@ -60,4 +24,8 @@ export * as KeymanFileTypes from './util/file-types.js';
export * as Schemas from './schemas.js';
export * as SchemaValidators from './schema-validators.js';
export * as xml2js from './deps/xml2js/xml2js.js';
export * as KMXPlus from './kmx/kmx-plus/kmx-plus.js';
// TODO: these exports are really not well named
export { UnicodeSetParser, UnicodeSet } from './ldml-keyboard/unicodeset-parser-api.js';
export { VariableParser, MarkerParser } from './ldml-keyboard/pattern-parser.js';
export { ElementString } from './kmx/kmx-plus/element-string.js';

View file

@ -1,5 +1,4 @@
import * as path from "path";
import * as fs from "fs";
import { fileURLToPath } from "url";
/**
@ -12,26 +11,3 @@ import { fileURLToPath } from "url";
export function makePathToFixture(...components: string[]): string {
return fileURLToPath(new URL(path.join('..', '..', '..', 'test', 'fixtures', ...components), import.meta.url));
}
export function loadFile(filename: string | URL): Buffer {
return fs.readFileSync(filename);
}
export function resolveFilename(baseFilename: string, filename: string) {
const basePath =
baseFilename.endsWith('/') || baseFilename.endsWith('\\') ?
baseFilename :
path.dirname(baseFilename);
// Transform separators to platform separators -- we are agnostic
// in our use here but path prefers files may use
// either / or \, although older kps files were always \.
if(path.sep == '/') {
filename = filename.replace(/\\/g, '/');
} else {
filename = filename.replace(/\//g, '\\');
}
if(!path.isAbsolute(filename)) {
filename = path.resolve(basePath, filename);
}
return filename;
}

View file

@ -9,7 +9,6 @@
"preserveConstEnums": true,
},
"include": [
"src/deps/xml2js/*.js",
"src/**/*.ts",
"src/schemas/*.mjs", // Import the validators
],

View file

@ -20,7 +20,7 @@ if hotdoc.found()
deps = files(
'../include/keyman/keyman_core_api.h',
'../src/jsonpp.hpp',
'../src/utfcodec.hpp'
'../../common/cpp/utfcodec.hpp'
)
docs = custom_target('docs',

View file

@ -126,7 +126,7 @@ core_files = files(
'keyboard.cpp',
'state.cpp',
'jsonpp.cpp',
'utfcodec.cpp',
'../../common/cpp/utfcodec.cpp',
)
mock_files = files(

View file

@ -10,7 +10,10 @@
cmpfiles = ['-c', 'import sys; a = open(sys.argv[1], \'r\').read(); b = open(sys.argv[2], \'r\').read(); exit(not (a==b))']
stnds = join_paths(meson.current_source_dir(), 'standards')
libsrc = include_directories(join_paths('../', 'src'))
libsrc = include_directories(
'../src',
'../../common/include'
)
# kmx_test_source is required for linux builds, so always enable it even when we
# disable all other tests

View file

@ -5,6 +5,6 @@
#
e = executable('utftest', 'utftest.cpp',
objects: lib.extract_objects('utfcodec.cpp'),
objects: lib.extract_objects('../../common/cpp/utfcodec.cpp'),
include_directories: [libsrc])
test('utftest', e)

View file

@ -127,6 +127,7 @@ files:
languages_mapping:
osx_code:
pt-PT: pt-PT.lproj
el-polyton: el.lproj
- source: /mac/Keyman4MacIM/Keyman4MacIM/KMConfiguration/en.lproj/preferences.strings
dest: /mac/app/preferences.strings
@ -134,6 +135,7 @@ files:
languages_mapping:
osx_code:
pt-PT: pt-PT.lproj
el-polyton: el.lproj
- source: /mac/Keyman4MacIM/Keyman4MacIM/KMInfoWindow/en.lproj/KMInfoWindowController.strings
dest: /mac/app/KMInfoWindowController.strings
@ -141,6 +143,7 @@ files:
languages_mapping:
osx_code:
pt-PT: pt-PT.lproj
el-polyton: el.lproj
- source: /mac/Keyman4MacIM/Keyman4MacIM/KMKeyboardHelpWindow/en.lproj/KMKeyboardHelpWindowController.strings
dest: /mac/app/KMKeyboardHelpWindowController.strings
@ -148,6 +151,7 @@ files:
languages_mapping:
osx_code:
pt-PT: pt-PT.lproj
el-polyton: el.lproj
- source: /mac/Keyman4MacIM/Keyman4MacIM/en.lproj/Localizable.strings
dest: /mac/app/Localizable.strings
@ -155,6 +159,7 @@ files:
languages_mapping:
osx_code:
pt-PT: pt-PT.lproj
el-polyton: el.lproj
- source: /mac/Keyman4MacIM/Keyman4MacIM/en.lproj/MainMenu.strings
dest: /mac/app/MainMenu.strings
@ -162,6 +167,7 @@ files:
languages_mapping:
osx_code:
pt-PT: pt-PT.lproj
el-polyton: el.lproj
# crowdin parameters descriptions:

View file

@ -0,0 +1 @@
The presence of this file tells CI that we can build Developer on mac and linux, as of 18.0. We will be able to remove this file in 19.0.

View file

@ -42,11 +42,29 @@ builder_describe \
"--npm-publish+ For publish, do a npm publish, not npm pack (only for CI)" \
"--dry-run,-n+ Don't actually publish anything to external endpoints, just dry run"
builder_describe_platform \
:ext win,delphi \
:kmanalyze win \
:kmdbrowserhost win,delphi \
:kmdecomp win \
:kmconvert win,delphi \
:samples win \
:server win \
:setup win,delphi \
:test win,delphi \
:tike win,delphi \
:inst win,delphi
# TODO: in future :server could be built on other platforms, potentially, but it
# has addons that are Windows-specific currently
builder_parse "$@"
#-------------------------------------------------------------------------------------------------------------------
source "$KEYMAN_ROOT/resources/build/win/environment.inc.sh"
if [[ $BUILDER_OS == win ]]; then
source "$KEYMAN_ROOT/resources/build/win/environment.inc.sh"
fi
#
# We want to do some checks before we head down the long publish path

View file

@ -11,5 +11,8 @@ builder_describe \
":delphi Delphi components" \
":web Web components"
builder_describe_platform \
:delphi win,delphi
builder_parse "$@"
builder_run_child_actions clean configure build test

View file

@ -8,7 +8,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh"
builder_describe "Keyman Developer unit test helpers" \
"@/common/web/types" \
"@/developer/src/common/web/utils" \
clean configure build test
builder_describe_outputs \

View file

@ -1,6 +1,6 @@
import * as fs from 'fs';
import * as path from 'path';
import { CompilerEvent, CompilerCallbacks, CompilerPathCallbacks, CompilerFileSystemCallbacks, CompilerError } from '@keymanapp/common-types';
import { CompilerEvent, CompilerCallbacks, CompilerPathCallbacks, CompilerFileSystemCallbacks, CompilerError } from '@keymanapp/developer-utils';
export { verifyCompilerMessagesObject } from './verifyCompilerMessagesObject.js';
/**

View file

@ -17,6 +17,6 @@
},
"license": "MIT",
"dependencies": {
"@keymanapp/common-types": "*"
"@keymanapp/developer-utils": "*"
}
}

View file

@ -1,4 +1,4 @@
import { CompilerError, CompilerErrorMask } from '@keymanapp/common-types';
import { CompilerError, CompilerErrorMask } from '@keymanapp/developer-utils';
import {assert, expect} from 'chai';
//

View file

@ -21,20 +21,42 @@ builder_describe "Build Keyman Developer web utility module" \
builder_describe_outputs \
configure /node_modules \
build /developer/src/common/web/utils/build/index.js
build /developer/src/common/web/utils/build/src/index.js
builder_parse "$@"
#-------------------------------------------------------------------------------------------------------------------
function copy_cldr_imports() {
# Store CLDR imports
# load all versions that have a cldr_info.json
for CLDR_INFO_PATH in "$KEYMAN_ROOT/resources/standards-data/ldml-keyboards/"*/cldr_info.json
do
# TODO-LDML: developer/src/inst/download.in.mak needs these also...
CLDR_PATH=$(dirname "$CLDR_INFO_PATH")
CLDR_VER=$(basename "$CLDR_PATH")
mkdir -p "$THIS_SCRIPT_PATH/build/src/import/$CLDR_VER"
# TODO-LDML: When these are copied, the DOCTYPE will break due to the wrong path. We don't use the DTD so it should be OK.
cp "$CLDR_INFO_PATH" "$CLDR_PATH/import/"*.xml "$THIS_SCRIPT_PATH/build/src/import/$CLDR_VER/"
done
}
function do_build() {
copy_cldr_imports
tsc --build
}
builder_run_action clean rm -rf ./build/
builder_run_action configure verify_npm_setup
builder_run_action build tsc --build
builder_run_action build do_build
if builder_start_action test; then
eslint .
tsc --build test
c8 --reporter=lcov --reporter=text --exclude-after-remap mocha
readonly C8_THRESHOLD=40
c8 --reporter=lcov --reporter=text --exclude-after-remap --lines $C8_THRESHOLD --statements $C8_THRESHOLD --branches $C8_THRESHOLD --functions $C8_THRESHOLD mocha
builder_echo warning "Coverage thresholds are currently $C8_THRESHOLD%, which is lower than ideal."
builder_echo warning "Please increase threshold in build.sh as test coverage improves."
builder_finish_action success test
fi

View file

@ -1,6 +0,0 @@
export { validateMITLicense } from './src/validate-mit-license.js';
export { KeymanSentry, SentryNodeOptions } from './src/KeymanSentry.js';
export { getOption, loadOptions, clearOptions } from './src/options.js';
export { escapeMarkdownChar } from './src/markdown.js';
export { KeymanUrls } from './src/keyman-urls.js';
export { isValidEmail } from './src/is-valid-email.js';

View file

@ -3,19 +3,29 @@
"description": "Keyman Developer utilities",
"type": "module",
"exports": {
".": "./build/index.js"
".": "./build/src/index.js"
},
"files": [
"/build/"
],
"dependencies": {
"@sentry/node": "^7.57.0"
"@sentry/node": "^7.57.0",
"@keymanapp/common-types": "*",
"eventemitter3": "^5.0.0",
"restructure": "^3.0.1",
"semver": "^7.5.2",
"sax": ">=0.6.0",
"xmlbuilder": "~11.0.0"
},
"devDependencies": {
"@types/git-diff": "^2.0.3",
"@types/node": "^20.4.1",
"typescript": "^5.4.5",
"@types/semver": "^7.3.12",
"@types/xml2js": "^0.4.5",
"c8": "^7.12.0",
"mocha": "^8.4.0"
"git-diff": "^2.0.6",
"mocha": "^8.4.0",
"typescript": "^5.4.5"
},
"scripts": {
"build": "tsc -b"

View file

@ -181,7 +181,7 @@ export class CompilerError {
*/
static severityNameToValue(name: string): CompilerErrorSeverity {
name = name.toLowerCase();
for(let level of CompilerErrorSeverityValues) {
for(const level of CompilerErrorSeverityValues) {
if(errorSeverityName[level].startsWith(name)) {
return level;
}

View file

@ -0,0 +1,47 @@
export { validateMITLicense } from './utils/validate-mit-license.js';
export { KeymanSentry, SentryNodeOptions } from './utils/KeymanSentry.js';
export { getOption, loadOptions, clearOptions } from './utils/options.js';
export { escapeMarkdownChar } from './utils/markdown.js';
export { KeymanUrls } from './utils/keyman-urls.js';
export * as KPJ from './types/kpj/kpj-file.js';
export { KPJFileReader } from './types/kpj/kpj-file-reader.js';
export { KeymanDeveloperProject, KeymanDeveloperProjectFile, KeymanDeveloperProjectType, } from './types/kpj/keyman-developer-project.js';
export { isValidEmail } from './is-valid-email.js';
export * as KpsFile from './types/kps/kps-file.js';
export { default as KvksFileReader } from './types/kvks/kvks-file-reader.js';
export { default as KvksFileWriter } from './types/kvks/kvks-file-writer.js';
export * as KvksFile from './types/kvks/kvks-file.js';
export { TouchLayoutFileReader } from './types/keyman-touch-layout/keyman-touch-layout-file-reader.js';
export { TouchLayoutFileWriter, TouchLayoutFileWriterOptions } from './types/keyman-touch-layout/keyman-touch-layout-file-writer.js';
export { default as KMXBuilder } from './types/kmx/kmx-builder.js';
export { default as KMXPlusBuilder} from './types/kmx/kmx-plus-builder/kmx-plus-builder.js';
export * as LDMLKeyboard from './types/ldml-keyboard/ldml-keyboard-xml.js';
export { LDMLKeyboardTestDataXMLSourceFile } from './types/ldml-keyboard/ldml-keyboard-testdata-xml.js';
export { LDMLKeyboardXMLSourceFileReader, LDMLKeyboardXMLSourceFileReaderOptions } from './types/ldml-keyboard/ldml-keyboard-xml-reader.js';
export { defaultCompilerOptions, CompilerBaseOptions, CompilerCallbacks, CompilerOptions, CompilerEvent, CompilerErrorNamespace,
CompilerErrorSeverity, CompilerPathCallbacks, CompilerFileSystemCallbacks, CompilerCallbackOptions,
CompilerError, CompilerMessageSpec, CompilerMessageSpecWithException, compilerErrorSeverity, CompilerErrorMask, CompilerFileCallbacks, compilerErrorSeverityName,
compilerErrorFormatCode, CompilerMessageDef,
compilerLogLevelToSeverity, CompilerLogLevel, compilerEventFormat, ALL_COMPILER_LOG_LEVELS,
ALL_COMPILER_LOG_FORMATS, CompilerLogFormat,
CompilerMessageOverride,
CompilerMessageOverrideMap,
KeymanCompilerArtifact,
KeymanCompilerArtifactOptional,
KeymanCompilerArtifacts,
KeymanCompilerResult,
KeymanCompiler
} from './compiler-interfaces.js';
export { CommonTypesMessages } from './common-events.js';
export * as xml2js from './deps/xml2js/xml2js.js';

View file

@ -0,0 +1,2 @@
// TODO: consider defining more types?
declare module 'restructure';

View file

@ -1,5 +1,6 @@
import { TouchLayoutFile } from "./keyman-touch-layout-file.js";
import SchemaValidators from '../schema-validators.js';
import { TouchLayout } from "@keymanapp/common-types";
import TouchLayoutFile = TouchLayout.TouchLayoutFile;
import { SchemaValidators } from '@keymanapp/common-types';
export class TouchLayoutFileReader {
public read(source: Uint8Array): TouchLayoutFile {
@ -22,7 +23,7 @@ export class TouchLayoutFileReader {
// `row.id` should be number, but may have been stringified; we use
// presence of `key` property to recognise this as a `TouchLayoutRow`.
if(this.key && key == 'id' && typeof value == 'string') {
let newValue = parseInt(value, 10);
const newValue = parseInt(value, 10);
/* c8 ignore next 3 */
if(isNaN(newValue)) {
throw new TypeError(`Invalid row.id: "${value}"`);
@ -39,7 +40,7 @@ export class TouchLayoutFileReader {
return undefined;
}
let newValue = parseInt(value, 10);
const newValue = parseInt(value, 10);
/* c8 ignore next 3 */
if(isNaN(newValue)) {
throw new TypeError(`Invalid [sub]key.${key}: "${value}"`);
@ -67,10 +68,10 @@ export class TouchLayoutFileReader {
}
public validate(source: TouchLayoutFile): void {
if(!SchemaValidators.touchLayoutClean(source))
if(!SchemaValidators.default.touchLayoutClean(source))
/* c8 ignore next 3 */
{
throw new Error(JSON.stringify((<any>SchemaValidators.touchLayoutClean).errors));
throw new Error(JSON.stringify((<any>SchemaValidators.default.touchLayoutClean).errors));
}
}

View file

@ -1,4 +1,8 @@
import { TouchLayoutFile, TouchLayoutPlatform, TouchLayoutKey, TouchLayoutSubKey } from "./keyman-touch-layout-file.js";
import { TouchLayout } from "@keymanapp/common-types";
import TouchLayoutFile = TouchLayout.TouchLayoutFile;
import TouchLayoutPlatform = TouchLayout.TouchLayoutPlatform;;
import TouchLayoutKey = TouchLayout.TouchLayoutKey;
import TouchLayoutSubKey = TouchLayout.TouchLayoutSubKey;
export interface TouchLayoutFileWriterOptions {
formatted?: boolean;
@ -87,24 +91,24 @@ export class TouchLayoutFileWriter {
// displayUnderlying is always written out by kmcomp, so we do the same for kmc:
platform.displayUnderlying = !!platform.displayUnderlying;
for(let layer of platform.layer) {
for(let row of layer.row) {
for(const layer of platform.layer) {
for(const row of layer.row) {
// this matches the old spec for touch layout files
(row.id as any) = row.id.toString();
for(let key of row.key) {
for(const key of row.key) {
fixupKey(key);
if(key.sk) {
for(let sk of key.sk) {
for(const sk of key.sk) {
fixupKey(sk);
}
}
if(key.multitap) {
for(let sk of key.multitap) {
for(const sk of key.multitap) {
fixupKey(sk);
}
}
if(key.flick) {
for(let id of Object.keys(key.flick)) {
for(const id of Object.keys(key.flick)) {
fixupKey((key.flick as any)[id] as TouchLayoutSubKey);
}
}

View file

@ -1,8 +1,18 @@
import { KMXPlus, KMX } from '@keymanapp/common-types';
import * as r from 'restructure';
import { KMXFile, GROUP, KEY, STORE, BUILDER_COMP_KEYBOARD, BUILDER_COMP_KEYBOARD_KMXPLUSINFO, BUILDER_COMP_STORE, BUILDER_COMP_GROUP, BUILDER_COMP_KEY } from './kmx.js';
import { KMXPlusFile } from './kmx-plus.js';
import KMXPlusBuilder from './kmx-plus-builder/kmx-plus-builder.js';
import KMXPlusFile = KMXPlus.KMXPlusFile;
import KMXFile = KMX.KMXFile;
import GROUP = KMX.GROUP;
import KEY = KMX.KEY;
import STORE = KMX.STORE;
import BUILDER_COMP_KEYBOARD = KMX.BUILDER_COMP_KEYBOARD;
import BUILDER_COMP_KEYBOARD_KMXPLUSINFO = KMX.BUILDER_COMP_KEYBOARD_KMXPLUSINFO;
import BUILDER_COMP_STORE = KMX.BUILDER_COMP_STORE;
import BUILDER_COMP_GROUP = KMX.BUILDER_COMP_GROUP;
import BUILDER_COMP_KEY = KMX.BUILDER_COMP_KEY;
export default class KMXBuilder {
file: KMXFile;
base_keyboard: number = 0;
@ -69,8 +79,8 @@ export default class KMXBuilder {
this.comp_header.dpStoreArray = this.comp_header.cxStoreArray ? size : 0;
let storeBase = size;
size += this.file.keyboard.stores.length * KMXFile.COMP_STORE_SIZE;
for(let store of this.file.keyboard.stores) {
let comp_store: BUILDER_COMP_STORE = {
for(const store of this.file.keyboard.stores) {
const comp_store: BUILDER_COMP_STORE = {
dwSystemID: store.dwSystemID,
dpName: 0,
dpString: 0
@ -90,8 +100,8 @@ export default class KMXBuilder {
this.comp_header.dpGroupArray = this.comp_header.cxGroupArray ? size : 0;
let groupBase = size;
size += this.file.keyboard.groups.length * KMXFile.COMP_GROUP_SIZE;
for(let group of this.file.keyboard.groups) {
let comp_group: BUILDER_COMP_GROUP = {
for(const group of this.file.keyboard.groups) {
const comp_group: BUILDER_COMP_GROUP = {
dpName: 0,
dpKeyArray: 0,
dpMatch: 0,
@ -100,7 +110,7 @@ export default class KMXBuilder {
fUsingKeys: group.fUsingKeys ? 1 : 0
};
let comp_keys: {base: number, key: KEY, obj: BUILDER_COMP_KEY}[] = [];
const comp_keys: {base: number, key: KEY, obj: BUILDER_COMP_KEY}[] = [];
this.comp_groups.push({base: groupBase, group: group, obj: comp_group, keys: comp_keys});
@ -116,8 +126,8 @@ export default class KMXBuilder {
let keyBase = size;
size += group.keys.length * KMXFile.COMP_KEY_SIZE;
for(let key of group.keys) {
let comp_key: BUILDER_COMP_KEY = {
for(const key of group.keys) {
const comp_key: BUILDER_COMP_KEY = {
Key: key.Key,
_padding: 0,
Line: key.Line,
@ -164,11 +174,11 @@ export default class KMXBuilder {
if(requireString && !str.length) {
// Just write zero terminator, as r.String for a zero-length string
// seems to fail.
let sbuf = r.uint16le;
const sbuf = r.uint16le;
file.set(sbuf.toBuffer(0), pos);
}
else if(pos && str.length) {
let sbuf = new r.String(null, 'utf16le'); // null-terminated string
const sbuf = new r.String(null, 'utf16le'); // null-terminated string
file.set(sbuf.toBuffer(str), pos);
}
}
@ -176,7 +186,7 @@ export default class KMXBuilder {
compile(): Uint8Array {
const fileSize = this.build();
let file: Uint8Array = new Uint8Array(fileSize);
const file: Uint8Array = new Uint8Array(fileSize);
// Write headers
@ -190,7 +200,7 @@ export default class KMXBuilder {
// Write store array and data
for(let store of this.comp_stores) {
for(const store of this.comp_stores) {
file.set(this.file.COMP_STORE.toBuffer(store.obj), store.base);
if(this.writeDebug) {
this.setString(file, store.obj.dpName, store.store.dpName);
@ -200,7 +210,7 @@ export default class KMXBuilder {
// Write group array and data
for(let group of this.comp_groups) {
for(const group of this.comp_groups) {
file.set(this.file.COMP_GROUP.toBuffer(group.obj), group.base);
if(this.writeDebug) {
this.setString(file, group.obj.dpName, group.group.dpName);
@ -208,7 +218,7 @@ export default class KMXBuilder {
this.setString(file, group.obj.dpMatch, group.group.dpMatch);
this.setString(file, group.obj.dpNoMatch, group.group.dpNoMatch);
for(let key of group.keys) {
for(const key of group.keys) {
file.set(this.file.COMP_KEY.toBuffer(key.obj), key.base);
// for back-compat reasons, these are never NULL strings
this.setString(file, key.obj.dpContext, key.key.dpContext, true);

View file

@ -1,8 +1,10 @@
import { constants } from '@keymanapp/ldml-keyboard-constants';
import { KMXPlusData } from "../kmx-plus.js";
import { KMXPlus } from "@keymanapp/common-types";
import { build_strs_index, BUILDER_STR_REF, BUILDER_STRS } from "./build-strs.js";
import { BUILDER_SECTION } from './builder-section.js';
import KMXPlusData = KMXPlus.KMXPlusData;
/* ------------------------------------------------------------------
* disp section
------------------------------------------------------------------ */
@ -27,7 +29,7 @@ export function build_disp(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS): BUILD
return null;
}
let disp: BUILDER_DISP = {
const disp: BUILDER_DISP = {
ident: constants.hex_section_id(constants.section.disp),
size: constants.length_disp + constants.length_disp_item * kmxplus.disp.disps.length,
_offset: 0,
@ -36,7 +38,7 @@ export function build_disp(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS): BUILD
items: []
};
for(let item of kmxplus.disp.disps) {
for(const item of kmxplus.disp.disps) {
disp.items.push({
to: build_strs_index(sect_strs, item.to),
id: build_strs_index(sect_strs, item.id),

View file

@ -1,10 +1,11 @@
import { constants } from "@keymanapp/ldml-keyboard-constants";
import { ElementString } from "../element-string.js";
import { Elem } from "../kmx-plus.js";
import { KMXPlus, ElementString } from "@keymanapp/common-types";
import { build_strs_index, BUILDER_STR_REF, BUILDER_STRS } from "./build-strs.js";
import { BUILDER_SECTION, BUILDER_U32CHAR } from "./builder-section.js";
import { build_uset_index, BUILDER_USET, BUILDER_USET_REF } from "./build-uset.js";
import Elem = KMXPlus.Elem;
/* ------------------------------------------------------------------
* elem section
------------------------------------------------------------------ */
@ -46,7 +47,7 @@ function binaryElemCompare(a: BUILDER_ELEM_STRING, b: BUILDER_ELEM_STRING): numb
}
export function build_elem(source_elem: Elem, sect_strs: BUILDER_STRS, sect_uset: BUILDER_USET): BUILDER_ELEM {
let result: BUILDER_ELEM = {
const result: BUILDER_ELEM = {
ident: constants.hex_section_id(constants.section.elem),
size: 0, // finalized below
_offset: 0,
@ -55,7 +56,7 @@ export function build_elem(source_elem: Elem, sect_strs: BUILDER_STRS, sect_uset
};
result.strings = source_elem.strings.map(item => {
let res: BUILDER_ELEM_STRING = {
const res: BUILDER_ELEM_STRING = {
offset: 0, // finalized below
length: item.length,
items: [],
@ -87,7 +88,7 @@ export function build_elem(source_elem: Elem, sect_strs: BUILDER_STRS, sect_uset
/* Calculate offsets and total size */
let offset = constants.length_elem + constants.length_elem_item * result.count;
for(let item of result.strings) {
for(const item of result.strings) {
if (item.length === 0) {
// no length gets a zero offset
item.offset = 0;

View file

@ -1,10 +1,14 @@
import { constants } from "@keymanapp/ldml-keyboard-constants";
import { KeysFlick, KMXPlusData, StrsItem } from "../kmx-plus.js";
import { KMXPlus } from "@keymanapp/common-types";
import { build_strs_index, BUILDER_STR_REF, BUILDER_STRS } from "./build-strs.js";
import { build_list_index, BUILDER_LIST, BUILDER_LIST_REF } from "./build-list.js";
import { BUILDER_SECTION, BUILDER_U32CHAR } from "./builder-section.js";
import KeysFlick = KMXPlus.KeysFlick;
import KMXPlusData = KMXPlus.KMXPlusData;
import StrsItem = KMXPlus.StrsItem;
/* ------------------------------------------------------------------
* keys section
------------------------------------------------------------------ */
@ -71,7 +75,7 @@ export function build_keys(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_l
return null;
}
let keys: BUILDER_KEYS = {
const keys: BUILDER_KEYS = {
ident: constants.hex_section_id(constants.section.keys),
size: 0,
keyCount: kmxplus.keys.keys.length,
@ -89,7 +93,7 @@ export function build_keys(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_l
// Note that per the Keys class and spec, there is always a flicks=0 meaning 'no flicks'
keys.flicks = kmxplus.keys.flicks.map((flicks) => {
let result : BUILDER_KEYS_FLICKS = {
const result : BUILDER_KEYS_FLICKS = {
count: flicks.flicks.length,
flick: keys.flick.length, // index of first flick
id: build_strs_index(sect_strs, flicks.id),
@ -113,7 +117,7 @@ export function build_keys(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_l
// now, keys
keys.keys = kmxplus.keys.keys.map((key) => {
let result : BUILDER_KEYS_KEY = {
const result : BUILDER_KEYS_KEY = {
to: build_strs_index(sect_strs, key.to),
flags: key.flags,
id: build_strs_index(sect_strs, key.id),
@ -136,7 +140,7 @@ export function build_keys(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_l
// finally, kmap
keys.kmap = kmxplus.keys.kmap.map(({vkey, mod, key}) => {
let result : BUILDER_KEYS_KMAP = {
const result : BUILDER_KEYS_KMAP = {
vkey,
mod,
key: keys.keys.findIndex(k => k._id === key),
@ -160,7 +164,7 @@ export function build_keys(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_l
return rc;
});
let offset = constants.length_keys +
const offset = constants.length_keys +
(constants.length_keys_key * keys.keyCount) +
(constants.length_keys_flick_element * keys.flickCount) +
(constants.length_keys_flick_list * keys.flicksCount) +

View file

@ -1,10 +1,15 @@
import { constants } from "@keymanapp/ldml-keyboard-constants";
import { KMXPlusData, LayrEntry, LayrRow, StrsItem } from "../kmx-plus.js";
import { KMXPlus } from "@keymanapp/common-types";
import { build_strs_index, BUILDER_STR_REF, BUILDER_STRS } from "./build-strs.js";
import { BUILDER_LIST } from "./build-list.js";
import { BUILDER_SECTION } from "./builder-section.js";
import KMXPlusData = KMXPlus.KMXPlusData;
import LayrEntry = KMXPlus.LayrEntry;
import LayrRow = KMXPlus.LayrRow;
import StrsItem = KMXPlus.StrsItem;
/* ------------------------------------------------------------------
* layr section -
------------------------------------------------------------------ */
@ -66,7 +71,7 @@ export function build_layr(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_l
return null; // if there aren't any layers at all (which should be an invalid keyboard)
}
let layr: BUILDER_LAYR = {
const layr: BUILDER_LAYR = {
ident: constants.hex_section_id(constants.section.layr),
size: constants.length_layr,
_offset: 0,
@ -145,7 +150,7 @@ export function build_layr(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_l
layr.rowCount = layr.rows.length;
layr.keyCount = layr.keys.length;
let offset = constants.length_layr +
const offset = constants.length_layr +
(constants.length_layr_list * layr.listCount) +
(constants.length_layr_entry * layr.layerCount) +
(constants.length_layr_row * layr.rowCount) +

View file

@ -1,8 +1,11 @@
import { constants } from "@keymanapp/ldml-keyboard-constants";
import { List, ListItem } from "../kmx-plus.js";
import { KMXPlus } from "@keymanapp/common-types";
import { build_strs_index, BUILDER_STR_REF, BUILDER_STRS } from "./build-strs.js";
import { BUILDER_SECTION } from "./builder-section.js";
import List = KMXPlus.List;
import ListItem = KMXPlus.ListItem;
/* ------------------------------------------------------------------
* list section
------------------------------------------------------------------ */
@ -40,7 +43,7 @@ export function build_list(source_list: List, sect_strs: BUILDER_STRS): BUILDER_
return null;
}
let result: BUILDER_LIST = {
const result: BUILDER_LIST = {
ident: constants.hex_section_id(constants.section.list),
size: 0,
_offset: 0,
@ -51,13 +54,13 @@ export function build_list(source_list: List, sect_strs: BUILDER_STRS): BUILDER_
};
result.lists = source_list.lists.map(array => {
let list : BUILDER_LIST_LIST = {
const list : BUILDER_LIST_LIST = {
index: result.indices.length, // the next indexcount
count: array.length,
_value: array
};
array.forEach((i) => {
let index : BUILDER_LIST_INDEX = {
const index : BUILDER_LIST_INDEX = {
// Get the final string index
str: build_strs_index(sect_strs, i.value),
_value: i.value.value, // unwrap the actual string value
@ -71,7 +74,7 @@ export function build_list(source_list: List, sect_strs: BUILDER_STRS): BUILDER_
// Sort the lists.
result.lists.sort((a,b) => a._value.compareTo(b._value));
let offset = constants.length_list +
const offset = constants.length_list +
(constants.length_list_item * result.listCount) +
(constants.length_list_index * result.indexCount);
result.size = offset;
@ -86,14 +89,14 @@ export function build_list(source_list: List, sect_strs: BUILDER_STRS): BUILDER_
* @returns
*/
export function build_list_index(sect_list: BUILDER_LIST, value: ListItem) : BUILDER_LIST_REF {
if (!value) {
if (!value) {
return 0; // empty list
}
if(!(value instanceof ListItem)) {
throw new Error('unexpected value '+ value);
}
let result = sect_list.lists.findIndex(v => v._value === value);
const result = sect_list.lists.findIndex(v => v._value === value);
if(result < 0) {
throw new Error('unexpectedly missing ListItem ' + value); // TODO-LDML: it's an array of strs
}

View file

@ -4,10 +4,12 @@
------------------------------------------------------------------ */
import { constants } from "@keymanapp/ldml-keyboard-constants";
import { KMXPlusData } from "../kmx-plus.js";
import { KMXPlus } from "@keymanapp/common-types";
import { build_strs_index, BUILDER_STR_REF, BUILDER_STRS } from "./build-strs.js";
import { BUILDER_SECTION } from "./builder-section.js";
import KMXPlusData = KMXPlus.KMXPlusData;
/**
* Builder for the 'loca' section
*/
@ -17,7 +19,7 @@ export interface BUILDER_LOCA extends BUILDER_SECTION {
};
export function build_loca(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS): BUILDER_LOCA {
let loca: BUILDER_LOCA = {
const loca: BUILDER_LOCA = {
ident: constants.hex_section_id(constants.section.loca),
size: constants.length_loca + constants.length_loca_item * kmxplus.loca.locales.length,
_offset: 0,
@ -25,7 +27,7 @@ export function build_loca(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS): BUILD
items: []
};
for(let item of kmxplus.loca.locales) {
for(const item of kmxplus.loca.locales) {
loca.items.push(build_strs_index(sect_strs, item));
}

View file

@ -4,10 +4,12 @@
------------------------------------------------------------------ */
import { constants } from "@keymanapp/ldml-keyboard-constants";
import { KMXPlusData } from "../kmx-plus.js";
import { KMXPlus } from "@keymanapp/common-types";
import { build_strs_index, BUILDER_STR_REF, BUILDER_STRS } from "./build-strs.js";
import { BUILDER_SECTION } from "./builder-section.js";
import KMXPlusData = KMXPlus.KMXPlusData;
/**
* Builder for the 'meta' section
*/

View file

@ -1,7 +1,10 @@
import { constants } from "@keymanapp/ldml-keyboard-constants";
import { Strs, StrsItem } from "../kmx-plus.js";
import { KMXPlus } from "@keymanapp/common-types";
import { BUILDER_SECTION } from "./builder-section.js";
import Strs = KMXPlus.Strs;
import StrsItem = KMXPlus.StrsItem;
/** reference from build_strs_index */
export type BUILDER_STR_REF = number;
@ -26,7 +29,7 @@ export interface BUILDER_STRS extends BUILDER_SECTION {
};
export function build_strs(source_strs: Strs): BUILDER_STRS {
let result: BUILDER_STRS = {
const result: BUILDER_STRS = {
ident: constants.hex_section_id(constants.section.strs),
size: 0, // finalized later
_offset: 0,
@ -39,7 +42,7 @@ export function build_strs(source_strs: Strs): BUILDER_STRS {
let offset = constants.length_strs + constants.length_strs_item * result.count;
// TODO: consider padding
for(let item of result.items) {
for(const item of result.items) {
item.offset = offset;
offset += item.length * 2 + 2; /* UTF-16 code units + sizeof null terminator */
}
@ -64,7 +67,7 @@ export function build_strs_index(sect_strs: BUILDER_STRS, value: StrsItem) : BUI
return <BUILDER_STR_REF>value.char;
}
let result = sect_strs.items.findIndex(v => v._value === value.value);
const result = sect_strs.items.findIndex(v => v._value === value.value);
if(result < 0) {
throw new Error('unexpectedly missing StrsItem '+value.value);
}

View file

@ -1,10 +1,13 @@
import { constants } from "@keymanapp/ldml-keyboard-constants";
import { Bksp, Tran } from "../kmx-plus.js";
import { KMXPlus } from "@keymanapp/common-types";
import { BUILDER_ELEM, BUILDER_ELEM_REF, build_elem_index } from "./build-elem.js";
import { BUILDER_STRS, BUILDER_STR_REF, build_strs_index } from "./build-strs.js";
import { BUILDER_SECTION } from "./builder-section.js";
import Bksp = KMXPlus.Bksp;
import Tran = KMXPlus.Tran;
/* ------------------------------------------------------------------
* tran section
------------------------------------------------------------------ */
@ -44,7 +47,7 @@ export function build_tran(source_tran: Tran | Bksp, sect_strs: BUILDER_STRS, se
return null;
}
let tran: BUILDER_TRAN = {
const tran: BUILDER_TRAN = {
ident: constants.hex_section_id(source_tran.id),
size: 0, // need to compute total transforms + reorders
_offset: 0,
@ -56,14 +59,14 @@ export function build_tran(source_tran: Tran | Bksp, sect_strs: BUILDER_STRS, se
reorders: [],
};
for (let group of source_tran.groups) {
for (const group of source_tran.groups) {
if (group.type === constants.tran_group_type_transform) {
tran.groups.push({
type: group.type,
count: group.transforms.length,
index: tran.transforms.length, // index of first item
});
for (let transform of group.transforms) {
for (const transform of group.transforms) {
tran.transforms.push({
from: build_strs_index(sect_strs, transform.from),
to: build_strs_index(sect_strs, transform.to),
@ -77,7 +80,7 @@ export function build_tran(source_tran: Tran | Bksp, sect_strs: BUILDER_STRS, se
count: group.reorders.length,
index: tran.reorders.length, // index of first item
});
for (let reorder of group.reorders) {
for (const reorder of group.reorders) {
tran.reorders.push({
elements: build_elem_index(sect_elem, reorder.elements),
before: build_elem_index(sect_elem, reorder.before),

View file

@ -1,8 +1,12 @@
import { constants } from "@keymanapp/ldml-keyboard-constants";
import { KMXPlusData, StrsItem, UsetItem } from "../kmx-plus.js";
import { KMXPlus } from "@keymanapp/common-types";
import { build_strs_index, BUILDER_STR_REF, BUILDER_STRS } from "./build-strs.js";
import { BUILDER_SECTION, BUILDER_U32CHAR } from "./builder-section.js";
import KMXPlusData = KMXPlus.KMXPlusData;
import StrsItem = KMXPlus.StrsItem;
import UsetItem = KMXPlus.UsetItem;
/** reference from build_uset_index */
export type BUILDER_USET_REF = number;
@ -80,7 +84,7 @@ export function build_uset_index(sect_uset: BUILDER_USET, value: UsetItem) {
}
}
let result = sect_uset.usets.findIndex(v => v._pattern.value === value.str.value);
const result = sect_uset.usets.findIndex(v => v._pattern.value === value.str.value);
if(result < 0) {
throw new Error('unexpectedly missing UsetItem ' + value.uset.toString());
}

View file

@ -1,10 +1,11 @@
import { constants } from "@keymanapp/ldml-keyboard-constants";
import { KMXPlusData } from "../kmx-plus.js";
import { KMXPlus } from "@keymanapp/common-types";
import { build_strs_index, BUILDER_STR_REF, BUILDER_STRS } from "./build-strs.js";
import { BUILDER_SECTION } from "./builder-section.js";
import { build_list_index, BUILDER_LIST, BUILDER_LIST_REF } from "./build-list.js";
import { build_elem_index, BUILDER_ELEM, BUILDER_ELEM_REF } from "./build-elem.js";
import KMXPlusData = KMXPlus.KMXPlusData;
interface BUILDER_VARS_ITEM {
type: number;

View file

@ -1,5 +1,5 @@
import * as r from 'restructure';
import { KMXPlusFile } from "../kmx-plus.js";
import { KMXPlus } from "@keymanapp/common-types";
import { constants, SectionIdent } from '@keymanapp/ldml-keyboard-constants';
import { BUILDER_SECTION } from './builder-section.js';
import { BUILDER_SECT, build_sect } from './build-sect.js';
@ -15,6 +15,8 @@ import { BUILDER_TRAN, build_tran } from './build-tran.js';
import { BUILDER_USET, build_uset } from './build-uset.js';
import { BUILDER_VARS, build_vars } from './build-vars.js';
import KMXPlusFile = KMXPlus.KMXPlusFile;
type BUILDER_BKSP = BUILDER_TRAN;
// type BUILDER_FINL = BUILDER_TRAN;
@ -50,7 +52,7 @@ export default class KMXPlusBuilder {
public compile(): Uint8Array {
const fileSize = this.build();
let file: Uint8Array = new Uint8Array(fileSize);
const file: Uint8Array = new Uint8Array(fileSize);
this.emitSection(file, this.file.COMP_PLUS_SECT, this.sect.sect);
// Keep the rest of these in order.
@ -155,13 +157,13 @@ export default class KMXPlusBuilder {
}
private emitStrings(file: Uint8Array) {
for(let item of this.sect.strs.items) {
for(const item of this.sect.strs.items) {
if(item._value === '') {
// We have a special case for the zero-length string
let sbuf = r.uint16le;
const sbuf = r.uint16le;
file.set(sbuf.toBuffer(0), item.offset + this.sect.strs._offset);
} else {
let sbuf = new r.String(null, 'utf16le');
const sbuf = new r.String(null, 'utf16le');
file.set(sbuf.toBuffer(item._value), item.offset + this.sect.strs._offset);
}
}
@ -169,9 +171,9 @@ export default class KMXPlusBuilder {
private emitElements(file: Uint8Array) {
if(this.sect.elem) {
for(let str of this.sect.elem.strings) {
for(const str of this.sect.elem.strings) {
if(str.items.length > 0) {
let COMP_PLUS_ELEM_ELEMENTS = new r.Array(this.file.COMP_PLUS_ELEM_ELEMENT, str.items.length);
const COMP_PLUS_ELEM_ELEMENTS = new r.Array(this.file.COMP_PLUS_ELEM_ELEMENT, str.items.length);
file.set(COMP_PLUS_ELEM_ELEMENTS.toBuffer(str.items), str.offset + this.sect.elem._offset);
}
}

View file

@ -2,8 +2,8 @@
// Version 1.0 and 2.0 of Keyman Developer Project .kpj file
//
import { KeymanFileTypes } from '../main.js';
import { CompilerCallbacks } from '../util/compiler-interfaces.js';
import { KeymanFileTypes } from '@keymanapp/common-types';
import { CompilerCallbacks } from '../../compiler-interfaces.js';
export class KeymanDeveloperProject {
options: KeymanDeveloperProjectOptions;
@ -29,13 +29,13 @@ export class KeymanDeveloperProject {
if(this.options.version != '2.0') {
throw new Error('populateFiles can only be called on a v2.0 project');
}
let sourcePath = this.resolveProjectPath(this.options.sourcePath);
const sourcePath = this.resolveProjectPath(this.options.sourcePath);
if(!this.callbacks.fs.existsSync(sourcePath)) {
return false;
}
let files = this.callbacks.fs.readdirSync(sourcePath);
for(let filename of files) {
let fullPath = this.callbacks.path.join(sourcePath, filename);
const files = this.callbacks.fs.readdirSync(sourcePath);
for(const filename of files) {
const fullPath = this.callbacks.path.join(sourcePath, filename);
if(KeymanFileTypes.filenameIs(filename, KeymanFileTypes.Source.LdmlKeyboard)) {
try {
const data = this.callbacks.loadFile(fullPath);
@ -51,7 +51,7 @@ export class KeymanDeveloperProject {
}
}
if(KeymanFileTypes.sourceTypeFromFilename(filename) !== null) {
let file = new KeymanDeveloperProjectFile20(fullPath, this.callbacks);
const file = new KeymanDeveloperProjectFile20(fullPath, this.callbacks);
this.files.push(file);
}
}
@ -109,7 +109,7 @@ export class KeymanDeveloperProject {
p = this.resolveProjectPath(p);
let f = file.filename.replace(new RegExp(`\\${sourceExt}$`, 'i'), targetExt);
const f = file.filename.replace(new RegExp(`\\${sourceExt}$`, 'i'), targetExt);
return this.callbacks.path.normalize(this.callbacks.path.join(p, f));
}

View file

@ -1,9 +1,9 @@
import * as xml2js from '../deps/xml2js/xml2js.js';
import { xml2js } from '../../index.js';
import { KPJFile, KPJFileProject } from './kpj-file.js';
import { boxXmlArray } from '../util/util.js';
import { util } from '@keymanapp/common-types';
import { KeymanDeveloperProject, KeymanDeveloperProjectFile10, KeymanDeveloperProjectType } from './keyman-developer-project.js';
import { CompilerCallbacks } from '../util/compiler-interfaces.js';
import SchemaValidators from '../schema-validators.js';
import { SchemaValidators } from '@keymanapp/common-types';
import { CompilerCallbacks } from '../../compiler-interfaces.js';
export class KPJFileReader {
constructor(private callbacks: CompilerCallbacks) {
@ -29,7 +29,7 @@ export class KPJFileReader {
});
data = this.boxArrays(data);
if(data.KeymanDeveloperProject?.Files?.File?.length) {
for(let file of data.KeymanDeveloperProject?.Files?.File) {
for(const file of data.KeymanDeveloperProject?.Files?.File) {
// xml2js imports <Details/> as '' so we will just delete the empty string
if(typeof file.Details == 'string') {
delete file.Details;
@ -40,11 +40,11 @@ export class KPJFileReader {
}
public validate(source: KPJFile): void {
if(!SchemaValidators.kpj(source)) {
if(!SchemaValidators.kpj90(source)) {
if(!SchemaValidators.default.kpj(source)) {
if(!SchemaValidators.default.kpj90(source)) {
// If the legacy schema also does not validate, then we will only report
// the errors against the modern schema
throw new Error(JSON.stringify((<any>SchemaValidators.kpj).errors));
throw new Error(JSON.stringify((<any>SchemaValidators.default.kpj).errors));
}
}
}
@ -60,8 +60,8 @@ export class KPJFileReader {
// NOTE: at this point, the xml should have been validated
// and matched the schema result so we can assume the source
// is a valid shape
let project = source.KeymanDeveloperProject;
let result: KeymanDeveloperProject = new KeymanDeveloperProject(projectFilename, project.Options?.Version || "1.0", this.callbacks);
const project = source.KeymanDeveloperProject;
const result: KeymanDeveloperProject = new KeymanDeveloperProject(projectFilename, project.Options?.Version || "1.0", this.callbacks);
if(result.options.version == '2.0') {
result.options.buildPath = (project.Options?.BuildPath || result.options.buildPath).replace(/\\/g, '/');
result.options.sourcePath = (project.Options?.SourcePath || result.options.sourcePath).replace(/\\/g, '/');
@ -88,9 +88,9 @@ export class KPJFileReader {
}
private transformFilesVersion10(project: KPJFileProject, result: KeymanDeveloperProject) {
let ids: { [id: string]: KeymanDeveloperProjectFile10; } = {};
for (let sourceFile of project.Files?.File) {
let file: KeymanDeveloperProjectFile10 = new KeymanDeveloperProjectFile10(
const ids: { [id: string]: KeymanDeveloperProjectFile10; } = {};
for (const sourceFile of project.Files?.File) {
const file: KeymanDeveloperProjectFile10 = new KeymanDeveloperProjectFile10(
sourceFile.ID || '',
(sourceFile.Filepath || '').replace(/\\/g, '/'),
sourceFile.FileVersion || '',
@ -123,7 +123,7 @@ export class KPJFileReader {
if(!source.KeymanDeveloperProject.Files || typeof source.KeymanDeveloperProject.Files == 'string') {
source.KeymanDeveloperProject.Files = {File:[]};
}
boxXmlArray(source.KeymanDeveloperProject.Files, 'File');
util.boxXmlArray(source.KeymanDeveloperProject.Files, 'File');
return source;
}
}

View file

@ -1,10 +1,19 @@
import * as xml2js from '../deps/xml2js/xml2js.js';
import { SchemaValidators as SV, KvkFile, util, Constants } from '@keymanapp/common-types';
import { xml2js } from '../../index.js'
import KVKSourceFile from './kvks-file.js';
import { boxXmlArray } from '../util/util.js';
import { DEFAULT_KVK_FONT, VisualKeyboard, VisualKeyboardHeaderFlags, VisualKeyboardKey, VisualKeyboardKeyFlags, VisualKeyboardLegalShiftStates, VisualKeyboardShiftState } from './visual-keyboard.js';
import { USVirtualKeyCodes } from '../consts/virtual-key-constants.js';
import { BUILDER_KVK_HEADER_VERSION, KVK_HEADER_IDENTIFIER_BYTES } from './kvk-file.js';
import SchemaValidators from '../schema-validators.js';
const SchemaValidators = SV.default;
import boxXmlArray = util.boxXmlArray;
import USVirtualKeyCodes = Constants.USVirtualKeyCodes;
import { VisualKeyboard as VK } from '@keymanapp/common-types';
import DEFAULT_KVK_FONT = VK.DEFAULT_KVK_FONT;
import VisualKeyboard = VK.VisualKeyboard;
import VisualKeyboardHeaderFlags = VK.VisualKeyboardHeaderFlags;
import VisualKeyboardKey = VK.VisualKeyboardKey;
import VisualKeyboardKeyFlags = VK.VisualKeyboardKeyFlags;
import VisualKeyboardLegalShiftStates = VK.VisualKeyboardLegalShiftStates;
import VisualKeyboardShiftState = VK.VisualKeyboardShiftState;
import BUILDER_KVK_HEADER_VERSION = KvkFile.BUILDER_KVK_HEADER_VERSION;
import KVK_HEADER_IDENTIFIER_BYTES = KvkFile.KVK_HEADER_IDENTIFIER_BYTES;
export default class KVKSFileReader {
@ -69,9 +78,9 @@ export default class KVKSFileReader {
}
}
for(let key of Object.keys(source)) {
for(const key of Object.keys(source)) {
if(Array.isArray(source[key])) {
for(let item of source[key]) {
for(const item of source[key]) {
if(typeof(item) === 'object') {
this.cleanupUnderscore(key, item);
}
@ -92,7 +101,7 @@ export default class KVKSFileReader {
// NOTE: at this point, the xml should have been validated
// and matched the schema result so we can assume properties exist
let result: VisualKeyboard = {
const result: VisualKeyboard = {
header: {
version: BUILDER_KVK_HEADER_VERSION,
flags: 0,
@ -117,22 +126,22 @@ export default class KVKSFileReader {
result.header.flags |= VisualKeyboardHeaderFlags.kvkhUseUnderlying;
}
for(let encoding of source.visualkeyboard.encoding) {
let isUnicode = (encoding.$?.name == 'unicode'),
for(const encoding of source.visualkeyboard.encoding) {
const isUnicode = (encoding.$?.name == 'unicode'),
font = isUnicode ? result.header.unicodeFont : result.header.ansiFont;
font.name = encoding.$?.fontname ?? DEFAULT_KVK_FONT.name;
font.size = parseInt(encoding.$?.fontsize ?? DEFAULT_KVK_FONT.size.toString(), 10);
for(let layer of encoding.layer) {
let shift = this.kvksShiftToKvkShift(layer.$?.shift);
for(let sourceKey of layer.key) {
let vkey = (USVirtualKeyCodes as any)[sourceKey.$?.vkey];
for(const layer of encoding.layer) {
const shift = this.kvksShiftToKvkShift(layer.$?.shift);
for(const sourceKey of layer.key) {
const vkey = (USVirtualKeyCodes as any)[sourceKey.$?.vkey];
if(!vkey) {
if(typeof invalidVkeys !== 'undefined') {
invalidVkeys.push(sourceKey.$?.vkey);
}
continue;
}
let key: VisualKeyboardKey = {
const key: VisualKeyboardKey = {
flags:
(isUnicode ? VisualKeyboardKeyFlags.kvkkUnicode : 0) |
(sourceKey.bitmap ? VisualKeyboardKeyFlags.kvkkBitmap : 0),
@ -167,9 +176,9 @@ export default class KVKSFileReader {
*/
private boxArrays(source: KVKSourceFile) {
boxXmlArray(source.visualkeyboard, 'encoding');
for(let encoding of source.visualkeyboard.encoding) {
for(const encoding of source.visualkeyboard.encoding) {
boxXmlArray(encoding, 'layer');
for(let layer of encoding.layer) {
for(const layer of encoding.layer) {
boxXmlArray(layer, 'key');
}
}
@ -181,7 +190,7 @@ export default class KVKSFileReader {
shift = shift.toUpperCase();
// TODO-LDML(lowpri): make a map of this?
for(let state of VisualKeyboardLegalShiftStates) {
for(const state of VisualKeyboardLegalShiftStates) {
if(state.name == shift) {
return state.shift;
}

View file

@ -1,7 +1,13 @@
import * as xml2js from '../deps/xml2js/xml2js.js';
import { VisualKeyboard as VK, Constants } from '@keymanapp/common-types';
import KVKSourceFile, { KVKSEncoding, KVKSFlags, KVKSKey, KVKSLayer } from './kvks-file.js';
import { VisualKeyboard, VisualKeyboardHeaderFlags, VisualKeyboardKeyFlags, VisualKeyboardLegalShiftStates, VisualKeyboardShiftState } from './visual-keyboard.js';
import { USVirtualKeyCodes } from '../consts/virtual-key-constants.js';
import { xml2js } from '../../index.js';
import USVirtualKeyCodes = Constants.USVirtualKeyCodes;
import VisualKeyboard = VK.VisualKeyboard;
import VisualKeyboardHeaderFlags = VK.VisualKeyboardHeaderFlags;
import VisualKeyboardKeyFlags = VK.VisualKeyboardKeyFlags;
import VisualKeyboardLegalShiftStates = VK.VisualKeyboardLegalShiftStates;
import VisualKeyboardShiftState = VK.VisualKeyboardShiftState;
export default class KVKSFileWriter {
public write(vk: VisualKeyboard): string {
@ -17,7 +23,7 @@ export default class KVKSFileWriter {
}
})
let flags: KVKSFlags = {};
const flags: KVKSFlags = {};
if(vk.header.flags & VisualKeyboardHeaderFlags.kvkhDisplayUnderlying) {
flags.displayunderlying = '';
}
@ -33,7 +39,7 @@ export default class KVKSFileWriter {
let kvks: KVKSourceFile = {
const kvks: KVKSourceFile = {
visualkeyboard: {
header: {
version: '10.0',
@ -46,9 +52,9 @@ export default class KVKSFileWriter {
if(vk.header.underlyingLayout) kvks.visualkeyboard.header.layout = vk.header.underlyingLayout;
let encodings: {ansi: {o: KVKSEncoding, l: {[name:string]:KVKSLayer}}, unicode: {o: KVKSEncoding, l: {[name:string]:KVKSLayer}}} = {ansi:null,unicode:null};
const encodings: {ansi: {o: KVKSEncoding, l: {[name:string]:KVKSLayer}}, unicode: {o: KVKSEncoding, l: {[name:string]:KVKSLayer}}} = {ansi:null,unicode:null};
for(let key of vk.keys) {
for(const key of vk.keys) {
const encoding = key.flags & VisualKeyboardKeyFlags.kvkkUnicode ? 'unicode' : 'ansi';
const shift = this.kvkShiftToKvksShift(key.shift);
@ -65,7 +71,7 @@ export default class KVKSFileWriter {
};
kvks.visualkeyboard.encoding.push(encodings[encoding].o);
}
let e = encodings[encoding];
const e = encodings[encoding];
if(!e.l[shift]) {
e.l[shift] = {
key: [],
@ -73,11 +79,11 @@ export default class KVKSFileWriter {
};
e.o.layer.push(e.l[shift]);
}
let l = e.l[shift];
const l = e.l[shift];
// TODO-LDML: map
let vkeyName = '';
for(let vkey of Object.keys(USVirtualKeyCodes)) {
for(const vkey of Object.keys(USVirtualKeyCodes)) {
if((USVirtualKeyCodes as any)[vkey] == key.vkey) {
vkeyName = vkey;
break;
@ -88,7 +94,7 @@ export default class KVKSFileWriter {
//TODO-LDML: warn
continue;
}
let k: KVKSKey = {
const k: KVKSKey = {
$: {vkey: vkeyName},
_: key.text,
}
@ -99,7 +105,7 @@ export default class KVKSFileWriter {
l.key.push(k);
}
let result = builder.buildObject(kvks);
const result = builder.buildObject(kvks);
return result; //Uint8Array.from(result);
}
@ -111,7 +117,7 @@ export default class KVKSFileWriter {
public kvkShiftToKvksShift(shift: VisualKeyboardShiftState): string {
// TODO-LDML(lowpri): make a map of this?
for(let state of VisualKeyboardLegalShiftStates) {
for(const state of VisualKeyboardLegalShiftStates) {
if(state.shift == shift) {
return state.name;
}

View file

@ -1,11 +1,12 @@
import * as xml2js from '../deps/xml2js/xml2js.js';
import { SchemaValidators, util } from '@keymanapp/common-types';
import { xml2js } from '../../index.js';
import { CommonTypesMessages } from '../../common-events.js';
import { CompilerCallbacks } from '../../compiler-interfaces.js';
import { LDMLKeyboardXMLSourceFile, LKImport, ImportStatus } from './ldml-keyboard-xml.js';
import { boxXmlArray } from '../util/util.js';
import { CompilerCallbacks } from '../util/compiler-interfaces.js';
import { constants } from '@keymanapp/ldml-keyboard-constants';
import { CommonTypesMessages } from '../util/common-events.js';
import { LDMLKeyboardTestDataXMLSourceFile, LKTTest, LKTTests } from './ldml-keyboard-testdata-xml.js';
import SchemaValidators from '../schema-validators.js';
import boxXmlArray = util.boxXmlArray;
interface NameAndProps {
'$'?: any; // content
@ -22,7 +23,7 @@ export class LDMLKeyboardXMLSourceFileReader {
}
static get defaultImportsURL(): [string,string] {
return ['../import/', import.meta.url];
return ['../../import/', import.meta.url];
}
readImportFile(version: string, subpath: string): Uint8Array {
@ -63,10 +64,10 @@ export class LDMLKeyboardXMLSourceFileReader {
boxXmlArray(source?.keyboard3?.locales, 'locale');
boxXmlArray(source?.keyboard3, 'transforms');
if(source?.keyboard3?.layers) {
for(let layers of source?.keyboard3?.layers) {
for(const layers of source?.keyboard3?.layers) {
boxXmlArray(layers, 'layer');
if(layers?.layer) {
for(let layer of layers?.layer) {
for(const layer of layers?.layer) {
boxXmlArray(layer, 'row');
}
}
@ -74,13 +75,13 @@ export class LDMLKeyboardXMLSourceFileReader {
}
if(source?.keyboard3?.forms?.form) {
boxXmlArray(source?.keyboard3?.forms, 'form');
for(let form of source?.keyboard3?.forms?.form) {
for(const form of source?.keyboard3?.forms?.form) {
boxXmlArray(form, 'scanCodes');
}
}
if(source?.keyboard3?.flicks) {
boxXmlArray(source?.keyboard3?.flicks, 'flick');
for(let flick of source?.keyboard3?.flicks?.flick) {
for(const flick of source?.keyboard3?.flicks?.flick) {
boxXmlArray(flick, 'flickSegment');
}
}
@ -90,9 +91,9 @@ export class LDMLKeyboardXMLSourceFileReader {
boxXmlArray(source?.keyboard3?.variables, 'uset');
}
if(source?.keyboard3?.transforms) {
for(let transforms of source.keyboard3.transforms) {
for(const transforms of source.keyboard3.transforms) {
boxXmlArray(transforms, 'transformGroup');
for (let transformGroup of transforms.transformGroup) {
for (const transformGroup of transforms.transformGroup) {
boxXmlArray(transformGroup, 'transform');
boxXmlArray(transformGroup, 'reorder');
}
@ -235,8 +236,8 @@ export class LDMLKeyboardXMLSourceFileReader {
* @returns true if valid, false if invalid
*/
public validate(source: LDMLKeyboardXMLSourceFile | LDMLKeyboardTestDataXMLSourceFile): boolean {
if(!SchemaValidators.ldmlKeyboard3(source)) {
for (let err of (<any>SchemaValidators.ldmlKeyboard3).errors) {
if(!SchemaValidators.default.ldmlKeyboard3(source)) {
for (const err of (<any>SchemaValidators.default.ldmlKeyboard3).errors) {
this.callbacks.reportMessage(CommonTypesMessages.Error_SchemaValidationError({
instancePath: err.instancePath,
keyword: err.keyword,
@ -250,9 +251,9 @@ export class LDMLKeyboardXMLSourceFileReader {
}
loadUnboxed(file: Uint8Array): LDMLKeyboardXMLSourceFile {
let source = (() => {
const source = (() => {
let a: LDMLKeyboardXMLSourceFile;
let parser = new xml2js.Parser({
const parser = new xml2js.Parser({
explicitArray: false,
mergeAttrs: true,
includeWhiteChars: false,
@ -289,9 +290,9 @@ export class LDMLKeyboardXMLSourceFileReader {
}
loadTestDataUnboxed(file: Uint8Array): any {
let source = (() => {
const source = (() => {
let a: any;
let parser = new xml2js.Parser({
const parser = new xml2js.Parser({
// explicitArray: false,
preserveChildrenOrder:true, // needed for test data
explicitChildren: true, // needed for test data

View file

@ -1,7 +1,7 @@
import * as fs from 'fs';
import * as path from 'path';
import { loadFile, resolveFilename } from '../helpers/index.js';
import { CompilerCallbacks, CompilerError, CompilerEvent, CompilerFileSystemCallbacks, CompilerPathCallbacks } from '../../src/util/compiler-interfaces.js';
import { loadFile, resolveFilename } from './helpers/index.js';
import { CompilerCallbacks, CompilerError, CompilerEvent, CompilerFileSystemCallbacks, CompilerPathCallbacks } from '../src/compiler-interfaces.js';
// This is related to developer/src/common/web/test-helpers/index.ts but has a slightly different API surface
// as this runs at a lower level than the compiler.
@ -40,7 +40,7 @@ export class TestCompilerCallbacks implements CompilerCallbacks {
return loadFile(filename);
} catch (e) {
if (e.code === 'ENOENT') {
return null;
return <Uint8Array><unknown>null;
} else {
throw e;
}

Some files were not shown because too many files have changed in this diff Show more