From 0f42e3c92cd54195a0197fd1e91ec69b0efeb98d Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 28 Jun 2023 06:07:32 +0700 Subject: [PATCH 1/9] fix(developer): key type checks were invalid Fixes #9097. --- .../src/kmc-kmn/src/kmw-compiler/validate-layout-file.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 1136a49c6a..5de2e662f6 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 @@ -101,7 +101,7 @@ function CheckKey( // if(FId.trim() == '') { - if(!(FKeyType in [TouchLayout.TouchLayoutKeySp.blank, TouchLayout.TouchLayoutKeySp.spacer]) && FNextLayer == '') { + if(!([TouchLayout.TouchLayoutKeySp.blank, TouchLayout.TouchLayoutKeySp.spacer].includes(FKeyType)) && FNextLayer == '') { callbacks.reportMessage(KmwCompilerMessages.Warn_TouchLayoutUnidentifiedKey({layerId: layer.id})); } return true; @@ -122,7 +122,7 @@ function CheckKey( // Check that each custom key code has at least *a* rule associated with it // - if (FValid == TKeyIdType.Key_Touch && FNextLayer == '' && FKeyType in [TouchLayout.TouchLayoutKeySp.normal, TouchLayout.TouchLayoutKeySp.deadkey]) { + if (FValid == TKeyIdType.Key_Touch && FNextLayer == '' && [TouchLayout.TouchLayoutKeySp.normal, TouchLayout.TouchLayoutKeySp.deadkey].includes(FKeyType)) { // Search for the key in the key dictionary - ignore K_LOPT, K_ROPT... if(FDictionary.indexOf(FId) < 0) { callbacks.reportMessage(KmwCompilerMessages.Warn_TouchLayoutCustomKeyNotDefined({keyId: FId, platformName: platformId, layerId: layer.id})); @@ -139,7 +139,7 @@ function CheckKey( if((CSpecialText10.includes(FText) || CSpecialText14.includes(FText)) && !CSpecialText14ZWNJ.includes(FText) && !IsKeyboardVersion14OrLater() && - !(FKeyType in [TouchLayout.TouchLayoutKeySp.special, TouchLayout.TouchLayoutKeySp.specialActive])) { + !([TouchLayout.TouchLayoutKeySp.special, TouchLayout.TouchLayoutKeySp.specialActive].includes(FKeyType))) { callbacks.reportMessage(KmwCompilerMessages.Warn_TouchLayoutSpecialLabelOnNormalKey({ keyId: FId, platformName: platformId, @@ -161,7 +161,7 @@ function CheckDictionaryKeyValidity(fk: KMX.KEYBOARD, FDictionary: string[]) { continue; } - if(KeyIdType(FDictionary[i]) in [TKeyIdType.Key_Invalid, TKeyIdType.Key_Constant]) { + if([TKeyIdType.Key_Invalid, TKeyIdType.Key_Constant].includes(KeyIdType(FDictionary[i]))) { for(let fgp of fk.groups) { if(fgp.fUsingKeys) { for(let fkp of fgp.keys) { From afa081a1705ccdc1359bd3385bde486cbdd00619 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 28 Jun 2023 06:09:04 +0700 Subject: [PATCH 2/9] fix(developer): content files can have mixed case in packages Fixes #9098. --- developer/src/kmc-package/src/compiler/package-validation.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/developer/src/kmc-package/src/compiler/package-validation.ts b/developer/src/kmc-package/src/compiler/package-validation.ts index 07fb5baaec..b663545fb0 100644 --- a/developer/src/kmc-package/src/compiler/package-validation.ts +++ b/developer/src/kmc-package/src/compiler/package-validation.ts @@ -13,8 +13,8 @@ const MODEL_ID_PATTERN_PACKAGE = /^[a-z_][a-z0-9_]*\.[a-z_][a-z0-9_-]*\.[a-z_][a // const MODEL_ID_PATTERN_PROJECT = /^[a-z_][a-z0-9_]*\.[a-z_][a-z0-9_-]*\.[a-z_][a-z0-9_]*\.model\.kpj$/; // "Content files" within the package should adhere to these pattern: -const CONTENT_FILE_BASENAME_PATTERN = /^[a-z0-9_+.-]+$/; -const CONTENT_FILE_EXTENSION_PATTERN = /^\.[a-z0-9_]+$/; +const CONTENT_FILE_BASENAME_PATTERN = /^[a-z0-9_+.-]+$/i; // base names can be case insensitive +const CONTENT_FILE_EXTENSION_PATTERN = /^\.[a-z0-9_]+$/; // extensions should be lower-case export class PackageValidation { From ed9975ee8148260a30fc45814845bca222765d22 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 28 Jun 2023 06:11:37 +0700 Subject: [PATCH 3/9] fix(developer): handle missing font spec in touch layout file Fixes #9101. --- .../src/kmc-kmn/src/kmw-compiler/validate-layout-file.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 5de2e662f6..162779cda9 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 @@ -217,9 +217,9 @@ export function ValidateLayoutFile(fk: KMX.KEYBOARD, FDebug: boolean, sLayoutFil // Test that the font matches on all platforms // I4872 if(FTouchLayoutFont == '') { - FTouchLayoutFont = platform.font; + FTouchLayoutFont = platform.font ?? ''; } - else if(platform.font.toLowerCase() != FTouchLayoutFont) { + else if(platform.font?.toLowerCase() ?? '' != FTouchLayoutFont) { callbacks.reportMessage(KmwCompilerMessages.Warn_TouchLayoutFontShouldBeSameForAllPlatforms()); // TODO: why support multiple font values if it has to be the same across all platforms?! } From d44e7819eab02f8d3f629037910a3b754571357a Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 28 Jun 2023 06:13:09 +0700 Subject: [PATCH 4/9] fix(developer): TypeError: String.prototype.replaceAll called with a non-global RegExp argument Fixes #9102. --- developer/src/kmc-kmn/src/kmw-compiler/kmw-compiler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a4521b4fdc..65e2dbd13c 100644 --- a/developer/src/kmc-kmn/src/kmw-compiler/kmw-compiler.ts +++ b/developer/src/kmc-kmn/src/kmw-compiler/kmw-compiler.ts @@ -8,7 +8,7 @@ import { VisualKeyboardFromFile } from "./visual-keyboard-compiler.js"; import { CompilerResult, STORETYPE_DEBUG, STORETYPE_OPTION, STORETYPE_RESERVED } from "../compiler/compiler.js"; function requote(s: string): string { - return "'" + s.replaceAll(/(['\\])/, "\\$1") + "'"; + return "'" + s.replaceAll(/(['\\])/g, "\\$1") + "'"; } export function RequotedString(s: string, RequoteSingleQuotes: boolean = false): string { From 1b6769195ea1a5cc538c537a2830b5ce6250cdd1 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 28 Jun 2023 06:13:57 +0700 Subject: [PATCH 5/9] fix(developer): resetopt and saveopt used uninitialized return variable Fixes #9103. --- developer/src/kmc-kmn/src/kmw-compiler/util.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/developer/src/kmc-kmn/src/kmw-compiler/util.ts b/developer/src/kmc-kmn/src/kmw-compiler/util.ts index 21aa9d3c14..1b67b9c719 100644 --- a/developer/src/kmc-kmn/src/kmw-compiler/util.ts +++ b/developer/src/kmc-kmn/src/kmw-compiler/util.ts @@ -142,15 +142,17 @@ export function ExpandSentinel(fk: KMX.KEYBOARD, pwsz: string, x: number): TSent }; break; case KMX.KMXFile.CODE_RESETOPT: // I3429 + const resetOptIdx = pwsz.charCodeAt(x) - 1; result.ResetOpt = { - StoreIndex: pwsz.charCodeAt(x) - 1, - Store: fk.stores[result.ResetOpt.StoreIndex] + StoreIndex: resetOptIdx, + Store: fk.stores[resetOptIdx] }; break; case KMX.KMXFile.CODE_SAVEOPT: // I3429 + const saveOptIdx = pwsz.charCodeAt(x) - 1; result.SaveOpt = { - StoreIndex: pwsz.charCodeAt(x) - 1, - Store: fk.stores[result.SaveOpt.StoreIndex] + StoreIndex: saveOptIdx, + Store: fk.stores[saveOptIdx] }; break; case KMX.KMXFile.CODE_IFOPT: // I3429 From 87c70a286ceda10b9568c7aa2d0e56d37063545f Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 28 Jun 2023 06:15:02 +0700 Subject: [PATCH 6/9] fix(developer): key id and text are optional Fixes #9104. Fixes #9106. --- .../src/kmc-kmn/src/kmw-compiler/validate-layout-file.ts | 6 ++++++ 1 file changed, 6 insertions(+) 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 162779cda9..bb9ebb1cbd 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 @@ -69,6 +69,12 @@ function CheckKey( FRequiredKeys: TRequiredKey[], FDictionary: string[] ): boolean { // I4119 + // + // Coerce missing ID and Text to empty strings for additional tests + // + + FId = FId ?? ''; + FText = FText ?? ''; // // Check that each touch layer has K_LOPT, [K_ROPT,] K_BKSP, K_ENTER From a0313671812e0ad5e6978eea127df9962bd3365b Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 28 Jun 2023 06:16:04 +0700 Subject: [PATCH 7/9] fix(developer): rewrite version object for followKeyboardVersion Fixes #9105. --- .../src/kmc-package/src/compiler/package-version-validation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/developer/src/kmc-package/src/compiler/package-version-validation.ts b/developer/src/kmc-package/src/compiler/package-version-validation.ts index 47e3e39b5c..b4f099ce13 100644 --- a/developer/src/kmc-package/src/compiler/package-version-validation.ts +++ b/developer/src/kmc-package/src/compiler/package-version-validation.ts @@ -73,7 +73,7 @@ export class PackageVersionValidation { if(result) { if(followKeyboardVersion) { - kmp.info.version.description = kmp.keyboards[0].version; + kmp.info.version = {description: kmp.keyboards[0].version}; } else if(kmp.info.version?.description != kmp.keyboards[0].version) { // Only need to compare against first keyboard as we compare keyboards above From 09a204116d81e859a56187a51b0b296a453f2abc Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 28 Jun 2023 06:18:34 +0700 Subject: [PATCH 8/9] fix(developer): ensure errors cancel the build in kmc Fixes #9108. --- developer/src/kmc/src/commands/build.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/developer/src/kmc/src/commands/build.ts b/developer/src/kmc/src/commands/build.ts index c2e550ccc5..0f3fb38200 100644 --- a/developer/src/kmc/src/commands/build.ts +++ b/developer/src/kmc/src/commands/build.ts @@ -4,7 +4,7 @@ import { buildActivities } from './buildClasses/buildActivities.js'; import { BuildProject } from './buildClasses/BuildProject.js'; import { NodeCompilerCallbacks } from '../messages/NodeCompilerCallbacks.js'; import { InfrastructureMessages } from '../messages/messages.js'; -import { CompilerOptions, KeymanFileTypes } from '@keymanapp/common-types'; +import { CompilerErrorSeverity, CompilerOptions, KeymanFileTypes } from '@keymanapp/common-types'; import { BaseOptions } from '../util/baseOptions.js'; @@ -79,8 +79,11 @@ async function build(filename: string, options: CompilerOptions): Promise failureCodes.includes(m.code & CompilerErrorSeverity.Severity_Mask)); + if(result && firstFailureMessage == undefined) { callbacks.reportMessage(InfrastructureMessages.Info_FileBuiltSuccessfully({filename})); } else { callbacks.reportMessage(InfrastructureMessages.Info_FileNotBuiltSuccessfully({filename})); From 60273605442f57725adf1a356968184bd65565e6 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 28 Jun 2023 07:27:42 +0700 Subject: [PATCH 9/9] fix(developer): handle empty File Details in package reader Fixes #9109. --- common/web/types/src/kpj/kpj-file-reader.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/common/web/types/src/kpj/kpj-file-reader.ts b/common/web/types/src/kpj/kpj-file-reader.ts index 21e92c975b..9ac1bc8dbc 100644 --- a/common/web/types/src/kpj/kpj-file-reader.ts +++ b/common/web/types/src/kpj/kpj-file-reader.ts @@ -23,6 +23,12 @@ export class KPJFileReader { }); parser.parseString(file, (e: unknown, r: unknown) => { data = r as KPJFile }); + for(let 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; + } + } data = this.boxArrays(data); return data as KPJFile; }