diff --git a/HISTORY.md b/HISTORY.md
index b2d53a5ced..f45e1e85cd 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -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)
diff --git a/LICENSE.md b/LICENSE.md
index e031c6cc13..5b20376235 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -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
diff --git a/README.md b/README.md
index acd890cc45..caab39c2f9 100644
--- a/README.md
+++ b/README.md
@@ -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).
diff --git a/VERSION.md b/VERSION.md
index e45f26b940..06ebe83646 100644
--- a/VERSION.md
+++ b/VERSION.md
@@ -1 +1 @@
-18.0.83
\ No newline at end of file
+18.0.89
\ No newline at end of file
diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-hdpi/sil_logo_blue_2017_1.9.png b/android/KMAPro/kMAPro/src/main/res/drawable-hdpi/sil_logo_blue_2017_1.9.png
deleted file mode 100644
index ddc2905347..0000000000
Binary files a/android/KMAPro/kMAPro/src/main/res/drawable-hdpi/sil_logo_blue_2017_1.9.png and /dev/null differ
diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-hdpi/sil_logo_color_tai_heritage_pro.9.png b/android/KMAPro/kMAPro/src/main/res/drawable-hdpi/sil_logo_color_tai_heritage_pro.9.png
new file mode 100644
index 0000000000..8f25377aa8
Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-hdpi/sil_logo_color_tai_heritage_pro.9.png differ
diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-mdpi/sil_logo_blue_2017_1.9.png b/android/KMAPro/kMAPro/src/main/res/drawable-mdpi/sil_logo_blue_2017_1.9.png
deleted file mode 100644
index 0e720d69a1..0000000000
Binary files a/android/KMAPro/kMAPro/src/main/res/drawable-mdpi/sil_logo_blue_2017_1.9.png and /dev/null differ
diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-mdpi/sil_logo_color_tai_heritage_pro.9.png b/android/KMAPro/kMAPro/src/main/res/drawable-mdpi/sil_logo_color_tai_heritage_pro.9.png
new file mode 100644
index 0000000000..24cc6b9c92
Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-mdpi/sil_logo_color_tai_heritage_pro.9.png differ
diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-xhdpi/sil_logo_blue_2017_1.9.png b/android/KMAPro/kMAPro/src/main/res/drawable-xhdpi/sil_logo_blue_2017_1.9.png
deleted file mode 100644
index 17f25f6cce..0000000000
Binary files a/android/KMAPro/kMAPro/src/main/res/drawable-xhdpi/sil_logo_blue_2017_1.9.png and /dev/null differ
diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-xhdpi/sil_logo_color_tai_heritage_pro.9.png b/android/KMAPro/kMAPro/src/main/res/drawable-xhdpi/sil_logo_color_tai_heritage_pro.9.png
new file mode 100644
index 0000000000..308a7c6f9a
Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-xhdpi/sil_logo_color_tai_heritage_pro.9.png differ
diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-xxhdpi/sil_logo_blue_2017_1.9.png b/android/KMAPro/kMAPro/src/main/res/drawable-xxhdpi/sil_logo_blue_2017_1.9.png
deleted file mode 100644
index 014572d691..0000000000
Binary files a/android/KMAPro/kMAPro/src/main/res/drawable-xxhdpi/sil_logo_blue_2017_1.9.png and /dev/null differ
diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-xxhdpi/sil_logo_color_tai_heritage_pro.9.png b/android/KMAPro/kMAPro/src/main/res/drawable-xxhdpi/sil_logo_color_tai_heritage_pro.9.png
new file mode 100644
index 0000000000..eee36efdec
Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-xxhdpi/sil_logo_color_tai_heritage_pro.9.png differ
diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-xxxhdpi/sil_logo_blue_2017_1.9.png b/android/KMAPro/kMAPro/src/main/res/drawable-xxxhdpi/sil_logo_blue_2017_1.9.png
deleted file mode 100644
index 04366bd151..0000000000
Binary files a/android/KMAPro/kMAPro/src/main/res/drawable-xxxhdpi/sil_logo_blue_2017_1.9.png and /dev/null differ
diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-xxxhdpi/sil_logo_color_tai_heritage_pro.9.png b/android/KMAPro/kMAPro/src/main/res/drawable-xxxhdpi/sil_logo_color_tai_heritage_pro.9.png
new file mode 100644
index 0000000000..3dec6473b9
Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-xxxhdpi/sil_logo_color_tai_heritage_pro.9.png differ
diff --git a/android/KMAPro/kMAPro/src/main/res/drawable/branded_logo.xml b/android/KMAPro/kMAPro/src/main/res/drawable/branded_logo.xml
index cb6b2cbabf..2f5d1eca2b 100644
--- a/android/KMAPro/kMAPro/src/main/res/drawable/branded_logo.xml
+++ b/android/KMAPro/kMAPro/src/main/res/drawable/branded_logo.xml
@@ -15,7 +15,7 @@
-
diff --git a/android/KMAPro/kMAPro/src/main/res/values-b+el/strings.xml b/android/KMAPro/kMAPro/src/main/res/values-b+el/strings.xml
index 43e43eb4ca..428bf5ad59 100644
--- a/android/KMAPro/kMAPro/src/main/res/values-b+el/strings.xml
+++ b/android/KMAPro/kMAPro/src/main/res/values-b+el/strings.xml
@@ -30,9 +30,9 @@
Μέγεθος κειμένου: %1$d
- Μεγαλῶστε τὸ κείμενο
+ Μεγαλῶστε τὴν γραμματοσειρά
- Μεγαλῶστε τὸ κείμενο
+ Μικρύνετε τὴν γραμματοσειρά
Ρύθμιση μεγέθους κειμένου
@@ -68,7 +68,7 @@
Μεταβολὴ ὕψους πληκτρολογίου
- Spacebar caption
+ Λεζάντα πλήκτρου διαστήματος
Πληκτρολόγιο
@@ -80,9 +80,9 @@
\'Ονομα πληκτρολογίου στὸ πλῆκτρο διαστήματος
- \'Ονομα γλώσσας στὸ πλῆκτρο διαστήματος
+ Ὄνομα γλώσσας στὸ πλῆκτρο διαστήματος
- \'Ονομα πληκτρολογίου καὶ γλώσσας στὸ πλῆκτρο διαστήματος
+ Ὄνομα πληκτρολογίου καὶ γλώσσας στὸ πλῆκτρο διαστήματος
Καμμία λεζάντα στὸ πλῆκτρο διαστήματος
@@ -92,13 +92,13 @@
Πρὸς ὑλοποίησιν
- Ὅταν εἶναι off, ἐμφανίζεται μόνο ὅταν ἔχει ἐνεργοποιηθεῖ τὸ προγνωστικὸ κείμενο
+ OFF: ἐμφάνιση μόνον ὅταν ἔχει ἐνεργοποιηθεῖ ἡ πρόβλεψη κειμένου
Ἐπιτρέψτε τὴν ἀποστολὴ ἀναφορῶν κατάρρευσης μέσῳ δικτύου
- Ὅταν εἶναι ΟΝ, θὰ ἀποστέλλονται ἀναφορὲς κατάρρευσης
+ ON: Ἀποστολὴ ἀναφορῶν κατάρρευσης
- Ὅταν εἶναι off, δὲν θὰ ἀποστέλλονται ἀναφορὲς κατάρρευσης
+ OFF: Δὲν ἀποστέλλονται ἀναφορὲς κατάρρευσης
Ἐγκατάσταση ἀπὸ τὸ keyman.com
@@ -118,9 +118,9 @@
Ὅλες οἱ γλῶσσες ἔχουν ἤδη ἐγκατασταθεῖ
- Σύρετε τὸ πληκτρολόγιο γιὰ νὰ ἀλλάξετε τὸ ὕψος
+ Σύρετε τὸ πληκτρολόγιο γιὰ νὰ ἀλλάξετε τὸ ὕψος του
- Περιστρέψτε τὴν συσκευὴ γιὰ λειτουργία πορτραίτου καὶ τοπίου
+ Περιστρέψτε τὴν συσκευὴ γιὰ προσαρμογὴ τοῦ ὕψους σὲ λειτουργία πορτραίτου καὶ τοπίου
Ἐπαναφέρετε τὶς προεπιλεγμένες ρυθμίσεις
@@ -150,9 +150,9 @@
Τὸ πακέτο πληκτρολογίου δὲν ἔχει βελτιστοποιημένα πληκτρολόγια ἀφῆς πρὸς ἐγκατάστασιν
- Δὲν ὑπάρχει νέο προγνωστικό κείμενο πρὸς ἐγκατάστασιν
+ Δὲν ὑπάρχουν προγνώσεις κειμένων πρὸς ἐγκατάστασιν
- Δὲν ὑπάρχουν πληκτρολόγια ἢ προγνωστικό κείμενο πρὸς ἐγκατάστασιν
+ Δὲν ὑπάρχουν πληκτρολόγια ἢ προγνώσεις κειμένων πρὸς ἐγκατάστασιν
Τὸ πακέτο πληκτρολογίου δὲν ἔχει σχετικὲς μὲ αὐτὸ γλῶσσες πρὸς ἐγκατάστασιν
diff --git a/android/KMEA/app/src/main/res/values-b+el/strings.xml b/android/KMEA/app/src/main/res/values-b+el/strings.xml
index 871171d63f..75c774ebd1 100644
--- a/android/KMEA/app/src/main/res/values-b+el/strings.xml
+++ b/android/KMEA/app/src/main/res/values-b+el/strings.xml
@@ -27,7 +27,7 @@
Κλεῖστε
- Κλεῖστε τὸ Κῆμαν
+ Κλεῖστε τὸ Keyman
Προχωρῆστε
@@ -53,11 +53,11 @@
Θὰ θέλατε νὰ κατεβάσετε τὴν τελευταία ἔκδοση αὐτοῦ τοῦ πληκτρολογίου;
- Θά θέλατε νὰ ἐνημερώσετε τώρα πληκτρολόγια καὶ λεξικά;
+ Θὰ θέλατε νὰ ἐνημερώσετε τώρα πληκτρολόγια καὶ λεξικά;
- Ἐνημερώσεις Πόρων
+ Ἐνημερώσεις
- Διαθέσιμες Ἐνημερώσεις Πόρων
+ Διαθέσιμες Ἐνημερώσεις
%1$s (Διαθέσιμη Ἐνημέρωση)
@@ -67,13 +67,13 @@
Ἔκδοση πληκτρολογίου
- Σύνδεσμος βοηθείας
+ Βοήθεια
Ἀπεγκαταστῆστε πληκτρολόγιο
[νέο] %1$s
- Σαρῶστε αὐτὸν τὸν κωδικό γιὰ νὰ φορτώσετε\nαὐτὸ τὸ πληκτρολόγιο σὲ ἄλλη συσκευή
+ Σαρῶστε αὐτὸν τὸν κωδικὸ γιὰ νὰ φορτώσετε\nαὐτὸ τὸ πληκτρολόγιο σὲ ἄλλη συσκευή
Καλωσορίσατε στὸ %1$s
@@ -81,22 +81,22 @@
Μοιραῖο σφάλμα πληκτρολογίου στὸ %1$s:%2$s γιὰ τὴν %3$s γλῶσσα. Φορτώνεται προεπιλεγμένο πληκτρολόγιο.
- Error in keyboard %1$s:%2$s for %3$s language.
+ Σφάλμα στὸ πληκτρολόγιο %1$s:%2$s γιὰ τὴν γλῶσσα \"%3$s\".
- Ἔλεγχος συσχετισμένου λεξικοῦ πρὸς λῆψιν
- Ἀδυναμία συνδέσεως μὲ τὸν διακομιστὴ Κῆμαν γιὰ τὸν ἔλεγχο συσχετισμένου λεξικοῦ πρὸς λῆψιν
+ Ἀναζήτηση σχετικοῦ λεξικοῦ πρὸς μεταφόρτωσιν
+ Ἀδυναμία συνδέσεως μὲ τὸν διακομιστὴ Keyman γιὰ τὴν εὕρεση σχετικοῦ λεξικοῦ πρὸς μεταφόρτωσιν
Θὰ θέλατε νὰ κατεβάσετε τὴν τελευταία ἔκδοση αὐτοῦ τοῦ λεξικοῦ;
- Δὲν ὑπάρχει λεξικὸ πρὸς λῆψιν
+ Δὲν ὑπάρχει λεξικὸ πρὸς μεταφόρτωσιν
Μὴ διαθέσιμος κατάλογος πόρων
Ἔχει ξεκινήσει ἐνημέρωση καταλόγου στὸ παρασκήνιο
- Ἡ λήψη τοῦ καταλόγου συνεχίζεται· παρακαλοῦμε ξαναδοκιμάστε σὲ λίγο!
+ Ἡ μεταφόρτωση τοῦ καταλόγου συνεχίζεται· παρακαλοῦμε ξαναδοκιμάστε σὲ λίγο!
- Ἔλεγχος πόρου σὲ ἐξέλιξη
+ Ἀναζήτηση πόρου σὲ ἐξέλιξη
Ἡ λήψη τοῦ πληκτρολογίου ἔχει ξεκινήσει στὸ παρασκήνιο
@@ -112,7 +112,7 @@
Ἡ λήψη ἀπέτυχε
- Ἀποτυχία ἀνακτήσεως ληφθέντος ἀρχείου
+ Ἀποτυχία ἀνακλήσεως ληφθέντος ἀρχείου
Ἀποτυχία προσβάσεως στὸν διακομιστή!
@@ -120,11 +120,11 @@
Ἕνας ἢ περισσότεροι πόροι ἀπέτυχαν νὰ ἐνημερωθοῦν!
- Οἱ πόροι ἐνημερώθηκαν ἐπιτυχῶς!
+ Ὅλες οἱ ἐνημερώσεις ὁλοκληρώθηκαν ἐπιτυχῶς!
Ἔκδοση λεξικοῦ
- Ἀπεγκαταστῆτε λεξικό
+ Ἀπεγκαταστῆστε λεξικό
Θὰ θέλατε νὰ διαγράψετε αὐτὸ τὸ λεξικό;
@@ -136,16 +136,16 @@
Ἐνεργοποιῆστε τὶς διορθώσεις
- Ἐνεργοποιῆστε προβλέψεις
+ Ἐνεργοποιῆστε προβλέψεις κειμένου
- Λεξικά
+ Λεξικό
- Λεξικό
- Λεξικά
- Ἔλεγχος διαθεσίμου λεξικοῦ
- Ἔλεγχος λεξικῶν ὀνλάϊν
+ Ἀναζήτηση διαθεσίμου λεξικοῦ
+ Ἀναζήτηση λεξικῶν ὀνλάϊν
Λεξικό: %1$s
diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000000..a455d3307f
--- /dev/null
+++ b/build.sh
@@ -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
diff --git a/common/build.sh b/common/build.sh
index 2d3c2ff8c4..5119bca8ac 100755
--- a/common/build.sh
+++ b/common/build.sh
@@ -16,6 +16,11 @@ builder_describe "Keyman common and resources modules" \
build \
test
+builder_describe_platform \
+ :linux linux \
+ :mac mac \
+ :windows win
+
builder_parse "$@"
#-------------------------------------------------------------------------------------------------------------------
diff --git a/common/cpp/km_u16.cpp b/common/cpp/km_u16.cpp
new file mode 100644
index 0000000000..84a6c4a75e
--- /dev/null
+++ b/common/cpp/km_u16.cpp
@@ -0,0 +1,389 @@
+/*
+ * Keyman is copyright (C) SIL International. MIT License.
+ *
+ * std::u16string functions and string conversion utility functions
+ */
+
+#include
+#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((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((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((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((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((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((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);
+}
diff --git a/core/src/utfcodec.cpp b/common/cpp/utfcodec.cpp
similarity index 100%
rename from core/src/utfcodec.cpp
rename to common/cpp/utfcodec.cpp
diff --git a/common/include/km_u16.h b/common/include/km_u16.h
new file mode 100644
index 0000000000..f0c2c2d16c
--- /dev/null
+++ b/common/include/km_u16.h
@@ -0,0 +1,76 @@
+#pragma once
+
+#include
+#include
+#include
+
+/** @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);
diff --git a/core/src/utfcodec.hpp b/common/include/utfcodec.hpp
similarity index 100%
rename from core/src/utfcodec.hpp
rename to common/include/utfcodec.hpp
diff --git a/common/web/keyboard-processor/build.sh b/common/web/keyboard-processor/build.sh
index a7647983f9..3921063bb9 100755
--- a/common/web/keyboard-processor/build.sh
+++ b/common/web/keyboard-processor/build.sh
@@ -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" \
diff --git a/common/web/lm-worker/src/test/mocha/cases/worker-model-compositor.js b/common/web/lm-worker/src/test/mocha/cases/worker-model-compositor.js
index 540aa51425..8dc108440b 100644
--- a/common/web/lm-worker/src/test/mocha/cases/worker-model-compositor.js
+++ b/common/web/lm-worker/src/test/mocha/cases/worker-model-compositor.js
@@ -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'));
});
});
diff --git a/common/web/recorder/tsconfig.json b/common/web/recorder/tsconfig.json
deleted file mode 100644
index 1a38d48f03..0000000000
--- a/common/web/recorder/tsconfig.json
+++ /dev/null
@@ -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" }
- ],
-}
diff --git a/common/web/types/build.sh b/common/web/types/build.sh
index df11540b42..7141bc1072 100755
--- a/common/web/types/build.sh
+++ b/common/web/types/build.sh
@@ -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
diff --git a/common/web/types/package.json b/common/web/types/package.json
index 9327e48590..20f84bc140 100644
--- a/common/web/types/package.json
+++ b/common/web/types/package.json
@@ -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"
diff --git a/common/web/types/src/kmx/element-string.ts b/common/web/types/src/kmx/kmx-plus/element-string.ts
similarity index 94%
rename from common/web/types/src/kmx/element-string.ts
rename to common/web/types/src/kmx/kmx-plus/element-string.ts
index 1b24c3eb45..c7597b4f6b 100644
--- a/common/web/types/src/kmx/element-string.ts
+++ b/common/web/types/src/kmx/kmx-plus/element-string.ts
@@ -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,
diff --git a/common/web/types/src/kmx/kmx-plus.ts b/common/web/types/src/kmx/kmx-plus/kmx-plus.ts
similarity index 97%
rename from common/web/types/src/kmx/kmx-plus.ts
rename to common/web/types/src/kmx/kmx-plus/kmx-plus.ts
index 6e3c73d33c..1d19cdd4d0 100644
--- a/common/web/types/src/kmx/kmx-plus.ts
+++ b/common/web/types/src/kmx/kmx-plus/kmx-plus.ts
@@ -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
diff --git a/common/web/types/src/kmx/string-list.ts b/common/web/types/src/ldml-keyboard/string-list.ts
similarity index 94%
rename from common/web/types/src/kmx/string-list.ts
rename to common/web/types/src/ldml-keyboard/string-list.ts
index f68e905369..5d11a5ca7c 100644
--- a/common/web/types/src/kmx/string-list.ts
+++ b/common/web/types/src/ldml-keyboard/string-list.ts
@@ -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.
diff --git a/common/web/types/src/main.ts b/common/web/types/src/main.ts
index 2e0ede953f..7e0dc2f7b2 100644
--- a/common/web/types/src/main.ts
+++ b/common/web/types/src/main.ts
@@ -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';
diff --git a/common/web/types/test/helpers/index.ts b/common/web/types/test/helpers/index.ts
index 9b2be1d605..3e305eeca8 100644
--- a/common/web/types/test/helpers/index.ts
+++ b/common/web/types/test/helpers/index.ts
@@ -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;
-}
diff --git a/common/web/types/tsconfig.json b/common/web/types/tsconfig.json
index 0473ae92ee..cd779632a0 100644
--- a/common/web/types/tsconfig.json
+++ b/common/web/types/tsconfig.json
@@ -9,7 +9,6 @@
"preserveConstEnums": true,
},
"include": [
- "src/deps/xml2js/*.js",
"src/**/*.ts",
"src/schemas/*.mjs", // Import the validators
],
diff --git a/core/doc/meson.build b/core/doc/meson.build
index 6039e2e2dd..a0f2bc4e6d 100644
--- a/core/doc/meson.build
+++ b/core/doc/meson.build
@@ -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',
diff --git a/core/src/meson.build b/core/src/meson.build
index 212b56f1c2..41c198543c 100644
--- a/core/src/meson.build
+++ b/core/src/meson.build
@@ -126,7 +126,7 @@ core_files = files(
'keyboard.cpp',
'state.cpp',
'jsonpp.cpp',
- 'utfcodec.cpp',
+ '../../common/cpp/utfcodec.cpp',
)
mock_files = files(
diff --git a/core/tests/meson.build b/core/tests/meson.build
index 84c17d4220..90e0ab2a54 100644
--- a/core/tests/meson.build
+++ b/core/tests/meson.build
@@ -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
diff --git a/core/tests/unit/utftest/meson.build b/core/tests/unit/utftest/meson.build
index eff79c10b7..4ab6cb74ca 100644
--- a/core/tests/unit/utftest/meson.build
+++ b/core/tests/unit/utftest/meson.build
@@ -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)
diff --git a/crowdin.yml b/crowdin.yml
index 3c95e40186..812cfa21c7 100644
--- a/crowdin.yml
+++ b/crowdin.yml
@@ -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:
diff --git a/developer/src/.build-builder b/developer/src/.build-builder
new file mode 100644
index 0000000000..a06440b36f
--- /dev/null
+++ b/developer/src/.build-builder
@@ -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.
diff --git a/developer/src/build.sh b/developer/src/build.sh
index de7ab49171..b45dea38f5 100755
--- a/developer/src/build.sh
+++ b/developer/src/build.sh
@@ -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
diff --git a/developer/src/common/build.sh b/developer/src/common/build.sh
index 53358c80b0..b37c2bc948 100755
--- a/developer/src/common/build.sh
+++ b/developer/src/common/build.sh
@@ -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
diff --git a/developer/src/common/web/test-helpers/build.sh b/developer/src/common/web/test-helpers/build.sh
index 175bce6616..c1664cfddd 100755
--- a/developer/src/common/web/test-helpers/build.sh
+++ b/developer/src/common/web/test-helpers/build.sh
@@ -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 \
diff --git a/developer/src/common/web/test-helpers/index.ts b/developer/src/common/web/test-helpers/index.ts
index be9157f69c..93dfb89b2c 100644
--- a/developer/src/common/web/test-helpers/index.ts
+++ b/developer/src/common/web/test-helpers/index.ts
@@ -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';
/**
diff --git a/developer/src/common/web/test-helpers/package.json b/developer/src/common/web/test-helpers/package.json
index 5aa6ec301f..d541894830 100644
--- a/developer/src/common/web/test-helpers/package.json
+++ b/developer/src/common/web/test-helpers/package.json
@@ -17,6 +17,6 @@
},
"license": "MIT",
"dependencies": {
- "@keymanapp/common-types": "*"
+ "@keymanapp/developer-utils": "*"
}
}
diff --git a/developer/src/common/web/test-helpers/verifyCompilerMessagesObject.ts b/developer/src/common/web/test-helpers/verifyCompilerMessagesObject.ts
index e9ed7b45a7..7f0d9aee76 100644
--- a/developer/src/common/web/test-helpers/verifyCompilerMessagesObject.ts
+++ b/developer/src/common/web/test-helpers/verifyCompilerMessagesObject.ts
@@ -1,4 +1,4 @@
-import { CompilerError, CompilerErrorMask } from '@keymanapp/common-types';
+import { CompilerError, CompilerErrorMask } from '@keymanapp/developer-utils';
import {assert, expect} from 'chai';
//
diff --git a/developer/src/common/web/utils/build.sh b/developer/src/common/web/utils/build.sh
index e58d585c5d..8829765237 100755
--- a/developer/src/common/web/utils/build.sh
+++ b/developer/src/common/web/utils/build.sh
@@ -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
diff --git a/developer/src/common/web/utils/index.ts b/developer/src/common/web/utils/index.ts
deleted file mode 100644
index 7a792af2a1..0000000000
--- a/developer/src/common/web/utils/index.ts
+++ /dev/null
@@ -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';
\ No newline at end of file
diff --git a/developer/src/common/web/utils/package.json b/developer/src/common/web/utils/package.json
index b93cca8efa..488051f8f0 100644
--- a/developer/src/common/web/utils/package.json
+++ b/developer/src/common/web/utils/package.json
@@ -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"
diff --git a/common/web/types/src/util/common-events.ts b/developer/src/common/web/utils/src/common-events.ts
similarity index 100%
rename from common/web/types/src/util/common-events.ts
rename to developer/src/common/web/utils/src/common-events.ts
diff --git a/common/web/types/src/util/compiler-interfaces.ts b/developer/src/common/web/utils/src/compiler-interfaces.ts
similarity index 99%
rename from common/web/types/src/util/compiler-interfaces.ts
rename to developer/src/common/web/utils/src/compiler-interfaces.ts
index df8ab48f33..e4ed62d750 100644
--- a/common/web/types/src/util/compiler-interfaces.ts
+++ b/developer/src/common/web/utils/src/compiler-interfaces.ts
@@ -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;
}
diff --git a/common/web/types/src/deps/xml2js/LICENSE b/developer/src/common/web/utils/src/deps/xml2js/LICENSE
similarity index 100%
rename from common/web/types/src/deps/xml2js/LICENSE
rename to developer/src/common/web/utils/src/deps/xml2js/LICENSE
diff --git a/common/web/types/src/deps/xml2js/README.md b/developer/src/common/web/utils/src/deps/xml2js/README.md
similarity index 100%
rename from common/web/types/src/deps/xml2js/README.md
rename to developer/src/common/web/utils/src/deps/xml2js/README.md
diff --git a/common/web/types/src/deps/xml2js/bom.js b/developer/src/common/web/utils/src/deps/xml2js/bom.js
similarity index 100%
rename from common/web/types/src/deps/xml2js/bom.js
rename to developer/src/common/web/utils/src/deps/xml2js/bom.js
diff --git a/common/web/types/src/deps/xml2js/builder.js b/developer/src/common/web/utils/src/deps/xml2js/builder.js
similarity index 100%
rename from common/web/types/src/deps/xml2js/builder.js
rename to developer/src/common/web/utils/src/deps/xml2js/builder.js
diff --git a/common/web/types/src/deps/xml2js/defaults.js b/developer/src/common/web/utils/src/deps/xml2js/defaults.js
similarity index 100%
rename from common/web/types/src/deps/xml2js/defaults.js
rename to developer/src/common/web/utils/src/deps/xml2js/defaults.js
diff --git a/common/web/types/src/deps/xml2js/parser.js b/developer/src/common/web/utils/src/deps/xml2js/parser.js
similarity index 100%
rename from common/web/types/src/deps/xml2js/parser.js
rename to developer/src/common/web/utils/src/deps/xml2js/parser.js
diff --git a/common/web/types/src/deps/xml2js/processors.js b/developer/src/common/web/utils/src/deps/xml2js/processors.js
similarity index 100%
rename from common/web/types/src/deps/xml2js/processors.js
rename to developer/src/common/web/utils/src/deps/xml2js/processors.js
diff --git a/common/web/types/src/deps/xml2js/xml2js.js b/developer/src/common/web/utils/src/deps/xml2js/xml2js.js
similarity index 100%
rename from common/web/types/src/deps/xml2js/xml2js.js
rename to developer/src/common/web/utils/src/deps/xml2js/xml2js.js
diff --git a/developer/src/common/web/utils/src/index.ts b/developer/src/common/web/utils/src/index.ts
new file mode 100644
index 0000000000..0e462c7c05
--- /dev/null
+++ b/developer/src/common/web/utils/src/index.ts
@@ -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';
diff --git a/developer/src/common/web/utils/src/restructure.d.ts b/developer/src/common/web/utils/src/restructure.d.ts
new file mode 100644
index 0000000000..9750d24473
--- /dev/null
+++ b/developer/src/common/web/utils/src/restructure.d.ts
@@ -0,0 +1,2 @@
+// TODO: consider defining more types?
+declare module 'restructure';
\ No newline at end of file
diff --git a/common/web/types/src/keyman-touch-layout/keyman-touch-layout-file-reader.ts b/developer/src/common/web/utils/src/types/keyman-touch-layout/keyman-touch-layout-file-reader.ts
similarity index 82%
rename from common/web/types/src/keyman-touch-layout/keyman-touch-layout-file-reader.ts
rename to developer/src/common/web/utils/src/types/keyman-touch-layout/keyman-touch-layout-file-reader.ts
index e0f4ea7917..81be30e387 100644
--- a/common/web/types/src/keyman-touch-layout/keyman-touch-layout-file-reader.ts
+++ b/developer/src/common/web/utils/src/types/keyman-touch-layout/keyman-touch-layout-file-reader.ts
@@ -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((SchemaValidators.touchLayoutClean).errors));
+ throw new Error(JSON.stringify((SchemaValidators.default.touchLayoutClean).errors));
}
}
diff --git a/common/web/types/src/keyman-touch-layout/keyman-touch-layout-file-writer.ts b/developer/src/common/web/utils/src/types/keyman-touch-layout/keyman-touch-layout-file-writer.ts
similarity index 86%
rename from common/web/types/src/keyman-touch-layout/keyman-touch-layout-file-writer.ts
rename to developer/src/common/web/utils/src/types/keyman-touch-layout/keyman-touch-layout-file-writer.ts
index 5de702eb1c..6261f80d4b 100644
--- a/common/web/types/src/keyman-touch-layout/keyman-touch-layout-file-writer.ts
+++ b/developer/src/common/web/utils/src/types/keyman-touch-layout/keyman-touch-layout-file-writer.ts
@@ -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);
}
}
diff --git a/common/web/types/src/kmx/kmx-builder.ts b/developer/src/common/web/utils/src/types/kmx/kmx-builder.ts
similarity index 85%
rename from common/web/types/src/kmx/kmx-builder.ts
rename to developer/src/common/web/utils/src/types/kmx/kmx-builder.ts
index 4a319bfe45..a8ce169d30 100644
--- a/common/web/types/src/kmx/kmx-builder.ts
+++ b/developer/src/common/web/utils/src/types/kmx/kmx-builder.ts
@@ -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);
diff --git a/common/web/types/src/kmx/kmx-plus-builder/build-disp.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-disp.ts
similarity index 88%
rename from common/web/types/src/kmx/kmx-plus-builder/build-disp.ts
rename to developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-disp.ts
index 712dafac27..6984aa2cfa 100644
--- a/common/web/types/src/kmx/kmx-plus-builder/build-disp.ts
+++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-disp.ts
@@ -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),
diff --git a/common/web/types/src/kmx/kmx-plus-builder/build-elem.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-elem.ts
similarity index 94%
rename from common/web/types/src/kmx/kmx-plus-builder/build-elem.ts
rename to developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-elem.ts
index 8e325f9591..8dafccced2 100644
--- a/common/web/types/src/kmx/kmx-plus-builder/build-elem.ts
+++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-elem.ts
@@ -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;
diff --git a/common/web/types/src/kmx/kmx-plus-builder/build-keys.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-keys.ts
similarity index 93%
rename from common/web/types/src/kmx/kmx-plus-builder/build-keys.ts
rename to developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-keys.ts
index ec7e505c57..fd48ec49ec 100644
--- a/common/web/types/src/kmx/kmx-plus-builder/build-keys.ts
+++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-keys.ts
@@ -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) +
diff --git a/common/web/types/src/kmx/kmx-plus-builder/build-layr.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-layr.ts
similarity index 94%
rename from common/web/types/src/kmx/kmx-plus-builder/build-layr.ts
rename to developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-layr.ts
index c0038246e2..07249368f4 100644
--- a/common/web/types/src/kmx/kmx-plus-builder/build-layr.ts
+++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-layr.ts
@@ -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) +
diff --git a/common/web/types/src/kmx/kmx-plus-builder/build-list.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-list.ts
similarity index 88%
rename from common/web/types/src/kmx/kmx-plus-builder/build-list.ts
rename to developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-list.ts
index 26659f8eb6..759f6498f4 100644
--- a/common/web/types/src/kmx/kmx-plus-builder/build-list.ts
+++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-list.ts
@@ -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
}
diff --git a/common/web/types/src/kmx/kmx-plus-builder/build-loca.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-loca.ts
similarity index 84%
rename from common/web/types/src/kmx/kmx-plus-builder/build-loca.ts
rename to developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-loca.ts
index 9a72402c8c..4a81fcd9ab 100644
--- a/common/web/types/src/kmx/kmx-plus-builder/build-loca.ts
+++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-loca.ts
@@ -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));
}
diff --git a/common/web/types/src/kmx/kmx-plus-builder/build-meta.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-meta.ts
similarity index 93%
rename from common/web/types/src/kmx/kmx-plus-builder/build-meta.ts
rename to developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-meta.ts
index 23dd303a7d..208051356e 100644
--- a/common/web/types/src/kmx/kmx-plus-builder/build-meta.ts
+++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-meta.ts
@@ -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
*/
diff --git a/common/web/types/src/kmx/kmx-plus-builder/build-sect.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-sect.ts
similarity index 100%
rename from common/web/types/src/kmx/kmx-plus-builder/build-sect.ts
rename to developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-sect.ts
diff --git a/common/web/types/src/kmx/kmx-plus-builder/build-strs.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-strs.ts
similarity index 89%
rename from common/web/types/src/kmx/kmx-plus-builder/build-strs.ts
rename to developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-strs.ts
index 503de2d404..89d733f22d 100644
--- a/common/web/types/src/kmx/kmx-plus-builder/build-strs.ts
+++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-strs.ts
@@ -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 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);
}
diff --git a/common/web/types/src/kmx/kmx-plus-builder/build-tran.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-tran.ts
similarity index 91%
rename from common/web/types/src/kmx/kmx-plus-builder/build-tran.ts
rename to developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-tran.ts
index 316df69853..2473651b88 100644
--- a/common/web/types/src/kmx/kmx-plus-builder/build-tran.ts
+++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-tran.ts
@@ -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),
diff --git a/common/web/types/src/kmx/kmx-plus-builder/build-uset.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-uset.ts
similarity index 89%
rename from common/web/types/src/kmx/kmx-plus-builder/build-uset.ts
rename to developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-uset.ts
index 8c73afb796..1edd4d339f 100644
--- a/common/web/types/src/kmx/kmx-plus-builder/build-uset.ts
+++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-uset.ts
@@ -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());
}
diff --git a/common/web/types/src/kmx/kmx-plus-builder/build-vars.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-vars.ts
similarity index 95%
rename from common/web/types/src/kmx/kmx-plus-builder/build-vars.ts
rename to developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-vars.ts
index 8c09a169f6..92acbba9be 100644
--- a/common/web/types/src/kmx/kmx-plus-builder/build-vars.ts
+++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-vars.ts
@@ -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;
diff --git a/common/web/types/src/kmx/kmx-plus-builder/builder-section.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/builder-section.ts
similarity index 100%
rename from common/web/types/src/kmx/kmx-plus-builder/builder-section.ts
rename to developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/builder-section.ts
diff --git a/common/web/types/src/kmx/kmx-plus-builder/kmx-plus-builder.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/kmx-plus-builder.ts
similarity index 93%
rename from common/web/types/src/kmx/kmx-plus-builder/kmx-plus-builder.ts
rename to developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/kmx-plus-builder.ts
index 381e1d6d19..acc732c932 100644
--- a/common/web/types/src/kmx/kmx-plus-builder/kmx-plus-builder.ts
+++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/kmx-plus-builder.ts
@@ -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);
}
}
diff --git a/common/web/types/src/kpj/keyman-developer-project.ts b/developer/src/common/web/utils/src/types/kpj/keyman-developer-project.ts
similarity index 92%
rename from common/web/types/src/kpj/keyman-developer-project.ts
rename to developer/src/common/web/utils/src/types/kpj/keyman-developer-project.ts
index 76f3ab709a..f678106a4c 100644
--- a/common/web/types/src/kpj/keyman-developer-project.ts
+++ b/developer/src/common/web/utils/src/types/kpj/keyman-developer-project.ts
@@ -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));
}
diff --git a/common/web/types/src/kpj/kpj-file-reader.ts b/developer/src/common/web/utils/src/types/kpj/kpj-file-reader.ts
similarity index 81%
rename from common/web/types/src/kpj/kpj-file-reader.ts
rename to developer/src/common/web/utils/src/types/kpj/kpj-file-reader.ts
index eb2a168a48..d776898753 100644
--- a/common/web/types/src/kpj/kpj-file-reader.ts
+++ b/developer/src/common/web/utils/src/types/kpj/kpj-file-reader.ts
@@ -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 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((SchemaValidators.kpj).errors));
+ throw new Error(JSON.stringify((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;
}
}
\ No newline at end of file
diff --git a/common/web/types/src/kpj/kpj-file.ts b/developer/src/common/web/utils/src/types/kpj/kpj-file.ts
similarity index 100%
rename from common/web/types/src/kpj/kpj-file.ts
rename to developer/src/common/web/utils/src/types/kpj/kpj-file.ts
diff --git a/common/web/types/src/package/kps-file.ts b/developer/src/common/web/utils/src/types/kps/kps-file.ts
similarity index 100%
rename from common/web/types/src/package/kps-file.ts
rename to developer/src/common/web/utils/src/types/kps/kps-file.ts
diff --git a/common/web/types/src/kvk/kvks-file-reader.ts b/developer/src/common/web/utils/src/types/kvks/kvks-file-reader.ts
similarity index 78%
rename from common/web/types/src/kvk/kvks-file-reader.ts
rename to developer/src/common/web/utils/src/types/kvks/kvks-file-reader.ts
index ff3a094e6f..6b2ad8e0a9 100644
--- a/common/web/types/src/kvk/kvks-file-reader.ts
+++ b/developer/src/common/web/utils/src/types/kvks/kvks-file-reader.ts
@@ -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;
}
diff --git a/common/web/types/src/kvk/kvks-file-writer.ts b/developer/src/common/web/utils/src/types/kvks/kvks-file-writer.ts
similarity index 73%
rename from common/web/types/src/kvk/kvks-file-writer.ts
rename to developer/src/common/web/utils/src/types/kvks/kvks-file-writer.ts
index 19327e779d..dd4962a8fa 100644
--- a/common/web/types/src/kvk/kvks-file-writer.ts
+++ b/developer/src/common/web/utils/src/types/kvks/kvks-file-writer.ts
@@ -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;
}
diff --git a/common/web/types/src/kvk/kvks-file.ts b/developer/src/common/web/utils/src/types/kvks/kvks-file.ts
similarity index 100%
rename from common/web/types/src/kvk/kvks-file.ts
rename to developer/src/common/web/utils/src/types/kvks/kvks-file.ts
diff --git a/common/web/types/src/ldml-keyboard/ldml-keyboard-testdata-xml.ts b/developer/src/common/web/utils/src/types/ldml-keyboard/ldml-keyboard-testdata-xml.ts
similarity index 100%
rename from common/web/types/src/ldml-keyboard/ldml-keyboard-testdata-xml.ts
rename to developer/src/common/web/utils/src/types/ldml-keyboard/ldml-keyboard-testdata-xml.ts
diff --git a/common/web/types/src/ldml-keyboard/ldml-keyboard-xml-reader.ts b/developer/src/common/web/utils/src/types/ldml-keyboard/ldml-keyboard-xml-reader.ts
similarity index 93%
rename from common/web/types/src/ldml-keyboard/ldml-keyboard-xml-reader.ts
rename to developer/src/common/web/utils/src/types/ldml-keyboard/ldml-keyboard-xml-reader.ts
index 9055e8ed1d..162cac4aac 100644
--- a/common/web/types/src/ldml-keyboard/ldml-keyboard-xml-reader.ts
+++ b/developer/src/common/web/utils/src/types/ldml-keyboard/ldml-keyboard-xml-reader.ts
@@ -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 (SchemaValidators.ldmlKeyboard3).errors) {
+ if(!SchemaValidators.default.ldmlKeyboard3(source)) {
+ for (const err of (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
diff --git a/common/web/types/src/ldml-keyboard/ldml-keyboard-xml.ts b/developer/src/common/web/utils/src/types/ldml-keyboard/ldml-keyboard-xml.ts
similarity index 100%
rename from common/web/types/src/ldml-keyboard/ldml-keyboard-xml.ts
rename to developer/src/common/web/utils/src/types/ldml-keyboard/ldml-keyboard-xml.ts
diff --git a/developer/src/common/web/utils/src/KeymanSentry.ts b/developer/src/common/web/utils/src/utils/KeymanSentry.ts
similarity index 100%
rename from developer/src/common/web/utils/src/KeymanSentry.ts
rename to developer/src/common/web/utils/src/utils/KeymanSentry.ts
diff --git a/developer/src/common/web/utils/src/keyman-urls.ts b/developer/src/common/web/utils/src/utils/keyman-urls.ts
similarity index 100%
rename from developer/src/common/web/utils/src/keyman-urls.ts
rename to developer/src/common/web/utils/src/utils/keyman-urls.ts
diff --git a/developer/src/common/web/utils/src/markdown.ts b/developer/src/common/web/utils/src/utils/markdown.ts
similarity index 100%
rename from developer/src/common/web/utils/src/markdown.ts
rename to developer/src/common/web/utils/src/utils/markdown.ts
diff --git a/developer/src/common/web/utils/src/options.ts b/developer/src/common/web/utils/src/utils/options.ts
similarity index 100%
rename from developer/src/common/web/utils/src/options.ts
rename to developer/src/common/web/utils/src/utils/options.ts
diff --git a/developer/src/common/web/utils/src/validate-mit-license.ts b/developer/src/common/web/utils/src/utils/validate-mit-license.ts
similarity index 100%
rename from developer/src/common/web/utils/src/validate-mit-license.ts
rename to developer/src/common/web/utils/src/utils/validate-mit-license.ts
diff --git a/common/web/types/test/helpers/TestCompilerCallbacks.ts b/developer/src/common/web/utils/test/TestCompilerCallbacks.ts
similarity index 87%
rename from common/web/types/test/helpers/TestCompilerCallbacks.ts
rename to developer/src/common/web/utils/test/TestCompilerCallbacks.ts
index d231290fef..d1413e477a 100644
--- a/common/web/types/test/helpers/TestCompilerCallbacks.ts
+++ b/developer/src/common/web/utils/test/TestCompilerCallbacks.ts
@@ -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 null;
} else {
throw e;
}
diff --git a/common/web/types/test/fixtures/keyman-touch-layout/khmer_angkor.keyman-touch-layout b/developer/src/common/web/utils/test/fixtures/keyman-touch-layout/khmer_angkor.keyman-touch-layout
similarity index 100%
rename from common/web/types/test/fixtures/keyman-touch-layout/khmer_angkor.keyman-touch-layout
rename to developer/src/common/web/utils/test/fixtures/keyman-touch-layout/khmer_angkor.keyman-touch-layout
diff --git a/common/web/types/test/fixtures/keyman-touch-layout/legacy.keyman-touch-layout b/developer/src/common/web/utils/test/fixtures/keyman-touch-layout/legacy.keyman-touch-layout
similarity index 100%
rename from common/web/types/test/fixtures/keyman-touch-layout/legacy.keyman-touch-layout
rename to developer/src/common/web/utils/test/fixtures/keyman-touch-layout/legacy.keyman-touch-layout
diff --git a/common/web/types/test/fixtures/kpj/khmer_angkor.kpj b/developer/src/common/web/utils/test/fixtures/kpj/khmer_angkor.kpj
similarity index 100%
rename from common/web/types/test/fixtures/kpj/khmer_angkor.kpj
rename to developer/src/common/web/utils/test/fixtures/kpj/khmer_angkor.kpj
diff --git a/common/web/types/test/fixtures/kpj/project-missing-file/project_missing_file.kpj b/developer/src/common/web/utils/test/fixtures/kpj/project-missing-file/project_missing_file.kpj
similarity index 100%
rename from common/web/types/test/fixtures/kpj/project-missing-file/project_missing_file.kpj
rename to developer/src/common/web/utils/test/fixtures/kpj/project-missing-file/project_missing_file.kpj
diff --git a/common/web/types/test/fixtures/kpj/project-missing-file/project_missing_files.kpj b/developer/src/common/web/utils/test/fixtures/kpj/project-missing-file/project_missing_files.kpj
similarity index 100%
rename from common/web/types/test/fixtures/kpj/project-missing-file/project_missing_files.kpj
rename to developer/src/common/web/utils/test/fixtures/kpj/project-missing-file/project_missing_files.kpj
diff --git a/developer/src/common/web/utils/test/fixtures/kvks/balochi_inpage.kvk b/developer/src/common/web/utils/test/fixtures/kvks/balochi_inpage.kvk
new file mode 100644
index 0000000000..56fee9dfbd
Binary files /dev/null and b/developer/src/common/web/utils/test/fixtures/kvks/balochi_inpage.kvk differ
diff --git a/common/web/types/test/fixtures/kvk/balochi_inpage.kvks b/developer/src/common/web/utils/test/fixtures/kvks/balochi_inpage.kvks
similarity index 100%
rename from common/web/types/test/fixtures/kvk/balochi_inpage.kvks
rename to developer/src/common/web/utils/test/fixtures/kvks/balochi_inpage.kvks
diff --git a/developer/src/common/web/utils/test/fixtures/kvks/khmer_angkor.kvk b/developer/src/common/web/utils/test/fixtures/kvks/khmer_angkor.kvk
new file mode 100644
index 0000000000..c64b3a5a54
Binary files /dev/null and b/developer/src/common/web/utils/test/fixtures/kvks/khmer_angkor.kvk differ
diff --git a/common/web/types/test/fixtures/kvk/khmer_angkor.kvks b/developer/src/common/web/utils/test/fixtures/kvks/khmer_angkor.kvks
similarity index 100%
rename from common/web/types/test/fixtures/kvk/khmer_angkor.kvks
rename to developer/src/common/web/utils/test/fixtures/kvks/khmer_angkor.kvks
diff --git a/common/web/types/test/fixtures/import-minimal.xml b/developer/src/common/web/utils/test/fixtures/ldml-keyboard/import-minimal.xml
similarity index 100%
rename from common/web/types/test/fixtures/import-minimal.xml
rename to developer/src/common/web/utils/test/fixtures/ldml-keyboard/import-minimal.xml
diff --git a/common/web/types/test/fixtures/import-minimal1.xml b/developer/src/common/web/utils/test/fixtures/ldml-keyboard/import-minimal1.xml
similarity index 100%
rename from common/web/types/test/fixtures/import-minimal1.xml
rename to developer/src/common/web/utils/test/fixtures/ldml-keyboard/import-minimal1.xml
diff --git a/common/web/types/test/fixtures/import-minimal2.xml b/developer/src/common/web/utils/test/fixtures/ldml-keyboard/import-minimal2.xml
similarity index 100%
rename from common/web/types/test/fixtures/import-minimal2.xml
rename to developer/src/common/web/utils/test/fixtures/ldml-keyboard/import-minimal2.xml
diff --git a/common/web/types/test/fixtures/import-symbols.xml b/developer/src/common/web/utils/test/fixtures/ldml-keyboard/import-symbols.xml
similarity index 100%
rename from common/web/types/test/fixtures/import-symbols.xml
rename to developer/src/common/web/utils/test/fixtures/ldml-keyboard/import-symbols.xml
diff --git a/common/web/types/test/fixtures/invalid-conforms-to.xml b/developer/src/common/web/utils/test/fixtures/ldml-keyboard/invalid-conforms-to.xml
similarity index 100%
rename from common/web/types/test/fixtures/invalid-conforms-to.xml
rename to developer/src/common/web/utils/test/fixtures/ldml-keyboard/invalid-conforms-to.xml
diff --git a/common/web/types/test/fixtures/invalid-import-base.xml b/developer/src/common/web/utils/test/fixtures/ldml-keyboard/invalid-import-base.xml
similarity index 100%
rename from common/web/types/test/fixtures/invalid-import-base.xml
rename to developer/src/common/web/utils/test/fixtures/ldml-keyboard/invalid-import-base.xml
diff --git a/common/web/types/test/fixtures/invalid-import-path.xml b/developer/src/common/web/utils/test/fixtures/ldml-keyboard/invalid-import-path.xml
similarity index 100%
rename from common/web/types/test/fixtures/invalid-import-path.xml
rename to developer/src/common/web/utils/test/fixtures/ldml-keyboard/invalid-import-path.xml
diff --git a/common/web/types/test/fixtures/invalid-import-readfail.xml b/developer/src/common/web/utils/test/fixtures/ldml-keyboard/invalid-import-readfail.xml
similarity index 100%
rename from common/web/types/test/fixtures/invalid-import-readfail.xml
rename to developer/src/common/web/utils/test/fixtures/ldml-keyboard/invalid-import-readfail.xml
diff --git a/common/web/types/test/fixtures/invalid-import-wrongroot.xml b/developer/src/common/web/utils/test/fixtures/ldml-keyboard/invalid-import-wrongroot.xml
similarity index 100%
rename from common/web/types/test/fixtures/invalid-import-wrongroot.xml
rename to developer/src/common/web/utils/test/fixtures/ldml-keyboard/invalid-import-wrongroot.xml
diff --git a/common/web/types/test/fixtures/invalid-structure-per-dtd.xml b/developer/src/common/web/utils/test/fixtures/ldml-keyboard/invalid-structure-per-dtd.xml
similarity index 100%
rename from common/web/types/test/fixtures/invalid-structure-per-dtd.xml
rename to developer/src/common/web/utils/test/fixtures/ldml-keyboard/invalid-structure-per-dtd.xml
diff --git a/common/web/types/test/fixtures/test-fr.xml b/developer/src/common/web/utils/test/fixtures/ldml-keyboard/test-fr.xml
similarity index 100%
rename from common/web/types/test/fixtures/test-fr.xml
rename to developer/src/common/web/utils/test/fixtures/ldml-keyboard/test-fr.xml
diff --git a/developer/src/common/web/utils/test/helpers/index.ts b/developer/src/common/web/utils/test/helpers/index.ts
index 9968fbfea6..e36d07429b 100644
--- a/developer/src/common/web/utils/test/helpers/index.ts
+++ b/developer/src/common/web/utils/test/helpers/index.ts
@@ -2,6 +2,7 @@
* Helpers and utilities for the Mocha tests.
*/
import * as path from 'path';
+import * as fs from "fs";
import { fileURLToPath } from 'url';
/**
@@ -16,3 +17,25 @@ import { fileURLToPath } from 'url';
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;
+}
diff --git a/common/web/types/test/helpers/reader-callback-test.ts b/developer/src/common/web/utils/test/helpers/reader-callback-test.ts
similarity index 88%
rename from common/web/types/test/helpers/reader-callback-test.ts
rename to developer/src/common/web/utils/test/helpers/reader-callback-test.ts
index 907793cdf7..c67d49dfdb 100644
--- a/common/web/types/test/helpers/reader-callback-test.ts
+++ b/developer/src/common/web/utils/test/helpers/reader-callback-test.ts
@@ -1,11 +1,11 @@
import 'mocha';
import {assert} from 'chai';
-import { loadFile, makePathToFixture } from '../helpers/index.js';
-import { LDMLKeyboardXMLSourceFileReader, LDMLKeyboardXMLSourceFileReaderOptions } from '../../src/ldml-keyboard/ldml-keyboard-xml-reader.js';
-import { CompilerEvent } from '../../src/util/compiler-interfaces.js';
-import { LDMLKeyboardXMLSourceFile } from '../../src/ldml-keyboard/ldml-keyboard-xml.js';
-import { LDMLKeyboardTestDataXMLSourceFile } from '../ldml-keyboard/ldml-keyboard-testdata-xml.js';
-import { TestCompilerCallbacks } from './TestCompilerCallbacks.js';
+import { loadFile, makePathToFixture } from './index.js';
+import { LDMLKeyboardXMLSourceFileReader, LDMLKeyboardXMLSourceFileReaderOptions } from '../../src/types/ldml-keyboard/ldml-keyboard-xml-reader.js';
+import { CompilerEvent } from '../../src/compiler-interfaces.js';
+import { LDMLKeyboardXMLSourceFile } from '../../src/types/ldml-keyboard/ldml-keyboard-xml.js';
+import { LDMLKeyboardTestDataXMLSourceFile } from '../../src/types/ldml-keyboard/ldml-keyboard-testdata-xml.js';
+import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
import { fileURLToPath } from 'url';
const readerOptions: LDMLKeyboardXMLSourceFileReaderOptions = {
@@ -77,14 +77,14 @@ export function testReaderCases(cases : CompilationCase[]) {
// we need our own callbacks rather than using the global so messages don't get mixed
const callbacks = new TestCompilerCallbacks();
const reader = new LDMLKeyboardXMLSourceFileReader(readerOptions, callbacks);
- for (let testcase of cases) {
+ for (const testcase of cases) {
const expectFailure = testcase.throws || !!(testcase.errors); // if true, we expect this to fail
const testHeading = expectFailure ? `should fail to load: ${testcase.subpath}`:
`should load: ${testcase.subpath}`;
it(testHeading, function () {
callbacks.clear();
- const data = loadFile(makePathToFixture(testcase.subpath));
+ const data = loadFile(makePathToFixture('ldml-keyboard', testcase.subpath));
assert.ok(data, `reading ${testcase.subpath}`);
const source = reader.load(data);
if (!testcase.loadfail) {
@@ -128,14 +128,14 @@ export function testTestdataReaderCases(cases : TestDataCase[]) {
// we need our own callbacks rather than using the global so messages don't get mixed
const callbacks = new TestCompilerCallbacks();
const reader = new LDMLKeyboardXMLSourceFileReader(readerOptions, callbacks);
- for (let testcase of cases) {
+ for (const testcase of cases) {
const expectFailure = testcase.throws || !!(testcase.errors); // if true, we expect this to fail
const testHeading = expectFailure ? `should fail to load: ${testcase.subpath}`:
`should load: ${testcase.subpath}`;
it(testHeading, function () {
callbacks.clear();
- const data = loadFile(makePathToFixture(testcase.subpath));
+ const data = loadFile(makePathToFixture('ldml-keyboard', testcase.subpath));
assert.ok(data, `reading ${testcase.subpath}`);
const source = reader.loadTestData(data);
if (!testcase.loadfail) {
diff --git a/common/web/types/test/keyman-touch-layout/test-keyman-touch-layout-file-reader.ts b/developer/src/common/web/utils/test/keyman-touch-layout/test-keyman-touch-layout-file-reader.ts
similarity index 96%
rename from common/web/types/test/keyman-touch-layout/test-keyman-touch-layout-file-reader.ts
rename to developer/src/common/web/utils/test/keyman-touch-layout/test-keyman-touch-layout-file-reader.ts
index 479f2c4ccb..bfebec85e8 100644
--- a/common/web/types/test/keyman-touch-layout/test-keyman-touch-layout-file-reader.ts
+++ b/developer/src/common/web/utils/test/keyman-touch-layout/test-keyman-touch-layout-file-reader.ts
@@ -2,7 +2,7 @@ import * as fs from 'fs';
import 'mocha';
import { assert } from 'chai';
import { makePathToFixture } from '../helpers/index.js';
-import { TouchLayoutFileReader } from "../../src/keyman-touch-layout/keyman-touch-layout-file-reader.js";
+import { TouchLayoutFileReader } from "../../src/types/keyman-touch-layout/keyman-touch-layout-file-reader.js";
describe('TouchLayoutFileReader', function () {
it('should read a valid file', function() {
diff --git a/common/web/types/test/keyman-touch-layout/test-keyman-touch-layout-round-trip.ts b/developer/src/common/web/utils/test/keyman-touch-layout/test-keyman-touch-layout-round-trip.ts
similarity index 81%
rename from common/web/types/test/keyman-touch-layout/test-keyman-touch-layout-round-trip.ts
rename to developer/src/common/web/utils/test/keyman-touch-layout/test-keyman-touch-layout-round-trip.ts
index f6a09d08d3..25870e6e09 100644
--- a/common/web/types/test/keyman-touch-layout/test-keyman-touch-layout-round-trip.ts
+++ b/developer/src/common/web/utils/test/keyman-touch-layout/test-keyman-touch-layout-round-trip.ts
@@ -2,8 +2,8 @@ import * as fs from 'fs';
import 'mocha';
import { assert } from 'chai';
import { makePathToFixture } from '../helpers/index.js';
-import { TouchLayoutFileReader } from "../../src/keyman-touch-layout/keyman-touch-layout-file-reader.js";
-import { TouchLayoutFileWriter } from "../../src/keyman-touch-layout/keyman-touch-layout-file-writer.js";
+import { TouchLayoutFileReader } from "../../src/types/keyman-touch-layout/keyman-touch-layout-file-reader.js";
+import { TouchLayoutFileWriter } from "../../src/types/keyman-touch-layout/keyman-touch-layout-file-writer.js";
describe('TouchLayoutFile', function () {
it('should round-trip from TouchLayoutFileReader to TouchLayoutFileWriter', function() {
@@ -26,7 +26,7 @@ describe('TouchLayoutFile', function () {
assert.deepEqual(layout, newLayout);
// And do the same without any options
- let output2 = writer.write(layout);
+ const output2 = writer.write(layout);
assert.deepEqual(output, output2);
newLayout = reader.read(output2);
diff --git a/common/web/types/test/ldml-keyboard/test-ldml-keyboard-testdata-reader.ts b/developer/src/common/web/utils/test/kmx/test-ldml-keyboard-testdata-reader.ts
similarity index 96%
rename from common/web/types/test/ldml-keyboard/test-ldml-keyboard-testdata-reader.ts
rename to developer/src/common/web/utils/test/kmx/test-ldml-keyboard-testdata-reader.ts
index 794adbbe66..d2ce6dc72a 100644
--- a/common/web/types/test/ldml-keyboard/test-ldml-keyboard-testdata-reader.ts
+++ b/developer/src/common/web/utils/test/kmx/test-ldml-keyboard-testdata-reader.ts
@@ -2,7 +2,7 @@ import { constants } from '@keymanapp/ldml-keyboard-constants';
import { assert } from 'chai';
import 'mocha';
import { testTestdataReaderCases } from '../helpers/reader-callback-test.js';
-import { LKTAnyAction } from './ldml-keyboard-testdata-xml.js';
+import { LKTAnyAction } from '../../src/types/ldml-keyboard/ldml-keyboard-testdata-xml.js';
describe('ldml keyboard xml reader tests', function () {
this.slow(500); // 0.5 sec -- json schema validation takes a while
diff --git a/common/web/types/test/ldml-keyboard/test-ldml-keyboard-xml-reader.ts b/developer/src/common/web/utils/test/kmx/test-ldml-keyboard-xml-reader.ts
similarity index 95%
rename from common/web/types/test/ldml-keyboard/test-ldml-keyboard-xml-reader.ts
rename to developer/src/common/web/utils/test/kmx/test-ldml-keyboard-xml-reader.ts
index fa99be5267..a79960c7ca 100644
--- a/common/web/types/test/ldml-keyboard/test-ldml-keyboard-xml-reader.ts
+++ b/developer/src/common/web/utils/test/kmx/test-ldml-keyboard-xml-reader.ts
@@ -1,9 +1,13 @@
-import { LKKey, ImportStatus } from './../../src/ldml-keyboard/ldml-keyboard-xml.js';
+import { LKKey, ImportStatus } from '../../src/types/ldml-keyboard/ldml-keyboard-xml.js';
import 'mocha';
import {assert} from 'chai';
-import { CommonTypesMessages } from '../../src/util/common-events.js';
+import { CommonTypesMessages } from '../../src/common-events.js';
import { testReaderCases } from '../helpers/reader-callback-test.js';
-import { CLDRScanToVkey, CLDRScanToKeyMap, USVirtualKeyCodes } from '../../src/consts/virtual-key-constants.js';
+import { Constants } from '@keymanapp/common-types';
+
+import CLDRScanToVkey = Constants.CLDRScanToVkey;
+import CLDRScanToKeyMap = Constants.CLDRScanToKeyMap;
+import USVirtualKeyCodes = Constants.USVirtualKeyCodes;
function pluckKeysFromKeybag(keys: LKKey[], ids: string[]) {
return keys.filter(({id}) => ids.indexOf(id) !== -1);
diff --git a/common/web/types/test/kpj/test-kpj-file-reader.ts b/developer/src/common/web/utils/test/kpj/test-kpj-file-reader.ts
similarity index 97%
rename from common/web/types/test/kpj/test-kpj-file-reader.ts
rename to developer/src/common/web/utils/test/kpj/test-kpj-file-reader.ts
index cbebdd7920..4b154af060 100644
--- a/common/web/types/test/kpj/test-kpj-file-reader.ts
+++ b/developer/src/common/web/utils/test/kpj/test-kpj-file-reader.ts
@@ -2,9 +2,9 @@ import * as fs from 'fs';
import 'mocha';
import {assert} from 'chai';
import { makePathToFixture } from '../helpers/index.js';
-import { KPJFileReader } from "../../src/kpj/kpj-file-reader.js";
-import { KeymanDeveloperProjectFile10, KeymanDeveloperProjectType } from '../../src/kpj/keyman-developer-project.js';
-import { TestCompilerCallbacks } from '../helpers/TestCompilerCallbacks.js';
+import { KPJFileReader } from "../../src/types/kpj/kpj-file-reader.js";
+import { KeymanDeveloperProjectFile10, KeymanDeveloperProjectType } from '../../src/types/kpj/keyman-developer-project.js';
+import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
const callbacks = new TestCompilerCallbacks();
diff --git a/common/web/types/test/kvk/test-kvk-round-trip.ts b/developer/src/common/web/utils/test/kvks/test-kvk-round-trip.ts
similarity index 85%
rename from common/web/types/test/kvk/test-kvk-round-trip.ts
rename to developer/src/common/web/utils/test/kvks/test-kvk-round-trip.ts
index 7211ac3a35..b056bf4eed 100644
--- a/common/web/types/test/kvk/test-kvk-round-trip.ts
+++ b/developer/src/common/web/utils/test/kvks/test-kvk-round-trip.ts
@@ -5,10 +5,9 @@ import Hexy from 'hexy';
import gitDiff from 'git-diff';
const { hexy } = Hexy;
import { makePathToFixture } from '../helpers/index.js';
-import KvksFileReader from "../../src/kvk/kvks-file-reader.js";
-import KvkFileReader from "../../src/kvk/kvk-file-reader.js";
-import KvkFileWriter from "../../src/kvk/kvk-file-writer.js";
-import KvksFileWriter from "../../src/kvk/kvks-file-writer.js";
+import KvksFileReader from "../../src/types/kvks/kvks-file-reader.js";
+import { KvkFileReader, KvkFileWriter } from "@keymanapp/common-types";
+import KvksFileWriter from "../../src/types/kvks/kvks-file-writer.js";
/**
*
@@ -28,7 +27,7 @@ function assertBufferMatch(actual: Buffer, expected: Buffer) {
describe('kvk-file-reader', function () {
it('kvk-file-reader should round-trip with kvk-file-writer', function() {
- const path = makePathToFixture('kvk', 'khmer_angkor.kvk');
+ const path = makePathToFixture('kvks', 'khmer_angkor.kvk');
const input = fs.readFileSync(path);
const reader = new KvkFileReader();
const vk = reader.read(input);
@@ -44,8 +43,8 @@ describe('kvk-file-reader', function () {
describe('kvks-file-reader', function () {
it('kvks-file-reader should compile with kvk-file-writer', function() {
- const inputPath = makePathToFixture('kvk', 'khmer_angkor.kvks');
- const compiledPath = makePathToFixture('kvk', 'khmer_angkor.kvk');
+ const inputPath = makePathToFixture('kvks', 'khmer_angkor.kvks');
+ const compiledPath = makePathToFixture('kvks', 'khmer_angkor.kvk');
const input = fs.readFileSync(inputPath);
const compiled = fs.readFileSync(compiledPath);
const reader = new KvksFileReader();
@@ -63,7 +62,7 @@ describe('kvks-file-reader', function () {
describe('kvks-file-writer', function() {
it('kvks-file-writer should match what kvk-file-reader reads', function() {
- const kvkIn = makePathToFixture('kvk', 'khmer_angkor.kvk');
+ const kvkIn = makePathToFixture('kvks', 'khmer_angkor.kvk');
const kvkBuf = fs.readFileSync(kvkIn);
const kvkReader = new KvkFileReader();
const kvksReader = new KvksFileReader();
@@ -85,7 +84,7 @@ describe('kvks-file-reader', function () {
});
it('should have identical input and output for kvk and kvks', function() {
- const path = makePathToFixture('kvk', 'balochi_inpage.kvks');
+ const path = makePathToFixture('kvks', 'balochi_inpage.kvks');
const input = fs.readFileSync(path);
const reader = new KvksFileReader();
@@ -104,7 +103,7 @@ describe('kvks-file-reader', function () {
assert.deepEqual(vk, vkExpected);
// Then compare against the .kvk
- const kvkPath = makePathToFixture('kvk', 'balochi_inpage.kvk');
+ const kvkPath = makePathToFixture('kvks', 'balochi_inpage.kvk');
const kvkInput = fs.readFileSync(kvkPath);
const kvkReader = new KvkFileReader();
diff --git a/developer/src/common/web/utils/test/kvks/test-kvk-utils.ts b/developer/src/common/web/utils/test/kvks/test-kvk-utils.ts
new file mode 100644
index 0000000000..fe4c626d72
--- /dev/null
+++ b/developer/src/common/web/utils/test/kvks/test-kvk-utils.ts
@@ -0,0 +1,48 @@
+// NOTE: this is a copy of common/web/types/test/kvk/test-kvk-utils.ts
+import 'mocha';
+import {assert} from 'chai';
+import { VisualKeyboard as VK } from "@keymanapp/common-types";
+import VisualKeyboard = VK.VisualKeyboard;
+import VisualKeyboardHeaderFlags = VK.VisualKeyboardHeaderFlags;
+import VisualKeyboardKeyFlags = VK.VisualKeyboardKeyFlags;
+import VisualKeyboardShiftState = VK.VisualKeyboardShiftState;
+import { Constants } from '@keymanapp/common-types';
+import USVirtualKeyCodes = Constants.USVirtualKeyCodes;
+
+export function verify_khmer_angkor(vk: VisualKeyboard) {
+ assert.equal(vk.header.flags, VisualKeyboardHeaderFlags.kvkhAltGr);
+ assert.equal(vk.header.associatedKeyboard, 'khmer_angkor');
+ assert.equal(vk.header.ansiFont.name, 'Arial');
+ assert.equal(vk.header.ansiFont.size, -12);
+ assert.equal(vk.header.unicodeFont.name, 'Khmer Busra Kbd');
+ assert.equal(vk.header.unicodeFont.size, 16);
+ assert.equal(vk.keys.length, 186);
+ assert.equal(vk.keys[0].flags, VisualKeyboardKeyFlags.kvkkUnicode);
+ assert.equal(vk.keys[0].vkey, USVirtualKeyCodes.K_B);
+ assert.equal(vk.keys[0].shift, VisualKeyboardShiftState.KVKS_RALT);
+ assert.equal(vk.keys[0].text, 'ឞ');
+ assert.equal(vk.keys[185].flags, VisualKeyboardKeyFlags.kvkkUnicode);
+ assert.equal(vk.keys[185].vkey, USVirtualKeyCodes.K_COMMA);
+ assert.equal(vk.keys[185].shift, VisualKeyboardShiftState.KVKS_SHIFT);
+ assert.equal(vk.keys[185].text, '');
+}
+
+export function verify_balochi_inpage(vk: VisualKeyboard) {
+ assert.equal(vk.header.flags,
+ VisualKeyboardHeaderFlags.kvkhAltGr | VisualKeyboardHeaderFlags.kvkhDisplayUnderlying);
+ assert.equal(vk.header.associatedKeyboard, 'balochi_inpage');
+ assert.equal(vk.header.unicodeFont.name, 'Lateef');
+ assert.equal(vk.header.unicodeFont.size, 14);
+ assert.equal(vk.keys.length, 147);
+ assert.equal(vk.keys[0].flags, VisualKeyboardKeyFlags.kvkkUnicode);
+ assert.equal(vk.keys[0].vkey, USVirtualKeyCodes.K_BKQUOTE);
+ assert.equal(vk.keys[0].shift, VisualKeyboardShiftState.KVKS_RALT);
+ assert.equal(vk.keys[0].text, '');
+ assert.equal(vk.keys[30].flags,
+ VisualKeyboardKeyFlags.kvkkUnicode | VisualKeyboardKeyFlags.kvkkBitmap);
+ assert.equal(vk.keys[30].vkey, USVirtualKeyCodes.K_COMMA);
+ assert.equal(vk.keys[30].shift,
+ VisualKeyboardShiftState.KVKS_LCTRL);
+ assert.equal(vk.keys[30].text, '');
+ assert.equal(vk.keys[30].bitmap.byteLength, 35766);
+}
\ No newline at end of file
diff --git a/common/web/types/test/kvk/test-kvks-file.ts b/developer/src/common/web/utils/test/kvks/test-kvks-file.ts
similarity index 82%
rename from common/web/types/test/kvk/test-kvks-file.ts
rename to developer/src/common/web/utils/test/kvks/test-kvks-file.ts
index 2cd1a965c6..80851647bd 100644
--- a/common/web/types/test/kvk/test-kvks-file.ts
+++ b/developer/src/common/web/utils/test/kvks/test-kvks-file.ts
@@ -1,14 +1,14 @@
import * as fs from 'fs';
import 'mocha';
import { makePathToFixture } from '../helpers/index.js';
-import KvksFileReader from "../../src/kvk/kvks-file-reader.js";
-import KvksFileWriter from "../../src/kvk/kvks-file-writer.js";
+import KvksFileReader from "../../src/types/kvks/kvks-file-reader.js";
+import KvksFileWriter from "../../src/types/kvks/kvks-file-writer.js";
import { verify_khmer_angkor, verify_balochi_inpage } from './test-kvk-utils.js';
import { assert } from 'chai';
describe('kvks-file-reader', function() {
it('should read a valid file', function() {
- const path = makePathToFixture('kvk', 'khmer_angkor.kvks');
+ const path = makePathToFixture('kvks', 'khmer_angkor.kvks');
const input = fs.readFileSync(path);
const reader = new KvksFileReader();
@@ -23,7 +23,7 @@ describe('kvks-file-reader', function() {
});
it('should read a valid file with bitmaps', function() {
- const path = makePathToFixture('kvk', 'balochi_inpage.kvks');
+ const path = makePathToFixture('kvks', 'balochi_inpage.kvks');
const input = fs.readFileSync(path);
const reader = new KvksFileReader();
const kvks = reader.read(input);
@@ -34,7 +34,7 @@ describe('kvks-file-reader', function() {
});
it('should give a sensible error on a .kvk file', function() {
- const path = makePathToFixture('kvk', 'khmer_angkor.kvk');
+ const path = makePathToFixture('kvks', 'khmer_angkor.kvk');
const input = fs.readFileSync(path);
const reader = new KvksFileReader();
@@ -44,7 +44,7 @@ describe('kvks-file-reader', function() {
describe('kvks-file-writer', function() {
it('should write a valid file', function() {
- const path = makePathToFixture('kvk', 'khmer_angkor.kvks');
+ const path = makePathToFixture('kvks', 'khmer_angkor.kvks');
const input = fs.readFileSync(path);
const reader = new KvksFileReader();
diff --git a/developer/src/common/web/utils/test/test-license.ts b/developer/src/common/web/utils/test/test-license.ts
index 653f89ba69..501f4f4711 100644
--- a/developer/src/common/web/utils/test/test-license.ts
+++ b/developer/src/common/web/utils/test/test-license.ts
@@ -2,7 +2,7 @@ import * as fs from 'fs';
import { assert } from 'chai';
import 'mocha';
import { makePathToFixture } from './helpers/index.js';
-import { validateMITLicense } from '../src/validate-mit-license.js';
+import { validateMITLicense } from '../src/utils/validate-mit-license.js';
function verifyLicenseFile(filename: string) {
return validateMITLicense(fs.readFileSync(makePathToFixture('license', filename), 'utf-8'));
diff --git a/developer/src/common/web/utils/tsconfig.json b/developer/src/common/web/utils/tsconfig.json
index c5980c82f9..3be972dbcb 100644
--- a/developer/src/common/web/utils/tsconfig.json
+++ b/developer/src/common/web/utils/tsconfig.json
@@ -7,7 +7,7 @@
"baseUrl": ".",
},
"include": [
- "index.ts",
"src/**/*.ts",
+ "src/deps/xml2js/*.js",
],
}
\ No newline at end of file
diff --git a/developer/src/kmc-analyze/src/analyzer-messages.ts b/developer/src/kmc-analyze/src/analyzer-messages.ts
index 4cf6b83273..1e4204595e 100644
--- a/developer/src/kmc-analyze/src/analyzer-messages.ts
+++ b/developer/src/kmc-analyze/src/analyzer-messages.ts
@@ -1,8 +1,7 @@
///
// above is required for now, seemingly https://github.com/microsoft/TypeScript/issues/42873
// probably addressed in ts 5.5.2
-import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m, CompilerMessageDef as def, CompilerMessageSpecWithException } from "@keymanapp/common-types";
-import { KeymanUrls } from "@keymanapp/developer-utils";
+import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m, CompilerMessageDef as def, CompilerMessageSpecWithException, KeymanUrls } from "@keymanapp/developer-utils";
const Namespace = CompilerErrorNamespace.Analyzer;
const SevInfo = CompilerErrorSeverity.Info | Namespace;
diff --git a/developer/src/kmc-analyze/src/osk-character-use/index.ts b/developer/src/kmc-analyze/src/osk-character-use/index.ts
index 86585ba961..36fbf0e78c 100644
--- a/developer/src/kmc-analyze/src/osk-character-use/index.ts
+++ b/developer/src/kmc-analyze/src/osk-character-use/index.ts
@@ -1,6 +1,6 @@
-import { CompilerCallbacks, KeymanFileTypes, KvksFile, KvksFileReader, TouchLayout, TouchLayoutFileReader } from "@keymanapp/common-types";
+import { KeymanFileTypes, TouchLayout } from "@keymanapp/common-types";
import { KmnCompilerMessages, Osk } from '@keymanapp/kmc-kmn';
-import { escapeMarkdownChar } from '@keymanapp/developer-utils';
+import { CompilerCallbacks, escapeMarkdownChar, KvksFile, KvksFileReader, TouchLayoutFileReader } from '@keymanapp/developer-utils';
import { getOskFromKmnFile } from "../util/get-osk-from-kmn-file.js";
import { AnalyzerMessages } from "../analyzer-messages.js";
diff --git a/developer/src/kmc-analyze/src/osk-rewrite-pua/index.ts b/developer/src/kmc-analyze/src/osk-rewrite-pua/index.ts
index fdc5143a30..dc56ebfb3a 100644
--- a/developer/src/kmc-analyze/src/osk-rewrite-pua/index.ts
+++ b/developer/src/kmc-analyze/src/osk-rewrite-pua/index.ts
@@ -1,4 +1,5 @@
-import { CompilerCallbacks, KeymanFileTypes, KvksFile, KvksFileReader, KvksFileWriter, TouchLayoutFileReader, TouchLayoutFileWriter } from "@keymanapp/common-types";
+import { KeymanFileTypes } from "@keymanapp/common-types";
+import { CompilerCallbacks, KvksFile, KvksFileReader, KvksFileWriter, TouchLayoutFileReader, TouchLayoutFileWriter } from '@keymanapp/developer-utils';
import { KmnCompilerMessages, Osk } from '@keymanapp/kmc-kmn';
import { getOskFromKmnFile } from "../util/get-osk-from-kmn-file.js";
import { AnalyzerMessages } from "../analyzer-messages.js";
diff --git a/developer/src/kmc-analyze/src/util/get-osk-from-kmn-file.ts b/developer/src/kmc-analyze/src/util/get-osk-from-kmn-file.ts
index 0e2ec28995..b9fd9cb602 100644
--- a/developer/src/kmc-analyze/src/util/get-osk-from-kmn-file.ts
+++ b/developer/src/kmc-analyze/src/util/get-osk-from-kmn-file.ts
@@ -1,4 +1,5 @@
-import { CompilerCallbacks, KMX, KmxFileReader } from "@keymanapp/common-types";
+import { KMX, KmxFileReader } from "@keymanapp/common-types";
+import { CompilerCallbacks } from "@keymanapp/developer-utils";
import { KmnCompiler } from "@keymanapp/kmc-kmn";
export async function getOskFromKmnFile(callbacks: CompilerCallbacks, filename: string): Promise<{
diff --git a/developer/src/kmc-keyboard-info/src/keyboard-info-compiler-messages.ts b/developer/src/kmc-keyboard-info/src/keyboard-info-compiler-messages.ts
index d1a4c632c0..285e272da5 100644
--- a/developer/src/kmc-keyboard-info/src/keyboard-info-compiler-messages.ts
+++ b/developer/src/kmc-keyboard-info/src/keyboard-info-compiler-messages.ts
@@ -1,4 +1,4 @@
-import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m, CompilerMessageDef as def, CompilerMessageSpecWithException } from "@keymanapp/common-types";
+import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m, CompilerMessageDef as def, CompilerMessageSpecWithException } from "@keymanapp/developer-utils";
const Namespace = CompilerErrorNamespace.KeyboardInfoCompiler;
// const SevInfo = CompilerErrorSeverity.Info | Namespace;
diff --git a/developer/src/kmc-keyboard-info/src/keyboard-info-compiler.ts b/developer/src/kmc-keyboard-info/src/keyboard-info-compiler.ts
index f829734ccc..7469955698 100644
--- a/developer/src/kmc-keyboard-info/src/keyboard-info-compiler.ts
+++ b/developer/src/kmc-keyboard-info/src/keyboard-info-compiler.ts
@@ -5,10 +5,10 @@
import { minKeymanVersion } from "./min-keyman-version.js";
import { KeyboardInfoFile, KeyboardInfoFileIncludes, KeyboardInfoFileLanguageFont, KeyboardInfoFilePlatform } from "./keyboard-info-file.js";
-import { KeymanFileTypes, CompilerCallbacks, KmpJsonFile, KmxFileReader, KMX, KeymanTargets, KeymanCompiler, CompilerOptions, KeymanCompilerResult, KeymanCompilerArtifacts, KeymanCompilerArtifact } from "@keymanapp/common-types";
+import { KeymanFileTypes, KmpJsonFile, KmxFileReader, KMX, KeymanTargets } from "@keymanapp/common-types";
import { KeyboardInfoCompilerMessages } from "./keyboard-info-compiler-messages.js";
import langtags from "./imports/langtags.js";
-import { KeymanUrls, isValidEmail, validateMITLicense } from "@keymanapp/developer-utils";
+import { CompilerCallbacks, KeymanCompiler, CompilerOptions, KeymanCompilerResult, KeymanCompilerArtifacts, KeymanCompilerArtifact, KeymanUrls, isValidEmail, validateMITLicense } from "@keymanapp/developer-utils";
import { KmpCompiler } from "@keymanapp/kmc-package";
import { SchemaValidators } from "@keymanapp/common-types";
diff --git a/developer/src/kmc-keyboard-info/test/test-keyboard-info-compiler-messages.ts b/developer/src/kmc-keyboard-info/test/test-keyboard-info-compiler-messages.ts
index 2d205f8f47..2bf73b7dd3 100644
--- a/developer/src/kmc-keyboard-info/test/test-keyboard-info-compiler-messages.ts
+++ b/developer/src/kmc-keyboard-info/test/test-keyboard-info-compiler-messages.ts
@@ -2,7 +2,8 @@ import { assert } from 'chai';
import 'mocha';
import { KeyboardInfoCompilerMessages } from '../src/keyboard-info-compiler-messages.js';
import { TestCompilerCallbacks, verifyCompilerMessagesObject } from '@keymanapp/developer-test-helpers';
-import { CompilerErrorNamespace, KmpJsonFile, KeymanFileTypes } from '@keymanapp/common-types';
+import { KmpJsonFile, KeymanFileTypes } from '@keymanapp/common-types';
+import { CompilerErrorNamespace } from '@keymanapp/developer-utils';
import { makePathToFixture } from './helpers/index.js';
import { KeyboardInfoCompiler, KeyboardInfoCompilerResult } from '../src/keyboard-info-compiler.js';
import { KeyboardInfoFile } from '../src/keyboard-info-file.js';
diff --git a/developer/src/kmc-keyboard-info/test/test-keyboard-info-compiler.ts b/developer/src/kmc-keyboard-info/test/test-keyboard-info-compiler.ts
index f857c5d896..9b61b8e93d 100644
--- a/developer/src/kmc-keyboard-info/test/test-keyboard-info-compiler.ts
+++ b/developer/src/kmc-keyboard-info/test/test-keyboard-info-compiler.ts
@@ -6,7 +6,8 @@ import { makePathToFixture } from './helpers/index.js';
import { KeyboardInfoCompiler, KeyboardInfoCompilerResult, unitTestEndpoints } from '../src/keyboard-info-compiler.js';
import langtags from "../src/imports/langtags.js";
import { KmpCompiler, KmpCompilerOptions } from '@keymanapp/kmc-package';
-import { CompilerCallbacks, KMX, KeymanFileTypes, KeymanTargets, KmpJsonFile } from '@keymanapp/common-types';
+import { KMX, KeymanFileTypes, KeymanTargets, KmpJsonFile } from '@keymanapp/common-types';
+import { CompilerCallbacks } from '@keymanapp/developer-utils';
import { KeyboardInfoFile, KeyboardInfoFileLanguage, KeyboardInfoFilePlatform } from './keyboard-info-file.js';
const callbacks = new TestCompilerCallbacks();
diff --git a/developer/src/kmc-kmn/src/compiler/compiler.ts b/developer/src/kmc-kmn/src/compiler/compiler.ts
index f8938be60e..afb980e2fc 100644
--- a/developer/src/kmc-kmn/src/compiler/compiler.ts
+++ b/developer/src/kmc-kmn/src/compiler/compiler.ts
@@ -6,8 +6,11 @@ TODO: implement additional interfaces:
*/
// TODO: rename wasm-host?
-import { UnicodeSetParser, UnicodeSet, VisualKeyboard, KvkFileReader, KeymanCompiler, KeymanCompilerArtifacts, KeymanCompilerArtifactOptional, KeymanCompilerResult, KeymanCompilerArtifact } from '@keymanapp/common-types';
-import { CompilerCallbacks, CompilerEvent, CompilerOptions, KeymanFileTypes, KvkFileWriter, KvksFileReader } from '@keymanapp/common-types';
+import { VisualKeyboard, KvkFileReader, UnicodeSetParser, UnicodeSet, KeymanFileTypes, KvkFileWriter } from '@keymanapp/common-types';
+import {
+ CompilerCallbacks, CompilerEvent, CompilerOptions, KeymanCompiler, KeymanCompilerArtifacts,
+ KeymanCompilerArtifactOptional, KeymanCompilerResult, KeymanCompilerArtifact, KvksFileReader
+} from '@keymanapp/developer-utils';
import * as Osk from './osk.js';
import loadWasmHost from '../import/kmcmplib/wasm-host.js';
import { KmnCompilerMessages } from './kmn-compiler-messages.js';
diff --git a/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts b/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts
index d40da3f492..8d2d4c88ea 100644
--- a/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts
+++ b/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts
@@ -1,6 +1,5 @@
-import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerEvent, CompilerMessageSpec as m, CompilerMessageDef as def, CompilerMessageSpecWithException } from "@keymanapp/common-types";
import { kmnfile } from "../kmw-compiler/compiler-globals.js";
-import { KeymanUrls } from "@keymanapp/developer-utils";
+import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerEvent, CompilerMessageSpec as m, CompilerMessageDef as def, CompilerMessageSpecWithException, KeymanUrls } from "@keymanapp/developer-utils";
const Namespace = CompilerErrorNamespace.KmnCompiler;
const SevInfo = CompilerErrorSeverity.Info | Namespace;
diff --git a/developer/src/kmc-kmn/src/kmw-compiler/compiler-globals.ts b/developer/src/kmc-kmn/src/kmw-compiler/compiler-globals.ts
index 520c468b3a..a8c1e1b72c 100644
--- a/developer/src/kmc-kmn/src/kmw-compiler/compiler-globals.ts
+++ b/developer/src/kmc-kmn/src/kmw-compiler/compiler-globals.ts
@@ -1,4 +1,5 @@
-import { KMX, CompilerCallbacks, CompilerOptions } from "@keymanapp/common-types";
+import { KMX } from "@keymanapp/common-types";
+import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils";
import { KmnCompilerResult } from "../compiler/compiler.js";
export let FTabStop: string;
diff --git a/developer/src/kmc-kmn/src/kmw-compiler/kmw-compiler-messages.ts b/developer/src/kmc-kmn/src/kmw-compiler/kmw-compiler-messages.ts
index 448b6bd6ac..5170a8d678 100644
--- a/developer/src/kmc-kmn/src/kmw-compiler/kmw-compiler-messages.ts
+++ b/developer/src/kmc-kmn/src/kmw-compiler/kmw-compiler-messages.ts
@@ -1,5 +1,5 @@
import { KmnCompilerMessages } from "../compiler/kmn-compiler-messages.js";
-import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerEvent, CompilerMessageDef as def, CompilerMessageSpec } from "@keymanapp/common-types";
+import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerEvent, CompilerMessageDef as def, CompilerMessageSpec } from "@keymanapp/developer-utils";
import { kmnfile } from "./compiler-globals.js";
const Namespace = CompilerErrorNamespace.KmwCompiler;
diff --git a/developer/src/kmc-kmn/src/kmw-compiler/kmw-compiler.ts b/developer/src/kmc-kmn/src/kmw-compiler/kmw-compiler.ts
index 65f2111ecf..5dcde400ea 100644
--- a/developer/src/kmc-kmn/src/kmw-compiler/kmw-compiler.ts
+++ b/developer/src/kmc-kmn/src/kmw-compiler/kmw-compiler.ts
@@ -1,4 +1,5 @@
-import { KMX, CompilerOptions, CompilerCallbacks, KvkFileReader, VisualKeyboard, KmxFileReader, KvkFile } from "@keymanapp/common-types";
+import { KMX, KvkFileReader, VisualKeyboard, KmxFileReader, KvkFile } from "@keymanapp/common-types";
+import { CompilerOptions, CompilerCallbacks } from "@keymanapp/developer-utils";
import { ExpandSentinel, incxstr, xstrlen } from "./util.js";
import { options, nl, FTabStop, setupGlobals, callbacks, FFix183_LadderLength, FCallFunctions, fk, minimumKeymanVersionToString, isKeyboardVersion10OrLater, isKeyboardVersion17OrLater } from "./compiler-globals.js";
import { JavaScript_ContextMatch, JavaScript_KeyAsString, JavaScript_Name, JavaScript_OutputString, JavaScript_Rules, JavaScript_Shift, JavaScript_ShiftAsString, JavaScript_Store, zeroPadHex } from './javascript-strings.js';
diff --git a/developer/src/kmc-kmn/src/kmw-compiler/validate-layout-file.ts b/developer/src/kmc-kmn/src/kmw-compiler/validate-layout-file.ts
index 7432204cb1..61d0985f87 100644
--- a/developer/src/kmc-kmn/src/kmw-compiler/validate-layout-file.ts
+++ b/developer/src/kmc-kmn/src/kmw-compiler/validate-layout-file.ts
@@ -1,4 +1,5 @@
-import { KMX, TouchLayout, TouchLayoutFileReader, TouchLayoutFileWriter } from "@keymanapp/common-types";
+import { KMX, TouchLayout } from "@keymanapp/common-types";
+import { TouchLayoutFileReader, TouchLayoutFileWriter } from "@keymanapp/developer-utils";
import { callbacks, minimumKeymanVersion, verifyAndSetMinimumRequiredKeymanVersion15,
isKeyboardVersion14OrLater, isKeyboardVersion17OrLater,
verifyAndSetMinimumRequiredKeymanVersion14,
diff --git a/developer/src/kmc-kmn/test/kmw/test-kmw-compiler.ts b/developer/src/kmc-kmn/test/kmw/test-kmw-compiler.ts
index 3e9cbaba87..37a58384b2 100644
--- a/developer/src/kmc-kmn/test/kmw/test-kmw-compiler.ts
+++ b/developer/src/kmc-kmn/test/kmw/test-kmw-compiler.ts
@@ -229,7 +229,7 @@ async function run_test_keyboard(kmnCompiler: KmnCompiler, id: string):
fs.writeFileSync(filenames.binary, value.actualCode);
}
- assert.deepEqual(value.actual.js, value.expected.js);
+ assert.deepEqual(value.actual.js.replaceAll(/\r\n/g, '\n'), value.expected.js.replaceAll(/\r\n/g, '\n'));
assert.deepEqual(JSON.parse(value.actual.touchLayout), JSON.parse(value.expected.touchLayout));
return value;
diff --git a/developer/src/kmc-kmn/test/kmw/test-kmw-messages.ts b/developer/src/kmc-kmn/test/kmw/test-kmw-messages.ts
index 2021f6787b..20a1a5c83b 100644
--- a/developer/src/kmc-kmn/test/kmw/test-kmw-messages.ts
+++ b/developer/src/kmc-kmn/test/kmw/test-kmw-messages.ts
@@ -4,7 +4,7 @@ import { KmwCompilerMessages } from '../../src/kmw-compiler/kmw-compiler-message
import { TestCompilerCallbacks, verifyCompilerMessagesObject } from '@keymanapp/developer-test-helpers';
import { makePathToFixture } from '../helpers/index.js';
import { KmnCompiler } from '../../src/main.js';
-import { CompilerErrorNamespace } from '@keymanapp/common-types';
+import { CompilerErrorNamespace } from '@keymanapp/developer-utils';
describe('KmwCompilerMessages', function () {
const callbacks = new TestCompilerCallbacks();
diff --git a/developer/src/kmc-kmn/test/test-messages.ts b/developer/src/kmc-kmn/test/test-messages.ts
index ea697a0174..0c3f17a58c 100644
--- a/developer/src/kmc-kmn/test/test-messages.ts
+++ b/developer/src/kmc-kmn/test/test-messages.ts
@@ -4,7 +4,7 @@ import { KmnCompilerMessageRanges, KmnCompilerMessages } from '../src/compiler/k
import { TestCompilerCallbacks, verifyCompilerMessagesObject } from '@keymanapp/developer-test-helpers';
import { makePathToFixture } from './helpers/index.js';
import { KmnCompiler } from '../src/main.js';
-import { CompilerErrorMask, CompilerErrorNamespace } from '@keymanapp/common-types';
+import { CompilerErrorMask, CompilerErrorNamespace } from '@keymanapp/developer-utils';
describe('KmnCompilerMessages', function () {
const callbacks = new TestCompilerCallbacks();
diff --git a/developer/src/kmc-kmn/test/test-wasm-uset.ts b/developer/src/kmc-kmn/test/test-wasm-uset.ts
index 7c25513651..ad67b35246 100644
--- a/developer/src/kmc-kmn/test/test-wasm-uset.ts
+++ b/developer/src/kmc-kmn/test/test-wasm-uset.ts
@@ -3,7 +3,7 @@ import { assert } from 'chai';
import { KmnCompiler } from '../src/main.js';
import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
import { KmnCompilerMessages } from '../src/compiler/kmn-compiler-messages.js';
-import { compilerErrorFormatCode } from '@keymanapp/common-types';
+import { compilerErrorFormatCode } from '@keymanapp/developer-utils';
describe('Compiler UnicodeSet function', function() {
it('should fixup "short" \\u{} escapes', function () {
diff --git a/developer/src/kmc-ldml/build.sh b/developer/src/kmc-ldml/build.sh
index 41b5e49478..73a40c79d7 100755
--- a/developer/src/kmc-ldml/build.sh
+++ b/developer/src/kmc-ldml/build.sh
@@ -14,6 +14,7 @@ builder_describe "Keyman kmc Keyboard Compiler module" \
"@/common/web/keyman-version" \
"@/common/web/types" \
"@/developer/src/kmc-kmn" \
+ "@/developer/src/common/web/utils" \
"@/developer/src/common/web/test-helpers" \
"configure" \
"build" \
diff --git a/developer/src/kmc-ldml/package.json b/developer/src/kmc-ldml/package.json
index ef1a17bd68..e423b9cd00 100644
--- a/developer/src/kmc-ldml/package.json
+++ b/developer/src/kmc-ldml/package.json
@@ -26,6 +26,7 @@
},
"dependencies": {
"@keymanapp/keyman-version": "*",
+ "@keymanapp/developer-utils": "*",
"@keymanapp/kmc-kmn": "*",
"@keymanapp/ldml-keyboard-constants": "*",
"semver": "^7.5.2"
diff --git a/developer/src/kmc-ldml/src/compiler/compiler.ts b/developer/src/kmc-ldml/src/compiler/compiler.ts
index 59ed5f9a07..77516ab564 100644
--- a/developer/src/kmc-ldml/src/compiler/compiler.ts
+++ b/developer/src/kmc-ldml/src/compiler/compiler.ts
@@ -1,4 +1,10 @@
-import { LDMLKeyboardXMLSourceFileReader, LDMLKeyboard, KMXPlus, CompilerCallbacks, LDMLKeyboardTestDataXMLSourceFile, UnicodeSetParser, KeymanCompiler, KeymanCompilerResult, KeymanCompilerArtifacts, defaultCompilerOptions, KMXBuilder, KvkFileWriter, KeymanCompilerArtifactOptional } from '@keymanapp/common-types';
+import { KMXPlus, UnicodeSetParser, KvkFileWriter } from '@keymanapp/common-types';
+import {
+ CompilerCallbacks, KeymanCompiler, KeymanCompilerResult, KeymanCompilerArtifacts,
+ defaultCompilerOptions, LDMLKeyboardXMLSourceFileReader, LDMLKeyboard,
+ LDMLKeyboardTestDataXMLSourceFile, KMXBuilder,
+ KeymanCompilerArtifactOptional
+} from "@keymanapp/developer-utils";
import { LdmlCompilerOptions } from './ldml-compiler-options.js';
import { LdmlCompilerMessages } from './ldml-compiler-messages.js';
import { BkspCompiler, TranCompiler } from './tran.js';
@@ -99,7 +105,7 @@ export class LdmlKeyboardCompiler implements KeymanCompiler {
* @returns false if initialization fails
*/
async init(callbacks: CompilerCallbacks, options: LdmlCompilerOptions): Promise {
- this.options = {...options};
+ this.options = { ...options };
this.callbacks = callbacks;
return true;
}
@@ -178,15 +184,15 @@ export class LdmlKeyboardCompiler implements KeymanCompiler {
* @returns true on success
*/
async write(artifacts: LdmlKeyboardCompilerArtifacts): Promise {
- if(artifacts.kmx) {
+ if (artifacts.kmx) {
this.callbacks.fs.writeFileSync(artifacts.kmx.filename, artifacts.kmx.data);
}
- if(artifacts.kvk) {
+ if (artifacts.kvk) {
this.callbacks.fs.writeFileSync(artifacts.kvk.filename, artifacts.kvk.data);
}
- if(artifacts.js) {
+ if (artifacts.js) {
this.callbacks.fs.writeFileSync(artifacts.js.filename, artifacts.js.data);
}
@@ -198,7 +204,7 @@ export class LdmlKeyboardCompiler implements KeymanCompiler {
* Construct or return a UnicodeSetParser, aka KmnCompiler
* @returns the held UnicodeSetParser
*/
- async getUsetParser() : Promise {
+ async getUsetParser(): Promise {
if (this.usetparser === undefined) {
// initialize
const compiler = new KmnCompiler();
@@ -228,14 +234,14 @@ export class LdmlKeyboardCompiler implements KeymanCompiler {
const reader = new LDMLKeyboardXMLSourceFileReader(this.options.readerOptions, this.callbacks);
// load the file from disk into a string
const data = this.callbacks.loadFile(filename);
- if(!data) {
- this.callbacks.reportMessage(LdmlCompilerMessages.Error_InvalidFile({errorText: 'Unable to read XML file'}));
+ if (!data) {
+ this.callbacks.reportMessage(LdmlCompilerMessages.Error_InvalidFile({ errorText: 'Unable to read XML file' }));
return null;
}
// parse (load) the string into an object tree
const source = reader.load(data);
- if(!source) {
- this.callbacks.reportMessage(LdmlCompilerMessages.Error_InvalidFile({errorText: 'Unable to load XML file'}));
+ if (!source) {
+ this.callbacks.reportMessage(LdmlCompilerMessages.Error_InvalidFile({ errorText: 'Unable to load XML file' }));
return null;
}
try {
@@ -243,8 +249,8 @@ export class LdmlKeyboardCompiler implements KeymanCompiler {
if (!reader.validate(source)) {
return null;
}
- } catch(e) {
- this.callbacks.reportMessage(LdmlCompilerMessages.Error_InvalidFile({errorText: e.toString()}));
+ } catch (e) {
+ this.callbacks.reportMessage(LdmlCompilerMessages.Error_InvalidFile({ errorText: e.toString() }));
return null;
}
@@ -261,14 +267,14 @@ export class LdmlKeyboardCompiler implements KeymanCompiler {
public loadTestData(filename: string): LDMLKeyboardTestDataXMLSourceFile | null {
const reader = new LDMLKeyboardXMLSourceFileReader(this.options.readerOptions, this.callbacks);
const data = this.callbacks.loadFile(filename);
- if(!data) {
- this.callbacks.reportMessage(LdmlCompilerMessages.Error_InvalidFile({errorText: 'Unable to read XML file'}));
+ if (!data) {
+ this.callbacks.reportMessage(LdmlCompilerMessages.Error_InvalidFile({ errorText: 'Unable to read XML file' }));
return null;
}
const source = reader.loadTestData(data);
/* c8 ignore next 4 */
- if(!source) {
- this.callbacks.reportMessage(LdmlCompilerMessages.Error_InvalidFile({errorText: 'Unable to load XML file'}));
+ if (!source) {
+ this.callbacks.reportMessage(LdmlCompilerMessages.Error_InvalidFile({ errorText: 'Unable to load XML file' }));
return null;
}
// TODO-LDML: The unboxed data doesn't match the schema anymore. Skipping validation, for now.
@@ -294,7 +300,7 @@ export class LdmlKeyboardCompiler implements KeymanCompiler {
* Runs any linter steps
* @internal
*/
- private async lint(source: LDMLKeyboardXMLSourceFile, kmx: KMXPlus.KMXPlusFile) : Promise {
+ private async lint(source: LDMLKeyboardXMLSourceFile, kmx: KMXPlus.KMXPlusFile): Promise {
// run each of the linters
for (const linter of this.buildLinters(source, kmx)) {
if (!await linter.lint()) {
@@ -340,8 +346,8 @@ export class LdmlKeyboardCompiler implements KeymanCompiler {
const kmx = new KMXPlusFile();
- for(let section of sections) {
- if(!section.validate()) {
+ for (let section of sections) {
+ if (!section.validate()) {
// TODO-LDML: coverage
passed = false;
// We'll keep validating other sections anyway, so we get a full set of
@@ -349,13 +355,13 @@ export class LdmlKeyboardCompiler implements KeymanCompiler {
continue;
}
// clone
- const globalSections : DependencySections = Object.assign({}, kmx.kmxplus);
+ const globalSections: DependencySections = Object.assign({}, kmx.kmxplus);
// pre-initialize the usetparser
globalSections.usetparser = await this.getUsetParser();
const dependencies = section.dependencies;
let dependencyProblem = false;
- Object.keys(constants.section).forEach((sectstr : string) => {
- const sectid : SectionIdent = constants.section[sectstr];
+ Object.keys(constants.section).forEach((sectstr: string) => {
+ const sectid: SectionIdent = constants.section[sectstr];
if (dependencies.has(sectid)) {
/* c8 ignore next 4 */
if (!kmx.kmxplus[sectid]) {
@@ -379,12 +385,12 @@ export class LdmlKeyboardCompiler implements KeymanCompiler {
}
const sect = section.compile(globalSections);
- if(!sect) {
+ if (!sect) {
passed = false;
continue;
}
/* c8 ignore next 4 */
- if(kmx.kmxplus[section.id]) {
+ if (kmx.kmxplus[section.id]) {
// Internal error useful during section bring-up
throw new Error(`Internal error: section ${section.id} would be assigned twice`);
}
@@ -393,8 +399,8 @@ export class LdmlKeyboardCompiler implements KeymanCompiler {
// give all sections a chance to postValidate
if (postValidate) {
- for(let section of sections) {
- if(!section.postValidate(kmx.kmxplus[section.id])) {
+ for (let section of sections) {
+ if (!section.postValidate(kmx.kmxplus[section.id])) {
passed = false;
}
}
diff --git a/developer/src/kmc-ldml/src/compiler/disp.ts b/developer/src/kmc-ldml/src/compiler/disp.ts
index 769a1a1788..03c411ce8d 100644
--- a/developer/src/kmc-ldml/src/compiler/disp.ts
+++ b/developer/src/kmc-ldml/src/compiler/disp.ts
@@ -1,5 +1,6 @@
import { constants } from "@keymanapp/ldml-keyboard-constants";
-import { KMXPlus, LDMLKeyboard } from '@keymanapp/common-types';
+import { LDMLKeyboard } from '@keymanapp/developer-utils';
+import { KMXPlus } from "@keymanapp/common-types";
import { LdmlCompilerMessages } from "./ldml-compiler-messages.js";
import { SectionCompiler } from "./section-compiler.js";
diff --git a/developer/src/kmc-ldml/src/compiler/empty-compiler.ts b/developer/src/kmc-ldml/src/compiler/empty-compiler.ts
index 78dc771ff6..92c364e4dc 100644
--- a/developer/src/kmc-ldml/src/compiler/empty-compiler.ts
+++ b/developer/src/kmc-ldml/src/compiler/empty-compiler.ts
@@ -1,6 +1,7 @@
import { SectionIdent, constants } from '@keymanapp/ldml-keyboard-constants';
import { SectionCompiler } from "./section-compiler.js";
-import { util, LDMLKeyboard, KMXPlus, CompilerCallbacks, MarkerParser } from "@keymanapp/common-types";
+import { util, KMXPlus, MarkerParser } from "@keymanapp/common-types";
+import { CompilerCallbacks, LDMLKeyboard } from "@keymanapp/developer-utils";
import { VarsCompiler } from './vars.js';
import { LdmlCompilerMessages } from './ldml-compiler-messages.js';
diff --git a/developer/src/kmc-ldml/src/compiler/keymanweb-compiler.ts b/developer/src/kmc-ldml/src/compiler/keymanweb-compiler.ts
index a35739247b..86402b6d45 100644
--- a/developer/src/kmc-ldml/src/compiler/keymanweb-compiler.ts
+++ b/developer/src/kmc-ldml/src/compiler/keymanweb-compiler.ts
@@ -1,4 +1,5 @@
-import { CompilerCallbacks, VisualKeyboard, LDMLKeyboard, TouchLayoutFileWriter, KeymanFileTypes } from "@keymanapp/common-types";
+import { VisualKeyboard, KeymanFileTypes } from "@keymanapp/common-types";
+import { CompilerCallbacks, LDMLKeyboard, TouchLayoutFileWriter } from "@keymanapp/developer-utils";
import { LdmlCompilerOptions } from "./ldml-compiler-options.js";
import { TouchLayoutCompiler } from "./touch-layout-compiler.js";
import { LdmlKeyboardVisualKeyboardCompiler } from "./visual-keyboard-compiler.js";
diff --git a/developer/src/kmc-ldml/src/compiler/keys.ts b/developer/src/kmc-ldml/src/compiler/keys.ts
index 9e5de13246..e341f3ac87 100644
--- a/developer/src/kmc-ldml/src/compiler/keys.ts
+++ b/developer/src/kmc-ldml/src/compiler/keys.ts
@@ -1,5 +1,6 @@
import { SectionIdent, constants } from '@keymanapp/ldml-keyboard-constants';
-import { LDMLKeyboard, KMXPlus, Constants } from '@keymanapp/common-types';
+import { KMXPlus, Constants } from '@keymanapp/common-types';
+import { LDMLKeyboard } from '@keymanapp/developer-utils';
import { LdmlCompilerMessages } from './ldml-compiler-messages.js';
import { SectionCompiler } from "./section-compiler.js";
diff --git a/developer/src/kmc-ldml/src/compiler/ldml-compiler-messages.ts b/developer/src/kmc-ldml/src/compiler/ldml-compiler-messages.ts
index 2d6aa07415..1b6752bdee 100644
--- a/developer/src/kmc-ldml/src/compiler/ldml-compiler-messages.ts
+++ b/developer/src/kmc-ldml/src/compiler/ldml-compiler-messages.ts
@@ -1,4 +1,5 @@
-import { util, CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m, CompilerMessageDef as def } from "@keymanapp/common-types";
+import { util } from "@keymanapp/common-types";
+import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m, CompilerMessageDef as def } from '@keymanapp/developer-utils';
// const SevInfo = CompilerErrorSeverity.Info | CompilerErrorNamespace.LdmlKeyboardCompiler;
const SevHint = CompilerErrorSeverity.Hint | CompilerErrorNamespace.LdmlKeyboardCompiler;
const SevWarn = CompilerErrorSeverity.Warn | CompilerErrorNamespace.LdmlKeyboardCompiler;
diff --git a/developer/src/kmc-ldml/src/compiler/ldml-compiler-options.ts b/developer/src/kmc-ldml/src/compiler/ldml-compiler-options.ts
index 9ea0f043bb..1b4f72113c 100644
--- a/developer/src/kmc-ldml/src/compiler/ldml-compiler-options.ts
+++ b/developer/src/kmc-ldml/src/compiler/ldml-compiler-options.ts
@@ -1,4 +1,4 @@
-import { CompilerOptions, LDMLKeyboardXMLSourceFileReaderOptions } from "@keymanapp/common-types";
+import { CompilerOptions, LDMLKeyboardXMLSourceFileReaderOptions } from "@keymanapp/developer-utils";
/**
* @public
diff --git a/developer/src/kmc-ldml/src/compiler/linter.ts b/developer/src/kmc-ldml/src/compiler/linter.ts
index 2a74dfd0b5..f01d4bd841 100644
--- a/developer/src/kmc-ldml/src/compiler/linter.ts
+++ b/developer/src/kmc-ldml/src/compiler/linter.ts
@@ -1,4 +1,5 @@
-import { LDMLKeyboard, KMXPlus, CompilerCallbacks } from "@keymanapp/common-types";
+import { KMXPlus } from "@keymanapp/common-types";
+import { CompilerCallbacks, LDMLKeyboard } from "@keymanapp/developer-utils";
/** newable interface to Linter c'tor */
export type LinterNew = new (source: LDMLKeyboard.LDMLKeyboardXMLSourceFile, kmx: KMXPlus.KMXPlusFile, callbacks: CompilerCallbacks) => Linter;
diff --git a/developer/src/kmc-ldml/src/compiler/loca.ts b/developer/src/kmc-ldml/src/compiler/loca.ts
index 3a46475581..fea8cc4338 100644
--- a/developer/src/kmc-ldml/src/compiler/loca.ts
+++ b/developer/src/kmc-ldml/src/compiler/loca.ts
@@ -1,5 +1,6 @@
import { constants } from "@keymanapp/ldml-keyboard-constants";
-import { LDMLKeyboard, KMXPlus } from '@keymanapp/common-types';
+import { KMXPlus } from '@keymanapp/common-types';
+import { LDMLKeyboard } from '@keymanapp/developer-utils';
import { SectionCompiler } from "./section-compiler.js";
import { LdmlCompilerMessages } from "./ldml-compiler-messages.js";
diff --git a/developer/src/kmc-ldml/src/compiler/section-compiler.ts b/developer/src/kmc-ldml/src/compiler/section-compiler.ts
index f2b14e56a3..e33eda1086 100644
--- a/developer/src/kmc-ldml/src/compiler/section-compiler.ts
+++ b/developer/src/kmc-ldml/src/compiler/section-compiler.ts
@@ -1,4 +1,5 @@
-import { LDMLKeyboard, KMXPlus, CompilerCallbacks } from "@keymanapp/common-types";
+import { KMXPlus } from "@keymanapp/common-types";
+import { CompilerCallbacks, LDMLKeyboard } from "@keymanapp/developer-utils";
import { SectionIdent, constants } from '@keymanapp/ldml-keyboard-constants';
/** newable interface to SectionCompiler c'tor */
diff --git a/developer/src/kmc-ldml/src/compiler/touch-layout-compiler.ts b/developer/src/kmc-ldml/src/compiler/touch-layout-compiler.ts
index 5c5c7eb194..a36ab9c097 100644
--- a/developer/src/kmc-ldml/src/compiler/touch-layout-compiler.ts
+++ b/developer/src/kmc-ldml/src/compiler/touch-layout-compiler.ts
@@ -1,4 +1,5 @@
-import { TouchLayout, LDMLKeyboard } from "@keymanapp/common-types";
+import { TouchLayout } from "@keymanapp/common-types";
+import { LDMLKeyboard } from "@keymanapp/developer-utils";
export class TouchLayoutCompiler {
public compileToJavascript(source: LDMLKeyboard.LDMLKeyboardXMLSourceFile): TouchLayout.TouchLayoutFile {
diff --git a/developer/src/kmc-ldml/src/compiler/tran.ts b/developer/src/kmc-ldml/src/compiler/tran.ts
index 84a0bc264f..a25cc2cc08 100644
--- a/developer/src/kmc-ldml/src/compiler/tran.ts
+++ b/developer/src/kmc-ldml/src/compiler/tran.ts
@@ -1,5 +1,6 @@
import { constants, SectionIdent } from "@keymanapp/ldml-keyboard-constants";
-import { util, KMXPlus, LDMLKeyboard, CompilerCallbacks, VariableParser, MarkerParser } from '@keymanapp/common-types';
+import { KMXPlus, VariableParser, MarkerParser, util } from '@keymanapp/common-types';
+import { CompilerCallbacks, LDMLKeyboard } from "@keymanapp/developer-utils";
import { SectionCompiler } from "./section-compiler.js";
import Bksp = KMXPlus.Bksp;
diff --git a/developer/src/kmc-ldml/src/compiler/vars.ts b/developer/src/kmc-ldml/src/compiler/vars.ts
index c54081292f..fb9b2f7596 100644
--- a/developer/src/kmc-ldml/src/compiler/vars.ts
+++ b/developer/src/kmc-ldml/src/compiler/vars.ts
@@ -1,6 +1,6 @@
import { SectionIdent, constants } from "@keymanapp/ldml-keyboard-constants";
-import { KMXPlus, LDMLKeyboard, CompilerCallbacks, MarkerParser } from '@keymanapp/common-types';
-import { VariableParser } from '@keymanapp/common-types';
+import { KMXPlus, VariableParser, MarkerParser } from '@keymanapp/common-types';
+import { LDMLKeyboard, CompilerCallbacks } from '@keymanapp/developer-utils';
import { SectionCompiler } from "./section-compiler.js";
import Vars = KMXPlus.Vars;
import StringVarItem = KMXPlus.StringVarItem;
diff --git a/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts b/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts
index e662b923e4..6182e6e2c8 100644
--- a/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts
+++ b/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts
@@ -1,4 +1,5 @@
-import { VisualKeyboard, LDMLKeyboard, CompilerCallbacks } from "@keymanapp/common-types";
+import { VisualKeyboard } from "@keymanapp/common-types";
+import { LDMLKeyboard, CompilerCallbacks } from "@keymanapp/developer-utils";
import { KeysCompiler } from "./keys.js";
import { LdmlCompilerMessages } from "./ldml-compiler-messages.js";
diff --git a/developer/src/kmc-ldml/src/util/util.ts b/developer/src/kmc-ldml/src/util/util.ts
index 21409e7299..dbb5dc0531 100644
--- a/developer/src/kmc-ldml/src/util/util.ts
+++ b/developer/src/kmc-ldml/src/util/util.ts
@@ -1,4 +1,4 @@
-import { LDMLKeyboard } from "@keymanapp/common-types";
+import { LDMLKeyboard } from "@keymanapp/developer-utils";
import { constants } from "@keymanapp/ldml-keyboard-constants";
/**
* Verifies that value is an item in the enumeration.
diff --git a/developer/src/kmc-ldml/test/helpers/index.ts b/developer/src/kmc-ldml/test/helpers/index.ts
index 2e9e16ff6a..0285088acc 100644
--- a/developer/src/kmc-ldml/test/helpers/index.ts
+++ b/developer/src/kmc-ldml/test/helpers/index.ts
@@ -5,7 +5,8 @@ import 'mocha';
import * as path from 'path';
import { fileURLToPath } from 'url';
import { SectionCompiler, SectionCompilerNew } from '../../src/compiler/section-compiler.js';
-import { util, KMXPlus, LDMLKeyboardXMLSourceFileReader, VisualKeyboard, CompilerEvent, LDMLKeyboardTestDataXMLSourceFile, compilerEventFormat, LDMLKeyboard, UnicodeSetParser, CompilerCallbacks } from '@keymanapp/common-types';
+import { util, KMXPlus, UnicodeSetParser, VisualKeyboard } from '@keymanapp/common-types';
+import { CompilerEvent, compilerEventFormat, CompilerCallbacks, LDMLKeyboardXMLSourceFileReader, LDMLKeyboardTestDataXMLSourceFile, LDMLKeyboard, } from "@keymanapp/developer-utils";
import { LdmlKeyboardCompiler } from '../../src/main.js'; // make sure main.js compiles
import { assert } from 'chai';
import { KMXPlusMetadataCompiler } from '../../src/compiler/metadata-compiler.js';
diff --git a/developer/src/kmc-ldml/test/test-compiler-e2e.ts b/developer/src/kmc-ldml/test/test-compiler-e2e.ts
index e6bc3f52e2..1f87e55a22 100644
--- a/developer/src/kmc-ldml/test/test-compiler-e2e.ts
+++ b/developer/src/kmc-ldml/test/test-compiler-e2e.ts
@@ -1,7 +1,7 @@
import 'mocha';
import {assert} from 'chai';
import hextobin from '@keymanapp/hextobin';
-import { KMXBuilder } from '@keymanapp/common-types';
+import { KMXBuilder } from '@keymanapp/developer-utils';
import {checkMessages, compileKeyboard, compilerTestCallbacks, compilerTestOptions, makePathToFixture} from './helpers/index.js';
import { LdmlKeyboardCompiler } from '../src/compiler/compiler.js';
diff --git a/developer/src/kmc-ldml/test/test-helpers.ts b/developer/src/kmc-ldml/test/test-helpers.ts
index 23bf3a258a..8a7a6ba542 100644
--- a/developer/src/kmc-ldml/test/test-helpers.ts
+++ b/developer/src/kmc-ldml/test/test-helpers.ts
@@ -1,4 +1,4 @@
-import { CompilerEvent } from '@keymanapp/common-types';
+import { CompilerEvent } from '@keymanapp/developer-utils';
import 'mocha';
import {assert} from 'chai';
import { CompilerEventOrMatch, matchCompilerEvents } from './helpers/index.js';
diff --git a/developer/src/kmc-ldml/test/test-messages.ts b/developer/src/kmc-ldml/test/test-messages.ts
index b13d3bf104..041e1ed214 100644
--- a/developer/src/kmc-ldml/test/test-messages.ts
+++ b/developer/src/kmc-ldml/test/test-messages.ts
@@ -1,7 +1,7 @@
import 'mocha';
import { LdmlCompilerMessages } from '../src/compiler/ldml-compiler-messages.js';
import { verifyCompilerMessagesObject } from '@keymanapp/developer-test-helpers';
-import { CompilerErrorNamespace } from '@keymanapp/common-types';
+import { CompilerErrorNamespace } from '@keymanapp/developer-utils';
describe('LdmlCompilerMessages', function () {
it('should have a valid LdmlCompilerMessages object', function() {
diff --git a/developer/src/kmc-ldml/test/test-utils.ts b/developer/src/kmc-ldml/test/test-utils.ts
index fcf1f78683..3b89e3c2af 100644
--- a/developer/src/kmc-ldml/test/test-utils.ts
+++ b/developer/src/kmc-ldml/test/test-utils.ts
@@ -5,7 +5,7 @@ import {
isValidEnumValue, calculateUniqueKeys, allUsedKeyIdsInLayers,
translateLayerAttrToModifier, validModifier, verifyValidAndUnique } from '../src/util/util.js';
import { constants } from "@keymanapp/ldml-keyboard-constants";
-import { LDMLKeyboard } from '@keymanapp/common-types';
+import { LDMLKeyboard } from '@keymanapp/developer-utils';
describe('test of util/util.ts', () => {
describe('isValidEnumValue()', () => {
diff --git a/developer/src/kmc-model-info/src/model-info-compiler-messages.ts b/developer/src/kmc-model-info/src/model-info-compiler-messages.ts
index 9a1c5fdbdc..e033d6c021 100644
--- a/developer/src/kmc-model-info/src/model-info-compiler-messages.ts
+++ b/developer/src/kmc-model-info/src/model-info-compiler-messages.ts
@@ -1,4 +1,4 @@
-import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m, CompilerMessageDef as def, CompilerMessageSpecWithException } from "@keymanapp/common-types";
+import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m, CompilerMessageDef as def, CompilerMessageSpecWithException } from "@keymanapp/developer-utils";
const Namespace = CompilerErrorNamespace.ModelInfoCompiler;
// const SevInfo = CompilerErrorSeverity.Info | Namespace;
diff --git a/developer/src/kmc-model-info/src/model-info-compiler.ts b/developer/src/kmc-model-info/src/model-info-compiler.ts
index 09e9fc45c8..d4f3d10d43 100644
--- a/developer/src/kmc-model-info/src/model-info-compiler.ts
+++ b/developer/src/kmc-model-info/src/model-info-compiler.ts
@@ -5,9 +5,9 @@
import { minKeymanVersion } from "./min-keyman-version.js";
import { ModelInfoFile } from "./model-info-file.js";
-import { CompilerCallbacks, CompilerOptions, KeymanCompiler, KeymanCompilerArtifact, KeymanCompilerArtifacts, KeymanCompilerResult, KmpJsonFile } from "@keymanapp/common-types";
+import { KmpJsonFile } from "@keymanapp/common-types";
import { ModelInfoCompilerMessages } from "./model-info-compiler-messages.js";
-import { KeymanUrls, isValidEmail, validateMITLicense } from "@keymanapp/developer-utils";
+import { CompilerCallbacks, CompilerOptions, KeymanCompiler, KeymanCompilerArtifact, KeymanCompilerArtifacts, KeymanCompilerResult,KeymanUrls, isValidEmail, validateMITLicense } from "@keymanapp/developer-utils";
/* c8 ignore start */
/**
diff --git a/developer/src/kmc-model-info/test/test-model-info-compiler-messages.ts b/developer/src/kmc-model-info/test/test-model-info-compiler-messages.ts
index 4dd1de538f..062fc9f3c0 100644
--- a/developer/src/kmc-model-info/test/test-model-info-compiler-messages.ts
+++ b/developer/src/kmc-model-info/test/test-model-info-compiler-messages.ts
@@ -1,7 +1,7 @@
import 'mocha';
import { ModelInfoCompilerMessages } from '../src/model-info-compiler-messages.js';
import { verifyCompilerMessagesObject } from '@keymanapp/developer-test-helpers';
-import { CompilerErrorNamespace } from '@keymanapp/common-types';
+import { CompilerErrorNamespace } from '@keymanapp/developer-utils';
describe('ModelInfoCompilerMessages', function () {
it('should have a valid ModelInfoCompilerMessages object', function() {
diff --git a/developer/src/kmc-model/src/compiler-callbacks.ts b/developer/src/kmc-model/src/compiler-callbacks.ts
index a077035003..401a68f568 100644
--- a/developer/src/kmc-model/src/compiler-callbacks.ts
+++ b/developer/src/kmc-model/src/compiler-callbacks.ts
@@ -1,4 +1,4 @@
-import { CompilerCallbacks } from "@keymanapp/common-types";
+import { CompilerCallbacks } from "@keymanapp/developer-utils";
export let callbacks: CompilerCallbacks;
diff --git a/developer/src/kmc-model/src/lexical-model-compiler.ts b/developer/src/kmc-model/src/lexical-model-compiler.ts
index 9add61ee23..e1071512a9 100644
--- a/developer/src/kmc-model/src/lexical-model-compiler.ts
+++ b/developer/src/kmc-model/src/lexical-model-compiler.ts
@@ -10,7 +10,7 @@ import {decorateWithScriptOverrides} from "./script-overrides-decorator.js";
import { LexicalModelSource, WordBreakerSpec, SimpleWordBreakerSpec } from "./lexical-model.js";
import { ModelCompilerError, ModelCompilerMessageContext, ModelCompilerMessages } from "./model-compiler-messages.js";
import { callbacks, setCompilerCallbacks } from "./compiler-callbacks.js";
-import { CompilerCallbacks, CompilerOptions, KeymanCompiler, KeymanCompilerArtifact, KeymanCompilerArtifacts, KeymanCompilerResult } from "@keymanapp/common-types";
+import { CompilerCallbacks, CompilerOptions, KeymanCompiler, KeymanCompilerArtifact, KeymanCompilerArtifacts, KeymanCompilerResult } from "@keymanapp/developer-utils";
/**
* An ECMAScript module as emitted by the TypeScript compiler.
diff --git a/developer/src/kmc-model/src/model-compiler-messages.ts b/developer/src/kmc-model/src/model-compiler-messages.ts
index 26126b5d13..51e4042ea8 100644
--- a/developer/src/kmc-model/src/model-compiler-messages.ts
+++ b/developer/src/kmc-model/src/model-compiler-messages.ts
@@ -1,4 +1,4 @@
-import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerEvent, CompilerMessageSpec, CompilerMessageDef as def, CompilerMessageSpecWithException } from "@keymanapp/common-types";
+import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerEvent, CompilerMessageSpec, CompilerMessageDef as def, CompilerMessageSpecWithException } from "@keymanapp/developer-utils";
const Namespace = CompilerErrorNamespace.ModelCompiler;
// const SevInfo = CompilerErrorSeverity.Info | Namespace;
diff --git a/developer/src/kmc-model/test/test-messages.ts b/developer/src/kmc-model/test/test-messages.ts
index df584d80d1..2f87dfd718 100644
--- a/developer/src/kmc-model/test/test-messages.ts
+++ b/developer/src/kmc-model/test/test-messages.ts
@@ -1,7 +1,7 @@
import 'mocha';
import { ModelCompilerMessages } from '../src/model-compiler-messages.js';
import { verifyCompilerMessagesObject } from '@keymanapp/developer-test-helpers';
-import { CompilerErrorNamespace } from '@keymanapp/common-types';
+import { CompilerErrorNamespace } from '@keymanapp/developer-utils';
describe('ModelCompilerMessages', function () {
it('should have a valid ModelCompilerMessages object', function() {
diff --git a/developer/src/kmc-package/build.sh b/developer/src/kmc-package/build.sh
index 27c725a963..0b2d7bda9b 100755
--- a/developer/src/kmc-package/build.sh
+++ b/developer/src/kmc-package/build.sh
@@ -14,6 +14,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
builder_describe "Build Keyman kmc Package Compiler module" \
"@/common/web/keyman-version" \
"@/developer/src/common/web/test-helpers" \
+ "@/developer/src/common/web/utils" \
"configure" \
"build" \
"api analyze API and prepare API documentation" \
diff --git a/developer/src/kmc-package/package.json b/developer/src/kmc-package/package.json
index 22bc7b024d..521ae02e44 100644
--- a/developer/src/kmc-package/package.json
+++ b/developer/src/kmc-package/package.json
@@ -30,6 +30,7 @@
},
"dependencies": {
"@keymanapp/common-types": "*",
+ "@keymanapp/developer-utils": "*",
"jszip": "^3.7.0",
"marked": "^7.0.0"
},
diff --git a/developer/src/kmc-package/src/compiler/kmp-compiler.ts b/developer/src/kmc-package/src/compiler/kmp-compiler.ts
index b36f2da682..04688d0e5a 100644
--- a/developer/src/kmc-package/src/compiler/kmp-compiler.ts
+++ b/developer/src/kmc-package/src/compiler/kmp-compiler.ts
@@ -1,8 +1,9 @@
-import { xml2js } from '@keymanapp/common-types';
+import { xml2js } from '@keymanapp/developer-utils';
import JSZip from 'jszip';
import KEYMAN_VERSION from "@keymanapp/keyman-version";
-import { KmpJsonFile, KpsFile, SchemaValidators, CompilerCallbacks, KeymanFileTypes, KvkFile, KeymanCompiler, CompilerOptions, KeymanCompilerResult, KeymanCompilerArtifacts, KeymanCompilerArtifact } from '@keymanapp/common-types';
+import { KmpJsonFile, SchemaValidators, KeymanFileTypes, KvkFile } from '@keymanapp/common-types';
+import { CompilerCallbacks, KpsFile, KeymanCompiler, CompilerOptions, KeymanCompilerResult, KeymanCompilerArtifacts, KeymanCompilerArtifact } from '@keymanapp/developer-utils';
import { PackageCompilerMessages } from './package-compiler-messages.js';
import { PackageMetadataCollector } from './package-metadata-collector.js';
import { KmpInfWriter } from './kmp-inf-writer.js';
diff --git a/developer/src/kmc-package/src/compiler/package-compiler-messages.ts b/developer/src/kmc-package/src/compiler/package-compiler-messages.ts
index b974996fa6..154cb2143e 100644
--- a/developer/src/kmc-package/src/compiler/package-compiler-messages.ts
+++ b/developer/src/kmc-package/src/compiler/package-compiler-messages.ts
@@ -1,4 +1,4 @@
-import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m, CompilerMessageDef as def, CompilerMessageSpecWithException } from "@keymanapp/common-types";
+import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m, CompilerMessageDef as def, CompilerMessageSpecWithException } from "@keymanapp/developer-utils";
const Namespace = CompilerErrorNamespace.PackageCompiler;
const SevInfo = CompilerErrorSeverity.Info | Namespace;
diff --git a/developer/src/kmc-package/src/compiler/package-keyboard-target-validator.ts b/developer/src/kmc-package/src/compiler/package-keyboard-target-validator.ts
index 91a362528d..06f36c7727 100644
--- a/developer/src/kmc-package/src/compiler/package-keyboard-target-validator.ts
+++ b/developer/src/kmc-package/src/compiler/package-keyboard-target-validator.ts
@@ -1,4 +1,5 @@
-import { KeymanTargets, CompilerCallbacks, KmpJsonFile } from "@keymanapp/common-types";
+import { KeymanTargets, KmpJsonFile } from "@keymanapp/common-types";
+import { CompilerCallbacks } from "@keymanapp/developer-utils";
import { PackageCompilerMessages } from "./package-compiler-messages.js";
import { KeyboardMetadataCollection } from "./package-metadata-collector.js";
diff --git a/developer/src/kmc-package/src/compiler/package-metadata-collector.ts b/developer/src/kmc-package/src/compiler/package-metadata-collector.ts
index 3c9c2fc7e3..89a8f35b09 100644
--- a/developer/src/kmc-package/src/compiler/package-metadata-collector.ts
+++ b/developer/src/kmc-package/src/compiler/package-metadata-collector.ts
@@ -1,4 +1,5 @@
-import { KmpJsonFile, CompilerCallbacks, KmxFileReader, KmxFileReaderError, KMX, KeymanFileTypes } from '@keymanapp/common-types';
+import { KmpJsonFile, KmxFileReader, KmxFileReaderError, KMX, KeymanFileTypes } from '@keymanapp/common-types';
+import { CompilerCallbacks } from "@keymanapp/developer-utils";
import { getCompiledKmxKeyboardMetadata } from './kmx-keyboard-metadata.js';
import { PackageCompilerMessages } from './package-compiler-messages.js';
import { getCompiledWebKeyboardMetadata, WebKeyboardMetadata } from './web-keyboard-metadata.js';
diff --git a/developer/src/kmc-package/src/compiler/package-validation.ts b/developer/src/kmc-package/src/compiler/package-validation.ts
index 1ba9911b31..a55610adad 100644
--- a/developer/src/kmc-package/src/compiler/package-validation.ts
+++ b/developer/src/kmc-package/src/compiler/package-validation.ts
@@ -1,7 +1,7 @@
-import { KmpJsonFile, CompilerCallbacks, CompilerOptions, KeymanFileTypes } from '@keymanapp/common-types';
+import { KmpJsonFile, KeymanFileTypes } from '@keymanapp/common-types';
import { PackageCompilerMessages } from './package-compiler-messages.js';
import { keymanEngineForWindowsFiles, keymanForWindowsInstallerFiles, keymanForWindowsRedistFiles } from './redist-files.js';
-import { isValidEmail } from '@keymanapp/developer-utils';
+import { isValidEmail, CompilerCallbacks, CompilerOptions } from '@keymanapp/developer-utils';
// The keyboard ID SHOULD adhere to this pattern:
const KEYBOARD_ID_PATTERN_PACKAGE = /^[a-z_][a-z0-9_]*\.(kps|kmp)$/;
diff --git a/developer/src/kmc-package/src/compiler/package-version-validator.ts b/developer/src/kmc-package/src/compiler/package-version-validator.ts
index 3456253a4f..1aad375d40 100644
--- a/developer/src/kmc-package/src/compiler/package-version-validator.ts
+++ b/developer/src/kmc-package/src/compiler/package-version-validator.ts
@@ -1,6 +1,7 @@
-import { KmpJsonFile, CompilerCallbacks, KpsFile } from '@keymanapp/common-types';
+import { KmpJsonFile } from '@keymanapp/common-types';
import { PackageCompilerMessages } from './package-compiler-messages.js';
import { KeyboardMetadataCollection } from './package-metadata-collector.js';
+import { KpsFile, CompilerCallbacks } from '@keymanapp/developer-utils';
export const DEFAULT_KEYBOARD_VERSION = '1.0';
export const MIN_LM_FILEVERSION_KMP_JSON = '12.0';
diff --git a/developer/src/kmc-package/src/compiler/windows-package-installer-compiler.ts b/developer/src/kmc-package/src/compiler/windows-package-installer-compiler.ts
index a41c86091b..3eefada898 100644
--- a/developer/src/kmc-package/src/compiler/windows-package-installer-compiler.ts
+++ b/developer/src/kmc-package/src/compiler/windows-package-installer-compiler.ts
@@ -11,7 +11,8 @@
*/
import JSZip from 'jszip';
-import { CompilerCallbacks, KeymanCompiler, KeymanCompilerArtifact, KeymanCompilerArtifacts, KeymanCompilerResult, KeymanFileTypes, KmpJsonFile, KpsFile } from "@keymanapp/common-types";
+import { KeymanFileTypes, KmpJsonFile } from "@keymanapp/common-types";
+import { CompilerCallbacks, KeymanCompiler, KeymanCompilerArtifact, KeymanCompilerArtifacts, KeymanCompilerResult, KpsFile } from '@keymanapp/developer-utils';
import KEYMAN_VERSION from "@keymanapp/keyman-version";
import { KmpCompiler, KmpCompilerOptions } from "./kmp-compiler.js";
import { PackageCompilerMessages } from "./package-compiler-messages.js";
diff --git a/developer/src/kmc-package/test/test-kmp-inf-writer.ts b/developer/src/kmc-package/test/test-kmp-inf-writer.ts
index b49f39311e..f852fc69b8 100644
--- a/developer/src/kmc-package/test/test-kmp-inf-writer.ts
+++ b/developer/src/kmc-package/test/test-kmp-inf-writer.ts
@@ -36,7 +36,7 @@ type InfFile = {[name:string]: Section};
* which never repeats
*/
function parseInf(inf: string): InfFile {
- let items = inf.split('\r\n');
+ let items = inf.replaceAll(/\r\n/g, '\n').split('\n');
let sections: InfFile = {}, newSection: Section = {};
sections[0] = newSection;
for(let item of items) {
diff --git a/developer/src/kmc-package/test/test-messages.ts b/developer/src/kmc-package/test/test-messages.ts
index c80e48d4a6..e8fdfa842a 100644
--- a/developer/src/kmc-package/test/test-messages.ts
+++ b/developer/src/kmc-package/test/test-messages.ts
@@ -4,7 +4,7 @@ import { TestCompilerCallbacks, verifyCompilerMessagesObject } from '@keymanapp/
import { PackageCompilerMessages } from '../src/compiler/package-compiler-messages.js';
import { makePathToFixture } from './helpers/index.js';
import { KmpCompiler } from '../src/compiler/kmp-compiler.js';
-import { CompilerErrorNamespace, CompilerOptions } from '@keymanapp/common-types';
+import { CompilerErrorNamespace, CompilerOptions } from '@keymanapp/developer-utils';
const debug = false;
const callbacks = new TestCompilerCallbacks();
diff --git a/developer/src/kmc-package/tsconfig.json b/developer/src/kmc-package/tsconfig.json
index 0ab78a91ff..4fae2b81ec 100644
--- a/developer/src/kmc-package/tsconfig.json
+++ b/developer/src/kmc-package/tsconfig.json
@@ -10,6 +10,7 @@
"src/**/*.ts",
],
"references": [
+ { "path": "../common/web/utils" },
{ "path": "../../../common/web/keyman-version" },
{ "path": "../../../common/web/types" },
]
diff --git a/developer/src/kmc/src/commands/analyze.ts b/developer/src/kmc/src/commands/analyze.ts
index 3c53609179..5085262f07 100644
--- a/developer/src/kmc/src/commands/analyze.ts
+++ b/developer/src/kmc/src/commands/analyze.ts
@@ -3,7 +3,7 @@ import * as path from 'path';
import { Command, Option } from 'commander';
import { NodeCompilerCallbacks } from '../util/NodeCompilerCallbacks.js';
import { InfrastructureMessages } from '../messages/infrastructureMessages.js';
-import { CompilerCallbacks, CompilerLogLevel } from '@keymanapp/common-types';
+import { CompilerCallbacks, CompilerLogLevel } from '@keymanapp/developer-utils';
import { AnalyzeOskCharacterUse, AnalyzeOskRewritePua } from '@keymanapp/kmc-analyze';
import { BaseOptions } from '../util/baseOptions.js';
import { runOnFiles } from '../util/projectRunner.js';
diff --git a/developer/src/kmc/src/commands/build.ts b/developer/src/kmc/src/commands/build.ts
index 9669997055..b8d5496c5b 100644
--- a/developer/src/kmc/src/commands/build.ts
+++ b/developer/src/kmc/src/commands/build.ts
@@ -5,7 +5,8 @@ import { buildActivities } from './buildClasses/buildActivities.js';
import { BuildProject } from './buildClasses/BuildProject.js';
import { NodeCompilerCallbacks } from '../util/NodeCompilerCallbacks.js';
import { InfrastructureMessages } from '../messages/infrastructureMessages.js';
-import { CompilerFileCallbacks, CompilerOptions, KeymanFileTypes } from '@keymanapp/common-types';
+import { KeymanFileTypes } from '@keymanapp/common-types';
+import { CompilerOptions, CompilerFileCallbacks } from '@keymanapp/developer-utils';
import { BaseOptions } from '../util/baseOptions.js';
import { expandFileLists } from '../util/fileLists.js';
import { isProject } from '../util/projectLoader.js';
diff --git a/developer/src/kmc/src/commands/buildClasses/BuildActivity.ts b/developer/src/kmc/src/commands/buildClasses/BuildActivity.ts
index 864611c26d..a8cde224bc 100644
--- a/developer/src/kmc/src/commands/buildClasses/BuildActivity.ts
+++ b/developer/src/kmc/src/commands/buildClasses/BuildActivity.ts
@@ -1,6 +1,7 @@
import * as fs from 'fs';
import * as path from 'path';
-import { CompilerCallbacks, CompilerOptions, KeymanCompiler, KeymanFileTypes } from "@keymanapp/common-types";
+import { KeymanFileTypes } from "@keymanapp/common-types";
+import { CompilerCallbacks, CompilerOptions, KeymanCompiler } from "@keymanapp/developer-utils";
import { InfrastructureMessages } from '../../messages/infrastructureMessages.js';
export abstract class BuildActivity {
diff --git a/developer/src/kmc/src/commands/buildClasses/BuildKeyboardInfo.ts b/developer/src/kmc/src/commands/buildClasses/BuildKeyboardInfo.ts
index e25297c735..4248000c7a 100644
--- a/developer/src/kmc/src/commands/buildClasses/BuildKeyboardInfo.ts
+++ b/developer/src/kmc/src/commands/buildClasses/BuildKeyboardInfo.ts
@@ -1,7 +1,8 @@
import * as fs from 'fs';
import * as path from 'path';
import { BuildActivity } from './BuildActivity.js';
-import { CompilerCallbacks, KeymanFileTypes } from '@keymanapp/common-types';
+import { KeymanFileTypes } from '@keymanapp/common-types';
+import { CompilerCallbacks } from '@keymanapp/developer-utils';
import { KeyboardInfoCompiler } from '@keymanapp/kmc-keyboard-info';
import { loadProject } from '../../util/projectLoader.js';
import { InfrastructureMessages } from '../../messages/infrastructureMessages.js';
diff --git a/developer/src/kmc/src/commands/buildClasses/BuildKmnKeyboard.ts b/developer/src/kmc/src/commands/buildClasses/BuildKmnKeyboard.ts
index e540aba451..a4d6f45b85 100644
--- a/developer/src/kmc/src/commands/buildClasses/BuildKmnKeyboard.ts
+++ b/developer/src/kmc/src/commands/buildClasses/BuildKmnKeyboard.ts
@@ -1,7 +1,8 @@
import * as path from 'path';
import { platform } from 'os';
import { KmnCompiler } from '@keymanapp/kmc-kmn';
-import { CompilerOptions, CompilerCallbacks, KeymanFileTypes } from '@keymanapp/common-types';
+import { KeymanFileTypes } from '@keymanapp/common-types';
+import { CompilerOptions, CompilerCallbacks } from '@keymanapp/developer-utils';
import { BuildActivity } from './BuildActivity.js';
export class BuildKmnKeyboard extends BuildActivity {
diff --git a/developer/src/kmc/src/commands/buildClasses/BuildLdmlKeyboard.ts b/developer/src/kmc/src/commands/buildClasses/BuildLdmlKeyboard.ts
index 0e0cfd9766..6ac98c9b92 100644
--- a/developer/src/kmc/src/commands/buildClasses/BuildLdmlKeyboard.ts
+++ b/developer/src/kmc/src/commands/buildClasses/BuildLdmlKeyboard.ts
@@ -1,5 +1,7 @@
import * as kmcLdml from '@keymanapp/kmc-ldml';
-import { CompilerCallbacks, LDMLKeyboardXMLSourceFileReader, CompilerOptions, KeymanFileTypes } from '@keymanapp/common-types';
+import { KeymanFileTypes } from '@keymanapp/common-types';
+import { CompilerOptions, CompilerCallbacks } from '@keymanapp/developer-utils';
+import { LDMLKeyboardXMLSourceFileReader } from '@keymanapp/developer-utils';
import { BuildActivity } from './BuildActivity.js';
import { fileURLToPath } from 'url';
diff --git a/developer/src/kmc/src/commands/buildClasses/BuildModel.ts b/developer/src/kmc/src/commands/buildClasses/BuildModel.ts
index b2afc59294..c01d1adf20 100644
--- a/developer/src/kmc/src/commands/buildClasses/BuildModel.ts
+++ b/developer/src/kmc/src/commands/buildClasses/BuildModel.ts
@@ -1,6 +1,7 @@
import { BuildActivity } from './BuildActivity.js';
import { LexicalModelCompiler } from '@keymanapp/kmc-model';
-import { CompilerCallbacks, CompilerOptions, KeymanFileTypes } from '@keymanapp/common-types';
+import { KeymanFileTypes } from '@keymanapp/common-types';
+import { CompilerOptions, CompilerCallbacks } from '@keymanapp/developer-utils';
export class BuildModel extends BuildActivity {
public get name(): string { return 'Lexical model'; }
diff --git a/developer/src/kmc/src/commands/buildClasses/BuildModelInfo.ts b/developer/src/kmc/src/commands/buildClasses/BuildModelInfo.ts
index 0fca855540..3924309f93 100644
--- a/developer/src/kmc/src/commands/buildClasses/BuildModelInfo.ts
+++ b/developer/src/kmc/src/commands/buildClasses/BuildModelInfo.ts
@@ -1,7 +1,8 @@
import * as fs from 'fs';
import * as path from 'path';
import { BuildActivity } from './BuildActivity.js';
-import { CompilerCallbacks, KeymanFileTypes } from '@keymanapp/common-types';
+import { KeymanFileTypes } from '@keymanapp/common-types';
+import { CompilerCallbacks } from '@keymanapp/developer-utils';
import { ModelInfoCompiler } from '@keymanapp/kmc-model-info';
import { KmpCompiler } from '@keymanapp/kmc-package';
import { loadProject } from '../../util/projectLoader.js';
diff --git a/developer/src/kmc/src/commands/buildClasses/BuildPackage.ts b/developer/src/kmc/src/commands/buildClasses/BuildPackage.ts
index 1bb26b3b7f..8ecc08dace 100644
--- a/developer/src/kmc/src/commands/buildClasses/BuildPackage.ts
+++ b/developer/src/kmc/src/commands/buildClasses/BuildPackage.ts
@@ -1,5 +1,6 @@
import { BuildActivity } from './BuildActivity.js';
-import { CompilerCallbacks, CompilerOptions, KeymanFileTypes } from '@keymanapp/common-types';
+import { KeymanFileTypes } from '@keymanapp/common-types';
+import { CompilerOptions, CompilerCallbacks } from '@keymanapp/developer-utils';
import { KmpCompiler } from '@keymanapp/kmc-package';
export class BuildPackage extends BuildActivity {
diff --git a/developer/src/kmc/src/commands/buildClasses/BuildProject.ts b/developer/src/kmc/src/commands/buildClasses/BuildProject.ts
index 4a5f9148bc..ee1204a7f0 100644
--- a/developer/src/kmc/src/commands/buildClasses/BuildProject.ts
+++ b/developer/src/kmc/src/commands/buildClasses/BuildProject.ts
@@ -1,6 +1,8 @@
import * as path from 'path';
import * as fs from 'fs';
-import { CompilerCallbacks, CompilerFileCallbacks, KeymanDeveloperProject, KeymanDeveloperProjectFile, KeymanDeveloperProjectType, KeymanFileTypes } from '@keymanapp/common-types';
+import { KeymanFileTypes } from '@keymanapp/common-types';
+import { CompilerFileCallbacks, CompilerCallbacks } from '@keymanapp/developer-utils';
+import { KeymanDeveloperProject, KeymanDeveloperProjectFile, KeymanDeveloperProjectType } from '@keymanapp/developer-utils';
import { BuildActivity } from './BuildActivity.js';
import { buildActivities, buildKeyboardInfoActivity, buildModelInfoActivity } from './buildActivities.js';
import { InfrastructureMessages } from '../../messages/infrastructureMessages.js';
diff --git a/developer/src/kmc/src/commands/buildTestData/index.ts b/developer/src/kmc/src/commands/buildTestData/index.ts
index 6e598954c1..c958673c2f 100644
--- a/developer/src/kmc/src/commands/buildTestData/index.ts
+++ b/developer/src/kmc/src/commands/buildTestData/index.ts
@@ -1,7 +1,7 @@
import * as fs from 'fs';
import * as path from 'path';
import * as kmcLdml from '@keymanapp/kmc-ldml';
-import { CompilerCallbacks, defaultCompilerOptions, LDMLKeyboardTestDataXMLSourceFile, LDMLKeyboardXMLSourceFileReader } from '@keymanapp/common-types';
+import { CompilerCallbacks, defaultCompilerOptions, LDMLKeyboardTestDataXMLSourceFile, LDMLKeyboardXMLSourceFileReader } from '@keymanapp/developer-utils';
import { NodeCompilerCallbacks } from '../../util/NodeCompilerCallbacks.js';
import { fileURLToPath } from 'url';
import { CommandLineBaseOptions } from 'src/util/baseOptions.js';
diff --git a/developer/src/kmc/src/commands/buildWindowsPackageInstaller/index.ts b/developer/src/kmc/src/commands/buildWindowsPackageInstaller/index.ts
index 591dfe2e02..06076db929 100644
--- a/developer/src/kmc/src/commands/buildWindowsPackageInstaller/index.ts
+++ b/developer/src/kmc/src/commands/buildWindowsPackageInstaller/index.ts
@@ -1,6 +1,6 @@
import * as fs from 'fs';
import * as path from 'path';
-import { CompilerCallbacks, defaultCompilerOptions } from '@keymanapp/common-types';
+import { CompilerCallbacks, defaultCompilerOptions } from '@keymanapp/developer-utils';
import { NodeCompilerCallbacks } from '../../util/NodeCompilerCallbacks.js';
import { WindowsPackageInstallerCompiler, WindowsPackageInstallerSources } from '@keymanapp/kmc-package';
import { CommandLineBaseOptions } from 'src/util/baseOptions.js';
diff --git a/developer/src/kmc/src/commands/messageCommand.ts b/developer/src/kmc/src/commands/messageCommand.ts
index 94b95f300f..ee568dad9c 100644
--- a/developer/src/kmc/src/commands/messageCommand.ts
+++ b/developer/src/kmc/src/commands/messageCommand.ts
@@ -1,14 +1,13 @@
import * as fs from 'fs';
import * as path from 'path';
-import { CompilerBaseOptions, CompilerCallbacks, CompilerError, CompilerErrorNamespace, CompilerEvent } from '@keymanapp/common-types';
import { Command, Option } from 'commander';
+import { escapeMarkdownChar, KeymanUrls, CompilerBaseOptions, CompilerCallbacks, CompilerError, CompilerErrorNamespace, CompilerEvent } from '@keymanapp/developer-utils';
import { CompilerMessageSource, messageNamespaceKeys, messageSources } from '../messages/messageNamespaces.js';
import { NodeCompilerCallbacks } from '../util/NodeCompilerCallbacks.js';
import { exitProcess } from '../util/sysexits.js';
import { InfrastructureMessages } from '../messages/infrastructureMessages.js';
import { CompilerMessageDetail, findMessageDetails, findMessagesById, getMessageIdentifiersSorted } from '../util/extendedCompilerOptions.js';
-import { escapeMarkdownChar, KeymanUrls } from '@keymanapp/developer-utils';
type MessageFormat = 'text'|'markdown'|'json';
diff --git a/developer/src/kmc/src/messages/infrastructureMessages.ts b/developer/src/kmc/src/messages/infrastructureMessages.ts
index 7c96917cae..b4d8cebd2e 100644
--- a/developer/src/kmc/src/messages/infrastructureMessages.ts
+++ b/developer/src/kmc/src/messages/infrastructureMessages.ts
@@ -1,4 +1,4 @@
-import { CompilerError, CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m, CompilerMessageDef as def, CompilerMessageSpecWithException } from "@keymanapp/common-types";
+import { CompilerError, CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m, CompilerMessageDef as def, CompilerMessageSpecWithException } from "@keymanapp/developer-utils";
const Namespace = CompilerErrorNamespace.Infrastructure;
const SevInfo = CompilerErrorSeverity.Info | Namespace;
diff --git a/developer/src/kmc/src/messages/messageNamespaces.ts b/developer/src/kmc/src/messages/messageNamespaces.ts
index 2e0bef61b5..fc0e7e4d27 100644
--- a/developer/src/kmc/src/messages/messageNamespaces.ts
+++ b/developer/src/kmc/src/messages/messageNamespaces.ts
@@ -1,4 +1,4 @@
-import { CommonTypesMessages, CompilerErrorNamespace } from '@keymanapp/common-types';
+import { CommonTypesMessages, CompilerErrorNamespace } from '@keymanapp/developer-utils';
import { AnalyzerMessages } from '@keymanapp/kmc-analyze';
import { KeyboardInfoCompilerMessages } from '@keymanapp/kmc-keyboard-info';
import { KmnCompilerMessages, KmwCompilerMessages } from '@keymanapp/kmc-kmn';
diff --git a/developer/src/kmc/src/util/NodeCompilerCallbacks.ts b/developer/src/kmc/src/util/NodeCompilerCallbacks.ts
index 446924913a..f94e06c18a 100644
--- a/developer/src/kmc/src/util/NodeCompilerCallbacks.ts
+++ b/developer/src/kmc/src/util/NodeCompilerCallbacks.ts
@@ -6,7 +6,7 @@ import { CompilerCallbacks, CompilerEvent,
compilerLogLevelToSeverity, CompilerErrorSeverity,
CompilerError,
CompilerCallbackOptions,
- CompilerFileCallbacks} from '@keymanapp/common-types';
+ CompilerFileCallbacks} from '@keymanapp/developer-utils';
import { InfrastructureMessages } from '../messages/infrastructureMessages.js';
import chalk from 'chalk';
import supportsColor from 'supports-color';
diff --git a/developer/src/kmc/src/util/baseOptions.ts b/developer/src/kmc/src/util/baseOptions.ts
index dd91f0bae6..ab07921dbd 100644
--- a/developer/src/kmc/src/util/baseOptions.ts
+++ b/developer/src/kmc/src/util/baseOptions.ts
@@ -1,4 +1,4 @@
-import { ALL_COMPILER_LOG_FORMATS, ALL_COMPILER_LOG_LEVELS, CompilerLogFormat, CompilerLogLevel } from "@keymanapp/common-types";
+import { ALL_COMPILER_LOG_FORMATS, ALL_COMPILER_LOG_LEVELS, CompilerLogFormat, CompilerLogLevel } from "@keymanapp/developer-utils";
import { Command, Option } from "commander";
/**
diff --git a/developer/src/kmc/src/util/extendedCompilerOptions.ts b/developer/src/kmc/src/util/extendedCompilerOptions.ts
index e9c90e47f0..0d72b5b550 100644
--- a/developer/src/kmc/src/util/extendedCompilerOptions.ts
+++ b/developer/src/kmc/src/util/extendedCompilerOptions.ts
@@ -1,4 +1,4 @@
-import { CompilerCallbacks, CompilerError, CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageOverride, CompilerMessageOverrideMap, CompilerOptions } from '@keymanapp/common-types';
+import { CompilerCallbacks, CompilerError, CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageOverride, CompilerMessageOverrideMap, CompilerOptions } from '@keymanapp/developer-utils';
import { InfrastructureMessages } from '../messages/infrastructureMessages.js';
import { CompilerMessageSource, messageNamespaceKeys, messageSources } from '../messages/messageNamespaces.js';
diff --git a/developer/src/kmc/src/util/fileLists.ts b/developer/src/kmc/src/util/fileLists.ts
index ecd786d0ae..29defb4b8d 100644
--- a/developer/src/kmc/src/util/fileLists.ts
+++ b/developer/src/kmc/src/util/fileLists.ts
@@ -1,6 +1,6 @@
import * as fs from 'fs';
import * as path from 'path';
-import { CompilerCallbacks } from "@keymanapp/common-types";
+import { CompilerCallbacks } from "@keymanapp/developer-utils";
import { InfrastructureMessages } from "../messages/infrastructureMessages.js";
/**
diff --git a/developer/src/kmc/src/util/projectLoader.ts b/developer/src/kmc/src/util/projectLoader.ts
index b26399ee39..04a1af2796 100644
--- a/developer/src/kmc/src/util/projectLoader.ts
+++ b/developer/src/kmc/src/util/projectLoader.ts
@@ -1,7 +1,8 @@
import * as path from 'path';
import * as fs from 'fs';
-import { CompilerCallbacks, KeymanDeveloperProject, KeymanFileTypes, KPJFileReader } from "@keymanapp/common-types";
+import { KeymanFileTypes } from "@keymanapp/common-types";
+import { CompilerCallbacks, KeymanDeveloperProject, KPJFileReader } from "@keymanapp/developer-utils";
import { InfrastructureMessages } from "../messages/infrastructureMessages.js";
export const isProject = (filename: string): boolean =>
diff --git a/developer/src/kmc/src/util/projectRunner.ts b/developer/src/kmc/src/util/projectRunner.ts
index 1f3ffdfcd3..c4186635b7 100644
--- a/developer/src/kmc/src/util/projectRunner.ts
+++ b/developer/src/kmc/src/util/projectRunner.ts
@@ -1,4 +1,5 @@
-import { CompilerCallbacks, KeymanFileTypes } from "@keymanapp/common-types";
+import { KeymanFileTypes } from '@keymanapp/common-types';
+import { CompilerCallbacks } from '@keymanapp/developer-utils';
import { isProject, loadProject } from './projectLoader.js';
async function runProject(callbacks: CompilerCallbacks, filename: string, callback: (filename:string)=>Promise): Promise {
diff --git a/developer/src/kmc/test/test-extendedCompilerOptions.ts b/developer/src/kmc/test/test-extendedCompilerOptions.ts
index f0a304f2f4..adda29dfdb 100644
--- a/developer/src/kmc/test/test-extendedCompilerOptions.ts
+++ b/developer/src/kmc/test/test-extendedCompilerOptions.ts
@@ -3,7 +3,7 @@ import { assert } from 'chai';
import 'mocha';
import { unitTestEndpoints } from '../src/util/extendedCompilerOptions.js';
import { InfrastructureMessages } from '../src/messages/infrastructureMessages.js';
-import { CompilerError, CompilerMessageOverride, CompilerErrorSeverity } from '@keymanapp/common-types';
+import { CompilerError, CompilerMessageOverride, CompilerErrorSeverity } from '@keymanapp/developer-utils';
import { KmnCompilerMessages } from '@keymanapp/kmc-kmn';
interface MessageTest {input: string, result: CompilerMessageOverride};
diff --git a/developer/src/kmc/test/test-infrastructureMessages.ts b/developer/src/kmc/test/test-infrastructureMessages.ts
index bd39a0a65b..37316a8f3c 100644
--- a/developer/src/kmc/test/test-infrastructureMessages.ts
+++ b/developer/src/kmc/test/test-infrastructureMessages.ts
@@ -1,15 +1,16 @@
import 'mocha';
+import * as fs from 'fs';
import { assert } from 'chai';
import { InfrastructureMessages } from '../src/messages/infrastructureMessages.js';
import { verifyCompilerMessagesObject } from '@keymanapp/developer-test-helpers';
import { makePathToFixture } from './helpers/index.js';
import { NodeCompilerCallbacks } from '../src/util/NodeCompilerCallbacks.js';
-import { CompilerErrorNamespace, CompilerEvent, KeymanFileTypes } from '@keymanapp/common-types';
+import { KeymanFileTypes } from '@keymanapp/common-types';
import { unitTestEndpoints } from '../src/commands/build.js';
import { KmnCompilerMessages } from '@keymanapp/kmc-kmn';
import { clearOptions } from '@keymanapp/developer-utils';
import { loadProject } from '../src/util/projectLoader.js';
-import { defaultCompilerOptions, CompilerOptions} from '@keymanapp/common-types';
+import { CompilerErrorNamespace, CompilerEvent, defaultCompilerOptions, CompilerOptions} from '@keymanapp/developer-utils';
import { analyzeUnitTestEndpoints } from '../src/commands/analyze.js';
import { BuildKeyboardInfo } from '../src/commands/buildClasses/BuildKeyboardInfo.js';
import { BuildModelInfo } from '../src/commands/buildClasses/BuildModelInfo.js';
@@ -171,10 +172,19 @@ describe('InfrastructureMessages', function () {
it('should generate HINT_FilenameHasDifferingCase if a referenced file has differing case', async function() {
// This message is generated by NodeCompilerCallbacks, because that's where the filesystem is visible,
// so we can't use our usual testForMessage pattern.
- const ncb = new NodeCompilerCallbacks({logLevel: 'silent'});
- const expectedMessages = [InfrastructureMessages.HINT_FilenameHasDifferingCase];
- ncb.loadFile(makePathToFixture('invalid-keyboards', 'Hint_Filename_Has_Differing_Case.kmn'));
- assertMessagesEqual(ncb.messages, expectedMessages);
+ const filename = makePathToFixture('invalid-keyboards', 'Hint_Filename_Has_Differing_Case.kmn');
+ if(fs.existsSync(filename)) {
+ // The file is actually named 'hint_filename_has_differing_case.kmn', so
+ // if we can see it, then we know we are not on a case-sensitive
+ // filesystem, and so we can test
+ const ncb = new NodeCompilerCallbacks({logLevel: 'silent'});
+ const expectedMessages = [InfrastructureMessages.HINT_FilenameHasDifferingCase];
+ assert.isNotNull(ncb.loadFile(filename), `Expected to load 'hint_filename_has_differing_case.kmn' with mixed case '${filename}'`);
+ assertMessagesEqual(ncb.messages, expectedMessages);
+ } else {
+ // We are on a case-sensitive filesystem, so this hint can never be generated
+ assert.isTrue(true);
+ }
});
// INFO_WarningsHaveFailedBuild
diff --git a/developer/src/kmcmplib/include/kmcompx.h b/developer/src/kmcmplib/include/kmcompx.h
index 7e7b270496..9d7ca75508 100644
--- a/developer/src/kmcmplib/include/kmcompx.h
+++ b/developer/src/kmcmplib/include/kmcompx.h
@@ -3,11 +3,6 @@
// TODO: merge with kmcmplib.h
-typedef wchar_t KMX_WCHART;
-typedef KMX_DWORD * PKMX_DWORD;
-typedef char * PKMX_STR;
-typedef KMX_WCHAR* PKMX_WCHAR ;
-
// TODO: these defines are copied out of unicode.h, because unicode.h still
// has windows-specific types. These should be remerged at a future date
diff --git a/developer/src/kmcmplib/src/CasedKeys.cpp b/developer/src/kmcmplib/src/CasedKeys.cpp
index 0a0508f11a..0883c401ce 100644
--- a/developer/src/kmcmplib/src/CasedKeys.cpp
+++ b/developer/src/kmcmplib/src/CasedKeys.cpp
@@ -1,13 +1,14 @@
#include "pch.h"
+#include "km_u16.h"
+#include "../../../../common/windows/cpp/include/vkeys.h"
+
#include "compfile.h"
#include "kmn_compiler_errors.h"
-#include "../../../../common/windows/cpp/include/vkeys.h"
#include "kmcmplib.h"
#include "CharToKeyConversion.h"
-#include "kmx_u16.h"
#include "xstring.h"
namespace kmcmp {
diff --git a/developer/src/kmcmplib/src/CheckForDuplicates.cpp b/developer/src/kmcmplib/src/CheckForDuplicates.cpp
index 9e5d63b9ef..e0fa0094bc 100644
--- a/developer/src/kmcmplib/src/CheckForDuplicates.cpp
+++ b/developer/src/kmcmplib/src/CheckForDuplicates.cpp
@@ -1,11 +1,11 @@
#include "pch.h"
+#include
#include "compfile.h"
#include
#include "kmcmplib.h"
#include
-#include "kmx_u16.h"
#include
#include "CheckForDuplicates.h"
diff --git a/developer/src/kmcmplib/src/Compiler.cpp b/developer/src/kmcmplib/src/Compiler.cpp
index 11c8f4a26f..3893a72855 100644
--- a/developer/src/kmcmplib/src/Compiler.cpp
+++ b/developer/src/kmcmplib/src/Compiler.cpp
@@ -102,7 +102,7 @@
#include "UnreachableRules.h"
#include "CheckForDuplicates.h"
-#include "kmx_u16.h"
+#include "km_u16.h"
/* These macros are adapted from winnt.h and legacy use only */
#define MAKELANGID(p, s) ((((uint16_t)(s)) << 10) | (uint16_t)(p))
@@ -580,7 +580,7 @@ KMX_BOOL ParseLine(PFILE_KEYBOARD fk, PKMX_WCHAR str) {
//swprintf(tstr, "%d", fk->currentGroup);
/* Record a system store for the line number of the begin statement */
//wcscpy(tstr, DEBUGSTORE_MATCH);
- u16sprintf(tstr, _countof(tstr), L"%ls%d ", u16fmt(DEBUGSTORE_MATCH).c_str(), (int) fk->currentGroup);
+ u16sprintf(tstr, _countof(tstr), L"%ls%d ", DEBUGSTORE_MATCH_L, (int) fk->currentGroup);
u16ncat(tstr, gp->szName, _countof(tstr));
AddDebugStore(fk, tstr);
@@ -619,7 +619,7 @@ KMX_BOOL ParseLine(PFILE_KEYBOARD fk, PKMX_WCHAR str) {
{
KMX_WCHAR tstr[128];
/* Record a system store for the line number of the begin statement */
- u16sprintf(tstr, _countof(tstr), L"%ls%d ", u16fmt(DEBUGSTORE_NOMATCH).c_str(), (int) fk->currentGroup);
+ u16sprintf(tstr, _countof(tstr), L"%ls%d ", DEBUGSTORE_NOMATCH_L, (int) fk->currentGroup);
u16ncat(tstr, gp->szName, _countof(tstr));
AddDebugStore(fk, tstr);
}
@@ -683,7 +683,7 @@ KMX_BOOL ProcessGroupLine(PFILE_KEYBOARD fk, PKMX_WCHAR p)
{
KMX_WCHAR tstr[128];
/* Record a system store for the line number of the begin statement */
- u16sprintf(tstr, _countof(tstr), L"%ls%d ", u16fmt(DEBUGSTORE_GROUP).c_str(), fk->cxGroupArray - 1);
+ u16sprintf(tstr, _countof(tstr), L"%ls%d ", DEBUGSTORE_GROUP_L, fk->cxGroupArray - 1);
u16ncat(tstr, gp->szName, _countof(tstr));
AddDebugStore(fk, tstr);
}
@@ -3595,7 +3595,7 @@ KMX_DWORD ImportBitmapFile(PFILE_KEYBOARD fk, PKMX_WCHAR szName, PKMX_DWORD File
return KmnCompilerMessages::ERROR_CannotReadBitmapFile;
}
- *FileSize = bufvec.size();
+ *FileSize = static_cast(bufvec.size());
*Buf = new KMX_BYTE[*FileSize];
std::copy(bufvec.begin(), bufvec.end(), *Buf);
@@ -3761,7 +3761,7 @@ void kmcmp::RecordDeadkeyNames(PFILE_KEYBOARD fk)
KMX_DWORD i;
for (i = 0; i < fk->cxDeadKeyArray; i++)
{
- u16sprintf(buf, _countof(buf), L"%ls%d ", u16fmt(DEBUGSTORE_DEADKEY).c_str(), (int)i);
+ u16sprintf(buf, _countof(buf), L"%ls%d ", DEBUGSTORE_DEADKEY_L, (int)i);
u16ncat(buf, fk->dpDeadKeyArray[i].szName, _countof(buf));
AddDebugStore(fk, buf);
@@ -3809,11 +3809,11 @@ bool UTF16TempFromUTF8(KMX_BYTE* infile, int sz, KMX_BYTE** tempfile, int *sz16)
}
if(hasPreamble(result)) {
- *sz16 = result.size() * 2 - 2;
+ *sz16 = static_cast(result.size()) * 2 - 2;
*tempfile = new KMX_BYTE[*sz16];
memcpy(*tempfile, result.c_str() + 1, *sz16);
} else {
- *sz16 = result.size() * 2;
+ *sz16 = static_cast(result.size()) * 2;
*tempfile = new KMX_BYTE[*sz16];
memcpy(*tempfile, result.c_str(), *sz16);
}
diff --git a/developer/src/kmcmplib/src/CompilerInterfaces.cpp b/developer/src/kmcmplib/src/CompilerInterfaces.cpp
index 11cbd95e59..ba36802832 100644
--- a/developer/src/kmcmplib/src/CompilerInterfaces.cpp
+++ b/developer/src/kmcmplib/src/CompilerInterfaces.cpp
@@ -38,7 +38,7 @@ EXTERN bool kmcmp_CompileKeyboard(
int sz;
std::vector bufvec = kmcmp::loadfileproc(pszInfile, "");
- sz = bufvec.size();
+ sz = static_cast(bufvec.size());
if(!sz) {
ReportCompilerMessage(KmnCompilerMessages::ERROR_InfileNotExist);
return FALSE;
diff --git a/developer/src/kmcmplib/src/NamedCodeConstants.cpp b/developer/src/kmcmplib/src/NamedCodeConstants.cpp
index 40e47d7a00..9cf322ab72 100644
--- a/developer/src/kmcmplib/src/NamedCodeConstants.cpp
+++ b/developer/src/kmcmplib/src/NamedCodeConstants.cpp
@@ -121,7 +121,7 @@ KMX_BOOL NamedCodeConstants::LoadFile(PFILE_KEYBOARD fk, const KMX_WCHAR *filena
int FileSize;
KMX_BYTE* Buf;
std::vector bufvec = loadfileproc(szNameUtf8, fk->extra->kmnFilename);
- FileSize = bufvec.size();
+ FileSize = static_cast(bufvec.size());
if(!FileSize) {
return FALSE;
}
diff --git a/developer/src/kmcmplib/src/UnreachableRules.cpp b/developer/src/kmcmplib/src/UnreachableRules.cpp
index c84bdfb1f5..40965db4d6 100644
--- a/developer/src/kmcmplib/src/UnreachableRules.cpp
+++ b/developer/src/kmcmplib/src/UnreachableRules.cpp
@@ -18,7 +18,7 @@ namespace kmcmp {
std::wstringstream key;
key << kp->Key << "," << kp->ShiftFlags << ",";
if (kp->dpContext) {
- std::wstring Context_ws = u16fmt((const PKMX_WCHAR) kp->dpContext);
+ std::wstring Context_ws = wstring_from_u16string((const PKMX_WCHAR) kp->dpContext);
key << Context_ws;
}
return key.str();
diff --git a/developer/src/kmcmplib/src/debugstore.h b/developer/src/kmcmplib/src/debugstore.h
index c54e3b45c3..d8bd4643df 100644
--- a/developer/src/kmcmplib/src/debugstore.h
+++ b/developer/src/kmcmplib/src/debugstore.h
@@ -5,16 +5,16 @@
#define DEBUGSTORE_BEGIN u"B"
#define DEBUGSTORE_BEGIN_C u'B'
-#define DEBUGSTORE_MATCH u"M"
-#define DEBUGSTORE_MATCH_C u'M'
+#define DEBUGSTORE_MATCH_U u"M"
+#define DEBUGSTORE_MATCH_L L"M"
-#define DEBUGSTORE_NOMATCH u"N"
-#define DEBUGSTORE_NOMATCH_C u'N'
+#define DEBUGSTORE_NOMATCH_U u"M"
+#define DEBUGSTORE_NOMATCH_L L"M"
-#define DEBUGSTORE_GROUP u"G"
-#define DEBUGSTORE_GROUP_C u'G'
+#define DEBUGSTORE_GROUP_U u"G"
+#define DEBUGSTORE_GROUP_L L"G"
-#define DEBUGSTORE_DEADKEY u"D"
-#define DEBUGSTORE_DEADKEY_C u'D'
+#define DEBUGSTORE_DEADKEY_U u"D"
+#define DEBUGSTORE_DEADKEY_L L"D"
#endif /* DEBUGSTORE_H */
diff --git a/developer/src/kmcmplib/src/kmx_u16.cpp b/developer/src/kmcmplib/src/kmx_u16.cpp
deleted file mode 100644
index 02e59f8c12..0000000000
--- a/developer/src/kmcmplib/src/kmx_u16.cpp
+++ /dev/null
@@ -1,293 +0,0 @@
-
-//#include "../../kmcompx/include/kmcompx.h"
-#include
-#include "kmx_u16.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-//String <- wstring
-std::string string_from_wstring(std::wstring const str) {
- std::wstring_convert, wchar_t> converter;
- return converter.to_bytes(str);
-}
-//wstring <- string
-std::wstring wstring_from_string(std::string const str) {
- std::wstring_convert, wchar_t> converter;
- return converter.from_bytes(str);
-}
-
-//u16String <- string
-std::u16string u16string_from_string(std::string const str) {
- std::wstring_convert, char16_t> converter;
- return converter.from_bytes(str);
-}
-
-//string <- u16string
-std::string string_from_u16string(std::u16string const str) {
- std::wstring_convert, char16_t> converter;
- return converter.to_bytes(str);
-}
-
-// often used with c_str() e.g. u16fmt( DEBUGSTORE_MATCH).c_str()
-// UTF16 (= const char16_t*) -> UTF8 (= std::string) -> UTF16 ( = std::wstring 16 bit)
-std::wstring u16fmt(const KMX_WCHAR * str) {
- std::wstring_convert, wchar_t> convert_wstring;
- std::wstring_convert, char16_t> convert;
-
- // UTF16 (= const char16_t*) -> UTF8 (= std::string) -> UTF16 ( = std::wstring 16 bit)
- std::string utf8str = convert.to_bytes(str); // UTF16 (= const char16_t*) -> UTF8 (= std::string)
- std::wstring wstr = convert_wstring.from_bytes(utf8str); // UTF8 (= std::string) -> UTF16 ( = std::wstring 16 bit)
- return wstr;
-}
-
-void u16sprintf(KMX_WCHAR * dst, const size_t sz, const wchar_t* fmt, ...) {
- // UTF16 (=const wchar_t*) -> -> std::string -> std::u16string -> UTF16 ( = char16_t*)
- wchar_t* wbuf = new wchar_t[sz];
- va_list args;
- va_start(args, fmt);
- vswprintf(wbuf, sz, fmt, args);
- va_end(args);
-
- std::wstring_convert, wchar_t> convert_wstring;
- std::wstring_convert, char16_t> convert;
-
- // UTF16 (=const wchar_t*) -> -> std::string -> std::u16string -> UTF16 ( = char16_t*)
- std::string utf8str = convert_wstring.to_bytes(wbuf); // UTF16 ( = const wchar_t*) -> std::string
- std::u16string u16str = convert.from_bytes(utf8str); // std::string -> std::u16string
- u16ncpy(dst, u16str.c_str(), sz); // std::u16string.c_str() -> char16_t*
- delete[] wbuf;
-}
-
- std::wstring convert_pchar16T_To_wstr(KMX_WCHAR *Name){
- // convert char16_t* -> std::u16string -> std::string -> std::wstring
- // char16_t* -> std::u16string
- std::u16string u16str(Name);
- // std::u16string -> std::string
- std::string stri = string_from_u16string(u16str);
- // std::string -> std::wstring
- std::wstring wstr = wstring_from_string(stri);
- return wstr;
- }
-
-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;
-}
-
-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;
-}
-
-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;
-}
-
-KMX_CHAR* strrchr_slash(KMX_CHAR* Name)
-{
- KMX_CHAR* cp = NULL;
- cp = strrchr(Name, '\\');
- if (cp == NULL)
- cp = strrchr(Name, '/');
- return cp;
-}
-
-// u16rchr returns last occurence of ch in p; It returns NULL if ch = '\0' and NULL if ch is not found
-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;
-}
-
-const KMX_WCHAR * u16chr(const KMX_WCHAR *p, KMX_WCHAR ch) {
- while (*p) {
- if (*p == ch) return p;
- p++;
- }
- return ch == 0 ? p : NULL;
-}
-
-const KMX_WCHAR * u16cpy(KMX_WCHAR *dst, const KMX_WCHAR *src) {
- KMX_WCHAR *o = dst;
- while (*src) {
- *dst++ = *src++;
- }
- *dst = 0;
- return o;
-}
-
-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;
-}
-
-size_t u16len(const KMX_WCHAR *p) {
- int i = 0;
- while (*p) {
- p++;
- i++;
- }
- return i;
-}
-
-int u16cmp(const KMX_WCHAR *p, const KMX_WCHAR *q) {
- while (*p && *q) {
- if (*p != *q) return *p - *q;
- p++;
- q++;
- }
- return *p - *q;
-}
-
-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;
-}
-
-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;
-}
-
-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;
-}
-
-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;
-}
-
-KMX_WCHAR * u16tok(KMX_WCHAR* p, const KMX_WCHAR* delim, KMX_WCHAR** ctx) {
- if (!p) {
- p = *ctx;
- if (!p) return NULL;
- }
-
- KMX_WCHAR * q = p;
- while (*q && !u16chr(delim, *q)) {
- q++;
- }
- if (*q) {
- *q = 0;
- q++;
- while (*q && u16chr(delim, *q)) q++;
- *ctx = q;
- }
- else {
- *ctx = NULL;
- }
- return *p ? p : NULL;
-}
-
-double u16tof( KMX_WCHAR* str)
-{
- double val = 0;
- int offsetdot=0;
- char digit;
-
- PKMX_WCHAR q = (PKMX_WCHAR)u16chr(str, '.');
- size_t pos_dot = (q-str < 0) ? u16len(str) : q-str;
-
- for (size_t i = 0; i < u16len(str); i++)
- {
- digit = static_cast(towupper(*str));
-
- if (i > pos_dot - 1)
- offsetdot = 1;
-
- if (digit != '.')
- val =val+ ((int(digit)) - 48) * pow(10, (pos_dot - 1- i + offsetdot));
-
- str++;
- }
- return val;
-}
diff --git a/developer/src/kmcmplib/src/kmx_u16.h b/developer/src/kmcmplib/src/kmx_u16.h
deleted file mode 100644
index 450c400e2f..0000000000
--- a/developer/src/kmcmplib/src/kmx_u16.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-#include "kmcompx.h"
-
-std::string string_from_wstring(std::wstring const str);
-std::wstring wstring_from_string(std::string const str);
-std::u16string u16string_from_string(std::string const str);
-std::string string_from_u16string(std::u16string const str);
-
-std::wstring u16fmt(const KMX_WCHAR * str);
-void u16sprintf(KMX_WCHAR * dst, const size_t sz, const wchar_t* fmt, ...) ;
-
-std::wstring convert_pchar16T_To_wstr(KMX_WCHAR *Name);
-
-size_t u16len(const KMX_WCHAR *p);
-int u16cmp(const KMX_WCHAR *p, const KMX_WCHAR *q);
-int u16icmp(const KMX_WCHAR *p, const KMX_WCHAR *q);
-int u16ncmp(const KMX_WCHAR *p, const KMX_WCHAR *q, size_t count);
-int u16nicmp(const KMX_WCHAR *p, const KMX_WCHAR *q, size_t count) ;
-const KMX_WCHAR * u16ncpy(KMX_WCHAR *dst, const KMX_WCHAR *src, size_t max);
-const KMX_WCHAR * u16cpy(KMX_WCHAR *dst, const KMX_WCHAR *src);
-const KMX_WCHAR * u16rchr(const KMX_WCHAR *p, KMX_WCHAR ch) ;
-const KMX_WCHAR * u16chr(const KMX_WCHAR *p, KMX_WCHAR ch) ;
-const KMX_WCHAR * u16ncat(KMX_WCHAR *dst, const KMX_WCHAR *src, size_t max);
-KMX_WCHAR * u16tok(KMX_WCHAR *p, const KMX_WCHAR ch, KMX_WCHAR **ctx) ;
-KMX_WCHAR * u16tok(KMX_WCHAR* p, const KMX_WCHAR* ch, KMX_WCHAR** ctx) ;
-long int u16tol(const KMX_WCHAR* str, KMX_WCHAR** endptr, int base) ;
-double u16tof( KMX_WCHAR* str);
-
-KMX_CHAR* strrchr_slash(KMX_CHAR* Name);
-const KMX_WCHAR* u16rchr_slash(KMX_WCHAR const* Name);
-
-std::string toHex(int num1);
diff --git a/developer/src/kmcmplib/src/meson.build b/developer/src/kmcmplib/src/meson.build
index 2b9a431e09..51acf70409 100644
--- a/developer/src/kmcmplib/src/meson.build
+++ b/developer/src/kmcmplib/src/meson.build
@@ -78,13 +78,14 @@ lib = library('kmcmplib',
'cp1252.cpp',
'DeprecationChecks.cpp',
'Edition.cpp',
- 'kmx_u16.cpp',
'NamedCodeConstants.cpp',
'UnreachableRules.cpp',
'uset-api.cpp',
'versioning.cpp',
'virtualcharkeys.cpp',
'xstring.cpp',
+ '../../../../common/cpp/km_u16.cpp',
+ '../../../../common/cpp/utfcodec.cpp',
'../../../../common/windows/cpp/src/ConvertUTF.c',
'../../../../common/windows/cpp/src/crc32.cpp',
'../../../../common/windows/cpp/src/vkeys.cpp',
diff --git a/developer/src/kmcmplib/src/pch.h b/developer/src/kmcmplib/src/pch.h
index 358e28998a..80bb639fb8 100644
--- a/developer/src/kmcmplib/src/pch.h
+++ b/developer/src/kmcmplib/src/pch.h
@@ -4,7 +4,7 @@
#define USE_CHAR16_T
#include
-#include "kmx_u16.h"
+#include
#include
#include "../../../../common/windows/cpp/include/crc32.h"
diff --git a/developer/src/kmcmplib/subprojects/gtest.wrap b/developer/src/kmcmplib/subprojects/gtest.wrap
index adb8a9a6d9..a77eb315bf 100644
--- a/developer/src/kmcmplib/subprojects/gtest.wrap
+++ b/developer/src/kmcmplib/subprojects/gtest.wrap
@@ -4,7 +4,7 @@ source_url = https://github.com/google/googletest/archive/refs/tags/v1.14.0.tar.
source_filename = gtest-1.14.0.tar.gz
source_hash = 8ad598c73ad796e0d8280b082cebd82a630d73e73cd3c70057938a6501bba5d7
patch_filename = gtest_1.14.0-2_patch.zip
-patch_url = https://wrapdb.mesonbuild.com/v2/gtest_1.14.0-2/get_patch
+patch_url = https://github.com/mesonbuild/wrapdb/releases/download/gtest_1.14.0-2/gtest_1.14.0-2_patch.zip
patch_hash = 4ec7f767364386a99f7b2d61678287a73ad6ba0f9998be43b51794c464a63732
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/gtest_1.14.0-2/gtest-1.14.0.tar.gz
wrapdb_version = 1.14.0-2
diff --git a/developer/src/kmcmplib/tests/gtest-compiler-test.cpp b/developer/src/kmcmplib/tests/gtest-compiler-test.cpp
index 22b38dccc6..1c20597645 100644
--- a/developer/src/kmcmplib/tests/gtest-compiler-test.cpp
+++ b/developer/src/kmcmplib/tests/gtest-compiler-test.cpp
@@ -1,7 +1,7 @@
#include
+#include
#include "../include/kmcompx.h"
#include "../include/kmcmplibapi.h"
-#include "../src/kmx_u16.h"
#include "../src/compfile.h"
#include "../src/CompilerErrors.h"
#include "../../common/include/kmn_compiler_errors.h"
diff --git a/developer/src/kmcmplib/tests/gtest-kmx_u16-test.cpp b/developer/src/kmcmplib/tests/gtest-km_u16-test.cpp
similarity index 94%
rename from developer/src/kmcmplib/tests/gtest-kmx_u16-test.cpp
rename to developer/src/kmcmplib/tests/gtest-km_u16-test.cpp
index aa1dca1de0..b67957bd31 100644
--- a/developer/src/kmcmplib/tests/gtest-kmx_u16-test.cpp
+++ b/developer/src/kmcmplib/tests/gtest-km_u16-test.cpp
@@ -1,9 +1,9 @@
#include
-#include "../src/kmx_u16.h"
+#include
+#include
#include "../src/compfile.h"
-#include "../../../../common/include/km_types.h"
-TEST(kmx_u16_Test, u16chr) {
+TEST(km_u16_Test, u16chr) {
KMX_WCHAR str[LINESIZE];
u16cpy(str, u"abc");
@@ -14,7 +14,7 @@ TEST(kmx_u16_Test, u16chr) {
EXPECT_EQ(3, u16chr(str, '\0') - str); // locate null terminator
}
-TEST(kmx_u16_Test, u16chr_compare_to_strchr) {
+TEST(km_u16_Test, u16chr_compare_to_strchr) {
// Compare behaviour of strchr:
char str[LINESIZE];
@@ -26,7 +26,7 @@ TEST(kmx_u16_Test, u16chr_compare_to_strchr) {
EXPECT_EQ(3, strchr(str, '\0') - str); // locate null terminator
}
-TEST(kmx_u16_Test, u16tok_char_delim) {
+TEST(km_u16_Test, u16tok_char_delim) {
// For char delimiter: KMX_WCHAR * u16tok(KMX_WCHAR *p, const KMX_WCHAR ch, KMX_WCHAR **ctx) ;
KMX_WCHAR str[LINESIZE];
@@ -67,7 +67,7 @@ TEST(kmx_u16_Test, u16tok_char_delim) {
EXPECT_TRUE(!u16cmp(u"def", ctx));
}
-TEST(kmx_u16_Test, u16tok_str_delim) {
+TEST(km_u16_Test, u16tok_str_delim) {
// For string delimiter: KMX_WCHAR * u16tok(KMX_WCHAR* p, const KMX_WCHAR* ch, KMX_WCHAR** ctx) ;
KMX_WCHAR str[LINESIZE];
@@ -126,7 +126,7 @@ TEST(kmx_u16_Test, u16tok_str_delim) {
EXPECT_EQ(nullptr, ctx);
}
-TEST(kmx_u16_Test, u16tok_str_compare_to_strtok) {
+TEST(km_u16_Test, u16tok_str_compare_to_strtok) {
// Compare behaviour of strtok:
char str[LINESIZE];
diff --git a/developer/src/kmcmplib/tests/meson.build b/developer/src/kmcmplib/tests/meson.build
index a5b6476c88..65915d1e9d 100644
--- a/developer/src/kmcmplib/tests/meson.build
+++ b/developer/src/kmcmplib/tests/meson.build
@@ -168,7 +168,7 @@ gtestcompilertest = executable('gtest-compiler-test', 'gtest-compiler-test.cpp',
test('gtest-compiler-test', gtestcompilertest)
-gtestkmx_u16test = executable('gtest-kmx_u16-test', 'gtest-kmx_u16-test.cpp',
+gtest_km_u16_test = executable('gtest-km_u16-test', 'gtest-km_u16-test.cpp',
cpp_args: defns + flags,
include_directories: inc,
name_suffix: name_suffix,
@@ -177,4 +177,4 @@ gtestkmx_u16test = executable('gtest-kmx_u16-test', 'gtest-kmx_u16-test.cpp',
dependencies: [ icuuc_dep, gtest_dep, gmock_dep ],
)
-test('gtest-kmx_u16-test', gtestkmx_u16test)
+test('gtest-km_u16-test', gtest_km_u16_test)
diff --git a/developer/src/kmcmplib/tests/util_filesystem.cpp b/developer/src/kmcmplib/tests/util_filesystem.cpp
index 7f9edd6b36..0873ff1328 100644
--- a/developer/src/kmcmplib/tests/util_filesystem.cpp
+++ b/developer/src/kmcmplib/tests/util_filesystem.cpp
@@ -117,23 +117,10 @@ FILE* Open_File(const KMX_CHAR* Filename, const KMX_CHAR* mode) {
#endif
};
-FILE* Open_File(const KMX_WCHART* Filename, const KMX_WCHART* mode) {
-#ifdef _MSC_VER
- std::wstring cpath = Filename; //, cmode = mode;
- std::replace(cpath.begin(), cpath.end(), '/', '\\');
- return _wfsopen(cpath.c_str(), mode, _SH_DENYWR);
-#else
- std::string cpath, cmode;
- cpath = string_from_wstring(Filename);
- cmode = string_from_wstring(mode);
- return fopen_wrapper(cpath.c_str(), cmode.c_str());
-#endif
-};
-
FILE* Open_File(const KMX_WCHAR* Filename, const KMX_WCHAR* mode) {
#ifdef _MSC_VER
- std::wstring cpath = convert_pchar16T_To_wstr((KMX_WCHAR*) Filename);
- std::wstring cmode = convert_pchar16T_To_wstr((KMX_WCHAR*) mode);
+ std::wstring cpath = wstring_from_u16string(Filename);
+ std::wstring cmode = wstring_from_u16string(mode);
std::replace(cpath.begin(), cpath.end(), '/', '\\');
return _wfsopen(cpath.c_str(), cmode.c_str(), _SH_DENYWR);
#else
diff --git a/developer/src/kmcmplib/tests/util_filesystem.h b/developer/src/kmcmplib/tests/util_filesystem.h
index 4c94dae6bf..c35967b05e 100644
--- a/developer/src/kmcmplib/tests/util_filesystem.h
+++ b/developer/src/kmcmplib/tests/util_filesystem.h
@@ -1,12 +1,11 @@
#pragma once
#include
-#include "../src/kmx_u16.h"
+#include
// Opens files on windows and non-windows platforms. Datatypes for Filename and mode must be the same.
// returns FILE* if file could be opened; FILE needs to be closed in calling function
FILE* Open_File(const KMX_CHAR* Filename, const KMX_CHAR* mode);
-FILE* Open_File(const KMX_WCHART* Filename, const KMX_WCHART* mode);
FILE* Open_File(const KMX_WCHAR* Filename, const KMX_WCHAR* mode);
KMX_BOOL kmcmp_FileExists(const KMX_CHAR *filename);
KMX_BOOL kmcmp_FileExists(const KMX_WCHAR *filename);
diff --git a/developer/src/server/build-addins.inc.sh b/developer/src/server/build-addins.inc.sh
index d48d44d1e7..052a24d77b 100644
--- a/developer/src/server/build-addins.inc.sh
+++ b/developer/src/server/build-addins.inc.sh
@@ -41,9 +41,10 @@ do_build_addins() {
# Build node-windows-trayicon
#
- pushd "$KEYMAN_ROOT/node_modules/node-windows-trayicon"
+ pushd "$KEYMAN_ROOT/developer/src/server/src/win32/trayicon/addon-src"
rm -rf build
- npx node-gyp clean configure build --arch=$ARCH --silent
+ npm ci
+ "$KEYMAN_ROOT/node_modules/.bin/node-gyp" clean configure build --arch=$ARCH --silent
cp build/Release/addon.node "$TRAYICON_SRC_TARGET"
cp build/Release/addon.node "$TRAYICON_BIN_TARGET"
popd
@@ -52,9 +53,9 @@ do_build_addins() {
# Build hetrodo-node-hide-console-window-napi
#
- pushd "$KEYMAN_ROOT/node_modules/hetrodo-node-hide-console-window-napi"
+ pushd "$KEYMAN_ROOT/node_modules/node-hide-console-window"
rm -rf build
- npx node-gyp clean configure build --arch=$ARCH --silent
+ "$KEYMAN_ROOT/node_modules/.bin/node-gyp" clean configure build --arch=$ARCH --silent
cp build/Release/node-hide-console-window.node "$HIDECONSOLE_SRC_TARGET"
cp build/Release/node-hide-console-window.node "$HIDECONSOLE_BIN_TARGET"
popd
diff --git a/developer/src/server/build.sh b/developer/src/server/build.sh
index e053d72b96..c73ed853f7 100755
--- a/developer/src/server/build.sh
+++ b/developer/src/server/build.sh
@@ -87,9 +87,16 @@ function build_server() {
# Post build
mkdir -p "$THIS_SCRIPT_PATH/build/src/site/"
- mkdir -p "$THIS_SCRIPT_PATH/build/src/win32/"
cp -r "$THIS_SCRIPT_PATH/src/site/"** "$THIS_SCRIPT_PATH/build/src/site/"
- cp -r "$THIS_SCRIPT_PATH/src/win32/"** "$THIS_SCRIPT_PATH/build/src/win32/"
+
+ mkdir -p "$THIS_SCRIPT_PATH/build/src/win32/"
+ mkdir -p "$THIS_SCRIPT_PATH/build/src/win32/console"
+ mkdir -p "$THIS_SCRIPT_PATH/build/src/win32/trayicon"
+ cp "$THIS_SCRIPT_PATH/src/win32/README.md" "$THIS_SCRIPT_PATH/build/src/win32/"
+ cp "$THIS_SCRIPT_PATH/src/win32/console/node-hide-console-window.node" "$THIS_SCRIPT_PATH/build/src/win32/console/"
+ cp "$THIS_SCRIPT_PATH/src/win32/console/node-hide-console-window.x64.node" "$THIS_SCRIPT_PATH/build/src/win32/console/"
+ cp "$THIS_SCRIPT_PATH/src/win32/trayicon/addon.node" "$THIS_SCRIPT_PATH/build/src/win32/trayicon/"
+ cp "$THIS_SCRIPT_PATH/src/win32/trayicon/addon.x64.node" "$THIS_SCRIPT_PATH/build/src/win32/trayicon/"
replaceVersionStrings "$THIS_SCRIPT_PATH/build/src/site/lib/sentry/init.js.in" "$THIS_SCRIPT_PATH/build/src/site/lib/sentry/init.js"
rm "$THIS_SCRIPT_PATH/build/src/site/lib/sentry/init.js.in"
@@ -114,10 +121,13 @@ function installer_server() {
rm -f node_modules/ngrok/bin/ngrok.exe
popd
- # @keymanapp/keyman-version is required in build/ now but we need to copy it in manually
+ # Dependencies are required in build/ but we need to copy them in manually
mkdir -p "$PRODBUILDTEMP/node_modules/@keymanapp/"
cp -R "$KEYMAN_ROOT/node_modules/@keymanapp/keyman-version/" "$PRODBUILDTEMP/node_modules/@keymanapp/"
cp -R "$KEYMAN_ROOT/node_modules/@keymanapp/developer-utils/" "$PRODBUILDTEMP/node_modules/@keymanapp/"
+ cp -R "$KEYMAN_ROOT/node_modules/@keymanapp/common-types/" "$PRODBUILDTEMP/node_modules/@keymanapp/"
+ cp -R "$KEYMAN_ROOT/node_modules/@keymanapp/ldml-keyboard-constants/" "$PRODBUILDTEMP/node_modules/@keymanapp/"
+ cp -R "$KEYMAN_ROOT/node_modules/eventemitter3/" "$PRODBUILDTEMP/node_modules/"
# We'll build in the $KEYMAN_ROOT/developer/bin/server/ folder
rm -rf "$KEYMAN_ROOT/developer/bin/server/"
@@ -144,8 +154,8 @@ function publish_server() {
builder_run_action clean:server clean_server
builder_run_action configure:server configure_server
-builder_run_action build:server build_server
builder_run_action build:addins build_addins
+builder_run_action build:server build_server
builder_run_action test:server test_server
# builder_run_action test:addins # no op
builder_run_action installer:server installer_server # TODO: rename to install-prep
diff --git a/developer/src/server/package.json b/developer/src/server/package.json
index c4c195ae1b..b0e438ad15 100644
--- a/developer/src/server/package.json
+++ b/developer/src/server/package.json
@@ -16,11 +16,14 @@
"multer": "^1.4.5-lts.1",
"ngrok": "^5.0.0-beta.2",
"open": "^8.4.0",
- "ws": "^8.17.1"
- },
+ "restructure": "^3.0.1",
+ "sax": ">=0.6.0",
+ "semver": "^7.5.2",
+ "ws": "^8.17.1",
+ "xmlbuilder": "~11.0.0"
+},
"optionalDependencies": {
- "hetrodo-node-hide-console-window-napi": "keymanapp/hetrodo-node-hide-console-window-napi#keyman-15.0",
- "node-windows-trayicon": "keymanapp/node-windows-trayicon#keyman-16.0"
+ "node-hide-console-window": "^2.2.0"
},
"devDependencies": {
"@keymanapp/keyman-version": "*",
@@ -32,6 +35,7 @@
"@types/ws": "^8.2.2",
"copyfiles": "^2.4.1",
"mocha": "^10.0.0",
+ "node-gyp": "^10.2.0",
"tsc-watch": "^4.5.0",
"typescript": "^5.4.5"
}
diff --git a/developer/src/server/src/win32/trayicon/README.md b/developer/src/server/src/win32/trayicon/README.md
index 2a6dfcff37..9dbc4b19f5 100644
--- a/developer/src/server/src/win32/trayicon/README.md
+++ b/developer/src/server/src/win32/trayicon/README.md
@@ -8,3 +8,8 @@ bundled libraries target for specific versions of node.
* Tree: https://github.com/mceSystems/node-windows-trayicon/tree/cbd7543ac186ca15ee8d7141aac43f26ceae1655
* License: MIT
* Built from: /developer/src/server/win32/node-windows-trayicon
+
+---
+
+The source for trayicon is currently in addon-src, as the original package is
+unmaintained.
\ No newline at end of file
diff --git a/developer/src/server/src/win32/trayicon/addon-src/.gitignore b/developer/src/server/src/win32/trayicon/addon-src/.gitignore
new file mode 100644
index 0000000000..c6bf5be1c7
--- /dev/null
+++ b/developer/src/server/src/win32/trayicon/addon-src/.gitignore
@@ -0,0 +1,62 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+bower_components
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (http://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# Typescript v1 declaration files
+typings/
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variables file
+.env
+
+.vscode
+build/
+test/icon.ico
\ No newline at end of file
diff --git a/developer/src/server/src/win32/trayicon/addon-src/LICENSE b/developer/src/server/src/win32/trayicon/addon-src/LICENSE
new file mode 100644
index 0000000000..454c5bc10a
--- /dev/null
+++ b/developer/src/server/src/win32/trayicon/addon-src/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018 mceSystems
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/developer/src/server/src/win32/trayicon/addon-src/README.md b/developer/src/server/src/win32/trayicon/addon-src/README.md
new file mode 100644
index 0000000000..6c429beb59
--- /dev/null
+++ b/developer/src/server/src/win32/trayicon/addon-src/README.md
@@ -0,0 +1,57 @@
+# windows-trayicon
+Native addon to add a windows tray icon with menu, built on windows-native libraries (no .NET dependency)
+
+# Installation
+```
+npm install --save windows-trayicon
+```
+
+# Usage
+```
+const WindowsTrayicon = require("windows-trayicon");
+const path = require("path");
+const fs = require("fs");
+
+const myTrayApp = new WindowsTrayicon({
+ title: "Trayicon Test",
+ icon: path.resolve(__dirname, "icon.ico"),
+ menu: [
+ {
+ id: "item-1-id",
+ caption: "First Item"
+ },
+ {
+ id: "item-2-id",
+ caption: "Second Item"
+ },
+ {
+ id: "item-3-id-exit",
+ caption: "Exit"
+ }
+ ]
+});
+
+myTrayApp.item((id) => {
+ console.log(`Menu id selected=${id}`);
+ switch (id) {
+ case "item-1-id": {
+ console.log("First item selected...");
+ break;
+ }
+ case "item-2-id": {
+ myTrayApp.balloon("Hello There!", "This is my message to you").then(() => {
+ console.log("Balloon clicked");
+ })
+ break;
+ }
+ case "item-3-id-exit": {
+ myTrayApp.exit();
+ process.exit(0)
+ break;
+ }
+ }
+});
+
+process.stdin.resume()
+
+```
\ No newline at end of file
diff --git a/developer/src/server/src/win32/trayicon/addon-src/TrayIcon.cpp b/developer/src/server/src/win32/trayicon/addon-src/TrayIcon.cpp
new file mode 100644
index 0000000000..549ff935e3
--- /dev/null
+++ b/developer/src/server/src/win32/trayicon/addon-src/TrayIcon.cpp
@@ -0,0 +1,512 @@
+/*
+* Copyright (c) Istvan Pasztor
+* This source has been published on www.codeproject.com under the CPOL license.
+*/
+#include "stdafx.h"
+#include "TrayIcon.h"
+#include
+
+#define TRAY_WINDOW_MESSAGE (WM_USER + 100)
+
+namespace
+{
+// A map that never holds allocated memory when it is empty. This map will be created with placement new as a static variable,
+// and its destructor will be never called, and it shouldn't leak memory if it contains no items at program exit.
+// This dirty trick is useful when you create your trayicon object as static. In this case we can not control the
+// order of destruction of this map object and the static trayicon object. However this dirty trick ensures that
+// the map is freed exactly when the destructor of the last static trayicon is unregistering itself.
+class CIdToTrayIconMap
+{
+ public:
+ typedef UINT KeyType;
+ typedef CTrayIcon *ValueType;
+
+ // typedef didn't work with VC++6
+ struct StdMap : public std::map
+ {
+ };
+ typedef StdMap::iterator iterator;
+
+ CIdToTrayIconMap() : m_Empty(true) {}
+ ValueType &operator[](KeyType k)
+ {
+ return GetOrCreateStdMap()[k];
+ }
+ ValueType *find(KeyType k)
+ {
+ if (m_Empty)
+ return false;
+ StdMap::iterator it = GetStdMap().find(k);
+ if (it == GetStdMap().end())
+ return NULL;
+ return &it->second;
+ }
+ int erase(KeyType k)
+ {
+ if (m_Empty)
+ return 0;
+ StdMap &m = GetStdMap();
+ int res = (int)m.erase(k);
+ if (m.empty())
+ {
+ m.~StdMap();
+ m_Empty = true;
+ }
+ return res;
+ }
+ bool empty() const
+ {
+ return m_Empty;
+ }
+ // Call this only when the container is not empty!!!
+ iterator begin()
+ {
+ assert(!m_Empty); // Call this only when the container is not empty!!!
+ return m_Empty ? iterator() : GetStdMap().begin();
+ }
+ // Call this only when the container is not empty!!!
+ iterator end()
+ {
+ assert(!m_Empty); // Call this only when the container is not empty!!!
+ return m_Empty ? iterator() : GetStdMap().end();
+ }
+
+ private:
+ StdMap &GetStdMap()
+ {
+ assert(!m_Empty);
+ return (StdMap &)m_MapBuffer;
+ }
+ StdMap &GetOrCreateStdMap()
+ {
+ if (m_Empty)
+ {
+ new ((void *)&m_MapBuffer) StdMap();
+ m_Empty = false;
+ }
+ return (StdMap &)m_MapBuffer;
+ }
+
+ private:
+ bool m_Empty;
+ char m_MapBuffer[sizeof(StdMap)];
+};
+
+static CIdToTrayIconMap &GetIdToTrayIconMap()
+{
+ // This hack prevents running the destructor of our map, so it isn't problem if someone tries to reach this from a static destructor.
+ // Because of using MyMap this will not cause a memory leak if the user removes all items from the container before exiting.
+ static char id_to_tray_icon_buffer[sizeof(CIdToTrayIconMap)];
+ static bool initialized = false;
+ if (!initialized)
+ {
+ initialized = true;
+ new ((void *)id_to_tray_icon_buffer) CIdToTrayIconMap();
+ }
+ return (CIdToTrayIconMap &)id_to_tray_icon_buffer;
+}
+
+static UINT GetNextTrayIconId()
+{
+ static UINT next_id = 1;
+ return next_id++;
+}
+}
+
+void CallJsWithOptionalString(Napi::Env env, Function callback, Context *context, std::string* data) {
+ if (env != nullptr) {
+ if (callback != nullptr) {
+ if (data) {
+ callback.Call(context->Value(), { String::New(env, *data) });
+ } else {
+ callback.Call(context->Value(), {});
+ }
+
+ }
+ }
+ if (data != nullptr) {
+ delete data;
+ }
+}
+
+static const UINT g_WndMsgTaskbarCreated = RegisterWindowMessage(TEXT("TaskbarCreated"));
+LRESULT CALLBACK CTrayIcon::MessageProcessorWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ if (uMsg == TRAY_WINDOW_MESSAGE)
+ {
+ if (CTrayIcon **ppIcon = GetIdToTrayIconMap().find((UINT)wParam))
+ (*ppIcon)->OnMessage((UINT)lParam);
+ return 0;
+ }
+ else if (uMsg == g_WndMsgTaskbarCreated)
+ {
+ CIdToTrayIconMap &id_to_tray = GetIdToTrayIconMap();
+ if (!id_to_tray.empty())
+ {
+ for (std::map::const_iterator it = id_to_tray.begin(), eit = id_to_tray.end(); it != eit; ++it)
+ {
+ CTrayIcon *pTrayIcon = it->second;
+ pTrayIcon->OnTaskbarCreated();
+ }
+ }
+ }
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+HWND CTrayIcon::GetMessageProcessorHWND()
+{
+ static HWND hWnd = NULL;
+ if (!hWnd)
+ {
+ static const TCHAR TRAY_ICON_MESSAGE_PROCESSOR_WND_CLASSNAME[] = TEXT("TRAY_ICON_MESSAGE_PROCESSOR_WND_CLASS");
+ HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
+
+ WNDCLASSEX wc;
+ wc.cbSize = sizeof(wc);
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
+ wc.hIconSm = NULL;
+ wc.hInstance = hInstance;
+ wc.lpfnWndProc = MessageProcessorWndProc;
+ wc.lpszClassName = TRAY_ICON_MESSAGE_PROCESSOR_WND_CLASSNAME;
+ wc.lpszMenuName = NULL;
+ wc.style = 0;
+ if (!RegisterClassEx(&wc))
+ return NULL;
+
+ hWnd = CreateWindowEx(
+ 0,
+ TRAY_ICON_MESSAGE_PROCESSOR_WND_CLASSNAME,
+ TEXT("TRAY_ICON_MESSAGE_PROCESSOR_WND"),
+ WS_POPUP,
+ 0, 0, 0, 0,
+ NULL,
+ NULL,
+ hInstance,
+ NULL);
+ }
+ return hWnd;
+}
+
+CTrayIcon::CTrayIcon(const char *name, bool visible, HICON hIcon, bool destroy_icon_in_destructor)
+ : m_Id(GetNextTrayIconId()), m_Name(name), m_hIcon(hIcon), m_Visible(false), m_DestroyIconInDestructor(destroy_icon_in_destructor), m_pOnMessageFunc(NULL), m_pListener(NULL)
+{
+ GetIdToTrayIconMap()[m_Id] = this;
+ SetVisible(visible);
+}
+
+CTrayIcon::~CTrayIcon()
+{
+ SetVisible(false);
+ SetIcon(NULL, m_DestroyIconInDestructor);
+ GetIdToTrayIconMap().erase(m_Id);
+}
+
+HICON CTrayIcon::InternalGetIcon() const
+{
+ return m_hIcon ? m_hIcon : ::LoadIcon(NULL, IDI_APPLICATION);
+}
+
+bool CTrayIcon::AddIcon()
+{
+ NOTIFYICONDATAA data;
+ FillNotifyIconData(data);
+ data.uFlags |= NIF_MESSAGE | NIF_ICON | NIF_TIP;
+ data.uCallbackMessage = TRAY_WINDOW_MESSAGE;
+ data.hIcon = InternalGetIcon();
+
+ size_t tip_len = max(sizeof(data.szTip) - 1, strlen(m_Name.c_str()));
+ memcpy(data.szTip, m_Name.c_str(), tip_len);
+ data.szTip[tip_len] = 0;
+
+ return FALSE != Shell_NotifyIconA(NIM_ADD, &data);
+}
+
+bool CTrayIcon::RemoveIcon()
+{
+ NOTIFYICONDATAA data;
+ FillNotifyIconData(data);
+ return FALSE != Shell_NotifyIconA(NIM_DELETE, &data);
+}
+
+void CTrayIcon::OnTaskbarCreated()
+{
+ if (m_Visible)
+ AddIcon();
+}
+
+void CTrayIcon::SetName(const char *name)
+{
+ m_Name = name;
+ if (m_Visible)
+ {
+ NOTIFYICONDATAA data;
+ FillNotifyIconData(data);
+ data.uFlags |= NIF_TIP;
+
+ size_t tip_len = max(sizeof(data.szTip) - 1, strlen(name));
+ memcpy(data.szTip, name, tip_len);
+ data.szTip[tip_len] = 0;
+
+ Shell_NotifyIconA(NIM_MODIFY, &data);
+ }
+}
+
+bool CTrayIcon::SetVisible(bool visible)
+{
+ if (m_Visible == visible)
+ return true;
+ m_Visible = visible;
+ if (m_Visible)
+ return AddIcon();
+ return RemoveIcon();
+}
+
+void CTrayIcon::SetIcon(HICON hNewIcon, bool destroy_current_icon)
+{
+ if (m_hIcon == hNewIcon)
+ return;
+ if (destroy_current_icon && m_hIcon)
+ DestroyIcon(m_hIcon);
+ m_hIcon = hNewIcon;
+
+ if (m_Visible)
+ {
+ NOTIFYICONDATAA data;
+ FillNotifyIconData(data);
+ data.uFlags |= NIF_ICON;
+ data.hIcon = InternalGetIcon();
+ Shell_NotifyIconA(NIM_MODIFY, &data);
+ }
+}
+
+bool CTrayIcon::ShowBalloonTooltip(const char *title, const char *msg, ETooltipIcon icon)
+{
+#ifndef NOTIFYICONDATA_V2_SIZE
+ return false;
+#else
+ if (!m_Visible)
+ return false;
+
+ NOTIFYICONDATAA data;
+ FillNotifyIconData(data);
+ data.cbSize = NOTIFYICONDATAA_V2_SIZE; // win2k and later
+ data.uFlags |= NIF_INFO;
+ data.dwInfoFlags = icon;
+ data.uTimeout = 10000; // deprecated as of Windows Vista, it has a min(10000) and max(30000) value on previous Windows versions.
+
+ strcpy_s(data.szInfoTitle, title);
+ strcpy_s(data.szInfo, msg);
+
+ return FALSE != Shell_NotifyIconA(NIM_MODIFY, &data);
+#endif
+}
+
+void CTrayIcon::OnMessage(UINT uMsg)
+{
+ if (m_pOnMessageFunc)
+ m_pOnMessageFunc(this, uMsg);
+ if (m_pListener)
+ m_pListener->OnTrayIconMessage(this, uMsg);
+}
+
+void CTrayIcon::FillNotifyIconData(NOTIFYICONDATAA &data)
+{
+ memset(&data, 0, sizeof(data));
+ // the basic functions need only V1
+#ifdef NOTIFYICONDATA_V1_SIZE
+ data.cbSize = NOTIFYICONDATA_V1_SIZE;
+#else
+ data.cbSize = sizeof(data);
+#endif
+ data.hWnd = GetMessageProcessorHWND();
+ assert(data.hWnd);
+ data.uID = m_Id;
+}
+
+void TrayOnMessage(CTrayIcon *pTrayIcon, UINT uMsg)
+{
+ switch (uMsg)
+ {
+ case WM_LBUTTONUP:
+ case WM_RBUTTONUP:
+ ((CTrayIconContainer *)pTrayIcon->GetUserData())->PopupMenu();
+ break;
+
+ case NIN_BALLOONUSERCLICK:
+ ((CTrayIconContainer *)pTrayIcon->GetUserData())->BalloonClick();
+ break;
+ }
+}
+
+HICON GetIconHandle(std::string iconPath)
+{
+ return (HICON)LoadImage(NULL, iconPath.c_str(), IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE | LR_SHARED);
+}
+
+
+CTrayIconContainer::CTrayIconContainer(const CallbackInfo& info) : ObjectWrap(info), m_OnBalloonClick(nullptr), m_OnMenuItem(nullptr) {}
+
+Object CTrayIconContainer::Init(Napi::Env env, Object exports){
+ Function func =
+ DefineClass(env,
+ "CTrayIconContainer",
+ {
+ InstanceMethod("Start", &CTrayIconContainer::Start),
+ InstanceMethod("SetIconPath", &CTrayIconContainer::SetIconPath),
+ InstanceMethod("SetTitle", &CTrayIconContainer::SetTitle),
+ InstanceMethod("Stop", &CTrayIconContainer::Stop),
+ InstanceMethod("AddMenuItem", &CTrayIconContainer::AddMenuItem),
+ InstanceMethod("OnMenuItem", &CTrayIconContainer::OnMenuItem),
+ InstanceMethod("ShowBalloon", &CTrayIconContainer::ShowBalloon),
+ }
+ );
+
+ FunctionReference* constructor = new FunctionReference();
+ *constructor = Napi::Persistent(func);
+ env.SetInstanceData(constructor);
+
+ exports.Set("CTrayIconContainer", func);
+ return exports;
+}
+
+void CTrayIconContainer::Stop(const CallbackInfo& info)
+{
+ if (m_OnMenuItem) {
+ m_OnMenuItem.Release();
+ m_OnMenuItem = nullptr;
+ }
+ if (m_OnBalloonClick) {
+ m_OnBalloonClick.Release();
+ m_OnBalloonClick = nullptr;
+ }
+ PostThreadMessage(GetThreadId(m_worker->native_handle()), WM_QUIT, NULL, NULL);
+ m_worker->join();
+ delete m_worker;
+ m_worker = nullptr;
+ m_tray.SetVisible(false);
+}
+
+LRESULT CALLBACK pWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+void CTrayIconContainer::SetIconPath(const CallbackInfo& info)
+{
+ std::string iconPath = info[0].As();
+ m_tray.SetIcon(GetIconHandle(iconPath));
+}
+void CTrayIconContainer::SetTitle(const CallbackInfo& info)
+{
+ std::string title = info[0].As();
+ m_tray.SetName(title.c_str());
+}
+void CTrayIconContainer::Start(const CallbackInfo& info)
+{
+ HANDLE ready = CreateEvent(nullptr, true, false, nullptr);
+
+ m_worker = new std::thread([this, ready] {
+ m_tray.SetUserData(this);
+ m_tray.SetVisible(true);
+ m_tray.SetListener(TrayOnMessage);
+
+ SetEvent(ready);
+
+ static const TCHAR *class_name = TEXT("MCE_HWND_MESSAGE");
+ WNDCLASSEX wx = {};
+ wx.cbSize = sizeof(WNDCLASSEX);
+ wx.lpfnWndProc = pWndProc;
+ wx.hInstance = 0;
+ wx.lpszClassName = class_name;
+ RegisterClassEx(&wx);
+ m_hwnd = CreateWindowEx(0, class_name, TEXT("MCE_HWND_MESSAGE"), 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
+
+ MSG msg;
+ while (GetMessage(&msg, NULL, 0, 0))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ DestroyWindow(m_hwnd);
+
+ return 0;
+ });
+
+ WaitForSingleObject(ready, INFINITE);
+ CloseHandle(ready);
+}
+
+void CTrayIconContainer::BalloonClick()
+{
+ m_OnBalloonClick.BlockingCall(nullptr);
+}
+
+void CTrayIconContainer::PopupMenu()
+{
+ POINT pt;
+ if (GetCursorPos(&pt))
+ {
+ HMENU menu = CreatePopupMenu();
+ int i = 1;
+ for (auto const &item : m_menuItems)
+ {
+ if(item.m_caption == "-")
+ {
+ AppendMenuA(menu, MF_SEPARATOR, -1, NULL);
+ }
+ else
+ {
+ AppendMenuA(menu, MF_STRING, i, item.m_caption.c_str());
+ }
+ i++;
+ }
+
+ HWND activeHwnd = GetForegroundWindow();
+ SetForegroundWindow(m_hwnd);
+ UINT cmd = TrackPopupMenu(menu, TPM_RETURNCMD | TPM_RIGHTBUTTON, pt.x, pt.y, 0, m_hwnd, NULL);
+ PostMessage(m_hwnd, WM_NULL, 0, 0);
+ SetForegroundWindow(activeHwnd);
+ if(cmd > 0) {
+ m_OnMenuItem.BlockingCall(new std::string(m_menuItems[cmd-1].m_id));
+ }
+ }
+}
+
+void CTrayIconContainer::AddMenuItem(const CallbackInfo& info)
+{
+ std::string id = info[0].As();
+ std::string caption = info[1].As();
+ m_menuItems.push_back(CTrayIconMenuItem(id, caption));
+}
+
+void CTrayIconContainer::OnMenuItem(const CallbackInfo& info)
+{
+ Function cb = info[0].As();
+ Context *context = new Reference(Persistent(info.This()));
+ if (m_OnMenuItem) {
+ m_OnMenuItem.Release();
+ }
+ m_OnMenuItem = TSFNOptString::New(info.Env(), cb, "wintrayicon_OnMenuItem", 0, 1, context);
+}
+
+void CTrayIconContainer::ShowBalloon(const CallbackInfo& info)
+{
+ std::string title = info[0].As();
+ std::string text = info[1].As();
+ int timeout = info[2].As();
+ Function cb = info[3].As();
+
+ Context *context = new Reference(Persistent(info.This()));
+
+ if (m_OnBalloonClick) {
+ m_OnBalloonClick.Release();
+ }
+
+ m_OnBalloonClick = TSFNOptString::New(info.Env(), cb, "wintrayicon_ShowBalloon", 0, 1, context);
+ m_tray.ShowBalloonTooltip(title.c_str(), text.c_str());
+}
diff --git a/developer/src/server/src/win32/trayicon/addon-src/TrayIcon.h b/developer/src/server/src/win32/trayicon/addon-src/TrayIcon.h
new file mode 100644
index 0000000000..ee0c85561e
--- /dev/null
+++ b/developer/src/server/src/win32/trayicon/addon-src/TrayIcon.h
@@ -0,0 +1,193 @@
+/*
+* Copyright (c) Istvan Pasztor
+* This source has been published on www.codeproject.com under the CPOL license.
+*/
+#ifndef __TRAY_ICON_H__
+#define __TRAY_ICON_H__
+#pragma once
+
+// NOTE: include the following headers in your stdafx.h: