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: +#include +#include +#include +#include +#include +#include +#include +#include +#include "napi.h" + +using namespace Napi; + +using Context = Reference; +void CallJsWithOptionalString(Napi::Env env, Function callback, Context *context, std::string* data); +using TSFNOptString = TypedThreadSafeFunction; + +struct ITrayIconListener; + +class CTrayIconMenuItem +{ +public: + CTrayIconMenuItem(std::string id, std::string caption) : + m_id(id), m_caption(caption) {} + + std::string m_id; + std::string m_caption; +}; + + +// You can use this class either by inheriting from it and overriding the OnMessage() method, +// or by instantiating this class directly and setting its listener object or function. +class CTrayIcon +{ +public: + CTrayIcon(const char* name="tray_icon", bool visible=false, HICON hIcon=NULL, bool destroy_icon_in_destructor=false); + // destroys the current m_hIcon if set + virtual ~CTrayIcon(); + + virtual void SetName(const char* name); + const char* GetName() const { return m_Name.c_str(); } + + virtual bool SetVisible(bool visible); + bool IsVisible() const { return m_Visible; } + + // The destructor may destroy the specified hIcon. If you want to avoid that, call + // SetIcon(NULL, false) or SetDestroyIconInDestructor(false). + virtual void SetIcon(HICON hNewIcon, bool destroy_current_icon=true); + HICON GetIcon() const { return m_hIcon; } + + void SetDestroyIconInDestructor(bool b) { m_DestroyIconInDestructor = b; } + bool GetDestroyIconInDestructor() const { return m_DestroyIconInDestructor; } + + enum ETooltipIcon + { + eTI_None, // NIIF_NONE(0) + eTI_Info, // NIIF_INFO(1) + eTI_Warning, // NIIF_WARNING(2) + eTI_Error // NIIF_ERROR(3) + }; + // ShowBalloonTooltip() works only on win2k and later + bool ShowBalloonTooltip(const char* title, const char* msg, ETooltipIcon icon=eTI_None); + + typedef void (*POnMessageFunc)(CTrayIcon* pTrayIcon, UINT uMsg); + void SetListener(POnMessageFunc pOnMessageFunc) { m_pOnMessageFunc = pOnMessageFunc; } + void SetListener(ITrayIconListener *pListener) { m_pListener = pListener; } + void SetUserData(const void* UserData) { m_userData = UserData; } + const void* GetUserData() { return m_userData; } + +protected: + // uMsg can be one of the following window messages: + // - WM_MOUSEMOVE + // - WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK + // - WM_RBUTTONDOWN, WM_RBUTTONUP, WM_RBUTTONDBLCLK + // - WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MBUTTONDBLCLK + // WinXP and later: + // - NIN_BALLOONXXX messages (eg.: NIN_BALLOONUSERCLICK) + // + // Use GetCursorPos() if you need the location of the cursor. + // The default implementation calls the listener. + virtual void OnMessage(UINT uMsg); + +private: + void FillNotifyIconData(NOTIFYICONDATAA& data); + // Never returns NULL! If GetIcon()==NULL, then this returns a system icon + HICON InternalGetIcon() const; + bool AddIcon(); + bool RemoveIcon(); + void OnTaskbarCreated(); + +private: + UINT m_Id; + std::string m_Name; + bool m_Visible; + HICON m_hIcon; + bool m_DestroyIconInDestructor; + POnMessageFunc m_pOnMessageFunc; + ITrayIconListener* m_pListener; + + static LRESULT CALLBACK MessageProcessorWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + static HWND GetMessageProcessorHWND(); + const void* m_userData; +}; + + +//------------------------------------------------------------------------------------------------- + + +struct ITrayIconListener +{ + virtual void OnTrayIconMouseMove(CTrayIcon* pTrayIcon) {} + + virtual void OnTrayIconLButtonDown(CTrayIcon* pTrayIcon) {} + virtual void OnTrayIconLButtonUp(CTrayIcon* pTrayIcon) {} + virtual void OnTrayIconLButtonDblClk(CTrayIcon* pTrayIcon) {} + + virtual void OnTrayIconRButtonDown(CTrayIcon* pTrayIcon) {} + virtual void OnTrayIconRButtonUp(CTrayIcon* pTrayIcon) {} + virtual void OnTrayIconRButtonDblClk(CTrayIcon* pTrayIcon) {} + + virtual void OnTrayIconMButtonDown(CTrayIcon* pTrayIcon) {} + virtual void OnTrayIconMButtonUp(CTrayIcon* pTrayIcon) {} + virtual void OnTrayIconMButtonDblClk(CTrayIcon* pTrayIcon) {} + + // WinXP and later + virtual void OnTrayIconSelect(CTrayIcon* pTrayIcon) {} + virtual void OnTrayIconBalloonShow(CTrayIcon* pTrayIcon) {} + virtual void OnTrayIconBalloonHide(CTrayIcon* pTrayIcon) {} + virtual void OnTrayIconBalloonTimeout(CTrayIcon* pTrayIcon) {} + virtual void OnTrayIconBalloonUserClick(CTrayIcon* pTrayIcon) {} + + // Use GetCursorPos() if you need the location of the cursor. + virtual void OnTrayIconMessage(CTrayIcon* pTrayIcon, UINT uMsg) + { + switch (uMsg) + { + case WM_MOUSEMOVE: OnTrayIconMouseMove(pTrayIcon); break; + case WM_LBUTTONDOWN: OnTrayIconLButtonDown(pTrayIcon); break; + case WM_LBUTTONUP: OnTrayIconLButtonUp(pTrayIcon); break; + case WM_LBUTTONDBLCLK: OnTrayIconLButtonDblClk(pTrayIcon); break; + case WM_RBUTTONDOWN: OnTrayIconRButtonDown(pTrayIcon); break; + case WM_RBUTTONUP: OnTrayIconRButtonUp(pTrayIcon); break; + case WM_RBUTTONDBLCLK: OnTrayIconRButtonDblClk(pTrayIcon); break; + case WM_MBUTTONDOWN: OnTrayIconMButtonDown(pTrayIcon); break; + case WM_MBUTTONUP: OnTrayIconMButtonUp(pTrayIcon); break; + case WM_MBUTTONDBLCLK: OnTrayIconMButtonDblClk(pTrayIcon); break; + +#ifdef NIN_SELECT + case NIN_SELECT: OnTrayIconSelect(pTrayIcon); break; + case NIN_BALLOONSHOW: OnTrayIconBalloonShow(pTrayIcon); break; + case NIN_BALLOONHIDE: OnTrayIconBalloonHide(pTrayIcon); break; + case NIN_BALLOONTIMEOUT: OnTrayIconBalloonTimeout(pTrayIcon); break; + case NIN_BALLOONUSERCLICK: OnTrayIconBalloonUserClick(pTrayIcon); break; +#endif + } + } +}; + + + +class CTrayIconContainer : public ObjectWrap +{ +public: + CTrayIconContainer(const CallbackInfo& info); + static Object Init(Napi::Env env, Object exports); + void Start(const CallbackInfo& info); + void SetIconPath(const CallbackInfo& info); + void SetTitle(const CallbackInfo& info); + void AddMenuItem(const CallbackInfo& info); + void OnMenuItem(const CallbackInfo& info); + void ShowBalloon(const CallbackInfo& info); + void Stop(const CallbackInfo& info); + void PopupMenu(); + void BalloonClick(); + +private: + CTrayIcon m_tray; + std::thread* m_worker; + HWND m_hwnd; + std::vector m_menuItems; + TSFNOptString m_OnMenuItem; + TSFNOptString m_OnBalloonClick; +}; + +#endif //!__TRAY_ICON_H__ diff --git a/developer/src/server/src/win32/trayicon/addon-src/TrayWrapper.cpp b/developer/src/server/src/win32/trayicon/addon-src/TrayWrapper.cpp new file mode 100644 index 0000000000..5ff13e6a04 --- /dev/null +++ b/developer/src/server/src/win32/trayicon/addon-src/TrayWrapper.cpp @@ -0,0 +1,8 @@ +#include "TrayIcon.h" + +Object Init(Env env, Object exports) { + CTrayIconContainer::Init(env, exports); + return exports; +} + +NODE_API_MODULE(addon, Init) \ No newline at end of file diff --git a/developer/src/server/src/win32/trayicon/addon-src/binding.gyp b/developer/src/server/src/win32/trayicon/addon-src/binding.gyp new file mode 100644 index 0000000000..b560112b45 --- /dev/null +++ b/developer/src/server/src/win32/trayicon/addon-src/binding.gyp @@ -0,0 +1,23 @@ +{ + "targets": [ + { + "target_name": "addon", + "conditions": [ + ['OS=="win"', { + "sources": [ + "TrayWrapper.cpp", + "TrayIcon.cpp" + ], + "include_dirs": [ + " { + for (const cb of this.__itemCallbacks) { + cb(id); + } + }) + this.__nativeTray.SetTitle(this.__trayTitle); + if(this.__icon && "string" === typeof this.__icon){ + this.__nativeTray.SetIconPath(this.__icon); + } + this.__nativeTray.Start(); + } + item(cb) { + if ("function" === typeof cb) { + this.__itemCallbacks.push(cb); + } + } + balloon(title, text, timeout = 5000) { + return new Promise((resolve) => { + this.__nativeTray.ShowBalloon(title, text, timeout, () => { + resolve(); + }) + }); + } + exit() { + this.__nativeTray.Stop(); + } +} + +module.exports = WindowsTrayicon; diff --git a/developer/src/server/src/win32/trayicon/addon-src/package-lock.json b/developer/src/server/src/win32/trayicon/addon-src/package-lock.json new file mode 100644 index 0000000000..d16aad04aa --- /dev/null +++ b/developer/src/server/src/win32/trayicon/addon-src/package-lock.json @@ -0,0 +1,1905 @@ +{ + "name": "windows-trayicon", + "version": "3.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "windows-trayicon", + "version": "3.0.0", + "hasInstallScript": true, + "license": "MIT", + "os": [ + "win32" + ], + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^3.1.0", + "node-gyp": "^10.2.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@npmcli/agent": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.2.tgz", + "integrity": "sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==", + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/fs": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", + "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/cacache": { + "version": "18.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz", + "integrity": "sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==", + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/env-paths": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", + "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" + }, + "node_modules/exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==" + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/foreground-child": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==" + }, + "node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "engines": { + "node": ">=16" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "node_modules/make-fetch-happen": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz", + "integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==", + "dependencies": { + "@npmcli/agent": "^2.0.0", + "cacache": "^18.0.0", + "http-cache-semantics": "^4.1.1", + "is-lambda": "^1.0.1", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "proc-log": "^4.2.0", + "promise-retry": "^2.0.1", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-collect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-fetch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", + "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-addon-api": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz", + "integrity": "sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==" + }, + "node_modules/node-gyp": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.2.0.tgz", + "integrity": "sha512-sp3FonBAaFe4aYTcFdZUn2NYkbP7xroPGYvQmP4Nl5PxamznItBnNCgjrVTKrEfQynInMsJvZrdmqUnysCJ8rw==", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^13.0.0", + "nopt": "^7.0.0", + "proc-log": "^4.1.0", + "semver": "^7.3.5", + "tar": "^6.2.1", + "which": "^4.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/nopt": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", + "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/proc-log": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", + "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "optional": true + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "dependencies": { + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" + }, + "node_modules/ssri": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", + "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/unique-filename": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/unique-slug": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + } + }, + "@npmcli/agent": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.2.tgz", + "integrity": "sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==", + "requires": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.3" + } + }, + "@npmcli/fs": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", + "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", + "requires": { + "semver": "^7.3.5" + } + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true + }, + "abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==" + }, + "agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "requires": { + "debug": "^4.3.4" + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "cacache": { + "version": "18.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz", + "integrity": "sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==", + "requires": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "requires": { + "ms": "2.1.2" + } + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "requires": { + "iconv-lite": "^0.6.2" + } + }, + "env-paths": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", + "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==" + }, + "err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" + }, + "exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "foreground-child": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + } + }, + "fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "requires": { + "minipass": "^7.0.3" + } + }, + "glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + }, + "http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "requires": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + } + }, + "https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "requires": { + "agent-base": "^7.0.2", + "debug": "4" + } + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + }, + "ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "requires": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==" + }, + "isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==" + }, + "jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, + "jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + }, + "lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "make-fetch-happen": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz", + "integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==", + "requires": { + "@npmcli/agent": "^2.0.0", + "cacache": "^18.0.0", + "http-cache-semantics": "^4.1.1", + "is-lambda": "^1.0.1", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "proc-log": "^4.2.0", + "promise-retry": "^2.0.1", + "ssri": "^10.0.0" + } + }, + "minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==" + }, + "minipass-collect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "requires": { + "minipass": "^7.0.3" + } + }, + "minipass-fetch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", + "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", + "requires": { + "encoding": "^0.1.13", + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "node-addon-api": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz", + "integrity": "sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==" + }, + "node-gyp": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.2.0.tgz", + "integrity": "sha512-sp3FonBAaFe4aYTcFdZUn2NYkbP7xroPGYvQmP4Nl5PxamznItBnNCgjrVTKrEfQynInMsJvZrdmqUnysCJ8rw==", + "requires": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^13.0.0", + "nopt": "^7.0.0", + "proc-log": "^4.1.0", + "semver": "^7.3.5", + "tar": "^6.2.1", + "which": "^4.0.0" + } + }, + "nopt": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", + "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", + "requires": { + "abbrev": "^2.0.0" + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "requires": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + } + }, + "proc-log": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", + "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==" + }, + "promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "requires": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + } + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "optional": true + }, + "semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" + }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" + }, + "socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "requires": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + } + }, + "socks-proxy-agent": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "requires": { + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" + } + }, + "sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" + }, + "ssri": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", + "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", + "requires": { + "minipass": "^7.0.3" + } + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + } + } + }, + "tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + } + } + }, + "unique-filename": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "requires": { + "unique-slug": "^4.0.0" + } + }, + "unique-slug": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "requires": { + "isexe": "^3.1.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/developer/src/server/src/win32/trayicon/addon-src/package.json b/developer/src/server/src/win32/trayicon/addon-src/package.json new file mode 100644 index 0000000000..54dcd5578a --- /dev/null +++ b/developer/src/server/src/win32/trayicon/addon-src/package.json @@ -0,0 +1,23 @@ +{ + "name": "windows-trayicon", + "version": "3.0.0", + "description": "Create tray icon for windows", + "main": "index.js", + "os": [ + "win32" + ], + "scripts": { + "install": "node-gyp configure build" + }, + "author": "mce", + "license": "MIT", + "dependencies": { + "node-gyp": "^10.2.0", + "bindings": "^1.5.0", + "node-addon-api": "^3.1.0" + }, + "repository": { + "type": "git", + "url": "https://github.com/mceSystems/node-windows-trayicon" + } +} diff --git a/developer/src/server/src/win32/trayicon/addon-src/stdafx.cpp b/developer/src/server/src/win32/trayicon/addon-src/stdafx.cpp new file mode 100644 index 0000000000..f1d63e0b43 --- /dev/null +++ b/developer/src/server/src/win32/trayicon/addon-src/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// ConsoleApplication1.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/developer/src/server/src/win32/trayicon/addon-src/stdafx.h b/developer/src/server/src/win32/trayicon/addon-src/stdafx.h new file mode 100644 index 0000000000..b005a839de --- /dev/null +++ b/developer/src/server/src/win32/trayicon/addon-src/stdafx.h @@ -0,0 +1,15 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include + + + +// TODO: reference additional headers your program requires here diff --git a/developer/src/server/src/win32/trayicon/addon-src/targetver.h b/developer/src/server/src/win32/trayicon/addon-src/targetver.h new file mode 100644 index 0000000000..87c0086de7 --- /dev/null +++ b/developer/src/server/src/win32/trayicon/addon-src/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/developer/src/server/src/win32/trayicon/addon-src/test/index.js b/developer/src/server/src/win32/trayicon/addon-src/test/index.js new file mode 100644 index 0000000000..1f0a032602 --- /dev/null +++ b/developer/src/server/src/win32/trayicon/addon-src/test/index.js @@ -0,0 +1,45 @@ +const WindowsTrayicon = require(".."); +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/tike/child/UfrmDebug.pas b/developer/src/tike/child/UfrmDebug.pas index d40993af4c..66116034dc 100644 --- a/developer/src/tike/child/UfrmDebug.pas +++ b/developer/src/tike/child/UfrmDebug.pas @@ -424,14 +424,21 @@ function TfrmDebug.ProcessKeyEvent(var Message: TMessage): Boolean; end; end; var - vkey, modifier: uint16_t; + scan, vkey, modifier: uint16_t; begin Assert(Assigned(FDebugCore)); // We always use the US virtual key code as a basis for our keystroke // mapping; the best way to do this is to extract the scan code from // the message data and work from that - vkey := MapScanCodeToUSVK((Message.LParam and $FF0000) shr 16); + + // Note: if a key event has a zero scan code, it has probably been + // injected, so we will do our best with it, using the VK as provided. + // See also #11978 + scan := (Message.LParam and $FF0000) shr 16; + if scan = 0 + then vkey := Message.WParam + else vkey := MapScanCodeToUSVK(scan); // We don't support the Right Shift modifier in Keyman; // we treat it as Left Shift, even though MapScanCodeToUSVK diff --git a/developer/src/tike/dialogs/UfrmAboutTike.dfm b/developer/src/tike/dialogs/UfrmAboutTike.dfm index 3210c1e0e3..d1146e625b 100644 --- a/developer/src/tike/dialogs/UfrmAboutTike.dfm +++ b/developer/src/tike/dialogs/UfrmAboutTike.dfm @@ -504,12 +504,12 @@ inherited frmAboutTike: TfrmAboutTike 6082} end object lblCopyright: TLabel - Left = 125 - Top = 347 + Left = 156 + Top = 304 Width = 200 Height = 11 Anchors = [akLeft, akBottom] - Caption = 'Copyright SIL International. All Rights Reserved' + Caption = 'Copyright SIL Global. All Rights Reserved' Font.Charset = ANSI_CHARSET Font.Color = clBlack Font.Height = -9 @@ -544,50 +544,98 @@ inherited frmAboutTike: TfrmAboutTike ExplicitWidth = 634 end object Image1: TImage - Left = 55 + Left = 39 Top = 256 - Width = 52 - Height = 58 + Width = 107 + Height = 64 AutoSize = True Picture.Data = { - 0954506E67496D61676589504E470D0A1A0A0000000D49484452000000340000 - 003A08020000007010EDCC000000097048597300000B1100000B11017F645F91 - 0000001674455874536F667477617265007061696E742E6E657420342E314CEF - C5FF000003664944415478DA6364889DC9305801E3A8E3461D37EAB851C78D3A - 6ED471A38E1B75DCA000A38E1B75DCA8E348751C2323839182A8BD86A48A181F - 2323E3C3379F2F3E7A7BEEC19B979FBE232B6366022A6484B0FF31FCFFF7EF3F - 5C8A152C0707BFFF20C951E2384B55F149315646F2A2C8A683ACFFFFBF76ED99 - F6CDE7215C0E56E6CB6DA10AA2BC10EEB26377E267ED872B3E54ED67A52A0EE7 - 8AE72C7EFBE507A58EF337525891E5CCCECA8C55367DFEE1D907AEC31D77B53D - 4C11E6B8A5C76EC7CE4438EE488D3FB2E344B31751EA38097ECEEB9DE1FC9C6C - B81418D5ADBDF0F0EDC038AE23CCACCCDB0059E4EBCFDFB75F7CFAF3EF9FB420 - B700179B40C682DF7FFF0D80E38049F86C53908E8C105CE4D8ED97811377BEFD - F213226BA8207CF2CE2B78BAA6ABE37838586F76854BF273C1451CDB371FBCF1 - 1C974174775C67B8A400C2712E9D5BF75D7B3A281C072C980ED7F85928234CDC - 7BEDA9FF849DDF7EFE1978C7014182ADDABC14076491D3F75F27CC3A70FDD9FB - 81771C30D5EFAFF44536140880213761D7E5E60DE77EFEF93B908E030259219E - DDE5DE6A12FC68E2C0200C99B4EBF1BBAF03E9382010E1E5589CEEE8AA23C384 - 5A7FDD7CFEC1AA69E3FB6F3F07D2710CE0CC116DA53A39D69A978315597CC1E1 - 5BC9730EFC1F58C7410030723716B8AB4B0AC045BEFCF8AD5CB2FCF5E71F03EF - 38205095E0BFDC1ACAC6C20417899CB677E5C9BB83C271C0F83DD51064282F0C - 17A9597BBA6DD3F941E1381626C68BADA19A5288982D5E7EA27FC7255A398E2D - 710E234E4906B814331313B00595EEA459E2A98FACC4AE75D3915B2F48759C6C - C1D2775F7FFEFF8FAF390C94637CFFE527FE9085D340EBD958505A9D0FDF7ED1 - AA58F5FDD71F521DF7F9FBEF7F0C841BEA8CFF886ACD6307590B8FCCD8770DC2 - 26C9714402321DF7F7DFFF093B2F97AD38415E7B8E568E0356A9579FBC6F587F - 66EBC547C86986268E2B5A761C1EFBFF71A4038823FEFCFDF7E4FDD7F30FDF3C - 7DF715B36BC7C2CC54EAA527C4CD0EE19E7BF076F9893B70D96C176D05111E92 - 1D37E43BD5A38E1B75DCA8E306011875DC30701CB0FF1466AE2C2BC4FDF0CD97 - 35A7EEFD1F548E9311E276D39171D395D97BF5E9B2E377BEFEFC33881CC7C3C1 - 5AE8AEFBE0CD676531BEB6CDE77FFDF937881C0704DCECAC5A5202D79E7DF8FA - F33703385A670DB4937002000B26443581ED65730000000049454E44AE426082} + 0954506E67496D61676589504E470D0A1A0A0000000D494844520000006B0000 + 004008060000001DD489F9000000017352474200AECE1CE90000000467414D41 + 0000B18F0BFC6105000000097048597300002E2200002E2201AAE2DD92000009 + 584944415478DAED9C7D6C55E51DC77FF7BDEFF6B65494F262CB4A41A0142302 + CA26533A20CE85B0CD04D1A0C365739B714BD438CDD8CCD8B24463BA65CB92C5 + B89704131707D9FE603AC44DDBA1825005456094BE496BDFDBDBDEB6F7F5ECF9 + 5E7AEF3DE7DCE79C7BCE6DE1DE933EDFA494F39C7BCE7D389FE7F77B7EBFDFF3 + 1C6C246419D9B2DD0121E312B02C2401CB4212B02C2401CB42D2845572A0CDCB + 7EDD96ED0EF254E6B1D38A52774ADF4702D1F677EFA93C173FAE79F86F2BA212 + 2DC9767FCDC861B39DB8F0C79D83BC737AB0EE60BF9AB3DD799E567BDD749DDB + AE689B8C48746628D838B0EBA61FC5DBAAF7BCD62849F478B6FB6B4676BBADA1 + F54F5F7F9377CE72B02A0B9C5455EC54B431EBA1D343411A0F471B7DBBAB04AC + 5C509EC346B7947BC8AEEA75DB58982E4F84F157012B57B4B2D44D5E8FD2FDF9 + 4251B83F92AE1C0A58B920041537335872C1FDB50C0568322CC59B04AC6C0B9D + 5CCBDC5F8153D9DD2E7F983AC6C3F226012BDB9A9FEFA09A1297A22DC0A2BF93 + 83819875C924606553E8E02DF33C94EF5076F5C26888FAA622EA8F0B58D9D4BC + 3C072DBF4E6955136C8E6A615625A57E5CC0E20903BDDCE3A012969C62D4E338 + C49EDE68304A3D2C8C8E48342BAA2B7353894B19019E6756D59F6A559080A5B8 + 19BB6251A19316B0E4D4A17135E6934F4682310B9889105020AF52DFFB8301AE + 554102565C456C84D7329794EF485FFFC54385AB9A092F542A50B190AB9D457F + 9FF9C35A97085810E68E652C22B39BA8D3E3A1B68F878D5FA0D23A1658786403 + 03DC4FF4072818D51C0102D6F50C540DB328AD0F4B1A370AB1877ABC5FD365E9 + AA9859F19A3265123C1C88C6DCAB8EE636AC521640ACF4BAB91F1C61C10492D2 + B1503466012807A913D78F8682B1F366B5A4C8199B1BE5FA9F2F44BD9311BDCB + E62EAC3C87ADB99E8D6E27C7F7753217D7A9727115CC026B5561F645F6803FD7 + 7FC05CE17B8B5451E0FBCC4A43515D3B9D9BB0BCAFB4DDC12CAA591D3643B0A6 + 2ECE24CF735D3CA8E904E35C7F7D9EA273FE7094052CC17497CE4D585B8FF46C + 629EAD49DD8EAA01AA073C016C9D0A5626418677DAF5CAD53D11A14B63A17497 + 660CCB6EB3D19A6A2FDDBCA4940AF39C34E80BD0B9AED1D84F243A4B49A3917E + 64026BFB9B3D9BD849052CACC67EC8C271AD8417F3DB2AD543E6145BD30A7315 + E62CB9741261B932827567DD7CDAB7BB9EAA6E284A3937EA0FD237F6FF875ABB + C7126DAF3E73272D5D509C38BEFD878729184ECECBEFFDFA1ECA733B12C7F7EE + 3B4A5DFD7E43FFF6598375663818AB506889571AD272997AC23D702FB94EB141 + 6220C9360DEB6B1B17D18BDF5917B32C9ED8F554FFE83F686C3269D5FFFC4503 + D52E2C49F677EF2105AC4F5FDA411E57B2FF5F7EEA0DEAE81D37F46F9F15587A + EE2F2E5435AA554BEEADCC75F54C980B30B01C52E854E657C77AA78CA400A660 + 95157BE8ED17B6C5DC9E963AFBFCB4F9C9D7156D390D0B2E1BCB11813405BFEA + 621703A6B488730CF0407AF7A5D046165CC88B2470BF270702462E3505EBA186 + 2FD0BE07D628DACEB40DD36B4D1DE46396B4F4C6622AF03868FF2BA7159FC969 + 58062777EEB2BBD93C0B69C2860A653D10AE172ED8804CC17AE1DBB7D2CE4DC9 + 9D6A7D2353B4F989D7692AA43FB87216166C0985D3745605DD3ACF13DBD422D7 + 71FDF2508A78C55B0416E747D30F163209EB773FD840DBD755268E4F5F1AA61D + CFBD95F64B721696D10785BC79A32A3702A3637D53863A19172FFCC79CD76AC0 + B2C924AC27BFB98A1EFD6A6DE2381C89D28E9FFD9BCE768EE87E49CEC2C27E3C + 9F0137C6B308446F88E2CC88976399C8D54CC15AC61EF8E1FD5B1491A06F2244 + 3FFD4B0BFDFDDD2ECD2FC949585311A9C9E0C4CE0DDB8702513A3B6268AE49A8 + FCCAD668451B2A209DC6C27FD3A1FBB3F7D7D1DEAD3529EDCD1FF7D2D32F9FA2 + EEC18994733909AB6B3CDC64F021D16296C82E5625B2D878890D986684D5E715 + A519E76AA6613998FF7E9E051A3B6E5F9C726E682C407B9E6FA64F3A946E3127 + 61B50C069A8CAEF6A2805BA14A643329E25E6B58F187F0C0DD4BE9A9FB56A5E4 + 5C8810B73F7B8486C7931E22E7602D3FD4B98985EC4D6450BC2AF9C72CDC1E09 + 9A5B1EE16DE63451B29A512177514521FDF6FBEB69759557D1FE87C317E857AF + 9E491CE71C2CB3BB9BD4892C84907FCAE4CE19BC1DB25A15609870A733AEBA17 + E5BB188C2D54595E9068FBACDF4F5F7A2259C5B0342C17F3FBEB5589AC891291 + F26139ED545FAE8405570A976A40B3B244F2CCAE3A7A645B32E8407D70D9B70E + 26AAEF9686853ADE5A55D81E9C5ED2372A9402115162CE525741609C58CF4225 + 0335CAC9F0D5DD83F1F33D6B69F75DD589E310FBEEE58F1C8A41832C0D8BE7BA + 0C2E16C6AC7261A1836EC8D7DEDAA61612F54BCC2D72568D15B0B6FEF85F8DEC + 135C58BCAF2A2A70D11757CDA7EFDD5B4B2E4772C09C6E1B66C972B2B26116D6 + DE17FF9B920248893F946D2CE56B78E3975FB97AB0784101126924D45A42C563 + 6181932A0B8D43920B967B76388417E8E4CD0A5892243512CD7CA5F8277F6EA1 + 036F5D4A1C9B8565525B6C36DB51DE895981C50BB7F560012E2AF47999509209 + 968542B12C88997558C7CEF6C5722DF96AB1A561618E59A9B22CDE9C85CDA155 + 0C5299C7AE7B3F148D3D2A9028398109AE2D96A508AAED69B3060B70FEFA4E3B + ED3FF0114D0695B9A2A561F1EA82D0C5E9AD63F9EC3C1626F1EA8E9E2D217800 + 1424E2D8782387D2C7EE73613A2254BF577C22B92AA08075B0B9C3102C494A5A + CD4480459EDD3E3AFA610F5D1E98E07EFEB907EBA9725E32B4FFEE6FDE8B1581 + E3FAFD631BC8E5D41F903A6AB87BED82AB3767E1261B3879965161DE69F58515 + EB5EBCEABBBC228254C135BD454E967CCFCDDD4D669362BCEC06CB31230C68D4 + 1E614DBC60FCA622278B1495E59F4136F23147C152E39D97AD0C085846A4F526 + BD96FCCCD5614F873FAC5D8EC2AD96716A8E7261DE7FBF7F2ABEE34AC0322A24 + B5B5CCC26C3AC010C1A1D6870545A3D50D6C4D43559F775FD5265201CB8C50CD + C05289D7ED485819463FDC149259FC64B26712967B63FE9597F7B04F03D01174 + A8AAFA025626C28DE37BE443D76E47AB80652109581692806521590ED6AECD55 + 545AE4A6931707E9F8B901012BDB9DD292D361A7BDDB6A28128952479F9F8E9C + EA16B0B2DD293D6D5C51117BE3A4EDF3716AEF1D17B0B2DD2933CA1416CACAF5 + D9EEBC495D66B05AE307350F1FAC952469F14C6E78ADE5B0DB4E9E7F79E710EF + 9CF80F8D2D2401CB4212B02C2401CB4212B02C2401CB42FA3FF896A69B0C9D8C + 0A0000000049454E44AE426082} end object Label1: TLabel - Left = 125 + Left = 156 Top = 284 Width = 184 Height = 18 - Caption = 'Created by SIL International' + Caption = 'Created by SIL Global' Color = clWhite Font.Charset = ANSI_CHARSET Font.Color = clBlack diff --git a/developer/src/tike/xml/project/globalwelcome.xsl b/developer/src/tike/xml/project/globalwelcome.xsl index aecd70d90f..5ef8c4a7e1 100644 --- a/developer/src/tike/xml/project/globalwelcome.xsl +++ b/developer/src/tike/xml/project/globalwelcome.xsl @@ -18,8 +18,8 @@

Version

-
Created by SIL International - +
Created by SIL Global +
diff --git a/developer/src/tike/xml/project/project.css b/developer/src/tike/xml/project/project.css index c9486e4ac6..cd29ef360f 100644 --- a/developer/src/tike/xml/project/project.css +++ b/developer/src/tike/xml/project/project.css @@ -281,7 +281,8 @@ k\:menuitem.down { #header-sil img { vertical-align: top; - margin-left: 4px; + margin-left: -6px; + margin-top: 7px; } #header-sil > div { diff --git a/developer/src/tike/xml/project/sil.png b/developer/src/tike/xml/project/sil.png index 08a4291d5e..b65c2a4e08 100644 Binary files a/developer/src/tike/xml/project/sil.png and b/developer/src/tike/xml/project/sil.png differ diff --git a/docs/file-formats/kmx-file-format.md b/docs/file-formats/kmx-file-format.md new file mode 100644 index 0000000000..6de14df56f --- /dev/null +++ b/docs/file-formats/kmx-file-format.md @@ -0,0 +1,307 @@ +# KMX Binary Format + +This document describes the binary format for KMX, compiled from Keyman .kmn +source files. + +## Principles + +- All integer values are unsigned 32-bit little-endian unless otherwise + specified. +- All offsets are 32-bit little-endian values. All offsets are relative to the + beginning of the data (normally start of file). A zero offset indicates that + the value is not present, equivalent to `NULL` -- no offset can ever point to + the start of the file. +- All strings are UTF-16LE unless otherwise specified and null terminated. + Strings are referenced by offset (see above). +- The file format has a header section followed by data. There is no specific + defined order for data in the file. Empty space is permitted but should be + zeroed. Note that `COMP_KEYBOARD_KMXPLUS` must follow immediately after + `COMP_KEYBOARD` with no empty space (that is at byte offset 64). + +A .kmx file is essentially a 32-bit memory mapped file. In a 32-bit process, the +file can be loaded into a memory buffer, and (assuming the file is valid), all +offset values in the file can be rewritten into pointers by adding the base of +the memory buffer to them. (In a 64-bit process, a fixup is needed to make space +for 64-bit pointers.) + +## `COMP_KEYBOARD`: KMX header + +The very first section is a header that describes the remainder of the file. + +| ∆ | Bits | Name | Description | +|---|------|----------------------|-----------------------------------------------------------------------------------| +| 0 | 32 | `dwIdentifier` | `KXTS` 0x5354584B, `kmx.FILEID_COMPILED` | +| 4 | 32 | `dwFileVersion` | minimum Keyman version that can read the file, `KMX_Version` enum | +| 8 | 32 | `dwCheckSum` | deprecated in 16.0, `0x0`; CRC32 checksum of entire file | +|12 | 32 | `KeyboardID` | deprecated in 10.0, `0x0`; Windows LANGID for keyboard | +|16 | 32 | `IsRegistered` | deprecated in 10.0, `0x1`; registration status of compiler | +|20 | 32 | `version` | deprecated, `0x0`; was version of keyboard, see `TSS_KEYBOARDVERSION` | +|24 | 32 | `cxStoreArray` | number of `COMP_STORE` entries in `COMP_KEYBOARD.dpStoreArray` | +|28 | 32 | `cxGroupArray` | number of `COMP_GROUP` entries in `COMP_KEYBOARD.dpGroupArray` | +|32 | 32 | `dpStoreArray` | offset of first `COMP_STORE` entry | +|36 | 32 | `dpGroupArray` | offset of first `COMP_GROUP` entry | +|40 | 32 | `StartGroup_ANSI` | deprecated; index of starting non-Unicode `COMP_GROUP`, `0xFFFFFFFF` means unused | +|44 | 32 | `StartGroup_Unicode` | index of starting Unicode `COMP_GROUP`, `0xFFFFFFFF` means unused | +|48 | 32 | `dwFlags` | global flags for the keyboard, see description below | +|52 | 32 | `dwHotKey` | default hotkey for keyboard, from [`&Hotkey`], see description below | +|56 | 32 | `dpBitmapOffset` | offset of keyboard icon, `0x0` if not present | +|60 | 32 | `dwBitmapSize` | size in bytes of keyboard icon, `0x0` if not present | + +This structure is present at the start of every .kmx file. The `KXTS` identifier +can be used as a 'magic' to determine whether a binary file is a .kmx file. + +### `dwFileVersion`: Minimum version of Keyman required to read the file + +The `dwFileVersion` property should be checked before attempting to read any +other data in the file. If it is not a recognized version, then no further +attempt should be made to read the file. The recognized versions are listed in +the `KMX_Version` enum: + +| Value | Identifier | Description | +|--------------|---------------|------------------------------------------------------------------| +| `0x00000300` | `VERSION_30` | Keyman 3.0. Non-Unicode, Windows 3.1 only, not supported | +| `0x00000301` | `VERSION_31` | Keyman 3.1. Non-Unicode, Windows 3.1 only, not supported | +| `0x00000302` | `VERSION_32` | Keyman 3.2. Non-Unicode, Windows 3.1, 95, 98 only, not supported | +| `0x00000400` | `VERSION_40` | Keyman 4.0. Non-Unicode, Windows 3.1, 95, 98 only, not supported | +| `0x00000500` | `VERSION_50` | Keyman 5.0. Unicode, Windows only | +| `0x00000501` | `VERSION_501` | Keyman 5.1, added support for `call()` statement | +| `0x00000600` | `VERSION_60` | Keyman 6.0 | +| `0x00000700` | `VERSION_70` | Keyman 7.0 | +| `0x00000800` | `VERSION_80` | Keyman 8.0 | +| `0x00000900` | `VERSION_90` | Keyman 9.0 | +| `0x00000A00` | `VERSION_100` | Keyman 10.0, first true multi-platform version | +| `0x00000E00` | `VERSION_140` | Keyman 14.0 (versions 11.0-13.0 had no binary format changes) | +| `0x00000F00` | `VERSION_150` | Keyman 15.0 | +| `0x00001000` | `VERSION_160` | Keyman 16.0 | +| `0x00001100` | `VERSION_170` | Keyman 17.0 | + +### `StartGroup` + +Keyboards may have up to 4 starting groups, defined by [`begin`] statements in +the source .kmn file.. The `begin ANSI` group and `begin Unicode` groups are +defined in the `COMP_KEYBOARD` header, however as they were introduced into the +format later, the `begin NewContext` and `begin PostKeystroke` groups are +defined as system stores. + +### `dwFlags` + +The following flags are defined for .kmx keyboards: + +| Bit value | Name | Description | +|--------------|-----------------------|---------------------------------------------------------------------------------------------| +| `0x00000001` | `KF_SHIFTFREESCAPS` | Pressing Shift releases Caps Lock (see [`&ShiftFreesCaps`]) | +| `0x00000002` | `KF_CAPSONONLY` | Caps Lock switches on only (see [`&CapsOnOnly`]) | +| `0x00000004` | `KF_CAPSALWAYSOFF` | Caps Lock state is disabled (see [`&CapsAlwaysOff`]) | +| `0x00000008` | `KF_LOGICALLAYOUT` | Unused, should never be set | +| `0x00000010` | `KF_AUTOMATICVERSION` | The compiler determined the minimum version of Keyman automatically (see [`&Version`]) | +| `0x00000020` | `KF_KMXPLUS` | 16.0+: A `COMP_KEYBOARD_KMXPLUSINFO` structure is present immediately after `COMP_KEYBOARD` | + +### `dwHotKey`: keyboard hotkeys + +This field is `0x0` if no default hotkey is specified. The value is a bitmask: + +| Bit mask | Name | Description | +|--------------|-------------|------------------------------------------| +| `0x000000FF` | virtual key | [Keyman virtual key] value of the hotkey | +| `0x00010000` | `HK_ALT` | Set if the hotkey uses Alt | +| `0x00020000` | `HK_CTRL` | Set if the hotkey uses Ctrl | +| `0x00040000` | `HK_SHIFT` | Set if the hotkey uses Shift | + +### Keyboard icon + +The `COMP_KEYBOARD.dpBitmapOffset` and `COMP_KEYBOARD.dwBitmapSize` members +describe the keyboard icon, if present. If not present, both members should have +the value `0x0`. The keyboard icon may be a 16x16 Windows .bmp format file, 4, +8, 24, or 32 bit color, or a Windows .ico format file, which may have multiple +icons present at different bit depths and resolutions. Refer to the Windows API +documentation for .bmp and .ico binary formats. + +By convention, the compiler stores the bitmap image at the end of the KMX +data, but this is not a requirement of the file format. + +## `COMP_KEYBOARD_KMXPLUSINFO`: KMX+ secondary header + +| ∆ | Bits | Name | Description | +|---|------|-----------------|----------------------------| +| 0 | 32 | `dpKMXPlus` | offset of KMX+ data | +| 4 | 32 | `dwKMXPlusSize` | size in bytes of KMX+ data | + +The `COMP_KEYBOARD_KMXPLUSINFO` structure is present only if +`COMP_KEYBOARD.dwFlags` flag has bit `KF_KMXPLUS` (`0x20`) set. If present, it +must be located immediately after the `COMP_KEYBOARD` structure, that is, at +byte offset 64. + +See [KMX+ File Format] for details of the KMX+ file format. + +## `COMP_STORE` + +| ∆ | Bits | Name | Description | +|---|------|--------------|------------------------------------------------------------------------| +| 0 | 32 | `dwSystemID` | `0x0` for a normal store, or a system store value | +| 4 | 32 | `dpName` | offset to name of the store from keyboard source, `0x0` if not present | +| 8 | 32 | `dpString` | offset to value of the store | + +The `COMP_STORE` structure describes a [`store`] in the keyboard source file. +`COMP_STORE` structures are also used for additional metadata such as compiler +version. + +Store names are compiled into keyboards if debug information is included (see +[Debug information for keyboards](#debug-information-for-keyboards)), or if the store is used for [keyboard +options]. If the store name is not included, `dpName` will have a `0x0` value. + +### System Stores + +If `dwSystemID` is non-zero, then it will be one of the following values: + +| Value | Identifier | Count | Version | Description | +|-------|---------------------------------|-------|---------|------------------------------------------------------------------------------------------| +| 0 | `TSS_NONE` | 0+ | 5.0 | (Not a system store, normal keyboard store data) | +| 1 | `TSS_BITMAP` | 0-1 | 5.0 | [`&Bitmap`] store, used during compile only; see `COMP_KEYBOARD.dpBitmapOffset` | +| 2 | `TSS_COPYRIGHT` | 0-1 | 5.0 | [`&Copyright`] store | +| 3 | `TSS_HOTKEY` | 0-1 | 5.0 | [`&Hotkey`] store (see also `COMP_KEYBOARD.dwHotkey`) | +| 4 | `TSS_LANGUAGE` | 0-1 | 5.0 | Deprecated, [`&Language`] store | +| 5 | `TSS_LAYOUT` | 0-1 | 5.0 | Deprecated, [`LAYOUT`] statement | +| 6 | `TSS_MESSAGE` | 0-1 | 5.0 | [`&Message`] store | +| 7 | `TSS_NAME` | 0-1 | 5.0 | [`&Name`] store, public name of keyboard | +| 8 | `TSS_VERSION` | 0-1 | 5.0 | [`&Version`] store; use `COMP_KEYBOARD.dwFileVersion` | +| 9 | `TSS_CAPSONONLY` | 0-1 | 5.0 | [`&CapsOnOnly`] store; use `TF_CAPSONONLY` | +| 10 | `TSS_CAPSALWAYSOFF` | 0-1 | 5.0 | [`&CapsAlwaysOff`] store; use `TF_CAPSALWAYSOFF` | +| 11 | `TSS_SHIFTFREESCAPS` | 0-1 | 5.0 | [`&ShiftFreesCaps`] store; use `TF_SHIFTFREESCAPS` | +| 12 | `TSS_LANGUAGENAME` | 0-1 | 5.0 | Deprecated, `LANGUAGENAME` statement | +| 13 | `TSS_CALLDEFINITION` | 0+ | 5.0 | Definition for an IMX call | +| 14 | `TSS_CALLDEFINITION_LOADFAILED` | 0 | 5.0 | Deprecated, unused, was used internally in KMX processor | +| 15 | `TSS_ETHNOLOGUECODE` | 0-1 | 5.0 | Deprecated, [`&EthnologueCode`] store | +| 16 | `TSS_DEBUG_LINE` | 0+ | 5.0 | [Debug information for keyboards](#debug-information-for-keyboards) | +| 17 | `TSS_MNEMONIC` | 0-1 | 5.0 | [`&MnemonicLayout`] store, `'0'` or `'1'` | +| 18 | `TSS_INCLUDECODES` | 0-1 | 5.0 | [`&IncludeCodes`] store, used during compile only | +| 19 | `TSS_OLDCHARPOSMATCHING` | 0-1 | 5.0 | Deprecated, [`&OldCharPosMatching`] store | +| 20 | `TSS_COMPILEDVERSION` | 0-1 | 5.0 | Version of compiler used, may be omitted if `--no-compiler-version` passed to kmc | +| 21 | `TSS_KEYMANCOPYRIGHT` | 0-1 | 5.0 | Copyright message from compiler, may be omitted if `--no-compiler-version` passed to kmc | +| 22 | `TSS_CUSTOMKEYMANEDITION` | 1 | 5.0 | Deprecated, always `'0'`, always present | +| 23 | `TSS_CUSTOMKEYMANEDITIONNAME` | 1 | 5.0 | Deprecated, always `'Keyman'`, always present | +| 24 | `TSS_VISUALKEYBOARD` | 0-1 | 7.0 | [`&VisualKeyboard`] store | +| 25 | `TSS_KMW_RTL` | 0-1 | 7.0 | [`&KMW_RTL`] store, `'0'` or `'1'` | +| 26 | `TSS_KMW_HELPFILE` | 0-1 | 7.0 | [`&KMW_HelpFile`] store, used during compile only | +| 27 | `TSS_KMW_HELPTEXT` | 0-1 | 7.0 | [`&KMW_HelpText`] store, used during compile only | +| 28 | `TSS_KMW_EMBEDJS` | 0-1 | 7.0 | [`&KMW_EmbedJS`] store, used during compile only | +| 29 | `TSS_WINDOWSLANGUAGES` | 0-1 | 7.0 | Deprecated, [`&WindowsLanguages`] store | +| 30 | `TSS_COMPARISON` | 0+ | 8.0 | Generated by compiler for use in `if()` statements | +| 31 | `TSS_PLATFORM` | 0-1 | 9.0 | Cannot be used in `COMP_STORE`; used for [`if(&platform)`]. [`platform()`] only | +| 32 | `TSS_BASELAYOUT` | 0-1 | 9.0 | Cannot be used in `COMP_STORE`; used for [`if(&baselayout)`], [`baselayout()`] only | +| 33 | `TSS_LAYER` | 0 | 9.0 | Cannot be used in `COMP_STORE`; used for [`if(&layer)`] and [`set(&layer)`] | +| 34 | `TSS_VKDICTIONARY` | 0-1 | 9.0 | Dictionary of `T_` and `U_` virtual key names for touch layouts, generated by compiler | +| 35 | `TSS_LAYOUTFILE` | 0-1 | 9.0 | Name of touch layout file, used during compile only | +| 36 | `TSS_KEYBOARDVERSION` | 0-1 | 9.0 | [`&KeyboardVersion`] store | +| 37 | `TSS_KMW_EMBEDCSS` | 0-1 | 9.0 | [`&KMW_EmbedCSS`] store, used during compile only | +| 38 | `TSS_TARGETS` | 0-1 | 9.0 | [`&Targets`] store | +| 39 | `TSS_CASEDKEYS` | 0-1 | 14.0 | [`&CasedKeys`] store, used during compile only | +| 40 | `TSS_BEGIN_NEWCONTEXT` | 0-1 | 15.0 | zero-based index of group referenced in [`begin NewContext`] | +| 41 | `TSS_BEGIN_POSTKEYSTROKE` | 0-1 | 15.0 | zero-based index of group referenced in [`begin PostKeystroke`] | +| 42 | `TSS_NEWLAYER` | 0 | 15.0 | Cannot be used in `COMP_STORE`; used for testing layer switch events | +| 43 | `TSS_OLDLAYER` | 0 | 15.0 | Cannot be used in `COMP_STORE`; used for testing layer switch events | +| 44 | `TSS_DISPLAYMAP` | 0-1 | 17.0 | [`&DisplayMap`] store | + +## `COMP_GROUP` + +| ∆ | Bits | Name | Description | +|----|------|--------------|-----------------------------------------------------------------------------| +| 0 | 32 | `dpName` | offset to name of the group from keyboard source, `0x0` if not present | +| 4 | 32 | `dpKeyArray` | offset to array of `COMP_KEY` entries | +| 8 | 32 | `dpMatch` | offset to string for the [`match`] statement output, `0x0` if not present | +| 12 | 32 | `dpNoMatch` | offset to string for the [`nomatch`] statement output, `0x0` if not present | +| 16 | 32 | `cxKeyArray` | number of `COMP_KEY` entries in `COMP_GROUP.dpKeyArray` | +| 20 | 32 | `fUsingKeys` | `0x1` if group is `using keys`, `0x0` otherwise | + +The `COMP_GROUP` structure describes a [`group`] in the keyboard source file. +Note that the `readonly` property of a group is only applicable in the source +file and is never written to the binary format. + +## `COMP_KEY` + +| ∆ | Bits | Name | Description | +|----|------|--------------|------------------------------------------------------------------------------------------------| +| 0 | 16 | `Key` | Keyman virtual key for the rule, 0 if unused | +| 2 | 16 | (unused) | padding, reserved | +| 4 | 32 | `Line` | Line number for the rule, 0 if not compiled with debug information | +| 8 | 32 | `ShiftFlags` | Modifier flags for the key, see description below | +| 12 | 32 | `dpOutput` | offset to string for the output of the rule, always present even for zero-length output | +| 16 | 32 | `dpContext` | offset to string for the context part of the rule, always present even for zero-length context | + +The `COMP_KEY` structure describes a single rule in a keyboard source file. The +compiler expands `any()` statements found in the key part of a rule into +multiple rules -- so the key part of the rule is always only ever matching a +single key combination. + +## Debug information for keyboards + +When debug information is present, it will be found in four places in compiled +keyboards: + +* `COMP_STORE.dpName`: the name of the store from the .kmn file +* `COMP_GROUP.dpName`: the name of the group from the .kmn file +* `COMP_KEY.Line`: the line number for the rule +* System stores with `COMP_STORE.dwSystemID` value of `TSS_DEBUG_LINE` + +When a keyboard is compiled with debug data, the `TSS_DEBUG_LINE` system store +contains debug information about each source line in the file. In each entry, +`COMP_STORE.dpName` contains debug metadata, and `COMP_STORE.dpString` contains +only the stringified .kmn source line number where the metadata is found. + +The name of the `TSS_DEBUG_LINE` system store starts with a single character +which describes the rest of the debug metadata in that store: + +| Character | Debug data type | Metadata | +|-----------|-----------------------|----------------------------------------------------------| +| `'B'` | [`begin`] statement | `Unicode` or `ANSI` | +| `'M'` | [`match`] statement | Stringified index of containing group, space, group name | +| `'N'` | [`nomatch`] statement | Stringified index of containing group, space, group name | +| `'G'` | [`group`] statement | Stringified index of group, space, group name | +| `'D'` | [`deadkey`] statement | Stringified index of deadkey, space, deadkey name | + + + + + +[KMX+ File Format]: kmx-plus-file-format.md +[`begin`]: https://help.keyman.com/developer/language/reference/begin +[`deadkey`]: https://help.keyman.com/developer/language/reference/deadkey +[`group`]: https://help.keyman.com/developer/language/reference/group +[`match`]: https://help.keyman.com/developer/language/reference/match +[`nomatch`]: https://help.keyman.com/developer/language/reference/nomatch +[`store`]: https://help.keyman.com/developer/language/reference/store +[Keyman virtual key]: https://help.keyman.com/developer/language/guide/virtual-keys +[keyboard options]: https://help.keyman.com/developer/language/guide/variable-stores +[`&Bitmap`]: https://help.keyman.com/developer/language/reference/bitmap +[`&Copyright`]: https://help.keyman.com/developer/language/reference/copyright +[`&Hotkey`]: https://help.keyman.com/developer/language/reference/hotkey +[`&Language`]: https://help.keyman.com/developer/language/reference/language +[`LAYOUT`]: https://help.keyman.com/developer/language/reference/layout +[`&Message`]: https://help.keyman.com/developer/language/reference/message +[`&Name`]: https://help.keyman.com/developer/language/reference/name +[`&Version`]: https://help.keyman.com/developer/language/reference/version +[`&CapsOnOnly`]: https://help.keyman.com/developer/language/reference/caps +[`&CapsAlwaysOff`]: https://help.keyman.com/developer/language/reference/caps +[`&ShiftFreesCaps`]: https://help.keyman.com/developer/language/reference/caps +[`&EthnologueCode`]: https://help.keyman.com/developer/language/reference/ethnologuecode +[`&MnemonicLayout`]: https://help.keyman.com/developer/language/reference/mnemoniclayout +[`&IncludeCodes`]: https://help.keyman.com/developer/language/reference/includecodes +[`&OldCharPosMatching`]: https://help.keyman.com/developer/language/reference/oldcharposmatching +[`if(&layer)`]: https://help.keyman.com/developer/language/reference/if +[`set(&layer)`]: https://help.keyman.com/developer/language/reference/set +[`&VisualKeyboard`]: https://help.keyman.com/developer/language/reference/visualkeyboard +[`&KMW_RTL`]: https://help.keyman.com/developer/language/reference/kmw_rtl +[`&KMW_HelpFile`]: https://help.keyman.com/developer/language/reference/kmw_helpfile +[`&KMW_HelpText`]: https://help.keyman.com/developer/language/reference/kmw_helptext +[`&KMW_EmbedJS`]: https://help.keyman.com/developer/language/reference/kmw_embedjs +[`&WindowsLanguages`]: https://help.keyman.com/developer/language/reference/windowslanguages +[`if(&platform)`]: https://help.keyman.com/developer/language/reference/if +[`platform()`]: https://help.keyman.com/developer/language/reference/platform +[`if(&baselayout)`]: https://help.keyman.com/developer/language/reference/if +[`baselayout()`]: https://help.keyman.com/developer/language/reference/baselayout +[`&KeyboardVersion`]: https://help.keyman.com/developer/language/reference/keyboardversion +[`&KMW_EmbedCSS`]: https://help.keyman.com/developer/language/reference/kmw_embedcss +[`&Targets`]: https://help.keyman.com/developer/language/reference/targets +[`&CasedKeys`]: https://help.keyman.com/developer/language/reference/casedkeys +[`begin NewContext`]: https://help.keyman.com/developer/language/reference/begin +[`begin PostKeystroke`]: https://help.keyman.com/developer/language/reference/begin +[`&DisplayMap`]: https://help.keyman.com/developer/language/reference/displaymap diff --git a/core/src/ldml/C7043_ldml.md b/docs/file-formats/kmx-plus-file-format.md similarity index 98% rename from core/src/ldml/C7043_ldml.md rename to docs/file-formats/kmx-plus-file-format.md index b1d2223d55..75e1df4295 100644 --- a/core/src/ldml/C7043_ldml.md +++ b/docs/file-formats/kmx-plus-file-format.md @@ -2,7 +2,7 @@ - copied from -- Authors: MD SL +- Authors: MD SRL ## C7043.0 Introduction @@ -13,7 +13,10 @@ Draft spec PR: ## C7043.1 Principles -- The data described here is located at byte offset `dpKMXPlus`. +- When embedded in a .kmx file, the data described here is located at byte + offset `COMP_KEYBOARD_KMXPLUS.dpKMXPlus`. See + [KMX file format](kmx-file-format.md) for a full description of the .kmx + format. - All integer values are unsigned 32-bit little-endian unless otherwise specified. - All strings are UTF-16LE unless otherwise specified. (See the `strs` section.) @@ -21,7 +24,7 @@ Draft spec PR: the `strs` table. - All offsets are 32-bit little-endian values. For all sections except for the `'sect'` section (which see), offsets are relative to the beginning of each - section. + section and must fall within the `size` of the section. ## C7043.2 Sections @@ -39,8 +42,8 @@ Draft spec PR: The very first section is a table of contents listing the rest of the sections. The table of contents does not list itself. -This is the only section where all byte offsets are relative to the value of -`dpKMXPlus`. +Unlike all other sections, all byte offsets are relative to start of the `sect` +section and do not have to be located within the `size` of the section. | ∆ | Bits | Name | Description | |---|------|---------|------------------------------------------| diff --git a/ios/engine/KMEI/KeymanEngine/el.lproj/Localizable.strings b/ios/engine/KMEI/KeymanEngine/el.lproj/Localizable.strings index 47b3aa9de0..1bd8c7713f 100644 --- a/ios/engine/KMEI/KeymanEngine/el.lproj/Localizable.strings +++ b/ios/engine/KMEI/KeymanEngine/el.lproj/Localizable.strings @@ -44,19 +44,19 @@ "command-uninstall-keyboard-confirm" = "Θὰ θέλατε νὰ ἀπεγκαταστήσετε αὐτὸ τὸ πληκτρολόγιο;"; /* Text for the command to uninstall a lexical model */ -"command-uninstall-lexical-model" = "Ἀπεγκαταστῆτε λεξικό"; +"command-uninstall-lexical-model" = "Ἀπεγκαταστῆστε λεξικό"; /* Confirmation text to display before uninstalling a lexical model */ "command-uninstall-lexical-model-confirm" = "Θὰ θέλατε νὰ ἀπεγκαταστήσετε αὐτὸ τὸ λεξικό;"; /* Text for error when a keyboard cannot load properly */ -"error-loading-keyboard" = "Ἀδυνατοῦμε νὰ φορτώσομε τὸ πληκτρολόγιο ποὺ ζητήσατε"; +"error-loading-keyboard" = "Ἀδυναμία φορτώσεως τοῦ πληκτρολογίου ποὺ ζητήσατε"; /* Text for error when a lexical model cannot load properly */ -"error-loading-lexical-model" = "Ἀδυνατοῦμε νὰ φορτώσομε τὸ λεξικὸ ποὺ ζητήσατε"; +"error-loading-lexical-model" = "Ἀδυναμία φορτώσεως τοῦ λεξικοῦ ποὺ ζητήσατε"; /* Text for error when an installed file is unexpectedly missing */ -"error-missing-file" = "Δὲν βρέθηκε κάποιο ἀπαραίτητο ἀρχεῖο."; +"error-missing-file" = "Δὲν βρέθηκε κάποιο ἀπαιτούμενο ἀρχεῖο."; /* Text for error when an installed file is unexpectedly missing */ "error-missing-file-critical" = "Κάποιο σημαντικὸ ἀρχεῖο δὲν εὑρέθη. Παρακαλοῦμε προσπαθῆστε νὰ ἐγκαταστήσετε ἐκ νέου τὴν ἐφαρμογή."; @@ -77,7 +77,7 @@ "error-update-no-link" = "Δὲν ὑπάρχει πηγαῖος κώδικας πρὸς ἐνημέρωσιν αὐτοῦ τοῦ πακέτου"; /* Text for error when updating a resource: Keyman does not know how to update the resource */ -"error-update-not-managed" = "Ἀδυνατοῦμε νὰ ἐνημερώσομε πόρο μὴ διαχειριζόμενο ἀπὸ τὴν μηχανὴ Κῆμαν"; +"error-update-not-managed" = "Ἀδυναμία ἐνημερώσεως πόρου μὴ διαχειριζομένου ἀπὸ μηχανὴ Keyman"; /* Text for the command to open the help page of a keyboard, as shown on resource information views */ "info-command-help-keyboard" = "Βοήθεια γιὰ τὸ πληκτρολόγιο"; @@ -155,7 +155,7 @@ "menu-langsettings-toggle-correct" = "Ἐνεργοποιῆστε τὶς διορθώσεις"; /* Label for the toggle that enables predictions that is displayed within a language-specific settings menu */ -"menu-langsettings-toggle-predict" = "Ἐνεργοποιῆστε προβλέψεις"; +"menu-langsettings-toggle-predict" = "Ἐνεργοποιῆστε τὶς προβλέψεις κειμένου"; /* Help message for a prompt that appears for confirming a lexical model download: language (1): lexical model (dictionary) name (2) */ "menu-lexical-model-install-message" = "Θὰ θέλατε νὰ ἐγκαταστήσετε αὐτὸ τὸ λεξικό;"; @@ -200,13 +200,13 @@ "menu-settings-spacebar-hint-blank" = "Καμμία λεζάντα στὸ πλῆκτρο διαστήματος"; /* Secondary text showing current setting for spacebar caption - keyboard */ -"menu-settings-spacebar-hint-keyboard" = "Νὰ ἐμφανίζεται στὸ στὸ πλῆκτρο διαστήματος τὸ ὄνομα τοῦ πληκτρολογίου"; +"menu-settings-spacebar-hint-keyboard" = "Ὄνομα πληκτρολογίου στὸ πλῆκτρο διαστήματος"; /* Secondary text showing current setting for spacebar caption - language */ -"menu-settings-spacebar-hint-language" = "Νὰ ἐμφανίζεται στὸ στὸ πλῆκτρο διαστήματος τὸ ὄνομα τῆς γλώσσας"; +"menu-settings-spacebar-hint-language" = "Ὄνομα γλώσσας στὸ πλῆκτρο διαστήματος"; /* Secondary text showing current setting for spacebar caption - language + keyboard */ -"menu-settings-spacebar-hint-languageKeyboard" = "Νὰ ἐμφανίζεται στὸ στὸ πλῆκτρο διαστήματος τὸ ὄνομα τοῦ πληκτρολογίου καὶ τῆς γλώσσας"; +"menu-settings-spacebar-hint-languageKeyboard" = "Ὄνομα πληκτρολογίου καὶ γλώσσας στὸ πλῆκτρο διαστήματος"; /* Label for the "Spacebar Caption" item on the main settings screen */ "menu-settings-spacebar-text" = "Λεζάντα Πλήκτρου Διαστήματος"; diff --git a/ios/engine/KMEI/KeymanEngine/el.lproj/Localizable.stringsdict b/ios/engine/KMEI/KeymanEngine/el.lproj/Localizable.stringsdict index afaf5ae03d..b0544d994e 100644 --- a/ios/engine/KMEI/KeymanEngine/el.lproj/Localizable.stringsdict +++ b/ios/engine/KMEI/KeymanEngine/el.lproj/Localizable.stringsdict @@ -13,9 +13,9 @@ NSStringFormatValueTypeKey u one - Τὸ λεξικὸ %u ἐγκατεστάθη + Ἐγκατεστάθη %u λεξικό other - %u λεξικὰ ἐγκατεστάθησαν + Ἐγκατεστάθησαν %u λεξικά notification-update-failed @@ -31,7 +31,7 @@ one %u ἐνημέρωση ἀπέτυχε other - %u ἐνημερώσεις ἀπέτυχαν + Ἀπέτυχαν %u ἐνημερώσεις notification-update-success diff --git a/ios/keyman/Keyman/Keyman/el.lproj/Localizable.strings b/ios/keyman/Keyman/Keyman/el.lproj/Localizable.strings index 2df136fccc..d5d0fcec49 100644 --- a/ios/keyman/Keyman/Keyman/el.lproj/Localizable.strings +++ b/ios/keyman/Keyman/Keyman/el.lproj/Localizable.strings @@ -24,7 +24,7 @@ /* The name of the iOS Settings menu option for giving the keyboard full access. (The menu entry underneath the app's name within the app-specific keyboard menu.) */ -"ios-settings-allow-full-access" = "Ἐπιστρέψτε πλήρη πρόσβαση"; +"ios-settings-allow-full-access" = "Ἐπιτρέψτε πλήρη πρόσβαση"; /* Short-form used when installing a font in order to display a language properly. */ "language-for-font" = "Γραμματοσειρά %@"; @@ -60,13 +60,13 @@ underneath the app's name within the app-specific keyboard menu.) */ "menu-show-browser" = "Φυλλομετρητής"; /* Menu option used to control in-app font size. */ -"menu-text-size" = "Μέγεθος κειμένου"; +"menu-text-size" = "Μέγεθος γραμματοσειρᾶς"; /* Used to describe the current font size */ -"text-size-label" = "Μέγεθος κειμένου: %i"; +"text-size-label" = "Μέγεθος γραμματοσειρᾶς: %i"; /* Text to indicate that a user should set a toggle within iOS Settings to 'active'. */ -"toggle-to-enable" = "Ἐνεργοποιῆστε %@"; +"toggle-to-enable" = "Ἐνεργοποίηση %@"; /* First option on the Get Started tutorial - Add a keyboard for your language */ "tutorial-add-keyboard" = "Προσθέστε πληκτρολόγιο γιὰ τὴν γλῶσσα σας"; @@ -75,7 +75,7 @@ underneath the app's name within the app-specific keyboard menu.) */ "tutorial-show-help" = "Περισσότερες πληροφορίες"; /* Second option on the Get Started tutorial - Set up Keyman as system-wide keyboard */ -"tutorial-system-keyboard" = "Ὁρίστε τὸ Κῆμαν ὡς παν-συστημικὸ πληκτρολόγιο"; +"tutorial-system-keyboard" = "Ὁρίστε τὸ Κῆμαν ὡς πληκτρολόγιο ὁλοκλήρου τοῦ συστήματος"; /* Used to display app version (as in \"Version: 1.0.2\" */ "version-label" = "Ἔκδοση: %@"; diff --git a/linux/keyman-config/locale/el_polyton.po b/linux/keyman-config/locale/el_polyton.po new file mode 100644 index 0000000000..fa9797acce --- /dev/null +++ b/linux/keyman-config/locale/el_polyton.po @@ -0,0 +1,332 @@ +msgid "" +msgstr "" +"Project-Id-Version: keyman\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-08-19 19:17+0200\n" +"PO-Revision-Date: 2024-08-06 22:57\n" +"Last-Translator: \n" +"Language-Team: Greek (Polytonic)\n" +"Language: el_polyton\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Crowdin-Project: keyman\n" +"X-Crowdin-Project-ID: 386703\n" +"X-Crowdin-Language: el-polyton\n" +"X-Crowdin-File: /master/linux/keyman-config.pot\n" +"X-Crowdin-File-ID: 504\n" + +#: keyman_config/__init__.py:68 +msgid "Neither sentry-sdk nor raven is available. Not enabling Sentry error reporting." +msgstr "Δὲν εἶναι διαθέσιμα οὔτε τὸ sentry-sdk οὔτε τὸ raven. Δὲν ἐνεργοποιεῖται ἡ ἀναφορὰ σφαλμάτων Sentry." + +#: keyman_config/downloadkeyboard.py:23 +msgid "Download Keyman keyboards" +msgstr "Μεταφόρτωση πληκτρολογίων Keyman" + +#: keyman_config/downloadkeyboard.py:37 keyman_config/keyboard_details.py:49 +#: keyman_config/keyboard_details.py:340 keyman_config/view_installed.py:205 +msgid "_Close" +msgstr "_Close" + +#: keyman_config/install_kmp.py:99 +msgid "You do not have permissions to install the keyboard files to the shared area /usr/local/share/keyman" +msgstr "Δὲν σᾶς ἐπιτρέπεται νὰ ἐγκαταστήσετε τὰ ἀρχεῖα τοῦ πληκτρολογίου στὴν κοινὴ περιοχὴ /usr/local/share/keyman" + +#: keyman_config/install_kmp.py:103 +msgid "You do not have permissions to install the documentation to the shared documentation area /usr/local/share/doc/keyman" +msgstr "Δὲν σᾶς ἐπιτρέπεται νὰ ἐγκαταστήσετε τὴν τεκμηρίωση στὴν κοινὴ περιοχὴ τεκμηρίωσης /usr/local/share/doc/keyman" + +#: keyman_config/install_kmp.py:107 +msgid "You do not have permissions to install the font files to the shared font area /usr/local/share/fonts" +msgstr "Δὲν σᾶς ἐπιτρέπεται νὰ ἐγκαταστήσετε τὰ ἀρχεῖα γραμματοσειρῶν στὴν κοινὴ περιοχὴ γραμματοσειρῶν /usr/local/share/fonts" + +#: keyman_config/install_kmp.py:179 +#, python-brace-format +msgid "install_kmp.py: error: No kmp.json or kmp.inf found in {package}" +msgstr "install_kmp.py: σφάλμα: Δὲν βρέθηκε kmp.json ἢ kmp.inf στὸ {package}" + +#: keyman_config/install_kmp.py:246 +#, python-brace-format +msgid "install_kmp.py: error: No kmp.json or kmp.inf found in {packageFile}" +msgstr "install_kmp.py: σφάλμα: Δὲν βρέθηκε kmp.json ἢ kmp.inf στὸ {packageFile}" + +#: keyman_config/install_window.py:54 +#, python-brace-format +msgid "Installing keyboard/package {keyboardid}" +msgstr "Ἐγκαθίσταται πληκτρολόγιο/πακέτο {keyboardid}" + +#: keyman_config/install_window.py:72 keyman_config/install_window.py:93 +msgid "Keyboard is installed already" +msgstr "Τὸ πληκτρολόγιο ἔχει ἤδη ἐγκατασταθεῖ" + +#: keyman_config/install_window.py:74 +#, python-brace-format +msgid "The {name} keyboard is already installed at version {version}. Do you want to uninstall then reinstall it?" +msgstr "Τὸ πληκτρολόγιο {name} ἔχει ἤδη ἐγκατασταθεῖ στὴν ἔκδοση {version}. Θέλετε νὰ τὸ ἀφαιρέσετε καὶ νὰ τὸ ἐγκαταστήσετε ἐκ νέου;" + +#: keyman_config/install_window.py:95 +#, python-brace-format +msgid "The {name} keyboard is already installed with a newer version {installedversion}. Do you want to uninstall it and install the older version {version}?" +msgstr "Τὸ πληκτρολόγιο {name} ἔχει ἤδη ἐγκατασταθεῖ μὲ τὴν νεώτερη ἔκδοση {installedversion}. Θέλετε νὰ τὸ ἀφαιρέσετε καὶ νὰ ἐγκαταστήσετε τὴν παλαιότερη ἔκδοση {version};" + +#: keyman_config/install_window.py:128 +msgid "Keyboard layouts: " +msgstr "Διατάξεις πληκτρολογίου: " + +#: keyman_config/install_window.py:147 +msgid "Fonts: " +msgstr "Γραμματοσειρές: " + +#: keyman_config/install_window.py:167 keyman_config/keyboard_details.py:96 +msgid "Package version: " +msgstr "Ἔκδοση πακέτου: " + +#: keyman_config/install_window.py:179 +msgid "Author: " +msgstr "Κατασκευαστής: " + +#: keyman_config/install_window.py:197 +msgid "Website: " +msgstr "Ἱστότοπος: " + +#: keyman_config/install_window.py:211 +msgid "Copyright: " +msgstr "Πνευματικὰ δικαιώματα: " + +#: keyman_config/install_window.py:245 +msgid "Details" +msgstr "Λεπτομέρειες" + +#: keyman_config/install_window.py:248 +msgid "README" +msgstr "README" + +#: keyman_config/install_window.py:256 keyman_config/view_installed.py:200 +msgid "_Install" +msgstr "_Install" + +#: keyman_config/install_window.py:260 +msgid "_Cancel" +msgstr "_Cancel" + +#: keyman_config/install_window.py:305 +#, python-brace-format +msgid "Keyboard {name} installed" +msgstr "Τὸ πληκτρολόγιο {name} ἐγκατεστάθη" + +#: keyman_config/install_window.py:310 keyman_config/install_window.py:315 +#, python-brace-format +msgid "Keyboard {name} could not be installed." +msgstr "Τὸ πληκτρολόγιο {name} δὲν μπόρεσε νὰ ἐγκατασταθεῖ." + +#: keyman_config/install_window.py:311 +msgid "Error Message:" +msgstr "Μήνυμα σφάλματος:" + +#: keyman_config/install_window.py:316 +msgid "Warning Message:" +msgstr "Προειδοποιητικὸ μήνυμα:" + +#: keyman_config/keyboard_details.py:37 +#, python-brace-format +msgid "{name} keyboard" +msgstr "πληκτρολόγιο {name}" + +#: keyman_config/keyboard_details.py:53 +msgid "ERROR: Keyboard metadata is damaged.\n" +"Please \"Uninstall\" and then \"Install\" the keyboard." +msgstr "ΣΦΑΛΜΑ: Ζημία σὲ μεταδεδομένα πληκτρολογίου.\n" +"Παρακαλοῦμε \"Ἀπεγκαταστῆστε\" καὶ κατόπιν \"Ἐγκαταστῆστε\" τὸ πληκτρολόγιο." + +#: keyman_config/keyboard_details.py:74 +msgid "Package name: " +msgstr "Ὄνομα πακέτου: " + +#: keyman_config/keyboard_details.py:85 +msgid "Package id: " +msgstr "Id πακέτου: " + +#: keyman_config/keyboard_details.py:108 +msgid "Package description: " +msgstr "Περιγραφὴ πακέτου: " + +#: keyman_config/keyboard_details.py:121 +msgid "Package author: " +msgstr "Κατασκευαστὴς πακέτου: " + +#: keyman_config/keyboard_details.py:133 +msgid "Package copyright: " +msgstr "Πνευματικὰ δικαιώματα πακέτου: " + +#: keyman_config/keyboard_details.py:174 +msgid "Keyboard filename: " +msgstr "Ὄνομα ἀρχείου πακέτου: " + +#: keyman_config/keyboard_details.py:187 +msgid "Keyboard name: " +msgstr "Ὄνομα πληκτρολογίου: " + +#: keyman_config/keyboard_details.py:198 +msgid "Keyboard id: " +msgstr "Id πληκτρολογίου: " + +#: keyman_config/keyboard_details.py:209 +msgid "Keyboard version: " +msgstr "Ἔκδοση πληκτρολογίου: " + +#: keyman_config/keyboard_details.py:221 +msgid "Keyboard author: " +msgstr "Σχεδιαστὴς πληκτρολογίου: " + +#: keyman_config/keyboard_details.py:232 +msgid "Keyboard license: " +msgstr "Ἄδεια χρήσης πληκτρολογίου: " + +#: keyman_config/keyboard_details.py:243 +msgid "Keyboard description: " +msgstr "Περιγραφὴ πληκτρολογίου: " + +#: keyman_config/keyboard_details.py:334 +#, python-brace-format +msgid "Scan this code to load this keyboard\n" +"on another device or share online" +msgstr "Σαρῶστε αὐτὸν τὸν κωδικὸ γιὰ νὰ φορτώσετε αὐτὸ τὸ πληκτρολόγιο\n" +"σὲ ἄλλη συσκευὴ ἢ μοιρασθῆτε το ὀνλάϊν" + +#: keyman_config/options.py:24 +#, python-brace-format +msgid "{packageId} Settings" +msgstr "Ρυθμίσεις {packageId}" + +#: keyman_config/view_installed.py:30 +msgid "Keyman Configuration" +msgstr "Παράμετροι Keyman" + +#: keyman_config/view_installed.py:60 +msgid "Choose a kmp file..." +msgstr "Ἐπιλέξτε ἀρχεῖο kmp..." + +#. i18n: file type in file selection dialog +#: keyman_config/view_installed.py:65 +msgid "KMP files" +msgstr "Ἀρχεῖα KMP" + +#. i18n: column header in table displaying installed keyboards +#: keyman_config/view_installed.py:141 +msgid "Icon" +msgstr "Εἰκονίδιο" + +#. i18n: column header in table displaying installed keyboards +#: keyman_config/view_installed.py:145 +msgid "Name" +msgstr "Ὄνομα" + +#. i18n: column header in table displaying installed keyboards +#: keyman_config/view_installed.py:148 +msgid "Version" +msgstr "Ἔκδοση" + +#: keyman_config/view_installed.py:161 +msgid "_Uninstall" +msgstr "_Uninstall" + +#: keyman_config/view_installed.py:162 keyman_config/view_installed.py:304 +msgid "Uninstall keyboard" +msgstr "Ἀπεγκαταστῆστε πληκτρολόγιο" + +#: keyman_config/view_installed.py:167 +msgid "_About" +msgstr "_About" + +#: keyman_config/view_installed.py:168 keyman_config/view_installed.py:306 +msgid "About keyboard" +msgstr "Περὶ τοῦ πληκτρολογίου" + +#: keyman_config/view_installed.py:173 +msgid "_Help" +msgstr "_Help" + +#: keyman_config/view_installed.py:174 keyman_config/view_installed.py:305 +msgid "Help for keyboard" +msgstr "Βοήθεια γιὰ τὸ πληκτρολόγιο" + +#: keyman_config/view_installed.py:179 +msgid "_Options" +msgstr "_Options" + +#: keyman_config/view_installed.py:180 keyman_config/view_installed.py:307 +msgid "Settings for keyboard" +msgstr "Ρυθμίσεις πληκτρολογίου" + +#: keyman_config/view_installed.py:190 +msgid "_Refresh" +msgstr "_Refresh" + +#: keyman_config/view_installed.py:191 +msgid "Refresh keyboard list" +msgstr "Ἀνανεῶστε τὸν κατάλογο πληκτρολογίων" + +#: keyman_config/view_installed.py:195 +msgid "_Download" +msgstr "_Download" + +#: keyman_config/view_installed.py:196 +msgid "Download and install a keyboard from the Keyman website" +msgstr "Κατεβάστε καὶ ἐγκαταστῆστε πληκτρολόγιο ἀπὸ τὸν ἱστότοπο Keyman" + +#: keyman_config/view_installed.py:201 +msgid "Install a keyboard from a file" +msgstr "Ἐγκαταστῆστε πληκτρολόγιο ἀπὸ ἀρχεῖο" + +#: keyman_config/view_installed.py:206 +msgid "Close window" +msgstr "Κλεῖστε τὸ παράθυρο" + +#: keyman_config/view_installed.py:278 +#, python-brace-format +msgid "Uninstall keyboard {package}" +msgstr "Ἀπεγκαταστῆστε πληκτρολόγιο {package}" + +#: keyman_config/view_installed.py:280 +#, python-brace-format +msgid "Help for keyboard {package}" +msgstr "Βοήθεια γιὰ πληκτρολόγιο {package}" + +#: keyman_config/view_installed.py:282 +#, python-brace-format +msgid "About keyboard {package}" +msgstr "Περὶ τοῦ πληκτρολογίου {package}" + +#: keyman_config/view_installed.py:284 +#, python-brace-format +msgid "Settings for keyboard {package}" +msgstr "Ρυθμίσεις πληκτρολογίου {package}" + +#: keyman_config/view_installed.py:349 +msgid "Uninstall keyboard package?" +msgstr "Θὰ ἀπεγκαταστήσετε τὸ πακέτο πληκτρολογίου;" + +#: keyman_config/view_installed.py:351 +#, python-brace-format +msgid "Are you sure that you want to uninstall the {keyboard} keyboard and its fonts?" +msgstr "Εἶσθε βέβαιοι ὅτι θέλετε νὰ ἀπεγκαταστήσετε τὸ πληκτρολόγιο {keyboard} καὶ τὶς γραμματοσειρές του;" + +#: keyman_config/welcome.py:22 +#, python-brace-format +msgid "{name} installed" +msgstr "Τὸ {name} ἐγκατεστάθη" + +#: keyman_config/welcome.py:40 +msgid "Open in _Web browser" +msgstr "Ἀνοῖξτε στὸν φυλλομετρητὴ _Web" + +#: keyman_config/welcome.py:42 +msgid "Open in the default web browser to do things like printing" +msgstr "Ἀνοῖξτε στὸν προεπιλεγμένο φυλλομετρητὴ γιὰ νὰ ἐκτελέσετε π.χ., μία ἐκτύπωση" + +#: keyman_config/welcome.py:45 +msgid "_OK" +msgstr "_OK" + diff --git a/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj b/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj index 8e0b973442..66dac595c8 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj +++ b/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj @@ -257,6 +257,12 @@ 29C1E1772800227700759EDE /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/KMKeyboardHelpWindowController.strings"; sourceTree = ""; }; 29C1E1782800227800759EDE /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/MainMenu.strings"; sourceTree = ""; }; 29C1E179280025A900759EDE /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Localizable.strings"; sourceTree = ""; }; + 29D470942C648D5100224B4F /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/KMAboutWindowController.strings; sourceTree = ""; }; + 29D470952C648D5100224B4F /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/preferences.strings; sourceTree = ""; }; + 29D470962C648D5200224B4F /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/KMInfoWindowController.strings; sourceTree = ""; }; + 29D470972C648D5200224B4F /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/KMKeyboardHelpWindowController.strings; sourceTree = ""; }; + 29D470982C648D5200224B4F /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/MainMenu.strings; sourceTree = ""; }; + 29D470992C648D7100224B4F /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/Localizable.strings; sourceTree = ""; }; 29DD8400276C49E20066A16E /* am */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = am; path = am.lproj/KMAboutWindowController.strings; sourceTree = ""; }; 29DD8401276C49E20066A16E /* am */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = am; path = am.lproj/preferences.strings; sourceTree = ""; }; 29DD8402276C49E30066A16E /* am */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = am; path = am.lproj/KMInfoWindowController.strings; sourceTree = ""; }; @@ -795,6 +801,7 @@ uk, ru, es, + el, ); mainGroup = 989C9BFF1A7876DE00A20425; productRefGroup = 989C9C091A7876DE00A20425 /* Products */; @@ -1053,6 +1060,7 @@ 298566D42980D47C004ACA95 /* uk */, 298566E02980E579004ACA95 /* ru */, CEFFECD82A417FEA00D58C36 /* es */, + 29D470942C648D5100224B4F /* el */, ); name = KMAboutWindowController.xib; sourceTree = ""; @@ -1079,6 +1087,7 @@ 298566D52980D47D004ACA95 /* uk */, 298566E12980E579004ACA95 /* ru */, CEFFECD92A417FEB00D58C36 /* es */, + 29D470952C648D5100224B4F /* el */, ); name = preferences.xib; path = Keyman4MacIM/KMConfiguration; @@ -1105,6 +1114,7 @@ 298566D92980D489004ACA95 /* uk */, 298566E52980E584004ACA95 /* ru */, CEFFECDD2A4180FD00D58C36 /* es */, + 29D470992C648D7100224B4F /* el */, ); name = Localizable.strings; sourceTree = ""; @@ -1131,6 +1141,7 @@ 298566D62980D47D004ACA95 /* uk */, 298566E22980E57A004ACA95 /* ru */, CEFFECDA2A417FEB00D58C36 /* es */, + 29D470962C648D5200224B4F /* el */, ); name = KMInfoWindowController.xib; path = Keyman4MacIM/KMInfoWindow; @@ -1158,6 +1169,7 @@ 298566D72980D47D004ACA95 /* uk */, 298566E32980E57A004ACA95 /* ru */, CEFFECDB2A417FEC00D58C36 /* es */, + 29D470972C648D5200224B4F /* el */, ); name = KMKeyboardHelpWindowController.xib; path = Keyman4MacIM/KMKeyboardHelpWindow; @@ -1185,6 +1197,7 @@ 298566D82980D47E004ACA95 /* uk */, 298566E42980E57A004ACA95 /* ru */, CEFFECDC2A417FEC00D58C36 /* es */, + 29D470982C648D5200224B4F /* el */, ); name = MainMenu.xib; sourceTree = ""; diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMAboutWindow/el.lproj/KMAboutWindowController.strings b/mac/Keyman4MacIM/Keyman4MacIM/KMAboutWindow/el.lproj/KMAboutWindowController.strings new file mode 100644 index 0000000000..a6dc5d6122 --- /dev/null +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMAboutWindow/el.lproj/KMAboutWindowController.strings @@ -0,0 +1,8 @@ +/* button text to close the About window */ +"Kab-Up-fYH.title" = "Κλεῖστε"; + +/* text of link to the license agreement */ +"hYC-Bx-aoP.title" = "Ἄδεια χρήσης"; + +/* button text to open Configuration window */ +"vkh-b5-vO7.title" = "Παράμετροι..."; diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMConfiguration/el.lproj/preferences.strings b/mac/Keyman4MacIM/Keyman4MacIM/KMConfiguration/el.lproj/preferences.strings new file mode 100644 index 0000000000..6b750343d0 --- /dev/null +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMConfiguration/el.lproj/preferences.strings @@ -0,0 +1,38 @@ +/* Checkbox text to always show on-screen keyboard */ +"4UX-80-0Vo.title" = "Νὰ ἐμφανίζεται πάντοτε τὸ πληκτρολόγιο ὀθόνης"; + +/* Checkbox text to enable verbose Console logging */ +"7J6-zy-R20.title" = "Χρησιμοποιῆστε λεπτομερῆ καταγραφὴ μηνυμάτων κονσόλας"; + +/* Support button text */ +"93O-x6-RLF.label" = "Ὑποστήριξη"; + +/* Download Keyboard button text */ +"CTw-kf-WNS.title" = "Κατεβάστε πληκτρολόγιο..."; + +/* Keyman Configuration window title */ +"F0z-JX-Cv5.title" = "Παράμετροι Keyman"; + +/* button text to go back to previous page */ +"JOK-JV-n8w.title" = "Πίσω"; + +/* Keyboards button text */ +"MPN-9N-wWc.label" = "Πληκτρολόγια"; + +/* text to explain verbose Console logging option */ +"MrI-GM-7d6.title" = "Ὅταν εἶναι ἐνεργὴ ἡ λεπτομερὴς καταγραφὴ μηνυμάτων κονσόλας, τὸ Keyman θὰ καταγράφει ἐνέργειες ποὺ θὰ βοηθήσουν τὴν ὁμάδα ὑποστήριξης Keyman νὰ διαγνώσει τυχὸν πρόβλημα. Μὲ τὸ πρόγραμμα κονσόλας μπορεῖτε νὰ δεῖτε τὰ μηνύματα τοῦ Keyman σὲ ἀρχεῖο. Στὴν Κονσόλα φιλτράρετε καὶ προβάλετε ὅλα τὰ μηνύματα ἀπὸ τὴν διεργασία \"Keyman\". Ἂν χρειασθεῖ, αὐτὴ ἡ ἀναφορὰ μπορεῖ νὰ ἐξαχθεῖ καὶ νὰ ἀποσταλεῖ στὴν ὑποστήριξη τοῦ Keyman."; + +/* button text to move forward to the next page */ +"eXr-8V-h1g.title" = "Μπροστά"; + +/* button text to return to the home help page */ +"fXS-aC-CMH.title" = "Ἀρχική"; + +/* Options button text */ +"frd-No-seV.label" = "Ἐπιλογές"; + +/* Installed Keyboard column heading */ +"jex-Nd-Qzg.headerCell.title" = "Ἐγκατεστημένο Πληκτρολόγιο"; + +/* Verbose logging tooltip text */ +"uWx-3J-U0D.ibShadowedToolTip" = "Ἐνεργοποιῆστε ἂν ἔχετε προβλήματα μὲ ἕνα συγκεκριμένο πληκτρολόγιο ἢ μὲ τὸ Keyman γενικῶς."; diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInfoWindow/el.lproj/KMInfoWindowController.strings b/mac/Keyman4MacIM/Keyman4MacIM/KMInfoWindow/el.lproj/KMInfoWindowController.strings new file mode 100644 index 0000000000..af78cc7f5f --- /dev/null +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInfoWindow/el.lproj/KMInfoWindowController.strings @@ -0,0 +1,8 @@ +/* Package Information window title */ +"F0z-JX-Cv5.title" = "Πληροφορίες πακέτου"; + +/* button text to show Details */ +"Fvy-XJ-s38.label" = "Λεπτομέρειες"; + +/* button text to show Read Me */ +"waA-IW-Qyn.label" = "Read Me"; diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMKeyboardHelpWindow/el.lproj/KMKeyboardHelpWindowController.strings b/mac/Keyman4MacIM/Keyman4MacIM/KMKeyboardHelpWindow/el.lproj/KMKeyboardHelpWindowController.strings new file mode 100644 index 0000000000..ed234ea2e2 --- /dev/null +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMKeyboardHelpWindow/el.lproj/KMKeyboardHelpWindowController.strings @@ -0,0 +1,8 @@ +/* Keyboard Help window title */ +"F0z-JX-Cv5.title" = "Βοήθεια γιὰ τὸ πληκτρολόγιο"; + +/* OK button text */ +"Zla-QF-m0K.title" = "OK"; + +/* Print button text */ +"fYY-Uj-y4S.title" = "Ἐκτυπῶστε..."; diff --git a/mac/Keyman4MacIM/Keyman4MacIM/el.lproj/Localizable.strings b/mac/Keyman4MacIM/Keyman4MacIM/el.lproj/Localizable.strings new file mode 100644 index 0000000000..006c96a99c --- /dev/null +++ b/mac/Keyman4MacIM/Keyman4MacIM/el.lproj/Localizable.strings @@ -0,0 +1,74 @@ +/* Message displayed to confirm delete of the Keyman keyboard selected by the user from the keyboard list */ +"message-confirm-delete-keyboard" = "Εἶσθε βέβαιοι ὅτι θέλετε νὰ διαγράψετε τὸ πληκτρολόγιο '%@';"; + +/* Delete keyboard confirmation info indicating that the delete action cannot be undone */ +"info-cannot-undo-delete-keyboard" = "Δὲν μπορεῖτε νὰ ἀναιρέσετε αὐτὴν τὴν ἐνέργεια."; + +/* Button text to cancel delete of the specified installed Keyman keyboard */ +"button-cancel-delete-keyboard" = "Ἀκυρῶστε"; + +/* Button text to confirm delete of the specified installed Keyman keyboard */ +"button-delete-keyboard" = "Διαγράψτε"; + +/* Message displayed to confirm installation of a keyboard from the specifed .kmp file double-clicked by the user */ +"message-confirm-install-keyboard" = "Θὰ ἐγκαταστήσετε πληκτρολόγιο Keyman;"; + +/* Message displayed to confirm installation of a keyboard from the specifed .kmp file double-clicked by the user */ +"info-install-keyboard-filename" = "Θέλετε ἡ ἐφαρμογὴ Keyman νὰ ἐγκαταστήσει τὸ πληκτρολόγιο ἀπὸ τὸ ἀρχεῖο '%@';"; + +/* Button text to cancel installation of the double-clicked Keyman file */ +"button-cancel-install-keyboard" = "Ἀκυρῶστε"; + +/* Button text to confirm installation of the double-clicked Keyman file */ +"button-install-keyboard" = "Ἐγκαταστῆστε"; + +/* Message displayed to inform user that .kmp file could not be read/unzipped */ +"message-keyboard-file-unreadable" = "Δὲν μπορέσαμε νὰ διαβάσομε τὸ ἀρχεῖο Keyman '%@'."; + +/* Message displayed in Configuration window when keyboard cannot be loaded */ +"message-error-loading-keyboard" = "(σφάλμα κατὰ τὴν φόρτωση πληκτρολογίου)"; + +/* Message displayed in Configuration window when keyboard metadata cannot be loaded */ +"message-error-unknown-metadata" = "ἄγνωστο"; + +/* Button text to acknowledge that .kmp file could not be read */ +"button-keyboard-file-unreadable" = "OK"; + +/* label text to identify Keyman version */ +"version-label-text" = "Ἔκδοση: %@"; + +/* Status text for keyboard downloading */ +"message-keyboard-downloading" = "Μεταφόρτωση σὲ ἐξέλιξη..."; + +/* Status text for keyboard download complete */ +"message-keyboard-download-complete" = "Ὁλοκλήρωση φόρτωσης."; + +/* Button text to cancel downloading keyboard */ +"button-cancel-downloading" = "Ἀκυρῶστε"; + +/* Button text keyboard download complete */ +"button-download-complete" = "Ἕτοιμοι"; + +/* keyboards label in the Package Information window */ +"keyboards-label" = "Πληκτρολόγια:"; + +/* fonts label in the Package Information window */ +"fonts-label" = "Γραμματοσειρές:"; + +/* package version label in the Package Information window */ +"package-version-label" = "Ἔκδοση πακέτου:"; + +/* author label in the Package Information window */ +"author-label" = "Δημιουργός:"; + +/* website label in the Package Information window */ +"website-label" = "Ἱστότοπος:"; + +/* copyright label in the Package Information window */ +"copyright-label" = "Πνευματικὰ δικαιώματα:"; + +/* message displayed to alert user to need grant accessibility permission */ +"privacy-alert-text" = "Τὸ Keyman, γιὰ νὰ λειτουργήσει σωστά, ἀπαιτεῖ ὁρισμένες δυνατότητες προσπέλασης:\n\nἘπιτρέψτε τὴν πρόσβαση στὶς Προτιμήσεις Συστήματος, τὴν Ἀσφάλεια & Ἰδιωτικότητα.\nἘπανεκκινῆστε τὸ σύστημά σας."; + +/* Text of menu item in Input Menu when no Keyboards are configured -- include parentheses */ +"no-keyboard-configured-menu-placeholder" = "(Δὲν ἔχει ἐγκατασταθεῖ πληκτρολόγιο)"; diff --git a/mac/Keyman4MacIM/Keyman4MacIM/el.lproj/MainMenu.strings b/mac/Keyman4MacIM/Keyman4MacIM/el.lproj/MainMenu.strings new file mode 100644 index 0000000000..dc5aae4d89 --- /dev/null +++ b/mac/Keyman4MacIM/Keyman4MacIM/el.lproj/MainMenu.strings @@ -0,0 +1,14 @@ +/* Configuration window menu text */ +"P1b-lE-yFw.title" = "Διαμόρφωση..."; + +/* Keyboards menu text */ +"bQa-j9-nHe.title" = "Πληκτρολόγια"; + +/* Keyboards menu text */ +"goP-aK-3WB.title" = "Πληκτρολόγια"; + +/* About menu text */ +"kb2-ww-RS3.title" = "Περὶ ἡμῶν"; + +/* On-Screen Keyboard menu text */ +"s96-JI-YDh.title" = "Πληκτρολόγιο ὀθόνης"; diff --git a/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/FVShared.java b/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/FVShared.java index 95158826ba..9b75b3eea9 100644 --- a/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/FVShared.java +++ b/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/FVShared.java @@ -7,22 +7,25 @@ import android.content.res.AssetManager; import android.net.Uri; import android.util.Log; import android.widget.Toast; +import com.keyman.engine.JSONParser; import com.keyman.engine.KMManager; import com.keyman.engine.data.Keyboard; import com.keyman.engine.packages.PackageProcessor; import com.keyman.engine.util.KMLog; -import java.io.BufferedReader; +import org.json.JSONArray; +import org.json.JSONObject; + import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -30,6 +33,8 @@ final class FVShared { private static FVShared instance = null; private boolean isInitialized = false; + // File containing keyboard+region info for each keyboard + private static final String FVKeyboards_JSON = "keyboards.json"; private static final String FVLoadedKeyboardList = "loaded_keyboards.dat"; // Keys from earlier versions of app, used only in the upgrade process @@ -107,7 +112,8 @@ final class FVShared { } this.context = context.getApplicationContext(); - this.regionList = loadRegionList(); + String keyboardsJSONPath = getPackagesDir() + FVDefault_PackageID + File.separator + FVKeyboards_JSON; + this.regionList = loadRegionList(keyboardsJSONPath); this.loadedKeyboards = loadLoadedKeyboardList(); isInitialized = true; @@ -123,54 +129,86 @@ final class FVShared { return instance; } - private FVRegionList loadRegionList() { - FVRegionList list = new FVRegionList(); - try { - // At this point in initialization, fv_all.kmp hasn't been extracted, so - // we get all the keyboard info from keyboards.csv - InputStream inputStream = context.getAssets().open("keyboards.csv"); - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + /** + * Parse keyboards.json file to associate region info for each keyboard + * @param keyboardsJSONPath - path to the keyboards.json file containing region info for each keyboard + * @return FVRegionList + */ + private FVRegionList loadRegionList(String keyboardsJSONPath) { + FVRegionList list = new FVRegionList(); + JSONParser parser = new JSONParser(); + File jsonFile = new File(keyboardsJSONPath); + if (!jsonFile.exists()) { + // Fatal error + throw new Error("keyboards.json file doesn't exist"); + } + try { + // At this point in initialization, fv_all.kmp is now extracted, so + // populate keyboard info from keyboards.json + JSONArray keyboardsArray = parser.getJSONObjectFromFile(jsonFile, JSONArray.class); - reader.readLine(); // skip header row - String line = reader.readLine(); + if (keyboardsArray == null) { + KMLog.LogError(TAG, "Unable to parse keyboards.json"); + return list; + } - while (line != null) { - while (line.contains(",,")) - line = line.replace(",,", ", ,"); + for (int i=0; i 0) { - // Read in column info - String kbId = values[1]; - String kbName = values[2]; - String regionName = values[3]; - String legacyId = values[4]; - String version = values[5]; - String lgId = values[6].toLowerCase(); // Normalize language ID - String lgName = values[7]; + String kbID = keyboardObj.getString("id"); + String kbName = keyboardObj.getString("name"); + JSONObject languageObj = languageArray.getJSONObject(0); + String lgID = languageObj.getString("id").toLowerCase(); // Normalize language Id + String lgName = languageObj.getString("name"); - FVRegion region = list.findRegion(regionName); - if(region == null) { - region = new FVRegion(regionName); - list.add(region); - } + // Override European keyboard info + if (kbID.equalsIgnoreCase("sil_euro_latin")) { + kbName = "English"; + lgID = "en"; + lgName = "English"; + } else if (kbID.equalsIgnoreCase("basic_kbdcan")) { + kbName = "Français"; + lgID = "fr-ca"; + lgName = "French"; + } - FVKeyboard keyboard = new FVKeyboard(kbId, kbName, legacyId, version, lgId, lgName); + FVKeyboard kbd = new FVKeyboard( + kbID, + kbName, + kbID, // unused legacy ID + keyboardObj.getString("version"), + lgID, + lgName); - region.keyboards.add(keyboard); - } + region.keyboards.add(kbd); + } + } catch (Exception e) { + // loadRegionList had malformed keyboard list + throw new Error(e.getMessage()); + } - line = reader.readLine(); - } + // Sort by region name + Collections.sort(list, (r1, r2) -> r1.name.compareTo(r2.name)); - inputStream.close(); - } catch (Exception e) { - Log.e("createKeyboardList", "Error: " + e); - // We'll return a malformed list for now in this situation - } - - return list; - } + for (int i=0; i k1.name.compareTo(k2.name)); + } + return list; + } private FVLoadedKeyboardList loadLoadedKeyboardList() { FVLoadedKeyboardList data = new FVLoadedKeyboardList(); diff --git a/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/MainActivity.java b/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/MainActivity.java index f91657203b..d38d5b9bc0 100644 --- a/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/MainActivity.java +++ b/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/MainActivity.java @@ -49,17 +49,17 @@ public class MainActivity extends AppCompatActivity implements OnKeyboardDownloa setContentView(R.layout.activity_main); + if (BuildConfig.DEBUG) { + KMManager.setDebugMode(true); + } + KMManager.initialize(getApplicationContext(), KMManager.KeyboardType.KEYBOARD_TYPE_INAPP); + FVShared.getInstance().initialize(this); FVShared.getInstance().upgradeTo12(); FVShared.getInstance().upgradeTo14(); FVShared.getInstance().preloadPackages(); - if (BuildConfig.DEBUG) { - KMManager.setDebugMode(true); - } - KMManager.initialize(getApplicationContext(), KMManager.KeyboardType.KEYBOARD_TYPE_INAPP); - /** * We need to set the default (fallback) keyboard to sil_euro_latin inside the fv_all package * rather than the normal default of sil_euro_latin inside the sil_euro_latin package. diff --git a/oem/firstvoices/android/build.sh b/oem/firstvoices/android/build.sh index 3e10a79ae6..e27be06974 100755 --- a/oem/firstvoices/android/build.sh +++ b/oem/firstvoices/android/build.sh @@ -61,13 +61,9 @@ if builder_start_action clean; then fi if builder_start_action configure; then - KEYBOARDS_CSV="$KEYMAN_ROOT/oem/firstvoices/keyboards.csv" - KEYBOARDS_CSV_TARGET="$KEYMAN_ROOT/oem/firstvoices/android/app/src/main/assets/keyboards.csv" - KEYBOARD_PACKAGE_ID="fv_all" KEYBOARDS_TARGET="$KEYMAN_ROOT/oem/firstvoices/android/app/src/main/assets/${KEYBOARD_PACKAGE_ID}.kmp" - cp "$KEYBOARDS_CSV" "$KEYBOARDS_CSV_TARGET" downloadKeyboardPackage "$KEYBOARD_PACKAGE_ID" "$KEYBOARDS_TARGET" builder_finish_action success configure diff --git a/package-lock.json b/package-lock.json index 26e925843d..9094794831 100644 --- a/package-lock.json +++ b/package-lock.json @@ -245,19 +245,6 @@ "typescript": "^5.4.5" } }, - "common/web/recorder": { - "name": "@keymanapp/recorder-core", - "license": "MIT", - "dependencies": { - "@keymanapp/keyboard-processor": "*", - "@keymanapp/keyman-version": "*", - "@keymanapp/models-types": "*", - "@keymanapp/web-utils": "*" - }, - "devDependencies": { - "typescript": "^5.4.5" - } - }, "common/web/sentry-manager": { "name": "@keymanapp/web-sentry-manager", "license": "MIT", @@ -275,24 +262,17 @@ "dependencies": { "@keymanapp/keyman-version": "*", "@keymanapp/ldml-keyboard-constants": "*", - "restructure": "3.0.1", - "sax": ">=0.6.0", - "semver": "^7.5.2", - "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" @@ -474,7 +454,7 @@ "name": "@keymanapp/developer-test-helpers", "license": "MIT", "dependencies": { - "@keymanapp/common-types": "*" + "@keymanapp/developer-utils": "*" }, "devDependencies": { "@types/node": "^20.4.1", @@ -485,11 +465,21 @@ "name": "@keymanapp/developer-utils", "license": "MIT", "dependencies": { - "@sentry/node": "^7.57.0" + "@keymanapp/common-types": "*", + "@sentry/node": "^7.57.0", + "eventemitter3": "^5.0.0", + "restructure": "^3.0.1", + "sax": ">=0.6.0", + "semver": "^7.5.2", + "xmlbuilder": "~11.0.0" }, "devDependencies": { + "@types/git-diff": "^2.0.3", "@types/node": "^20.4.1", + "@types/semver": "^7.3.12", + "@types/xml2js": "^0.4.5", "c8": "^7.12.0", + "git-diff": "^2.0.6", "mocha": "^8.4.0", "typescript": "^5.4.5" } @@ -1225,6 +1215,7 @@ "name": "@keymanapp/kmc-ldml", "license": "MIT", "dependencies": { + "@keymanapp/developer-utils": "*", "@keymanapp/keyman-version": "*", "@keymanapp/kmc-kmn": "*", "@keymanapp/ldml-keyboard-constants": "*", @@ -1670,6 +1661,7 @@ "license": "MIT", "dependencies": { "@keymanapp/common-types": "*", + "@keymanapp/developer-utils": "*", "jszip": "^3.7.0", "marked": "^7.0.0" }, @@ -2014,7 +2006,11 @@ "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" }, "devDependencies": { "@keymanapp/keyman-version": "*", @@ -2026,12 +2022,12 @@ "@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" }, "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" } }, "developer/src/server/node_modules/@types/mocha": { @@ -2671,12 +2667,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "optional": true - }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", @@ -2718,6 +2708,102 @@ "integrity": "sha512-tWZNBIS1CoekcwlMuyG2mr0a1Wo5lb5lEHwwWvZo+5GLgr3e9LLDTtmgtCWEwBpXMkxn9D+2W9j2FY6eZQq0tA==", "dev": true }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", "dev": true, @@ -2851,7 +2937,7 @@ "link": true }, "node_modules/@keymanapp/recorder-core": { - "resolved": "common/web/recorder", + "resolved": "web/src/tools/testing/recorder-core", "link": true }, "node_modules/@keymanapp/resources-gosh": { @@ -3227,43 +3313,80 @@ "node": ">= 8" } }, - "node_modules/@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", - "optional": true, + "node_modules/@npmcli/agent": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.2.tgz", + "integrity": "sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/agent/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@npmcli/agent/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@npmcli/agent/node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@npmcli/agent/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/@npmcli/fs": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", + "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", + "dev": true, "dependencies": { - "@gar/promisify": "^1.1.3", "semver": "^7.3.5" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "optional": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/@npmcli/move-file/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "optional": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/@octokit/auth-token": { @@ -3418,6 +3541,16 @@ "@octokit/openapi-types": "^11.2.0" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@puppeteer/browsers": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.2.2.tgz", @@ -4261,15 +4394,6 @@ "node": ">=10" } }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "optional": true, - "engines": { - "node": ">= 10" - } - }, "node_modules/@tootallnate/quickjs-emscripten": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", @@ -5499,10 +5623,13 @@ } }, "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "optional": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } }, "node_modules/accepts": { "version": "1.3.8", @@ -5548,7 +5675,7 @@ }, "node_modules/agent-base": { "version": "6.0.2", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "debug": "4" @@ -5557,25 +5684,11 @@ "node": ">= 6.0.0" } }, - "node_modules/agentkeepalive": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", - "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", - "optional": true, - "dependencies": { - "debug": "^4.1.0", - "depd": "^1.1.2", - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "optional": true, + "dev": true, "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -5749,36 +5862,6 @@ "version": "1.0.0", "license": "MIT" }, - "node_modules/aproba": { - "version": "2.0.0", - "license": "ISC", - "optional": true - }, - "node_modules/are-we-there-yet": { - "version": "3.0.1", - "license": "ISC", - "optional": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "3.6.0", - "license": "MIT", - "optional": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/arg": { "version": "4.1.3", "dev": true, @@ -5950,7 +6033,7 @@ }, "node_modules/balanced-match": { "version": "1.0.0", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/bare-events": { @@ -6040,15 +6123,6 @@ "node": ">=8" } }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "optional": true, - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, "node_modules/body-parser": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", @@ -6104,7 +6178,7 @@ }, "node_modules/brace-expansion": { "version": "1.1.11", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -6230,93 +6304,104 @@ } }, "node_modules/cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", - "optional": true, + "version": "18.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz", + "integrity": "sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==", + "dev": true, "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", + "ssri": "^10.0.0", "tar": "^6.1.11", - "unique-filename": "^2.0.0" + "unique-filename": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^16.14.0 || >=18.0.0" } }, "node_modules/cacache/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "optional": true, + "dev": true, "dependencies": { "balanced-match": "^1.0.0" } }, - "node_modules/cacache/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "optional": true, + "node_modules/cacache/node_modules/foreground-child": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">=12" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/cacache/node_modules/lru-cache": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.16.1.tgz", - "integrity": "sha512-9kkuMZHnLH/8qXARvYSjNvq8S1GYFFzynQTAfKeaJ0sIrR3PUPuu37Z+EiIANiZBvpfTf2B5y8ecDLSMWlLv+w==", - "optional": true, - "engines": { - "node": ">=12" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true }, "node_modules/cacache/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "optional": true, + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/cacache/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "optional": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, + "node_modules/cacache/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, "engines": { - "node": ">=10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/cache-content-type": { @@ -6493,7 +6578,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "optional": true, + "dev": true, "engines": { "node": ">=10" } @@ -6546,7 +6631,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "optional": true, + "dev": true, "engines": { "node": ">=6" } @@ -6673,14 +6758,6 @@ "version": "1.1.4", "license": "MIT" }, - "node_modules/color-support": { - "version": "1.1.3", - "license": "ISC", - "optional": true, - "bin": { - "color-support": "bin.js" - } - }, "node_modules/combine-source-map": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", @@ -6789,7 +6866,7 @@ }, "node_modules/concat-map": { "version": "0.0.1", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/concat-stream": { @@ -6805,11 +6882,6 @@ "typedarray": "^0.0.6" } }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "license": "ISC", - "optional": true - }, "node_modules/content-disposition": { "version": "0.5.4", "license": "MIT", @@ -7116,12 +7188,12 @@ }, "node_modules/delegates": { "version": "1.0.0", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/depd": { "version": "1.1.2", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -7191,6 +7263,12 @@ "dev": true, "license": "MIT" }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/ee-first": { "version": "1.1.1", "license": "MIT" @@ -7249,7 +7327,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "optional": true, + "dev": true, "engines": { "node": ">=6" } @@ -7258,7 +7336,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "optional": true + "dev": true }, "node_modules/errorstacks": { "version": "2.4.1", @@ -8496,6 +8574,12 @@ "which": "bin/which" } }, + "node_modules/exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "dev": true + }, "node_modules/express": { "version": "4.19.2", "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", @@ -8703,12 +8787,6 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "optional": true - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -8862,20 +8940,20 @@ } }, "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "optional": true, + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "dev": true, "dependencies": { - "minipass": "^3.0.0" + "minipass": "^7.0.3" }, "engines": { - "node": ">= 8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/fs.realpath": { "version": "1.0.0", - "devOptional": true, + "dev": true, "license": "ISC" }, "node_modules/fsevents": { @@ -8925,72 +9003,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gauge": { - "version": "4.0.4", - "license": "ISC", - "optional": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/gauge/node_modules/ansi-regex": { - "version": "5.0.1", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/node_modules/string-width": { - "version": "4.2.3", - "license": "MIT", - "optional": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/node_modules/strip-ansi": { - "version": "6.0.1", - "license": "MIT", - "optional": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/node_modules/wide-align": { - "version": "1.1.5", - "license": "ISC", - "optional": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, "node_modules/get-caller-file": { "version": "2.0.5", "license": "ISC", @@ -9188,7 +9200,7 @@ }, "node_modules/glob": { "version": "7.1.6", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -9303,7 +9315,7 @@ }, "node_modules/graceful-fs": { "version": "4.2.10", - "devOptional": true, + "dev": true, "license": "ISC" }, "node_modules/graphemer": { @@ -9396,11 +9408,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "license": "ISC", - "optional": true - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -9421,17 +9428,6 @@ "he": "bin/he" } }, - "node_modules/hetrodo-node-hide-console-window-napi": { - "name": "node-hide-console-window", - "version": "2.0.1", - "resolved": "git+ssh://git@github.com/keymanapp/hetrodo-node-hide-console-window-napi.git#858b23036a9963b40ad6ff3c5bacd421e5839b92", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/hexy": { "version": "0.3.4", "dev": true, @@ -9495,8 +9491,9 @@ } }, "node_modules/http-cache-semantics": { - "version": "4.1.0", - "license": "BSD-2-Clause" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, "node_modules/http-errors": { "version": "2.0.0", @@ -9530,17 +9527,45 @@ } }, "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "optional": true, + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": ">= 6" + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/http2-wrapper": { @@ -9558,7 +9583,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "devOptional": true, + "dev": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -9567,15 +9592,6 @@ "node": ">= 6" } }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "optional": true, - "dependencies": { - "ms": "^2.0.0" - } - }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -9649,7 +9665,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "devOptional": true, + "dev": true, "engines": { "node": ">=0.8.19" } @@ -9658,17 +9674,11 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "optional": true, + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "optional": true - }, "node_modules/inflation": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.1.0.tgz", @@ -9680,7 +9690,7 @@ }, "node_modules/inflight": { "version": "1.0.6", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -9735,7 +9745,26 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", - "devOptional": true + "dev": true + }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dev": true, + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true }, "node_modules/ipaddr.js": { "version": "1.9.1", @@ -9917,7 +9946,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "optional": true + "dev": true }, "node_modules/is-module": { "version": "1.0.0", @@ -10154,6 +10183,21 @@ "node": ">=8" } }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jju": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", @@ -10177,6 +10221,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "dev": true + }, "node_modules/jsdom": { "version": "23.0.1", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-23.0.1.tgz", @@ -10246,19 +10296,6 @@ } } }, - "node_modules/jsdom/node_modules/http-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", - "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/jsdom/node_modules/https-proxy-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", @@ -10821,39 +10858,26 @@ "peer": true }, "node_modules/make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "optional": true, + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz", + "integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==", + "dev": true, "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", + "@npmcli/agent": "^2.0.0", + "cacache": "^18.0.0", + "http-cache-semantics": "^4.1.1", "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", + "proc-log": "^4.2.0", "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" + "ssri": "^10.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.16.1.tgz", - "integrity": "sha512-9kkuMZHnLH/8qXARvYSjNvq8S1GYFFzynQTAfKeaJ0sIrR3PUPuu37Z+EiIANiZBvpfTf2B5y8ecDLSMWlLv+w==", - "optional": true, - "engines": { - "node": ">=12" + "node": "^16.14.0 || >=18.0.0" } }, "node_modules/map-stream": { @@ -10952,7 +10976,7 @@ }, "node_modules/minimatch": { "version": "3.1.2", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -10966,41 +10990,38 @@ "license": "MIT" }, "node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "optional": true, - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "optional": true, + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "dev": true, "dependencies": { - "minipass": "^3.0.0" + "minipass": "^7.0.3" }, "engines": { - "node": ">= 8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "optional": true, + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", + "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", + "dev": true, "dependencies": { - "minipass": "^3.1.6", + "minipass": "^7.0.3", "minipass-sized": "^1.0.3", "minizlib": "^2.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" }, "optionalDependencies": { "encoding": "^0.1.13" @@ -11010,7 +11031,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "optional": true, + "dev": true, "dependencies": { "minipass": "^3.0.0" }, @@ -11018,11 +11039,23 @@ "node": ">= 8" } }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/minipass-pipeline": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "optional": true, + "dev": true, "dependencies": { "minipass": "^3.0.0" }, @@ -11030,11 +11063,23 @@ "node": ">=8" } }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/minipass-sized": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "optional": true, + "dev": true, "dependencies": { "minipass": "^3.0.0" }, @@ -11042,11 +11087,23 @@ "node": ">=8" } }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/minizlib": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "optional": true, + "dev": true, "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" @@ -11055,6 +11112,18 @@ "node": ">= 8" } }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/mitt": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", @@ -11410,12 +11479,6 @@ "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", "dev": true }, - "node_modules/node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "optional": true - }, "node_modules/node-cleanup": { "version": "2.1.2", "dev": true, @@ -11440,44 +11503,134 @@ } }, "node_modules/node-gyp": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.1.tgz", - "integrity": "sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==", - "optional": true, + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.2.0.tgz", + "integrity": "sha512-sp3FonBAaFe4aYTcFdZUn2NYkbP7xroPGYvQmP4Nl5PxamznItBnNCgjrVTKrEfQynInMsJvZrdmqUnysCJ8rw==", + "dev": true, "dependencies": { "env-paths": "^2.2.0", - "glob": "^7.1.4", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", + "make-fetch-happen": "^13.0.0", + "nopt": "^7.0.0", + "proc-log": "^4.1.0", "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" + "tar": "^6.2.1", + "which": "^4.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" }, "engines": { - "node": "^12.13 || ^14.13 || >=16" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/node-windows-trayicon": { - "name": "windows-trayicon", - "version": "3.0.0", - "resolved": "git+ssh://git@github.com/keymanapp/node-windows-trayicon.git#b3dda72327141cd99b4e21d3f5d7002bb17c2131", + "node_modules/node-gyp/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/node-gyp/node_modules/foreground-child": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/node-gyp/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dev": true, + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/node-hide-console-window": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-hide-console-window/-/node-hide-console-window-2.2.0.tgz", + "integrity": "sha512-CNLpd14IJbDQqzl6ryrpc4tjB2modRV+OvKekuu0KvLhqBj7ybmDWTXxHexG6LRrWW55Hfky/ZyZheh0xVXxDg==", "hasInstallScript": true, - "license": "MIT", "optional": true, "os": [ "win32" - ], - "dependencies": { - "bindings": "^1.5.0", - "node-addon-api": "^3.1.0", - "node-gyp": "^9.1.0" - } + ] }, "node_modules/noms": { "version": "0.0.0", @@ -11510,18 +11663,18 @@ "license": "MIT" }, "node_modules/nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "optional": true, + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", + "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", + "dev": true, "dependencies": { - "abbrev": "^1.0.0" + "abbrev": "^2.0.0" }, "bin": { "nopt": "bin/nopt.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/normalize-path": { @@ -11559,20 +11712,6 @@ "node": ">=4" } }, - "node_modules/npmlog": { - "version": "6.0.2", - "license": "ISC", - "optional": true, - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/number-is-nan": { "version": "1.0.1", "dev": true, @@ -11778,7 +11917,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "optional": true, + "dev": true, "dependencies": { "aggregate-error": "^3.0.0" }, @@ -11837,19 +11976,6 @@ } } }, - "node_modules/pac-proxy-agent/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/pac-proxy-agent/node_modules/https-proxy-agent": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", @@ -11863,20 +11989,6 @@ "node": ">= 14" } }, - "node_modules/pac-proxy-agent/node_modules/socks-proxy-agent": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.3.tgz", - "integrity": "sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.7.1" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/pac-resolver": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", @@ -11890,6 +12002,12 @@ "node": ">= 14" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true + }, "node_modules/pako": { "version": "1.0.11", "license": "(MIT AND Zlib)" @@ -11947,7 +12065,7 @@ }, "node_modules/path-is-absolute": { "version": "1.0.1", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -11966,6 +12084,28 @@ "dev": true, "license": "MIT" }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, "node_modules/path-to-regexp": { "version": "0.1.7", "license": "MIT" @@ -12074,6 +12214,15 @@ "node": ">= 0.8.0" } }, + "node_modules/proc-log": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", + "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "license": "MIT" @@ -12086,17 +12235,11 @@ "node": ">=0.4.0" } }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "optional": true - }, "node_modules/promise-retry": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "optional": true, + "dev": true, "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" @@ -12170,19 +12313,6 @@ } } }, - "node_modules/proxy-agent/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/proxy-agent/node_modules/https-proxy-agent": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", @@ -12205,20 +12335,6 @@ "node": ">=12" } }, - "node_modules/proxy-agent/node_modules/socks-proxy-agent": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.3.tgz", - "integrity": "sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.7.1" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/proxy-from-env": { "version": "1.1.0", "dev": true, @@ -12590,13 +12706,14 @@ "node_modules/restructure": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.1.tgz", - "integrity": "sha512-6neDpI/yE9eogQo22qmWwKIA9wFPRyYjQleDEh6zaNAf2ZPqLJYUvNBJBWEWNoBlCeQMQkvIOe2YI/K2GOag+g==" + "integrity": "sha512-6neDpI/yE9eogQo22qmWwKIA9wFPRyYjQleDEh6zaNAf2ZPqLJYUvNBJBWEWNoBlCeQMQkvIOe2YI/K2GOag+g==", + "license": "MIT" }, "node_modules/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "optional": true, + "dev": true, "engines": { "node": ">= 4" } @@ -12613,7 +12730,7 @@ }, "node_modules/rimraf": { "version": "3.0.2", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "glob": "^7.1.3" @@ -12856,11 +12973,6 @@ "node": ">= 0.8.0" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "license": "ISC", - "optional": true - }, "node_modules/set-immediate-shim": { "version": "1.0.1", "license": "MIT", @@ -13046,45 +13158,57 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "devOptional": true, + "dev": true, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" } }, "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "devOptional": true, + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "dev": true, "dependencies": { - "ip": "^2.0.0", + "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" }, "engines": { - "node": ">= 10.13.0", + "node": ">= 10.0.0", "npm": ">= 3.0.0" } }, "node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "optional": true, + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "dev": true, "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" }, "engines": { - "node": ">= 10" + "node": ">= 14" + } + }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" } }, "node_modules/socks-proxy-agent/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "optional": true, + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -13133,15 +13257,15 @@ "dev": true }, "node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "optional": true, + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", + "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", + "dev": true, "dependencies": { - "minipass": "^3.1.1" + "minipass": "^7.0.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/statuses": { @@ -13214,6 +13338,51 @@ "node": ">=0.10.0" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/string.prototype.codepointat": { "version": "0.2.1", "license": "MIT" @@ -13277,6 +13446,28 @@ "node": ">=0.10.0" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -13387,7 +13578,7 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "optional": true, + "dev": true, "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -13425,11 +13616,35 @@ "streamx": "^2.15.0" } }, + "node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/tar/node_modules/minipass": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "optional": true, + "dev": true, "engines": { "node": ">=8" } @@ -13438,7 +13653,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "optional": true, + "dev": true, "bin": { "mkdirp": "bin/cmd.js" }, @@ -13830,27 +14045,27 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "optional": true, + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "dev": true, "dependencies": { - "unique-slug": "^3.0.0" + "unique-slug": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "optional": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "dev": true, "dependencies": { "imurmurhash": "^0.1.4" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/universal-user-agent": { @@ -14026,7 +14241,7 @@ }, "node_modules/which": { "version": "2.0.2", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -14133,6 +14348,68 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wrap-ansi/node_modules/ansi-regex": { "version": "5.0.1", "license": "MIT", @@ -14563,6 +14840,19 @@ "jsdom": "^23.0.1", "mocha": "^10.0.0" } + }, + "web/src/tools/testing/recorder-core": { + "name": "@keymanapp/recorder-core", + "license": "MIT", + "dependencies": { + "@keymanapp/keyboard-processor": "*", + "@keymanapp/keyman-version": "*", + "@keymanapp/models-types": "*", + "@keymanapp/web-utils": "*" + }, + "devDependencies": { + "typescript": "^5.4.5" + } } } } diff --git a/resources/build/builder.md b/resources/build/builder.md index 3855288392..0e3ef901f7 100644 --- a/resources/build/builder.md +++ b/resources/build/builder.md @@ -229,6 +229,14 @@ builder_describe \ "--feature=FOO Enable feature foo" ``` +## Constraining build targets by platform or tooling + +You can use [`builder_describe_platform`](#builderdescribeplatform-function) to +constrain certain targets to only run on specific platforms or if specific +toolchains are installed. + +## Parsing command line + After describing the available parameters, you need to pass the command line parameters in for parsing and validation: @@ -555,6 +563,48 @@ repository root, not filesystem root. -------------------------------------------------------------------------------- +## `builder_describe_platform` function + +Describes the platforms for which a given target will be available, and +filters the list of targets accordingly, removing targets that cannot be built +on the current platform. Removed targets will be listed in a separate section +in the help documentation. + +### Usage + +```bash +builder_describe_platform :target platform[,...] [:target platform[,...] ...] +``` + +### Parameters + +* `target platform[s]` ...: Target and its list of corresponding platform(s) + +### Description + +Multiple targets can be listed. Each target must be followed by a comma +separated list of platforms. The currently supported platforms are: + +Operating System platforms: +* `win`: Windows +* `mac`: macOS +* `linux`: Linux + +Development tooling platforms: +* `delphi`: Delphi is installed (Windows only) +* `android-studio`: Android Studio is installed (`$ANDROID_HOME` variable) + +Targets not specified will be built on all platforms. + +### Example + +```bash +builder_describe_platform \ + :tike win,delphi +``` + +-------------------------------------------------------------------------------- + ## `builder_display_usage` function Prints the help for the script, constructed from the [`builder_describe`] @@ -795,6 +845,21 @@ available anyway. -------------------------------------------------------------------------------- +## `builder_is_target_excluded_by_platform` function + +Returns `true` (aka 0) if the target has been excluded from the build because +it is for a different platform, or because the required tools are not installed. + +### Usage + +```bash +if builder_is_target_excluded_by_platform $target; then + ... +fi +``` + +-------------------------------------------------------------------------------- + ## `builder_parse` function Initializes a build.sh script, parses command line. Will abort the script if diff --git a/resources/build/test/builder-platform.test.sh b/resources/build/test/builder-platform.test.sh new file mode 100755 index 0000000000..78b40fb348 --- /dev/null +++ b/resources/build/test/builder-platform.test.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +set -eu + +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" +. "${THIS_SCRIPT%/*}/../../../resources/builder.inc.sh" +# END STANDARD BUILD SCRIPT INCLUDE + +. "${THIS_SCRIPT_PATH}/test-utils.inc.sh" + +# Test overrides which disable win, delphi + +BUILDER_PLATFORM_OVERRIDE=linux +BUILDER_TOOLS_OVERRIDE= + +builder_describe \ + "Tests platform requirements" \ + build \ + :linux-project \ + :mac-project \ + :win-project \ + :delphi-project + +builder_describe_platform \ + :linux-project linux \ + :mac-project mac \ + :win-project win \ + :delphi-project win,delphi + +assert-equal "${_builder_targets[*]}" ":linux-project" "_builder_targets" + +# seems bash associative array order is unstable? so sort array for test +readarray -t btebp_sorted < <(printf '%s\n' "${!_builder_targets_excluded_by_platform[@]}" | sort) +assert-equal "${btebp_sorted[*]}" ":delphi-project :mac-project :win-project" "_builder_targets_excluded_by_platform" + +# Test overrides with enable win, delphi + +BUILDER_PLATFORM_OVERRIDE=win +BUILDER_TOOLS_OVERRIDE=(delphi) + +builder_describe \ + "Tests platform requirements" \ + build \ + :linux-project \ + :mac-project \ + :win-project \ + :delphi-project + +builder_describe_platform \ + :linux-project linux \ + :mac-project mac \ + :win-project win \ + :delphi-project win,delphi + +readarray -t bt_sorted < <(printf '%s\n' "${_builder_targets[@]}" | sort) +assert-equal "${bt_sorted[*]}" ":delphi-project :win-project" "_builder_targets" + +readarray -t btebp_sorted < <(printf '%s\n' "${!_builder_targets_excluded_by_platform[@]}" | sort) +assert-equal "${btebp_sorted[*]}" ":linux-project :mac-project" "_builder_targets_excluded_by_platform" diff --git a/resources/build/test/test-utils.inc.sh b/resources/build/test/test-utils.inc.sh new file mode 100644 index 0000000000..47f0aca33e --- /dev/null +++ b/resources/build/test/test-utils.inc.sh @@ -0,0 +1,14 @@ +function assert-equal() { + local actual="$1" + local expected="$2" + local message= + if [[ $# -gt 2 ]]; then + message="$3: " + fi + + if [[ "$actual" != "$expected" ]]; then + builder_die "FAIL: ${message}expected actual '$actual' to equal expected '$expected'" + else + builder_echo green "PASS: ${message}expected actual '$actual' to be equal to expected '$expected'" + fi +} diff --git a/resources/build/test/test.sh b/resources/build/test/test.sh index 60c86072b0..1cbaa25476 100755 --- a/resources/build/test/test.sh +++ b/resources/build/test/test.sh @@ -206,6 +206,10 @@ echo -e "${COLOR_BLUE}## Running dependency tests${COLOR_RESET}" "$THIS_SCRIPT_PATH/debug-deps/test.sh" "$THIS_SCRIPT_PATH/ignored-flags/test.sh" +echo -e "${COLOR_BLUE}## Test builder.inc.sh platform and tool constraints${COLOR_RESET}" +"$THIS_SCRIPT_PATH/builder-platform.test.sh" + + echo -e "${COLOR_BLUE}## Test builder.inc.sh 'builder-style' script${COLOR_RESET}" ./builder-invalid-script.test.sh || builder_die "FAIL: builder-invalid-script.test.sh returned failure code $?" diff --git a/resources/build/trigger-definitions.inc.sh b/resources/build/trigger-definitions.inc.sh index 8876cb727b..aa8312f453 100644 --- a/resources/build/trigger-definitions.inc.sh +++ b/resources/build/trigger-definitions.inc.sh @@ -50,7 +50,7 @@ bc_test_linux=(KeymanLinux_TestPullRequests Keyman_Linux_Test_Integration Keyman bc_test_mac=(Keyman_KeymanMac_PullRequests Keyman_Common_KPAPI_TestPullRequests_macOS) bc_test_windows=(KeymanDesktop_TestPullRequests KeymanDesktop_TestPrRenderOnScreenKeyboards Keyman_Common_KPAPI_TestPullRequests_Windows) bc_test_web=(Keymanweb_TestPullRequests Keyman_Common_LMLayer_TestPullRequests Keyman_Common_KPAPI_TestPullRequests_WASM) -bc_test_developer=(Keyman_Developer_Test) +bc_test_developer=(Keyman_Developer_Test Keyman_Test_Developer_Mac Keyman_Test_Developer_Linux) bc_test_common_web=(Keyman_Test_Common_Web) bc_test_common_windows=(Keyman_Test_Common_Windows) @@ -135,3 +135,15 @@ bc_stable_17_0_web=(Keymanweb_Build) bc_stable_17_0_developer=(Keyman_Developer_Release) vcs_stable_17_0=HttpsGithubComKeymanappKeyman + +# Stable 17.0 Build Configurations + +bc_stable_18_0_android=(KeymanAndroid_Build) +bc_stable_18_0_ios=(Keyman_iOS_Master) +bc_stable_18_0_linux=(KeymanLinux_Master deb-release-packaging_GitHub) +bc_stable_18_0_mac=(KeymanMac_Master) +bc_stable_18_0_windows=(Keyman_Build) +bc_stable_18_0_web=(Keymanweb_Build) +bc_stable_18_0_developer=(Keyman_Developer_Release) + +vcs_stable_18_0=HttpsGithubComKeymanappKeyman diff --git a/resources/builder.inc.sh b/resources/builder.inc.sh index 9dc7f17994..b233614029 100755 --- a/resources/builder.inc.sh +++ b/resources/builder.inc.sh @@ -834,6 +834,7 @@ builder_describe() { _builder_deps=() # array of all dependencies for this script _builder_options_inheritable=() # array of all options that should be passed to child scripts _builder_default_action=build + declare -A -g _builder_targets_excluded_by_platform=() declare -A -g _builder_params declare -A -g _builder_options_short declare -A -g _builder_options_var @@ -865,6 +866,7 @@ builder_describe() { IFS="=" read -r -a sub <<< "$value" target_path="${sub[@]:1}" value="${sub[0]}" + original_value="$value" if [[ ! -d "$THIS_SCRIPT_PATH/$target_path" ]]; then builder_die "Target path '$target_path' for $value does not exist." fi @@ -1325,7 +1327,14 @@ _builder_parse_expanded_parameters() { # apply the selected action to all targets if [[ ! -z $target ]]; then # A target was specified but is not valid - _builder_parameter_error "$0" target "$target" + if builder_is_target_excluded_by_platform "$target"; then + builder_echo red "$0: Target $target is unavailable because it requires ${_builder_targets_excluded_by_platform[$target]}" + echo + builder_display_usage + exit 64 + else + _builder_parameter_error "$0" target "$target" + fi fi for e in "${_builder_targets[@]}"; do @@ -1392,7 +1401,17 @@ _builder_parse_expanded_parameters() { ;; *) # script does not recognize anything of action or target form at this point. - if builder_is_child_build; then + if [[ $key =~ ^: ]]; then + # This is an unsupported target + if builder_is_target_excluded_by_platform "$key"; then + builder_echo red "$0: Target $key is unavailable because it requires ${_builder_targets_excluded_by_platform[$key]}" + echo + builder_display_usage + exit 64 + else + _builder_parameter_error "$0" target "$key" + fi + elif builder_is_child_build; then # For child builds, don't fail the build when pass inheritable # parameters (#11408) builder_echo_debug "Parameter '$key' is not supported, ignoring" @@ -1520,6 +1539,19 @@ builder_display_usage() { _builder_pad $width " $e" "$description" done + if [[ ${#_builder_targets_excluded_by_platform[@]} -gt 0 ]]; then + echo + echo "Unavailable Targets: " + for e in "${!_builder_targets_excluded_by_platform[@]}"; do + if [[ ! -z "${_builder_params[$e]+x}" ]]; then + description="${_builder_params[$e]}" + else + description=$(_builder_get_default_description "$e") + fi + _builder_pad $width " $e" "$description (requires ${_builder_targets_excluded_by_platform[$e]})" + done + fi + echo echo "Options: " @@ -1893,6 +1925,126 @@ _builder_has_function_been_called() { return 1 } +################################################################################ +# Platform restrictions +################################################################################ + +# Describes the platforms for which a given target will be available, and +# filters the list of targets accordingly, removing targets that cannot be built +# on the current platform. Removed targets will be listed in a separate section +# in the help documentation. +# +# Parameters: target platform[s] ... Target and its list of corresponding +# platform(s) +# +# Multiple targets can be listed. Each target must be followed by a comma +# separated list of platforms. The currently supported platforms are: +# +# Operating System platforms: +# win Windows +# mac macOS +# linux Linux +# +# Development tooling platforms: +# delphi Delphi is installed (on Windows only) +# android Android Studio is installed +# +builder_describe_platform() { + + local builder_platforms=(linux mac win) + local builder_tools=(android-studio delphi) + + # --- Detect platform --- + + # Default value, since it's the most general case/configuration to detect. + local builder_platform=linux + + # This is copied from build-utils.sh to avoid creating a dependency on it + if [[ $OSTYPE == darwin* ]]; then + builder_platform=mac + elif [[ $OSTYPE == msys ]]; then + builder_platform=win + elif [[ $OSTYPE == cygwin ]]; then + builder_platform=win + fi + + # --- Detect tools --- + + local builder_installed_tools=() + + # Detect delphi compiler (see also delphi_environment.inc.sh) + if [[ $builder_platform == win ]]; then + local ProgramFilesx86="$(cygpath -w -F 42)" + if [[ -x "$(cygpath -u "$ProgramFilesx86\\Embarcadero\\Studio\\20.0\\bin\\dcc32.exe")" ]]; then + builder_installed_tools+=(delphi) + fi + fi + + # Detect Android Studio based on ANDROID_HOME environment variable + if [[ ! -z ${ANDROID_HOME+x} ]]; then + builder_installed_tools+=(android-studio) + fi + + # --- Overrides --- + + # For testing, we can override the current platform + if [[ ! -z "${BUILDER_PLATFORM_OVERRIDE+x}" ]]; then + builder_warn "BUILDER_PLATFORM_OVERRIDE variable found. Overriding detected platform '$builder_platform' with '$BUILDER_PLATFORM_OVERRIDE'" + builder_platform="$BUILDER_PLATFORM_OVERRIDE" + fi + + # For testing, we can override the current tools + if [[ ! -z "${BUILDER_TOOLS_OVERRIDE+x}" ]]; then + builder_warn "BUILDER_TOOLS_OVERRIDE variable found. Overriding detected tools (${builder_installed_tools[@]}) with (${BUILDER_TOOLS_OVERRIDE[@]})" + builder_installed_tools=("${BUILDER_TOOLS_OVERRIDE[@]}") + fi + + # --- Exclude targets depending on missing tools and platforms + while [[ $# -gt 1 ]]; do + local target="$1" + shift + local platforms platform + IFS="," read -r -a platforms <<< "$1" + shift + + for platform in "${platforms[@]}"; do + if _builder_item_in_array "$platform" "${builder_platforms[@]}"; then + # Check operating system + if [[ "$platform" != "$builder_platform" ]]; then + _builder_targets_excluded_by_platform[$target]=$platform + _builder_targets=( ${_builder_targets[@]/$target} ) + fi + elif _builder_item_in_array "$platform" "${builder_tools[@]}"; then + # Check installed tools + if ! _builder_item_in_array "$platform" "${builder_installed_tools[@]}"; then + _builder_targets_excluded_by_platform[$target]=$platform + _builder_targets=( ${_builder_targets[@]/$target} ) + fi + else + builder_warn "Available platforms: ${builder_platforms[@]}" + builder_warn "Available tools: ${builder_tools[@]}" + builder_die "Invalid platform or tool specified for builder_describe_platforms: $platform" + fi + done + done +} + +# Returns 0 if the specified target is excluded by platform requirements +# +# Parameters: target Target to verify +# +builder_is_target_excluded_by_platform() { + local target="$1" + if [[ ! -z "${_builder_targets_excluded_by_platform[$target]+x}" ]]; then + return 0 + fi + return 1 +} + +################################################################################ +# Final initialization +################################################################################ + # # Initialize builder once all functions are declared # diff --git a/web/src/engine/osk/src/config/commonConfiguration.ts b/web/src/engine/osk/src/config/commonConfiguration.ts index 6782d4a011..36d06f2974 100644 --- a/web/src/engine/osk/src/config/commonConfiguration.ts +++ b/web/src/engine/osk/src/config/commonConfiguration.ts @@ -2,6 +2,7 @@ import { DeviceSpec } from "@keymanapp/web-utils"; import EmbeddedGestureConfig from './embeddedGestureConfig.js'; import { OSKResourcePathConfiguration } from "keyman/engine/interfaces"; +import { GestureParams } from "../input/gestures/specsForLayout.js"; export default interface CommonConfiguration { /** @@ -30,4 +31,9 @@ export default interface CommonConfiguration { * embedded within a WebView. */ embeddedGestureConfig?: EmbeddedGestureConfig; + + /** + * Specifies the gesture parameterizations to use for the active keyboard. + */ + gestureParams?: GestureParams; } \ No newline at end of file diff --git a/web/src/engine/osk/src/input/gestures/specsForLayout.ts b/web/src/engine/osk/src/input/gestures/specsForLayout.ts index 943d8e91b9..34d5576e23 100644 --- a/web/src/engine/osk/src/input/gestures/specsForLayout.ts +++ b/web/src/engine/osk/src/input/gestures/specsForLayout.ts @@ -21,12 +21,16 @@ import { calcLockedDistance, lockedAngleForDir, MAX_TOLERANCE_ANGLE_SKEW, type O import specs = gestures.specs; export interface GestureParams { - longpress: { + readonly longpress: { /** - * Allows enabling or disabling the longpress up-flick shortcut for keyboards that do not - * include any defined flick gestures. + * Allows enabling or disabling the longpress up-flick shortcut for + * keyboards that do not include any defined flick gestures. * - * Will be ignored (in favor of `false`) for keyboards that do have defined flicks. + * Will be ignored (in favor of `false`) for keyboards that do have defined + * flicks. + * + * Note: this is automatically overwritten during keyboard initialization + * to match the keyboard's properties. */ permitsFlick: (item?: Item) => boolean, @@ -57,7 +61,7 @@ export interface GestureParams { */ waitLength: number }, - multitap: { + readonly multitap: { /** * The duration (in ms) permitted between taps. Taps with a greater time interval * between them will be considered separate. @@ -70,7 +74,7 @@ export interface GestureParams { */ holdLength: number; }, - flick: { + readonly flick: { /** * The minimum _net_ touch-path distance that must be traversed to "lock in" on * a flick gesture. When keys support both longpresses and flicks, this distance @@ -248,7 +252,14 @@ export function gestureSetForLayout(flags: LayoutGestureSupportFlags, params: Ge const _initialTapModel: GestureModel = deepCopy(!doRoaming ? initialTapModel(params) : initialTapModelWithReset(params)); const _simpleTapModel: GestureModel = deepCopy(!doRoaming ? simpleTapModel(params) : simpleTapModelWithReset(params)); - const _longpressModel: GestureModel = deepCopy(longpressModel(params, true, doRoaming)); + // Ensure all deep-copy operations for longpress modeling occur before the property-redefining block. + const _longpressModel: GestureModel = withKeySpecFiltering(deepCopy(longpressModel(params, true, doRoaming)), 0); + + // `deepCopy` does not preserve property definitions, instead raw-copying its value. + // We need to re-instate the longpress delay property here. + Object.defineProperty(_longpressModel.contacts[0].model.timer, 'duration', { + get: () => params.longpress.waitLength + }); // #region Functions for implementing and/or extending path initial-state checks function withKeySpecFiltering(model: GestureModel, contactIndices: number | number[]) { @@ -281,7 +292,7 @@ export function gestureSetForLayout(flags: LayoutGestureSupportFlags, params: Ge const specialStartModel = specialKeyStartModel(); const _modipressStartModel = modipressStartModel(); const gestureModels: GestureModel[] = [ - withKeySpecFiltering(_longpressModel, 0), + _longpressModel, withKeySpecFiltering(multitapStartModel(params), 0), multitapEndModel(params), _initialTapModel, @@ -481,7 +492,8 @@ export function longpressContactModel(params: GestureParams, enabledFlicks: bool itemPriority: 0, pathResolutionAction: 'resolve', timer: { - duration: spec.waitLength, + // Needs to be a getter so that it dynamically updates if the backing value is changed. + get duration() { return spec.waitLength }, expectedResult: true }, validateItem: (_: KeyElement, baseKey: KeyElement) => !!baseKey?.key.spec.sk, diff --git a/web/src/engine/osk/src/views/oskView.ts b/web/src/engine/osk/src/views/oskView.ts index afdc99f882..d55eb8a8f8 100644 --- a/web/src/engine/osk/src/views/oskView.ts +++ b/web/src/engine/osk/src/views/oskView.ts @@ -26,6 +26,7 @@ import { EventListener, KeyEventHandler, KeyEventSourceInterface, LegacyEventEmi import Configuration from '../config/viewConfiguration.js'; import Activator, { StaticActivator } from './activator.js'; import TouchEventPromiseMap from './touchEventPromiseMap.js'; +import { DEFAULT_GESTURE_PARAMS, GestureParams } from '../input/gestures/specsForLayout.js'; // These will likely be eliminated from THIS file at some point.\ @@ -172,6 +173,18 @@ export default abstract class OSKView metadata: KeyboardProperties }; + /** + * Provides the current parameterization for timings and distances used by + * any gesture-supporting keyboards. Changing properties of its objects will + * automatically update keyboards to use the new configuration. + * + * If `gestureParams` was set in the configuration object passed in at + * construction time, this will be the same instance. + */ + get gestureParams(): GestureParams { + return this.config.gestureParams; + } + /** * The configured width for this OSKManager. May be `undefined` or `null` * to allow automatic width scaling. @@ -216,6 +229,8 @@ export default abstract class OSKView // Clone the config; do not allow object references to be altered later. this.config = configuration = {...configuration}; + // If gesture parameters were not provided in advance, initialize them from defaults. + this.config.gestureParams ||= DEFAULT_GESTURE_PARAMS; // `undefined` is falsy, but we want a `true` default behavior for this config property. if(this.config.allowHideAnimations === undefined) { @@ -820,7 +835,8 @@ export default abstract class OSKView family: 'SpecialOSK', files: [`${resourcePath}/keymanweb-osk.ttf`], path: '' // Not actually used. - } + }, + gestureParams: this.config.gestureParams }); vkbd.on('keyevent', (keyEvent, callback) => this.emit('keyevent', keyEvent, callback)); diff --git a/web/src/engine/osk/src/visualKeyboard.ts b/web/src/engine/osk/src/visualKeyboard.ts index fac43d5125..a8152a0db0 100644 --- a/web/src/engine/osk/src/visualKeyboard.ts +++ b/web/src/engine/osk/src/visualKeyboard.ts @@ -151,8 +151,8 @@ export default class VisualKeyboard extends EventEmitter implements Ke /** * Tweakable gesture parameters referenced by supported gestures and the gesture engine. */ - readonly gestureParams: GestureParams = { - ...DEFAULT_GESTURE_PARAMS, + get gestureParams(): GestureParams { + return this.config.gestureParams; }; // Legacy alias, maintaining a reference for code built against older @@ -307,6 +307,10 @@ export default class VisualKeyboard extends EventEmitter implements Ke this.isStatic = config.isStatic; } + this.config.gestureParams ||= { + ...DEFAULT_GESTURE_PARAMS, + }; + this._fixedWidthScaling = this.device.touchable && !this.isStatic; this._fixedHeightScaling = this.device.touchable && !this.isStatic; diff --git a/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js b/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js index ba4808e66a..6bd0f7555c 100644 --- a/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js +++ b/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.spec.js @@ -118,6 +118,65 @@ describe("PredictionContext", () => { assert.equal(suggestions.find((obj) => obj.transform.deleteLeft != 0).displayAs, 'apps'); }); + it('ignores outdated predictions', async function () { + const langProcessor = new LanguageProcessor(worker, new TranscriptionCache()); + await langProcessor.loadModel(appleDummyModel); // await: must fully 'configure', load script into worker. + + const kbdProcessor = new KeyboardProcessor(deviceSpec); + const predictiveContext = new PredictionContext(langProcessor, kbdProcessor); + + let updateFake = sinon.fake(); + predictiveContext.on('update', updateFake); + + let mock = new Mock("appl", 4); // "appl|", with '|' as the caret position. + const initialMock = Mock.from(mock); + const promise = predictiveContext.setCurrentTarget(mock); + + // Initial predictive state: no suggestions. context.initializeState() has not yet been called. + assert.equal(updateFake.callCount, 1); + assert.isEmpty(updateFake.firstCall.args[0]); // should have no suggestions. (if convenient for testing) + + await promise; + let suggestions; + + // Initialization results: our first set of dummy suggestions. + assert.equal(updateFake.callCount, 2); + suggestions = updateFake.secondCall.args[0]; + assert.deepEqual(suggestions.map((obj) => obj.displayAs), ['apple', 'apply', 'apples']); + assert.isNotOk(suggestions.find((obj) => obj.tag == 'keep')); + assert.isNotOk(suggestions.find((obj) => obj.transform.deleteLeft != 0)); + + const baseTranscription = mock.buildTranscriptionFrom(initialMock, null, true); + + // Mocking: corresponds to the second set of mocked predictions - round 2 of + // 'apple', 'apply', 'apples'. + const skippedPromise = langProcessor.predict(baseTranscription, kbdProcessor.layerId); + + mock.insertTextBeforeCaret('e'); // appl| + e = apple + const finalTranscription = mock.buildTranscriptionFrom(initialMock, null, true); + + // Mocking: corresponds to the third set of mocked predictions - 'applied'. + const expectedPromise = langProcessor.predict(finalTranscription, kbdProcessor.layerId); + + await Promise.all([skippedPromise, expectedPromise]); + const expected = await expectedPromise; + + // Despite two predict calls, we should only increase the counter by ONE - we ignore + // the 'outdated' / 'skipped' round because it could not respond before its followup. + assert.equal(updateFake.callCount, 3); + suggestions = updateFake.thirdCall.args[0]; + + // This does re-use the apply-revert oriented mocking. + // Should skip the (second) "apple", "apply", "apps" round, as it became outdated + // by its following request before its response could be received. + assert.deepEqual(suggestions.map((obj) => obj.displayAs), ['“apple”', 'applied']); + assert.equal(suggestions.find((obj) => obj.tag == 'keep').displayAs, '“apple”'); + assert.equal(suggestions.find((obj) => obj.transform.deleteLeft != 0).displayAs, 'applied'); + // Our reused mocking doesn't directly provide the 'keep' suggestion; we + // need to remove it before testing for set equality. + assert.deepEqual(suggestions.splice(1), expected); + }); + it('sendUpdateState retrieves the most recent suggestion set', async function() { const langProcessor = new LanguageProcessor(worker, new TranscriptionCache()); await langProcessor.loadModel(appleDummyModel); // await: must fully 'configure', load script into worker. diff --git a/common/web/recorder/.gitignore b/web/src/tools/testing/recorder-core/.gitignore similarity index 100% rename from common/web/recorder/.gitignore rename to web/src/tools/testing/recorder-core/.gitignore diff --git a/common/web/recorder/build.sh b/web/src/tools/testing/recorder-core/build.sh similarity index 88% rename from common/web/recorder/build.sh rename to web/src/tools/testing/recorder-core/build.sh index f34bbc3111..0b89ce7701 100755 --- a/common/web/recorder/build.sh +++ b/web/src/tools/testing/recorder-core/build.sh @@ -7,7 +7,7 @@ ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" -. "${THIS_SCRIPT%/*}/../../../resources/build/builder.inc.sh" +. "${THIS_SCRIPT%/*}/../../../../../resources/build/builder.inc.sh" ## END STANDARD BUILD SCRIPT INCLUDE . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" @@ -24,7 +24,7 @@ builder_describe \ builder_describe_outputs \ configure "/node_modules" \ - build "/common/web/recorder/build/obj/index.js" + build "/web/src/tools/testing/recorder-core/build/obj/index.js" builder_parse "$@" diff --git a/common/web/recorder/package.json b/web/src/tools/testing/recorder-core/package.json similarity index 100% rename from common/web/recorder/package.json rename to web/src/tools/testing/recorder-core/package.json diff --git a/common/web/recorder/src/index.ts b/web/src/tools/testing/recorder-core/src/index.ts similarity index 100% rename from common/web/recorder/src/index.ts rename to web/src/tools/testing/recorder-core/src/index.ts diff --git a/common/web/recorder/src/nodeProctor.ts b/web/src/tools/testing/recorder-core/src/nodeProctor.ts similarity index 100% rename from common/web/recorder/src/nodeProctor.ts rename to web/src/tools/testing/recorder-core/src/nodeProctor.ts diff --git a/common/web/recorder/src/proctor.ts b/web/src/tools/testing/recorder-core/src/proctor.ts similarity index 100% rename from common/web/recorder/src/proctor.ts rename to web/src/tools/testing/recorder-core/src/proctor.ts diff --git a/web/src/tools/testing/recorder-core/tsconfig.json b/web/src/tools/testing/recorder-core/tsconfig.json new file mode 100644 index 0000000000..a7bd08c374 --- /dev/null +++ b/web/src/tools/testing/recorder-core/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../../../tsconfig.base.json", + + "compilerOptions": { + "types": ["node"], + "baseUrl": "./", + "outDir": "./build/obj/", + "tsBuildInfoFile": "./build/obj/tsconfig.tsbuildinfo", + "rootDir": "./src" + }, + + "include": [ + "src/**/*.ts" + ], + + "references": [ + { "path": "../../../../../common/web/keyman-version" }, + { "path": "../../../../../common/web/utils/" }, + { "path": "../../../../../common/web/keyboard-processor/" }, + { "path": "../../../../../common/web/lm-message-types" } + ], +} diff --git a/web/src/tools/testing/recorder/build.sh b/web/src/tools/testing/recorder/build.sh index d165585400..28cc43a767 100755 --- a/web/src/tools/testing/recorder/build.sh +++ b/web/src/tools/testing/recorder/build.sh @@ -17,7 +17,7 @@ SUBPROJECT_NAME=tools/testing/recorder builder_describe "Builds the Keyman Engine for Web's test-sequence recording tool" \ "@/common/web/keyman-version" \ "@/common/web/keyboard-processor" \ - "@/common/web/recorder" \ + "@../recorder-core" \ "clean" \ "configure" \ "build" diff --git a/web/src/tools/testing/recorder/tsconfig.json b/web/src/tools/testing/recorder/tsconfig.json index 14dbcb58a2..63cb543efa 100644 --- a/web/src/tools/testing/recorder/tsconfig.json +++ b/web/src/tools/testing/recorder/tsconfig.json @@ -13,8 +13,8 @@ { "path": "../../../../../common/web/keyman-version" }, { "path": "../../../../../common/web/utils" }, { "path": "../../../../../common/web/keyboard-processor" }, - { "path": "../../../../../common/web/recorder" }, { "path": "../../../../../common/web/lm-message-types" }, - { "path": "../../../../../web/src/app/browser" } + { "path": "../../../../../web/src/app/browser" }, + { "path": "../recorder-core" }, ] } diff --git a/windows/src/desktop/kmshell/locale/el-polyton/strings.xml b/windows/src/desktop/kmshell/locale/el-polyton/strings.xml new file mode 100644 index 0000000000..04263b7013 --- /dev/null +++ b/windows/src/desktop/kmshell/locale/el-polyton/strings.xml @@ -0,0 +1,915 @@ + + + + + + + Ἀ. Δεληγιάννη + + + + Segoe UI + + + + 9 + + + + &Ναί + + + + &Ὄχι + + + + OK + + + + Ἀκύρωση + + + + Κλεῖστε + + + + OK + + + + Ἀκύρωση + + + + Προσθέστε/ἀφαιρέστε γλῶσσα... + + + + Πατῆστε αὐτὸ τὸ εἰκονίδιο γιὰ νὰ ἐπιλέξετε γλῶσσα + + + + Τὸ Keyman λειτουργεῖ ἀκόμα. Γιὰ νὰ χρησιμοποιήσετε τὸ πληκτρολόγιο γλώσσας σας, πατῆστε σ\' αὐτὸ τὸ εἰκονίδιο + + + + Τὸ Keyman βρίσκεται ἤδη σὲ λειτουργία. Πατῆστε τὸ εἰκονίδιο Keyman στὴν περιοχὴ εἰδοποιήσεων συστήματος γιὰ νὰ χρησιμοποιήσετε τὸ πληκτρολόγιο τῆς γλώσσας σας + + + + Παραμετροποίηση Keyman + + + + Βοήθεια + + + + Ἀπεγκατάσταση + + + + Ἐνεργοποίηση + + + + Ἀπενεργοποίηση + + + + Πληκτρολόγια + + + + K + + + + Ἐπιλογές + + + + O + + + + Πλῆκτρα συντομεύσεως + + + + H + + + + Ὑποστήριξη + + + + S + + + + Παραμείνετε σὲ ἐπαφή + + + + T + + + + Ὄνομα ἀρχείου: + + + + Ἔκδοση πακέτου: + + + + Ἔκδοση πληκτρολογίου: + + + + Δημιουργός: + + + + Ἱστότοπος: + + + + Πακέτο: + + + + Γραμματοσειρές: + + + + Πληκτρολόγια: + + + + Πληκτρολόγιο: + + + + Γλῶσσα πληκτρολογίου: + + + + Κωδικοποιήσεις: + + + + Τύπος πληκτρολογίου: + + + + Σταθερό (σύμφωνα μὲ τὴν θέση) + + + + Σύμφωνα μὲ τὴν διάταξη τῶν Windows (Μνημονικό) + + + + Γλῶσσες: + + + + + + + + Προσθέστε γλῶσσα + + + + Προσθέστε/ἀφαιρέστε γλῶσσα + + + + Πληκτρολόγιο ὀθόνης: + + + + Ἐξατομικευμένο + + + + Ἐγκατεστημένο + + + + Μὴ ἐγκατεστημένο + + + + Τεκμηρίωση: + + + + Ἐγκατεστημένη + + + + Μὴ ἐγκατεστημένη + + + + Μήνυμα: + + + + Πνευματικὰ δικαιώματα: + + + + Οἱ ἀλλαγὲς ἐφαρμόζονται ἀμέσως + + + + Ἐγκαταστῆστε πληκτρολόγιο... + + + + Κατεβάστε πληκτρολόγιο... + + + + Ἐπιλογὲς πληκτρολογίου... + + + + Δὲν ἔχετε ἐγκατεστημένα πληκτρολόγια. Πατῆστε τὸ πλῆκτρο \"Κατεβάστε πληκτρολόγιο\" καὶ ἐγκαταστῆστε ἕνα πληκτρολόγιο ἀπὸ τὸν ἱστότοπο τοῦ Keyman. + + + + + Μπορεῖτε νὰ ἀφαιρέσετε τὸ πληκτρολόγιο \'%1$s\' μόνον ἂν εἶσθε Διαχειριστής + + + + Μοιρασθῆτε πληκτρολόγιο + + + + Σαρῶστε αὐτὸν τὸν κωδικό γιὰ νὰ φορτώσετε τὸ πληκτρολόγιο σὲ ἄλλη συσκευή ἢ + + + + μοιρασθῆτε ὀνλάϊν + + + + + + + + Γενικά + + + + Ἔναρξη + + + + Πληκτρολόγιο ὀθόνης + + + + Προχωρημένες ἐπιλογές + + + + Τὰ πλῆκτρα συντομεύσεως ἀνοιγοκλείνουν τὴν ἐνεργοποίηση τοῦ πληκτρολογίου + + + + Ἐξομοιῶστε τὸ AltGr μὲ τὸ Ctrl+Alt + + + + Χρησιμοποιῆστε τὰ νεκρὰ πλῆκτρα ὡς συνήθη πλῆκτρα + + + + Προβάλετε μηνύματα-ὑποδείξεις + + + + Ἀναφέρετε σφάλματα στὸ keyman.com αὐτομάτως + + + + Μοιρασθῆτε ἀνώνυμα στατιστικὰ στοιχεῖα χρήσεως μὲ τὸ keyman.com + + + + Ἔναρξη μαζὶ μὲ τὰ Windows + + + + Προβάλετε τὴν ἐναρκτήρια ὀθονη + + + + Προβάλετε τὴν ὀθόνης καλωσορίσματος + + + + Νὰ ἐλέγχετε σὲ ἑβδομαδιαία βάση τὸ keyman.com γιὰ ἐνημερώσεις + + + + Κατὰ τὴν ἔναρξη τοῦ Keyman, νὰ ἐξετάζετε ἂν ὑπάρχουν μὴ συμβατὲς ἐφαρμογές + + + + Μετὰ τὸ πάτημα πλήκτρου νὰ ἐλευθερώνετε τὸ Shift/Ctrl/Alt στὸ πληκτρολόγιο ὀθόνης + + + + Ὅταν ἐπιλέγετε πληκτρολόγιο Keyman, νὰ προβάλλετε πάντα τὸ πληκτρολόγιο ὀθόνης + + + + Μόλις ἐπιλεγεῖ πληκτρολόγιο νὰ ἐμφανίζεται αὐτομάτως τὸ κατάλληλο πληκτρολόγιο ὀθόνης ἢ ὀθόνη βοηθείας + + + + Διερεύνηση σφαλμάτων + + + + Πληκτρολόγιο ἀφετηρίας... + + + + + + + + + + + + + (δὲν ἔχει ὁρισθεῖ πλῆκτρο συντομεύσεως) + + + + Κλεῖστε τὸ Keyman + + + + Ἀνοῖξτε τὸ μενοῦ τοῦ πληκτρολογίου + + + + Προβάλετε τὸ πληκτρολόγιο ὀθόνης + + + + Ἀνοῖξτε τὴν παραμετροποίηση + + + + Προβάλετε τὸν βοηθὸ γραμματοσειρῶν + + + + Προβάλετε τὸν χάρτη χαρακτήρων + + + + Ἀνοῖξτε τὸν ἐπεξεργαστὴ κειμένου + + + + Ἀνοῖξτε τὴν ἐναλλαγὴ γλώσσας + + + + Γενικὰ πλῆκτρα συντομεύσεως + + + + Διατάξεις πληκτρολογίου + + + + Ἂν ἔχετε προβλήματα μὲ τὴν χρήση τοῦ Keyman, ὑποβάλετε ἐρώτημα στὸ φόρουμ τῆς κοινότητας Keyman. + + + + Ἀνοῖξτε τὸ φόρουμ τῆς κοινότητας Keyman + + + + Δημιουργός: SIL International + + + + Πνευματικὰ δικαιώματα © SIL International. All Rights Reserved. + + + + Ἔκδοση + + + + Χρήσιμοι σύνδεσμοι + + + + Βοήθεια ὀνλάϊν + + + + Δεῖτε ἂν ὑπάρχουν ἐνημερώσεις + + + + Ρυθμίσεις ἐνδιάμεσου διακομιστῆ... + + + + Ρυθμίσεις συστήματος Keyman... + + + + Διαγνωστικά + + + + Κατεβάστε πληκτρολόγιο ἀπὸ τὸ keyman.com + + + + Μὴν ἐγκαθιστᾶτε, ἁπλῶς κατεβάστε + + + + + Ἀδύνατον νὰ κατεβάσομε πληκτρολόγιο, σφάλμα %2$d: %1$s + + + + < Πίσω + + + + Ἐγκαταστῆστε πληκτρολόγιο / πακέτο + + + + Λεπτομέρειες + + + + Readme + + + + Ἐγκαταστῆστε + + + + Παραμετροποίηση ἐνδιάμεσου διακομιστῆ (proxy) + + + + Διακομιστής: + + + + Θύρα: + + + + Ὄνομα χρήστη: + + + + Συνθηματικὸς κωδικός: + + + + Ὁρίστε τὸ βασικὸ πληκτρολόγιο + + + + Ἐπιλέξτε τὸ βασικὸ λατινικὸ πληκτρολόγιο ποὺ χρησιμοποιεῖτε στὰ Windows. Τὰ πληκτρολόγια Κῆμαν θὰ προσαρμοσθοῦν αὐτομάτως στὴν διάταξη πληκτρων ποὺ προτιμᾶτε. + + + + Ἀλλάξτε πλῆκτρο συντομεύσεως + + + + + Ἐπιλέξτε ἕνα σύνηθες πλῆκτρο συντομεύσεως. Ἐναλλακτικά, ἐπιλέξτε \'Ἐξατομικευμένο\', κρατῆστε πατημένα τὰ Ctrl,Shift καὶ/ἢ Alt καὶ πληκτρολογῆστε τὸ ἐπιθυμητὸ πλῆκτρο συντομεύσεως γιὰ τὴν γλῶσσα %1$s: + + + + Ἐπιλέξτε ἕνα σύνηθες πλῆκτρο συντομεύσεως. Ἐναλλακτικά, ἐπιλέξτε \"Ἐξατομικευμένο\", κρατῆστε πατημένα τὰ Ctrl,Shift καὶ/ἢ Alt καὶ πληκτρολογῆστε τὸ πλῆκτρο συντομεύσεως ποὺ ἐπιθυμεῖτε: + + + + + Τὸ πλῆκτρο συντομεύσεως %1$s δημιουργεῖ πρόβλημα στὴν κανονικὴ χρήση τοῦ πληκτρολογίου. Πρέπει νὰ χρησιμοποιήσετε τοὐλάχιστον τὸ Ctrl ἢ τὸ Alt. Θέλετε νὰ τὸ ἀλλάξετε τώρα\; + + + + + Τὸ πλῆκτρο συντομεύσεως %1$s δημιουργεῖ πρόβλημα στὸ πλῆκτρο συντομεύσεως ποὺ ἔχετε ἐπιλέξει γιὰ τὸ πληκτρολόγιο %2$s. Ἂν συνεχίσετε, τὸ πλῆκτρο συντομεύσεως γιὰ τὸ %2$s θὰ διαγραφεῖ. Θὰ συνεχίσετε\; + + + + + Τὸ πλῆκτρο συντομεύσεως %1$s δημιουργεῖ πρόβλημα σὲ ἄλλο πλῆκτρο συντομεύσεως. Ἂν συνεχίσετε, τὸ ἄλλο πλῆκτρο θὰ διαγραφεῖ. Θὰ συνεχίσετε\; + + + + Ὑπάρχουν συνιστῶσες Keyman πρὸς ἐνημέρωσιν + + + + Ὑπάρχουν ἐνημερώσεις Keyman πρὸς ἐγκατάστασιν + + + + Παρακαλοῦμε ἐπιλέξτε ποιὲς ἐνημερώσεις θέλετε νὰ ἐγκαταστήσετε: + + + + Μπορεῖτε νὰ κατεβάσετε τὴν νέα ἔκδοση ἀπὸ τό: + + + + Ἐγκαταστῆστε τώρα + + + + Ἀκυρῶστε + + + + Παλαιὰ ἔκδοση + + + + Ἐνημερωμένη συνιστῶσα + + + + Μέγεθος + + + + + Keyman %1$s + + + + + Πληκτρολόγιο %1$s %2$s + + + + Ἀδυναμία ἐπικοινωνίας μὲ τὸ keyman.com - Παρακαλοῦμε βεβαιωθῆτε ὅτι ἔχετε ἐνεργὴ διαδικτυακὴ σύνδεση καὶ ξαναδοκιμάστε. + + + + + Ἀδυναμία ἐπικοινωνίας μὲ τὸ keyman.com - Παρακαλοῦμε βεβαιωθῆτε ὅτι ἔχετε ἐνεργὴ διαδικτυακὴ σύνδεση καὶ ξαναδοκιμάστε. Τὸ ληφθὲν σφάλμα ἦταν: %1$s + + + + Ὑπάρχουν διαθέσιμες ἐνημερώσεις Keyman + + + + Πατῆστε σ΄ αὐτὸ τὸ εἰκονίδιο γιὰ νὰ κατεβάσετε καὶ νὰ ἐγκαταστήσετε ἐνημερώσεις + + + + Δεῖτε καὶ &ἐγκαταστῆστε ἐνημερώσεις Keyman + + + + Τερματισμὸς ἐλέγχου ὀνλάϊν ἐνημερώσεων + + + + Keyman + + + + Ἔναρξη Keyman + + + + Ἔξοδος + + + + Παραμετροποίηση + + + + Προβάλλετε αὐτὴν τὴν ὀθόνη κατὰ τὴν ἐκκίνηση + + + + Γλῶσσα προβολῆς + + + + Βρεῖτε ὀνλάϊν ἄλλες γλῶσσες προβολῆς... + + + + Βοηθῆστε τὴν μετάφραση τῆς διεπαφῆς χρήστη... + + + + Ἑλληνικά Πολυτονικά + + + + Ἑλληνικά Πολυτονικά (Greek Polytonic) + + + + el + + + + en + + + + Keyman + + + + Ἐπαναφέρετε τὰ μηνύματα-ὑποδείξεις + + + + Ὅλα τὰ μηνύματα-ὑποδείξεις ἐπανῆλθαν καὶ θὰ ἐπαναπροβληθοῦν. + + + + + Θέλετε νὰ τερματίσετε τὸ Keyman\; + + + + + Σίγουρα θέλετε νὰ βγῆτε ἀπὸ τὸ Keyman\; Τὰ πληκτρολόγια Keyman θὰ ἐξακολουθοῦν νὰ ἐμφανίζονται στὶς γλῶσσες τῶν Windows, ἀλλὰ δὲν θὰ εἶναι λειτουργικὰ μέχρι νὰ ἐπανεκκινήσετε τὸ Keyman. + + + + + Τὸ πληκτρολόγιο ὀθόνης ἔκλεισε + + + + + Κλείσατε τὸ πληκτρολόγιο ὀθόνης. Τὸ Keyman λειτουργεῖ ἀκόμα. Μπορεῖτε νὰ ἀνοίξετε ὁποτεδήποτε τὸ πληκτρολόγιο ὀθόνης πατῶντας στὸ εἰκονίδιο τοῦ Keyman καὶ ἐπιλέγοντας \"Πληκτρολόγιο ὀθόνης\" + + + + Μὴν ξαναπροβάλετε αὐτὴν τὴν ὑπόδειξη + + + + Βοήθεια Keyman + + + + Περιεχόμενα βοήθειας + + + + Βοήθεια γιὰ τὸ \" + + + + πληκτρολόγιο \" + + + + Δεῖτε τὸ πληκτρολόγιο ὀθόνης + + + + Δεῖτε τὸν βοηθὸ γραμματοσειρῶν + + + + Δεῖτε τὸν πίνακα τῶν χαρακτήρων + + + + Ἀνοῖξτε τὴν παραμετροποίηση τοῦ Κῆμαν + + + + Ἀνοῖξτε τὴν βοήθεια + + + + Κλεῖστε τὸ πληκτρολόγιο ὀθόνης + + + + Ἀπενεργοποιῆστε τὸ Κῆμαν + + + + Πληκτρολόγιο &ὀθόνης + + + + &Ἀνεύρεση γραμματοσειρῶν + + + + Πίνακας &χαρακτήρων + + + + &Ἐπεξεργαστὴς κειμένου... + + + + &Παραμετροποίηση... + + + + &Βοήθεια... + + + + Ἔ&ξοδος + + + + Ὅταν εἶναι ἀνενεργό, νὰ ἀχνοφαίνεται + + + + Νὰ ἐμφανίζεται ἡ γραμμὴ ἐργαλείων + + + + Ἀποθηκεῦστε ὡς ἱστοσελίδα... + + + + Ἐκτυπῶστε... + + + + Keyman + + + + + Ἔκδοση %1$s + + + + Ἐ&κτυπῶστε... + + + + + Ὑπάρχει ἤδη ἐγκατεστημένο πακέτο μέ ὄνομα %1$s. Θέλετε νὰ τὸ ἀπεγκαταστήσετε καὶ νὰ ἐγκαταστήσετε τὸ καινούργιο\; + + + + + Ἔχει ἤδη ἐγκατασταθεῖ πληκτρολόγιο μὲ ὄνομα \'%1$s\'. Ἂν συνεχίσετε, αὐτὸ θὰ ἀπεγκατασταθεῖ πρὶν ἐγκαταστήσετε τὸ καινούργιο. Νὰ συνεχίσομε\; + + + + + Τὸ πληκτρολόγιο \'%1$s\' ἀνήκει στὸ πακέτο \'%2$s\'. Πρέπει νὰ ἀπεγκαταστήσετε ὁλόκληρο τὸ πακέτο. Νὰ συνεχίσομε\; + + + + + Ἀδυνατοῦμε νὰ ἐγκαταστήσομε μία ἀκόμα γλῶσσα· τὰ Windows ἔχουν ὅριο 4 ἐξατομικευμένων \'μεταβατικῶν\' γλωσσῶν καὶ ἴσως νὰ ἔχετε φθάσει σ΄ αὐτὸ τὸ ὅριο. + + + + + Τὸ πακέτο ἢ πληκτρολόγιο \'%1$s\' δὲν περιλαμβάνουν εἰσαγωγικὴ βοήθεια. + + + + Αὐτὸ τὸ λειτουργικὸ σύστημα δὲν ὑποστηρίζεται. + + + + KeymanDesktop.chm + + + + Τὸ ἀρχεῖο βοηθείας δὲν εὑρέθη. + + + + Κωδικοσελίδα + + + + Unicode + + + + Κατεβάζομε ἀρχεῖο + + + + + Σίγουρα θέλετε νὰ ἀφαιρέσετε τὸ πληκτρολόγιο ὀθόνης ποὺ ἔχει ἐγκατασταθεῖ γιὰ τὸ %1$s\; + + + + + Σίγουρα θέλετε νὰ ἀπεγκαταστήσετε τὸ πληκτρολόγιο %1$s\; + + + + + Σίγουρα θέλετε νὰ ἀπεγκαταστήσετε τὸ πακέτο %1$s\;\n\n%2$s + + + + + Θὰ ἀπεγκατασταθοῦν καὶ οἱ ἑξῆς γραμματοσειρές: %1$s. + + + + Ὁ Πίνακας Χαρακτήρων, γιὰ νὰ χρησιμοποιηθεῖ, ἀπαιτεῖ νὰ ἔχει κατασκευασθεῖ προηγουμένως μία βάση δεδομένων χαρακτήρων. Νὰ τὴν κατασκευάσομε τώρα\; + + + + + Ἡ βάση δεδομένων χαρακτήρων Unicode δὲν μπόρεσε νὰ διαγραφεῖ ὥστε νὰ ἀναδομηθεῖ. Λεπτομέρειες σφάλματο: %1$s + + + + + Ἡ βάση δεδομένων χαρακτήρων Unicode δὲν μπόρεσε νὰ δημιουργηθεῖ καὶ ἀπενεργοποιήθηκε. Λεπτομέρειες σφάλματο: %1$s + + + + + Ἡ βάση δεδομένων χαρακτήρων Unicode δὲν φορτώθηκε ἐπιτυχῶς (%1$s). Νὰ τὴν ἀναδομήσομε τώρα\; + + + + + Τὸ Keyman δὲν κατάφερε νὰ ξεκινήσει. Πρὶν συνεχίσετε, παρακαλοῦμε ἐλέγξτε τὶς ρυθμίσεις ἀσφαλείας σας γιὰ νὰ βεβαιωθῆτε ὅτι τὸ πρόγραμμα keyman.exe μπορεῖ νὰ ξεκινήσει. Τὸ ἐπιστραφὲν σφάλμα ἦταν:\n\n\"%1$s\"\n\nΘέλετε νὰ δοκιμάσετε νὰ ἐπανεκκινήσετε τώρα τὸ Keyman\; + + + + Οἱ πληροφορίες ἐντοπισμοῦ σφαλμάτων τοῦ Keyman θὰ ἀποθηκεύονται σὲ ἀρχεῖο-ἀναφορὰ μὲ τὸ ὄνομα %LOCALAPPDATA%\Keyman\Diag\system#.etl (ὅπου # εἶναι ἀριθμός). >>Γιὰ νὰ διαγράψετε αὐτὸ τὸ ἀρχεῖο, πρέπει νὰ βγῆτε ἀπὸ τὸ Keyman.\n\n\ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Αὐτὸ τὸ ἀρχεῖο μπορεῖ νὰ μεγαλώσει πολὺ γρήγορα. Ἡ ἐνεργοποίηση τοῦ ἐντοπισμοῦ σφαλμάτων μπορεῖ νὰ καταστήσει πολὺ βραδύτερο τὸ σύστημά σας, γι\' αὐτὸ θὰ πρέπει νὰ ἐκτελεῖται μόνον κατόπιν συστάσεως τῆς τεχνικῆς ὑποστήριξης.\n\nΠΡΟΕΙΔΟΠΟΙΗΣΗ ΙΔΙΩΤΙΚΟΤΗΤΟΣ: Παρακαλοῦμε σημειῶστε ὅτι στὸ ἀρχεῖο καταγραφῆς προβλημάτων ἀποθηκεύεται ὅ,τι πληκτρολογεῖτε στὸ πληκτρολόγιο. Ἡ ἐνεργοποίηση τοῦ ἀρχείου καταγραφῆς θὰ πρέπει νὰ γίνεται μόνον ὅσο διαρκεῖ μία ἀναζήτηση ἢ διάγνωση προβλήματος. + + + + Παρακαλοῦμε περιμένετε· ἀναζητοῦμε γραμματοσειρὲς γιὰ τὸ πληκτρολόγιο %1$s + + + + Τὸ πληκτρολόγιο %1$s δὲν εἶναι Unicode. Δὲν μποροῦν νὰ ἐντοπισθοῦν αὐτομάτως γραμματοσειρές. Γιὰ πληροφορίες γραμματοσειρῶν παρακαλοῦμε ἐλέγξτε τὴν τεκμηρίωση τοῦ πληκτρολογίου. + + + + Δὲν ἔχουν μέχρι στιγμῆς ἐγκατασταθεῖ ἢ φορτωθεῖ διατάξεις πληκτρολογίων. + + + + Παρακαλοῦμε ἀνοῖξτε ἕνα πληκτρολόγιο Κῆμαν καὶ βρῆτε ἀνάλογες γραμματοσειρές. + + + + Δὲν εὑρέθησαν προτάσεις γραμματοσειρῶν γιὰ τὸ πληκτρολόγιο %1$s. + + + + Ἐπεξεργαστὴς κειμένου - Keyman + diff --git a/windows/src/desktop/setup/locale/el-polyton/strings.xml b/windows/src/desktop/setup/locale/el-polyton/strings.xml new file mode 100644 index 0000000000..ddacddd5b8 --- /dev/null +++ b/windows/src/desktop/setup/locale/el-polyton/strings.xml @@ -0,0 +1,78 @@ + + + Ἑλληνικά Πολυτονικά + Ἐγκατάσταση $APPNAME $VERSION + Ἐγκαταστῆστε $APPNAME $VERSION + Τὸ $APPNAME $VERSION ἐγκατεστάθη ἐπιτυχῶς. + Εἶσθε βέβαιοι ὅτι θέλετε νὰ ἀκυρώσετε τὴν ἐγκατάσταση τοῦ $APPNAME? + Ἐξαγωγὴ πακέτου... + Ἔλεγχος πακέτων... + Ἀναζητοῦνται ἐνημερώσεις ὀνλάϊν... + Ἐλέγχονται ἐγκατεστημένες ἐκδόσεις... + Τελειώνουμε... + + • %1:s $APPNAME %0:s + + • %2:s %0:s %1:s + + • %3:s %0:s %1:s γιὰ %2:s + Δὲν ὑπάρχει τίποτε πρὸς ἐγκατάστασιν. + + (μεταφόρτωση %0:s) + Ἡ ἐγκατάσταση περιλαμβάνει: + Τὸ $APPNAME $VERSION προσφέρεται δωρεὰν καὶ εἶναι ἐφαρμογὴ ἀνοικτοῦ κώδικα + &Διαβάστε τὴν ἄδεια χρήσης + &Ἐπιλογὲς ἐγκατάστασης + Ἐγκατάσταση $APPNAME + OK + &Ἐγκατάσταση + Ἀκύρωση + Ἔξοδος + Ἐγκαθίσταται τὸ $APPNAME + Ἀφαιροῦνται παλαιότερες ἐκδόσεις + Ἡ ἐγκατάσταση ὁλοκληρώθηκε + Γιὰ νὰ ὁλοκληρωθεῖ ἡ ἐγκατάσταση, πρέπει νὰ ἐπανεκκινήσετε τὰ Windows. Ἀφοῦ τὸ κάνετε ἡ ἐγκατάσταση θὰ συνεχισθεῖ. + +Νὰ γίνει ἐπανεκκίνηση τώρα; + Τὰ Windows δὲν μπόρεσαν νὰ ξεκινήσουν αὐτομάτως. Θὰ πρέπει νὰ ἐπανεκκινήσετε τὰ Windows πρὶν προσπαθήσετε νὰ ξεκινήσετε τὸ $APPNAME. + Γιὰ νὰ ὁλοκληρώσετε τὴν ἐγκατάσταση θὰ πρέπει νὰ ἐπανεκκινήσετε τὰ Windows. Ὅταν τὸ κάνετε, ἡ ἐγκατάσταση θὰ τελειώσει. + Τὸ $APPNAME $VERSION ἀπαιτεῖ Windows 7 ἢ νεώτερα. Ὡστόσο ἀνιχνεύθηκαν τὰ Keyman Desktop 7, 8 ἢ 9. Θέλετε νὰ ἐγκαταστήσετε τὰ πληκτρολόγια ποὺ περιέχονται σὲ αὐτὸ τὸ πακέτο ἐγκατάστασης στὴν ἤδη ἐγκατεστημένη ἔκδοση τοῦ Keyman Desktop; + Αὐτὴ ἡ ἔκδοση τοῦ $APPNAME ἀπαιτεῖ τὰ Windows 7 ἢ νεώτερα. Θέλετε νὰ κατεβάσετε τὸ Keyman Desktop 8; + Ἐπιλογὲς ἐγκατάστασης + Ἐπιλογὲς ἐγκατάστασης + Προκαθορισμένες ρυθμίσεις $APPNAME + Ἑνότητες πρὸς ἐγκατάστασιν ἢ ἀναβάθμισιν + Ἡ γλῶσσα τοῦ πληκτρολογίου + Ἡ πρὸς ἐγκατάστασιν ἔκδοση + Ξεκινῆστε τὸ $APPNAME μόλις ξεκινήσουν τὰ Windows + Ξεκινῆστε τὸ $APPNAME μόλις ὁλοκληρωθεῖ ἡ ἐγκατάσταση + Ἐλέγχετε ὀνλάϊν περιοδικῶς ἂν ὑπάρχουν ἀναβαθμίσεις + Ἀναβαθμίστε πληκτρολόγια ἐγκατεστημένα μὲ παλαιότερες ἐκδόσεις στὴν ἔκδοση $VERSION + Μοιρασθῆτε ἀνώνυμα στατιστικὰ στοιχεῖα χρήσεως μὲ τὸ keyman.com + + Ἔκδοση ἐγκατάστασης: %0:s + Ἐγκαταστῆστε τὸ $APPNAME + Ἀναβαθμίστε τὸ $APPNAME + + Τὸ $APPNAME %0:s ἔχει ἤδη ἐγκατασταθεῖ. + + Κατεβάστε τὴν ἔκδοση %0:s (%1:s) + + Ἔκδοση %0:s + + Ἐγκαταστῆστε τὸ %0:s + + Κατεβάστε τὴν ἔκδοση %0:s (%1:s) + + Ἔκδοση %0:s + + Ἐπιλέξτε τὴν γλῶσσα ποὺ θέλετε νὰ χρησιμοποιήσετε μὲ τὸ πληκτρολόγιο %0:s + Ἡ προεπιλεγμένη γλῶσσα + + Φορτώνεται τὸ %0:s + + Φορτώνεται τὸ %0:s + Τὸ πρόγραμμα ἐγκατάστασης τοῦ $APPNAME δὲν μπόρεσε νὰ συνδεθεῖ μὲ τὸ keyman.com γιὰ νὰ κατεβάσει πρόσθετους πόρους. + Παρακαλοῦμε ἐλέγξτε ἂν εἶσθε ὀνλάϊν καὶ ἐπιτρέψτε στὸ πρόγραμμα ἐγκατάστασης τοῦ $APPNAME νὰ προσπελάσει τὸ Διαδίκτυο ρυθμίζοντας ἀναλόγως τὸ τοῖχος προστασίας σας. + Πατῆστε \"Διακοπή\" γιὰ νὰ σταματήσετε τὴν ἐγκατάσταση, \"Ξαναδοκιμάστε\" γιὰ νὰ προσπαθήσετε ἐκ νέου νὰ φορτώσετε πόρους ἢ \"Ἀγνοῆστε\" γιὰ νὰ συνεχίσετε χωρὶς ὀνλάϊν σύνδεση. +