Merge pull request #9116 from keymanapp/fix/developer/various-kmc-kmw-bugs

fix(developer): various bugs in kmc and related packages 🗜
This commit is contained in:
Marc Durdin 2023-06-30 12:02:19 +10:00 • committed by GitHub
commit 88eaab55af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 33 additions and 16 deletions

View file

@ -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 <Details/> 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;
}

View file

@ -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 {

View file

@ -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

View file

@ -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
@ -101,7 +107,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 +128,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 +145,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 +167,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) {
@ -217,9 +223,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?!
}

View file

@ -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 {

View file

@ -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

View file

@ -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<boolea
}
}
const failureCodes = [CompilerErrorSeverity.Fatal, CompilerErrorSeverity.Error];
// TODO: #9100: .concat(options.compilerWarningsAsErrors ? [CompilerErrorSeverity.Warn] : []);
let result = await builder.build(filename, callbacks, options);
if(result) {
const firstFailureMessage = callbacks.messages.find(m => failureCodes.includes(m.code & CompilerErrorSeverity.Severity_Mask));
if(result && firstFailureMessage == undefined) {
callbacks.reportMessage(InfrastructureMessages.Info_FileBuiltSuccessfully({filename}));
} else {
callbacks.reportMessage(InfrastructureMessages.Info_FileNotBuiltSuccessfully({filename}));