diff --git a/common/web/types/package.json b/common/web/types/package.json index 4cff8739a58..66083ac8e29 100644 --- a/common/web/types/package.json +++ b/common/web/types/package.json @@ -28,7 +28,7 @@ "dependencies": { "@keymanapp/keyman-version": "*", "ajv": "^8.11.0", - "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#49d129cf0916d082a7278bb09296fb89cecfcc50", + "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#7a188a1e26f8f36a175d95b67ffece8702363dfc", "semver": "^7.3.7", "xml2js": "git+https://github.com/keymanapp/dependency-node-xml2js#535fe732dc408d697e0f847c944cc45f0baf0829" }, diff --git a/common/web/types/src/kmx/kmx-file-reader.ts b/common/web/types/src/kmx/kmx-file-reader.ts index 45131ade770..57f58751d1d 100644 --- a/common/web/types/src/kmx/kmx-file-reader.ts +++ b/common/web/types/src/kmx/kmx-file-reader.ts @@ -1,5 +1,10 @@ import { KMXFile, BUILDER_COMP_KEYBOARD, KEYBOARD, STORE, GROUP, KEY } from "./kmx.js"; import * as r from 'restructure'; +import { KeymanTypesError } from "../util/errors.js"; + +export class KmxFileReaderError extends KeymanTypesError { + +} export class KmxFileReader { private readonly rString = new r.String(null, 'utf16le'); @@ -13,7 +18,17 @@ export class KmxFileReader { return this.rString.fromBuffer(source.slice(offset)); } - private processSystemStore(store: STORE, result: KEYBOARD) { + private isValidCodeUse(s: string, keyboard: KEYBOARD): boolean { + return ( + s.length == 3 && + s.charCodeAt(0) == KMXFile.UC_SENTINEL && + s.charCodeAt(1) == KMXFile.CODE_USE && + s.charCodeAt(2) > 0 && + s.charCodeAt(2) <= keyboard.groups.length + ); + } + + private processSystemStore(store: STORE, result: KEYBOARD): void { switch(store.dwSystemID) { case KMXFile.TSS_MNEMONIC: result.isMnemonic = store.dpString == '1'; @@ -22,25 +37,18 @@ export class KmxFileReader { result.keyboardVersion = store.dpString; break; case KMXFile.TSS_BEGIN_NEWCONTEXT: - if(store.dpString.length == 3 && store.dpString.charCodeAt(0) == 0xFFFF && store.dpString.charCodeAt(1) == KMXFile.CODE_USE) { - result.startGroup.newContext = store.dpString.charCodeAt(2) - 1; - } - else { - // TODO: error - return false; + if(!this.isValidCodeUse(store.dpString, result)) { + throw new KmxFileReaderError(`Invalid TSS_BEGIN_NEWCONTEXT system store`); } + result.startGroup.newContext = store.dpString.charCodeAt(2) - 1; break; case KMXFile.TSS_BEGIN_POSTKEYSTROKE: - if(store.dpString.length == 3 && store.dpString.charCodeAt(0) == 0xFFFF && store.dpString.charCodeAt(1) == KMXFile.CODE_USE) { - result.startGroup.postKeystroke = store.dpString.charCodeAt(2) - 1; - } - else { - // TODO: error - return false; + if(!this.isValidCodeUse(store.dpString, result)) { + throw new KmxFileReaderError(`Invalid TSS_BEGIN_POSTKEYSTROKE system store`); } + result.startGroup.postKeystroke = store.dpString.charCodeAt(2) - 1; break; } - return true; } public read(source: Uint8Array): KEYBOARD { @@ -48,8 +56,7 @@ export class KmxFileReader { let kmx = new KMXFile(); binaryKeyboard = kmx.COMP_KEYBOARD.fromBuffer(source); if(binaryKeyboard.dwIdentifier != KMXFile.FILEID_COMPILED) { - // TODO: error - return null; + throw new KmxFileReaderError(`Not a .kmx file: header does not contain FILEID_COMPILED`); } let result = new KEYBOARD(); @@ -59,32 +66,39 @@ export class KmxFileReader { result.startGroup = { ansi: binaryKeyboard.StartGroup_ANSI == 0xFFFFFFFF ? -1 : binaryKeyboard.StartGroup_ANSI, unicode: binaryKeyboard.StartGroup_Unicode == 0xFFFFFFFF ? -1 : binaryKeyboard.StartGroup_Unicode, - newContext: -1, //TODO - postKeystroke: -1 // TODO + newContext: -1, + postKeystroke: -1 } // Informative data + result.keyboardVersion = ''; result.isMnemonic = false; - let offset = binaryKeyboard.dpStoreArray; - for(let i = 0; i < binaryKeyboard.cxStoreArray; i++) { - let binaryStore = kmx.COMP_STORE.fromBuffer(source.slice(offset)); - let store = new STORE(); - store.dwSystemID = binaryStore.dwSystemID; - store.dpName = this.readString(source, binaryStore.dpName); - store.dpString = this.readString(source, binaryStore.dpString); - result.stores.push(store); + this.readStores(binaryKeyboard, kmx, source, result); + this.readGroupsAndRules(binaryKeyboard, kmx, source, result); - if(!this.processSystemStore(store, result)) { - return null; - } + // Process system stores once we have all stores and groups loaded + for(let store of result.stores) { + this.processSystemStore(store, result); + } - offset += KMXFile.COMP_STORE_SIZE; + // TODO: KMXPlusFile + + // Validate startGroup offsets + let gp: keyof KEYBOARD['startGroup']; + for(gp in result.startGroup) { + if(result.startGroup[gp] < -1 || result.startGroup[gp] >= result.groups.length) { + throw new KmxFileReaderError(`Invalid begin group reference`); + } } - offset = binaryKeyboard.dpGroupArray; - for(let i = 0; i < binaryKeyboard.cxGroupArray; i++) { + return result; + } + + private readGroupsAndRules(binaryKeyboard: BUILDER_COMP_KEYBOARD, kmx: KMXFile, source: Uint8Array, result: KEYBOARD) { + let offset = binaryKeyboard.dpGroupArray; + for (let i = 0; i < binaryKeyboard.cxGroupArray; i++) { let binaryGroup = kmx.COMP_GROUP.fromBuffer(source.slice(offset)); let group = new GROUP(); group.dpMatch = this.readString(source, binaryGroup.dpMatch); @@ -94,7 +108,7 @@ export class KmxFileReader { group.keys = []; let keyOffset = binaryGroup.dpKeyArray; - for(let j = 0; j < binaryGroup.cxKeyArray; j++) { + for (let j = 0; j < binaryGroup.cxKeyArray; j++) { let binaryKey = kmx.COMP_KEY.fromBuffer(source.slice(keyOffset)); let key = new KEY(); key.Key = binaryKey.Key; @@ -109,18 +123,18 @@ export class KmxFileReader { result.groups.push(group); offset += KMXFile.COMP_GROUP_SIZE; } + } - // TODO: KMXPlusFile - - // Validate startGroup offsets - let gp: keyof KEYBOARD['startGroup']; - for(gp in result.startGroup) { - if(result.startGroup[gp] < -1 || result.startGroup[gp] >= result.groups.length) { - // TODO: error - return null; - } + private readStores(binaryKeyboard: BUILDER_COMP_KEYBOARD, kmx: KMXFile, source: Uint8Array, result: KEYBOARD): void { + let offset = binaryKeyboard.dpStoreArray; + for (let i = 0; i < binaryKeyboard.cxStoreArray; i++) { + let binaryStore = kmx.COMP_STORE.fromBuffer(source.slice(offset)); + let store = new STORE(); + store.dwSystemID = binaryStore.dwSystemID; + store.dpName = this.readString(source, binaryStore.dpName); + store.dpString = this.readString(source, binaryStore.dpString); + result.stores.push(store); + offset += KMXFile.COMP_STORE_SIZE; } - - return result; } }; \ No newline at end of file diff --git a/common/web/types/src/main.ts b/common/web/types/src/main.ts index ddaa318d3e0..ad161d1a1bf 100644 --- a/common/web/types/src/main.ts +++ b/common/web/types/src/main.ts @@ -2,7 +2,7 @@ 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 } from './kmx/kmx-file-reader.js'; +export { KmxFileReader, KmxFileReaderError } from './kmx/kmx-file-reader.js'; export * as VisualKeyboard from './kvk/visual-keyboard.js'; export { default as KMXPlusBuilder} from './kmx/kmx-plus-builder/kmx-plus-builder.js'; @@ -18,7 +18,7 @@ export { LDMLKeyboardXMLSourceFileReader, LDMLKeyboardXMLSourceFileReaderOptions export * as Constants from './consts/virtual-key-constants.js'; -export { CompilerCallbacks, CompilerSchema, CompilerEvent, CompilerErrorNamespace, CompilerErrorSeverity, CompilerPathCallbacks, CompilerFileSystemCallbacks, CompilerMessageSpec, compilerErrorSeverityName, compilerExceptionToString, compilerErrorFormatCode } from './util/compiler-interfaces.js'; +export { CompilerCallbacks, CompilerOptions, CompilerSchema, CompilerEvent, CompilerErrorNamespace, CompilerErrorSeverity, CompilerPathCallbacks, CompilerFileSystemCallbacks, CompilerMessageSpec, compilerErrorSeverityName, compilerExceptionToString, compilerErrorFormatCode } from './util/compiler-interfaces.js'; export { CommonTypesMessages } from './util/common-events.js'; export * as TouchLayout from './keyman-touch-layout/keyman-touch-layout-file.js'; diff --git a/common/web/types/src/util/compiler-interfaces.ts b/common/web/types/src/util/compiler-interfaces.ts index d3932b7bfa8..5486c3794e6 100644 --- a/common/web/types/src/util/compiler-interfaces.ts +++ b/common/web/types/src/util/compiler-interfaces.ts @@ -141,6 +141,16 @@ export interface CompilerCallbacks { debug(msg: string): void; }; +/** + * Abstract interface for compiler options + */ +export interface CompilerOptions { + shouldAddCompilerVersion?: boolean; + saveDebug?: boolean; + compilerWarningsAsErrors?: boolean; + warnDeprecatedCode?: boolean; +}; + /** * Convenience function for constructing CompilerEvents * @param code diff --git a/common/web/types/src/util/errors.ts b/common/web/types/src/util/errors.ts new file mode 100644 index 00000000000..b4b35af32f4 --- /dev/null +++ b/common/web/types/src/util/errors.ts @@ -0,0 +1,6 @@ +/** + * Base class for all common/web/types errors thrown + */ +export class KeymanTypesError extends Error { + +} \ No newline at end of file diff --git a/developer/src/kmc-kmn/src/compiler/compiler.ts b/developer/src/kmc-kmn/src/compiler/compiler.ts index 5e910ff45b8..6684f0b457a 100644 --- a/developer/src/kmc-kmn/src/compiler/compiler.ts +++ b/developer/src/kmc-kmn/src/compiler/compiler.ts @@ -6,7 +6,7 @@ TODO: implement additional interfaces: */ // TODO: rename wasm-host? -import { CompilerCallbacks, CompilerEvent, KvkFileWriter, KvksFileReader } from '@keymanapp/common-types'; +import { CompilerCallbacks, CompilerEvent, CompilerOptions, KvkFileWriter, KvksFileReader } from '@keymanapp/common-types'; import loadWasmHost from '../import/kmcmplib/wasm-host.js'; import { CompilerMessages, mapErrorFromKmcmplib } from './messages.js'; @@ -21,15 +21,11 @@ export interface CompilerResult { js?: CompilerResultFile; }; -export interface CompilerOptions { - shouldAddCompilerVersion?: boolean; - saveDebug?: boolean; - compilerWarningsAsErrors?: boolean; - warnDeprecatedCode?: boolean; +export interface KmnCompilerOptions extends CompilerOptions { target?: 'kmx' | 'js'; }; -const baseOptions: CompilerOptions = { +const baseOptions: KmnCompilerOptions = { shouldAddCompilerVersion: true, saveDebug: true, compilerWarningsAsErrors: false, @@ -90,7 +86,7 @@ export class KmnCompiler { return true; } - public run(infile: string, outfile: string, options?: CompilerOptions): boolean { + public run(infile: string, outfile: string, options?: KmnCompilerOptions): boolean { let result = this.runCompiler(infile, outfile, options); if(result) { if(result.kmx) { @@ -146,7 +142,7 @@ export class KmnCompiler { return 1; } - public runCompiler(infile: string, outfile: string, options: CompilerOptions): CompilerResult { + public runCompiler(infile: string, outfile: string, options: KmnCompilerOptions): CompilerResult { if(!this.verifyInitialized()) { /* c8 ignore next 2 */ return null; diff --git a/developer/src/kmc-kmw/package.json b/developer/src/kmc-kmw/package.json index c1494fb1392..5fdfd3297dd 100644 --- a/developer/src/kmc-kmw/package.json +++ b/developer/src/kmc-kmw/package.json @@ -24,9 +24,10 @@ }, "dependencies": { "@keymanapp/common-types": "*", + "@keymanapp/keyman-version": "*", "@keymanapp/kmc-kmn": "*", "ajv": "^8.11.0", - "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#49d129cf0916d082a7278bb09296fb89cecfcc50", + "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#7a188a1e26f8f36a175d95b67ffece8702363dfc", "semver": "^7.3.7", "xml2js": "git+https://github.com/keymanapp/dependency-node-xml2js#535fe732dc408d697e0f847c944cc45f0baf0829" }, diff --git a/developer/src/kmc-kmw/src/compiler/callbacks.ts b/developer/src/kmc-kmw/src/compiler/callbacks.ts deleted file mode 100644 index bdc7a174642..00000000000 --- a/developer/src/kmc-kmw/src/compiler/callbacks.ts +++ /dev/null @@ -1,14 +0,0 @@ -export interface CompilerEvent { - line: number; - code: number; - message: string; -}; - -export default interface CompilerCallbacks { - loadFile(baseFilename: string, filename: string): Buffer; - loadLdmlKeyboardSchema(): Buffer; - loadKvksJsonSchema(): Buffer; - reportMessage(event: CompilerEvent): void; -}; - -// TODO: eliminate this \ No newline at end of file diff --git a/developer/src/kmc-kmw/src/compiler/compiler-globals.ts b/developer/src/kmc-kmw/src/compiler/compiler-globals.ts index bb4874a5590..167015b0d41 100644 --- a/developer/src/kmc-kmw/src/compiler/compiler-globals.ts +++ b/developer/src/kmc-kmw/src/compiler/compiler-globals.ts @@ -1,5 +1,4 @@ -import { KMX, CompilerCallbacks } from "@keymanapp/common-types"; -import CompilerOptions from "./compiler-options.js"; +import { KMX, CompilerCallbacks, CompilerOptions } from "@keymanapp/common-types"; export let FTabStop: string; export let nl: string; diff --git a/developer/src/kmc-kmw/src/compiler/compiler-options.ts b/developer/src/kmc-kmw/src/compiler/compiler-options.ts deleted file mode 100644 index bcb99c5d433..00000000000 --- a/developer/src/kmc-kmw/src/compiler/compiler-options.ts +++ /dev/null @@ -1,15 +0,0 @@ - - -export default interface CompilerOptions { - /** - * Add debug information to the .kmx file when compiling - */ - debug: boolean; - - /** - * Add metadata about the compiler version to .kmx file when compiling - */ - addCompilerVersion: boolean; -}; - -// TODO: we have a shared CompilerOptions intf, eliminate this \ No newline at end of file diff --git a/developer/src/kmc-kmw/src/compiler/javascript-strings.ts b/developer/src/kmc-kmw/src/compiler/javascript-strings.ts index 731e8377678..dc4d802709f 100644 --- a/developer/src/kmc-kmw/src/compiler/javascript-strings.ts +++ b/developer/src/kmc-kmw/src/compiler/javascript-strings.ts @@ -15,7 +15,7 @@ export function JavaScript_Name(i: number, pwszName: string, KeepNameForPersiste let FChanged: boolean = false; let p = pwszName; - if((pwszName == null || pwszName == undefined || pwszName == '') || (!options.debug && !KeepNameForPersistentStorage)) { // I3659 // I3681 + if((pwszName == null || pwszName == undefined || pwszName == '') || (!options.saveDebug && !KeepNameForPersistentStorage)) { // I3659 // I3681 return i.toString(10); // for uniqueness } else { @@ -135,7 +135,7 @@ function JavaScript_Rule(FTabStops: string, FElse: string, fk: KMX.KEYBOARD, fgp let predicate: string = '1', linecomment: string = '', FIndent: string; let result = ''; - if(fkp.Line > 0 && options.debug) { // I4384 + if(fkp.Line > 0 && options.saveDebug) { // I4384 linecomment = ' // Line '+fkp.Line.toString(); // I4373 } @@ -315,7 +315,7 @@ export function JavaScript_Shift(fkp: KMX.KEY, FMnemonic: boolean): number { * '16656' */ export function JavaScript_ShiftAsString(fkp: KMX.KEY, FMnemonic: boolean): string { - if(!options.debug) { + if(!options.saveDebug) { return JavaScript_Shift(fkp, FMnemonic).toString(); } return ' '+FormatModifierAsBitflags(JavaScript_Shift(fkp, FMnemonic)); @@ -719,7 +719,7 @@ export function JavaScript_Key(fkp: KMX.KEY, FMnemonic: boolean): number { /// @return string representation of the key value, e.g. 'keyCodes.K_A /* 0x41 */' or '65' /// export function JavaScript_KeyAsString(fkp: KMX.KEY, FMnemonic: boolean): string { - if(options.debug) { + if(options.saveDebug) { return ' '+FormatKeyAsString(JavaScript_Key(fkp, FMnemonic)); } else { return JavaScript_Key(fkp, FMnemonic).toString(); diff --git a/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts b/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts index 082c7a1881d..2f4b3e28504 100644 --- a/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts +++ b/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts @@ -1,9 +1,6 @@ -import { VisualKeyboard } from "@keymanapp/common-types"; -import { KMX, CompilerCallbacks, KvkFileReader, KvksFileReader } from "@keymanapp/common-types"; +import { KMX, CompilerOptions, CompilerCallbacks, KvkFileReader, KvksFileReader, VisualKeyboard } from "@keymanapp/common-types"; import { ExpandSentinel, incxstr, xstrlen } from "../util/util.js"; -// import { KEY, KEYBOARD, KMX.KMXFile, STORE } from "../../../../../common/web/types/src/kmx/kmx.js"; import { options, nl, FTabStop, setupGlobals, IsKeyboardVersion10OrLater } from "./compiler-globals.js"; -import CompilerOptions from "./compiler-options.js"; import { JavaScript_ContextMatch, JavaScript_KeyAsString, JavaScript_Name, JavaScript_OutputString, JavaScript_Rules, JavaScript_Shift, JavaScript_ShiftAsString, JavaScript_Store, zeroPadHex } from './javascript-strings.js'; import { CERR_InvalidBegin, CWARN_DontMixChiralAndNonChiralModifiers, ReportError } from "./messages.js"; import { ValidateLayoutFile } from "./validate-layout-file.js"; @@ -40,8 +37,8 @@ export function RequotedString(s: string, RequoteSingleQuotes: boolean = false): export function WriteCompiledKeyboard(callbacks: CompilerCallbacks, kmnfile: string, kmxfile: string, name: string, keyboard: KMX.KEYBOARD, FDebug: boolean = false): string { let opts: CompilerOptions = { - addCompilerVersion: false, - debug: FDebug + shouldAddCompilerVersion: false, + saveDebug: FDebug }; setupGlobals(callbacks, opts, FDebug?' ':'', FDebug?'\r\n':'', keyboard); @@ -177,7 +174,7 @@ export function WriteCompiledKeyboard(callbacks: CompilerCallbacks, kmnfile: str if (sLayoutFile != '') { // I3483 let path = callbacks.resolveFilename(kmnfile, sLayoutFile); - let result = ValidateLayoutFile(keyboard, options.debug, path, sVKDictionary); + let result = ValidateLayoutFile(keyboard, options.saveDebug, path, sVKDictionary); if(!result.result) { sLayoutFile = ''; // TODO: error @@ -213,7 +210,7 @@ export function WriteCompiledKeyboard(callbacks: CompilerCallbacks, kmnfile: str kvk = reader.read(callbacks.loadFile(path)); } - let result = VisualKeyboardFromFile(kvk, options.debug); + let result = VisualKeyboardFromFile(kvk, options.saveDebug); if(!result.result) { // TODO: error sVisualKeyboard = 'null'; @@ -478,7 +475,7 @@ function GetKeyboardModifierBitmask(keyboard: KMX.KEYBOARD, fMnemonic: boolean): ReportError(0, CWARN_DontMixChiralAndNonChiralModifiers, 'This keyboard contains Ctrl,Alt and LCtrl,LAlt,RCtrl,RAlt sets of modifiers. Use only one or the other set for web target.'); } - if(options.debug) { + if(options.saveDebug) { return FormatModifierAsBitflags(bitMask & KMX.KMXFile.MASK_KEYS); // Exclude KMX_ISVIRTUALKEY, KMX_VIRTUALCHARKEY } @@ -494,7 +491,7 @@ function GetKeyboardModifierBitmask(keyboard: KMX.KEYBOARD, fMnemonic: boolean): /// function JavaScript_SetupDebug() { if(IsKeyboardVersion10OrLater()) { - if(options.debug) { + if(options.saveDebug) { return 'var modCodes = keyman.osk.modifierCodes;'+nl+ FTabStop+'var keyCodes = keyman.osk.keyCodes;'+nl; } diff --git a/developer/src/kmc-kmw/test/fixtures/.gitignore b/developer/src/kmc-kmw/test/fixtures/.gitignore new file mode 100644 index 00000000000..1d79c8e24b8 --- /dev/null +++ b/developer/src/kmc-kmw/test/fixtures/.gitignore @@ -0,0 +1,7 @@ +# Files generated during unit tests that do not need to be committed but are +# kept around for comparison if needed +khmer_angkor.js.strip.js +khmer_angkor.kmx +khmer_angkor.kvk +khmer_angkor.test.js +khmer_angkor.test.js.strip.js \ No newline at end of file diff --git a/developer/src/kmc-ldml/package.json b/developer/src/kmc-ldml/package.json index fda0b44272a..7bc61836cc1 100644 --- a/developer/src/kmc-ldml/package.json +++ b/developer/src/kmc-ldml/package.json @@ -29,7 +29,7 @@ "@keymanapp/keyman-version": "*", "@keymanapp/ldml-keyboard-constants": "*", "ajv": "^8.11.0", - "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#49d129cf0916d082a7278bb09296fb89cecfcc50", + "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#7a188a1e26f8f36a175d95b67ffece8702363dfc", "semver": "^7.3.7", "xml2js": "git+https://github.com/keymanapp/dependency-node-xml2js#535fe732dc408d697e0f847c944cc45f0baf0829" }, diff --git a/developer/src/kmc-ldml/src/compiler/compiler-options.ts b/developer/src/kmc-ldml/src/compiler/compiler-options.ts index da81ef2f7d5..8b461484414 100644 --- a/developer/src/kmc-ldml/src/compiler/compiler-options.ts +++ b/developer/src/kmc-ldml/src/compiler/compiler-options.ts @@ -1,5 +1,6 @@ import { LDMLKeyboardXMLSourceFileReaderOptions } from "@keymanapp/common-types"; +// TODO: inherit from common-types CompilerOptions, noting alternate names for debug and addCompilerVersion! export interface CompilerOptions { /** * Add debug information to the .kmx file when compiling diff --git a/developer/src/kmc-package/src/compiler/messages.ts b/developer/src/kmc-package/src/compiler/messages.ts index 56727fea9bf..f47d0d38c6f 100644 --- a/developer/src/kmc-package/src/compiler/messages.ts +++ b/developer/src/kmc-package/src/compiler/messages.ts @@ -39,8 +39,8 @@ export class CompilerMessages { `Keyboard ${o.id} was listed in but a corresponding .kmx file was not found in `); static ERROR_KeyboardContentFileNotFound = SevError | 0x0008; - static Error_KeyboardFileNotValid = (o:{filename:string}) => m(this.ERROR_KeyboardFileNotValid, - `Keyboard file ${o.filename} is not a valid .kmx file`); + static Error_KeyboardFileNotValid = (o:{filename:string, e:any}) => m(this.ERROR_KeyboardFileNotValid, + `Keyboard file ${o.filename} is not a valid .kmx file: ${(o.e ?? 'unknown error').toString()}`); static ERROR_KeyboardFileNotValid = SevError | 0x0009; static Info_KeyboardFileHasNoKeyboardVersion = (o:{filename:string}) => m(this.INFO_KeyboardFileHasNoKeyboardVersion, 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 4f8ad4a41c1..5762f15ada1 100644 --- a/developer/src/kmc-package/src/compiler/package-version-validation.ts +++ b/developer/src/kmc-package/src/compiler/package-version-validation.ts @@ -1,4 +1,4 @@ -import { KmpJsonFile, CompilerCallbacks, KpsFile, KmxFileReader, KMX } from '@keymanapp/common-types'; +import { KmpJsonFile, CompilerCallbacks, KpsFile, KmxFileReader, KmxFileReaderError, KMX } from '@keymanapp/common-types'; import { KeymanTarget, TouchKeymanTargets } from './keyman-targets.js'; import { CompilerMessages } from './messages.js'; @@ -132,11 +132,18 @@ export class PackageVersionValidation { return null; } const kmxReader: KmxFileReader = new KmxFileReader(); - const kmx: KMX.KEYBOARD = kmxReader.read(kmxFileData); - if(!kmx) { - // The file couldn't be read, it might not be a .kmx file - this.callbacks.reportMessage(CompilerMessages.Error_KeyboardFileNotValid({filename})); - return null; + let kmx: KMX.KEYBOARD; + try { + kmx = kmxReader.read(kmxFileData); + } catch(e) { + if(e instanceof KmxFileReaderError) { + // The file couldn't be read, it might not be a .kmx file + this.callbacks.reportMessage(CompilerMessages.Error_KeyboardFileNotValid({filename, e})); + return null; + } else { + // Unknown error, bubble it up + throw e; + } } return kmx; diff --git a/developer/src/kmc/src/commands/build.ts b/developer/src/kmc/src/commands/build.ts index f21356577c2..d3f65b153df 100644 --- a/developer/src/kmc/src/commands/build.ts +++ b/developer/src/kmc/src/commands/build.ts @@ -1,8 +1,8 @@ import * as fs from 'fs'; import { Command } from 'commander'; -import { BuildActivityOptions } from './build/BuildActivity.js'; -import { buildActivities } from './build/buildActivities.js'; -import { BuildProject, PROJECT_EXTENSION } from './build/BuildProject.js'; +import { BuildActivityOptions } from './buildClasses/BuildActivity.js'; +import { buildActivities } from './buildClasses/buildActivities.js'; +import { BuildProject, PROJECT_EXTENSION } from './buildClasses/BuildProject.js'; import { NodeCompilerCallbacks } from '../messages/NodeCompilerCallbacks.js'; import { InfrastructureMessages } from '../messages/messages.js'; diff --git a/developer/src/kmc/src/commands/build/BuildActivity.ts b/developer/src/kmc/src/commands/buildClasses/BuildActivity.ts similarity index 100% rename from developer/src/kmc/src/commands/build/BuildActivity.ts rename to developer/src/kmc/src/commands/buildClasses/BuildActivity.ts diff --git a/developer/src/kmc/src/commands/build/BuildKmnKeyboard.ts b/developer/src/kmc/src/commands/buildClasses/BuildKmnKeyboard.ts similarity index 100% rename from developer/src/kmc/src/commands/build/BuildKmnKeyboard.ts rename to developer/src/kmc/src/commands/buildClasses/BuildKmnKeyboard.ts diff --git a/developer/src/kmc/src/commands/build/BuildLdmlKeyboard.ts b/developer/src/kmc/src/commands/buildClasses/BuildLdmlKeyboard.ts similarity index 100% rename from developer/src/kmc/src/commands/build/BuildLdmlKeyboard.ts rename to developer/src/kmc/src/commands/buildClasses/BuildLdmlKeyboard.ts diff --git a/developer/src/kmc/src/commands/build/BuildModel.ts b/developer/src/kmc/src/commands/buildClasses/BuildModel.ts similarity index 100% rename from developer/src/kmc/src/commands/build/BuildModel.ts rename to developer/src/kmc/src/commands/buildClasses/BuildModel.ts diff --git a/developer/src/kmc/src/commands/build/BuildPackage.ts b/developer/src/kmc/src/commands/buildClasses/BuildPackage.ts similarity index 100% rename from developer/src/kmc/src/commands/build/BuildPackage.ts rename to developer/src/kmc/src/commands/buildClasses/BuildPackage.ts diff --git a/developer/src/kmc/src/commands/build/BuildProject.ts b/developer/src/kmc/src/commands/buildClasses/BuildProject.ts similarity index 100% rename from developer/src/kmc/src/commands/build/BuildProject.ts rename to developer/src/kmc/src/commands/buildClasses/BuildProject.ts diff --git a/developer/src/kmc/src/commands/build/buildActivities.ts b/developer/src/kmc/src/commands/buildClasses/buildActivities.ts similarity index 100% rename from developer/src/kmc/src/commands/build/buildActivities.ts rename to developer/src/kmc/src/commands/buildClasses/buildActivities.ts diff --git a/developer/src/kmc/test/test-project-build.ts b/developer/src/kmc/test/test-project-build.ts index e16c9fd464d..84a10e4a46d 100644 --- a/developer/src/kmc/test/test-project-build.ts +++ b/developer/src/kmc/test/test-project-build.ts @@ -1,7 +1,7 @@ import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers'; import { assert } from 'chai'; import 'mocha'; -import { BuildProject } from '../src/commands/build/BuildProject.js'; +import { BuildProject } from '../src/commands/buildClasses/BuildProject.js'; import { makePathToFixture } from './helpers/index.js'; const callbacks = new TestCompilerCallbacks(); diff --git a/package-lock.json b/package-lock.json index fbd15530d66..0f3efc0fc91 100644 --- a/package-lock.json +++ b/package-lock.json @@ -322,7 +322,7 @@ "dependencies": { "@keymanapp/keyman-version": "*", "ajv": "^8.11.0", - "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#49d129cf0916d082a7278bb09296fb89cecfcc50", + "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#7a188a1e26f8f36a175d95b67ffece8702363dfc", "semver": "^7.3.7", "xml2js": "git+https://github.com/keymanapp/dependency-node-xml2js#535fe732dc408d697e0f847c944cc45f0baf0829" }, @@ -503,6 +503,12 @@ "dev": true, "license": "MIT" }, + "common/web/types/node_modules/restructure": { + "version": "3.0.0", + "resolved": "git+ssh://git@github.com/keymanapp/dependency-restructure.git#7a188a1e26f8f36a175d95b67ffece8702363dfc", + "integrity": "sha512-TxgE+TFgblOfmvJyv9TCzABfDo4nvNHeYD0+awQ5UoE/KhSuENJ1Uhc1rtegx8SbmvI3nqXFaHgnVATNcCOhXw==", + "license": "MIT" + }, "common/web/types/node_modules/supports-color": { "version": "5.5.0", "dev": true, @@ -1036,9 +1042,10 @@ "license": "MIT", "dependencies": { "@keymanapp/common-types": "*", + "@keymanapp/keyman-version": "*", "@keymanapp/kmc-kmn": "*", "ajv": "^8.11.0", - "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#49d129cf0916d082a7278bb09296fb89cecfcc50", + "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#7a188a1e26f8f36a175d95b67ffece8702363dfc", "semver": "^7.3.7", "xml2js": "git+https://github.com/keymanapp/dependency-node-xml2js#535fe732dc408d697e0f847c944cc45f0baf0829" }, @@ -1230,6 +1237,12 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "developer/src/kmc-kmw/node_modules/restructure": { + "version": "3.0.0", + "resolved": "git+ssh://git@github.com/keymanapp/dependency-restructure.git#7a188a1e26f8f36a175d95b67ffece8702363dfc", + "integrity": "sha512-TxgE+TFgblOfmvJyv9TCzABfDo4nvNHeYD0+awQ5UoE/KhSuENJ1Uhc1rtegx8SbmvI3nqXFaHgnVATNcCOhXw==", + "license": "MIT" + }, "developer/src/kmc-kmw/node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -1293,7 +1306,7 @@ "@keymanapp/keyman-version": "*", "@keymanapp/ldml-keyboard-constants": "*", "ajv": "^8.11.0", - "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#49d129cf0916d082a7278bb09296fb89cecfcc50", + "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#7a188a1e26f8f36a175d95b67ffece8702363dfc", "semver": "^7.3.7", "xml2js": "git+https://github.com/keymanapp/dependency-node-xml2js#535fe732dc408d697e0f847c944cc45f0baf0829" }, @@ -1486,6 +1499,12 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "developer/src/kmc-ldml/node_modules/restructure": { + "version": "3.0.0", + "resolved": "git+ssh://git@github.com/keymanapp/dependency-restructure.git#7a188a1e26f8f36a175d95b67ffece8702363dfc", + "integrity": "sha512-TxgE+TFgblOfmvJyv9TCzABfDo4nvNHeYD0+awQ5UoE/KhSuENJ1Uhc1rtegx8SbmvI3nqXFaHgnVATNcCOhXw==", + "license": "MIT" + }, "developer/src/kmc-ldml/node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -6483,6 +6502,7 @@ "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": [ @@ -9136,12 +9156,6 @@ "lowercase-keys": "^2.0.0" } }, - "node_modules/restructure": { - "version": "3.0.0", - "resolved": "git+ssh://git@github.com/keymanapp/dependency-restructure.git#49d129cf0916d082a7278bb09296fb89cecfcc50", - "integrity": "sha512-2vBFOLc0+dkUb3Pnpl87o+B4SIc3MAm3P8PXT8YFkP51URFGsgTgm3gAnwTX2jXSEd/5eT9n7C733loG6OaVgw==", - "license": "MIT" - }, "node_modules/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",