diff --git a/developer/src/kmc-convert/src/converter-messages.ts b/developer/src/kmc-convert/src/converter-messages.ts index 1d8aa5e70b..115315cc03 100644 --- a/developer/src/kmc-convert/src/converter-messages.ts +++ b/developer/src/kmc-convert/src/converter-messages.ts @@ -25,41 +25,40 @@ export class ConverterMessages { static ERROR_NoConverterFound = SevError | 0x0002; static Error_NoConverterFound = (o: { inputFilename: string, outputFilename: string; }) => m( this.ERROR_NoConverterFound, - `No converter is available that can convert from '${def(o.inputFilename)}' to '${def(o.outputFilename)}'.` + `No converter is available that can convert from '${def(o.inputFilename)}' to '${def(o.outputFilename)}'.`, ); static ERROR_FileNotFound = SevError | 0x0003; static Error_FileNotFound = (o: { inputFilename: string; }) => m( - this.ERROR_FileNotFound, `Input filename '${def(o.inputFilename)} - ' does not exist or could not be loaded.` + this.ERROR_FileNotFound, + `Input filename '${def(o.inputFilename)} ' does not exist or could not be loaded.`, ); static ERROR_UnableToRead = SevError | 0x0004; static Error_UnableToRead = (o: { inputFilename: string; }) => m( - this.ERROR_UnableToRead, `Input file '${def(o.inputFilename)} - ' could not be read.` + this.ERROR_UnableToRead, + `Input file '${def(o.inputFilename)} ' could not be read.`, ); static ERROR_UnableToConvert = SevError | 0x0005; static Error_UnableToConvert = (o: { inputFilename: string; }) => m( - this.ERROR_UnableToConvert, `Input file '${def(o.inputFilename)} - ' could not be converted.` + this.ERROR_UnableToConvert, + `Input file '${def(o.inputFilename)} ' could not be converted.`, ); static ERROR_UnableToWrite = SevError | 0x0006; static Error_UnableToWrite = (o: { outputFilename: string; }) => m( - this.ERROR_UnableToWrite, `Output file for '${def(o.outputFilename)} - ' could not be written.` + this.ERROR_UnableToWrite, + `Output file for '${def(o.outputFilename)} ' could not be written.`, ); static ERROR_UnsupportedCharactersDetected = SevError | 0x0007; static Error_UnsupportedCharactersDetected = (o: { inputFilename: string, keymap_index: string, key: string, output: string; }) => m( - this.ERROR_UnsupportedCharactersDetected, `Input file ${def(o.inputFilename)} contains unsupported character ('${def(o.output)}') on key (${def(o.key)}) at keyMap index ${def(o.keymap_index)}` + this.ERROR_UnsupportedCharactersDetected, + `Input file ${def(o.inputFilename)} contains unsupported character ('${def(o.output)}') on key ( ${def(o.key)}) at keyMap index ${def(o.keymap_index)}`, ); static ERROR_InvalidFile = SevError | 0x0008; static Error_InvalidFile = (o: { errorText: string; }) => m( - this.ERROR_InvalidFile, `The source file has an invalid structure: ${def(o.errorText)}` - ); - + this.ERROR_InvalidFile, `The source file has an invalid structure: ${def(o.errorText)}`); } diff --git a/developer/src/kmc-convert/src/converter.ts b/developer/src/kmc-convert/src/converter.ts index 2e9911073a..8335c052db 100644 --- a/developer/src/kmc-convert/src/converter.ts +++ b/developer/src/kmc-convert/src/converter.ts @@ -83,7 +83,8 @@ export class Converter implements KeymanCompiler { const converter = new ConverterClass(this.callbacks, converterOptions); const artifacts = await converter.run(inputFilename, outputFilename); // Note: any subsequent errors in conversion will have been reported by the converter - return artifacts ? { artifacts } : null; + //return artifacts ? { artifacts } : null; + return artifacts ? artifacts : null; } /** diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts index 0c4e9e0e0d..4e18cbc17b 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts @@ -7,19 +7,32 @@ * */ -import { CompilerCallbacks, CompilerOptions } from "@keymanapp/developer-utils"; -import { ConverterToKmnArtifacts } from "../converter-artifacts.js"; +import { CompilerCallbacks, CompilerOptions, KeymanCompilerResult, } from "@keymanapp/developer-utils"; import { KmnFileWriter } from './kmn-file-writer.js'; import { KeylayoutFileReader } from './keylayout-file-reader.js'; import { ConverterMessages } from '../converter-messages.js'; +import { ConverterArtifacts } from "../converter-artifacts.js"; +import { ConverterToKmnArtifacts } from "../converter-artifacts.js" import { KeylayoutXMLSourceFile } from '../../../common/web/utils/src/types/keylayout/keylayout-xml.js'; -/** - * Object holding all important data for the conversion between - * input (*.keylayout) format and output (*.kmn) format. - * It contains input and output filenames, an array of all used modifiers - * and all preprocessed key rules for up to 3 key/modifier combinations. - */ + +export interface ConverterResult extends KeymanCompilerResult { + /** + * Internal in-memory build artifacts from a successful compilation. Caller + * can write these to disk with {@link Converter.write} + */ + artifacts: ConverterArtifacts; +}; + +export interface ConverterToKmnResult extends ConverterResult { + /** + * Internal in-memory build artifacts from a successful compilation. Caller + * can write these to disk with {@link Converter.write} + */ + artifacts: ConverterToKmnArtifacts; +}; + + export interface convert_object { keylayout_filename: string, kmn_filename: string, @@ -51,14 +64,15 @@ export class KeylayoutToKmnConverter { * @param outputFilename the resulting keyman .kmn-file * @return null on success */ - async run(inputFilename: string, outputFilename?: string): Promise { - + async run(inputFilename: string, outputFilename?: string): Promise { if (!inputFilename) { this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename })); return null; } + outputFilename = outputFilename ?? inputFilename.replace(/\.keylayout$/, '.kmn'); + const KeylayoutReader = new KeylayoutFileReader(this.callbacks/*, this.options*/); const jsonO: KeylayoutXMLSourceFile = KeylayoutReader.read(inputFilename); @@ -76,8 +90,6 @@ export class KeylayoutToKmnConverter { return null; } - outputFilename = outputFilename ?? inputFilename.replace(/\.keylayout$/, '.kmn'); - const outArray: convert_object = await this.convert(jsonO, outputFilename); if (!outArray) { this.callbacks.reportMessage(ConverterMessages.Error_UnableToConvert({ inputFilename })); @@ -86,15 +98,27 @@ export class KeylayoutToKmnConverter { const kmnFileWriter = new KmnFileWriter(this.callbacks, this.options); - const out_text_ok: boolean = kmnFileWriter.write(outArray); + // _S2 still write to file - will be removed later + const out_text_ok: boolean = kmnFileWriter.writeToFile(outArray); if (!out_text_ok) { this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ outputFilename })); return null; } - return null; - } + // write to object/ConverterToKmnResult + const out_Uint8: Uint8Array = kmnFileWriter.write(outArray); + const Result_toBeReturned: ConverterToKmnResult = { + artifacts: { + kmn: { data: out_Uint8, filename: outputFilename } + } + }; + if (!out_Uint8) { + this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({ outputFilename })); + return null; + } + return Result_toBeReturned; + } /** * @brief member function to read filename and behaviour of a json object into a convert_object diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts index b78f69fbcc..906be3538f 100644 --- a/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts +++ b/developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts @@ -23,7 +23,7 @@ export class KmnFileWriter { * @param outputfilename the file that will be written; if no outputfilename is given an outputfilename will be created from data_ukelele.keylayout_filename * @return true if data has been written; false if not */ - public write(data_ukelele: convert_object): boolean { + public writeToFile(data_ukelele: convert_object): boolean { let data: string = "\n"; @@ -37,29 +37,12 @@ export class KmnFileWriter { this.callbacks.fs.writeFileSync(data_ukelele.kmn_filename, new TextEncoder().encode(data)); return true; } catch (err) { - this.callbacks.reportMessage(ConverterMessages.Error_OutputFilenameIsRequired()); + this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({outputFilename: data_ukelele.kmn_filename})); return false; } } - public writeToString(data_ukelele: convert_object): string { - let data: string = "\n"; - - // add top part of kmn file: STORES - data += this.write_KmnFileHeader(data_ukelele); - - // add bottom part of kmn file: RULES - data += this.writeData_Rules(data_ukelele); - - try { - return data; - } catch (err) { - this.callbacks.reportMessage(ConverterMessages.Error_OutputFilenameIsRequired()); - return null; - } - } - - public writeToUint8Array(data_ukelele: convert_object): Uint8Array { + public write(data_ukelele: convert_object): Uint8Array { let data: string = "\n"; // add top part of kmn file: STORES @@ -71,7 +54,7 @@ export class KmnFileWriter { try { return new TextEncoder().encode(data); } catch (err) { - this.callbacks.reportMessage(ConverterMessages.Error_OutputFilenameIsRequired()); + this.callbacks.reportMessage(ConverterMessages.Error_UnableToWrite({outputFilename: data_ukelele.kmn_filename})); return null; } } diff --git a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts index 9474abc36c..5f47448c33 100644 --- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts +++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts @@ -22,7 +22,7 @@ describe('KmnFileWriter', function () { compilerTestCallbacks.clear(); }); - describe("write() ", function () { + describe("writeToFile() ", function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); @@ -35,59 +35,19 @@ describe('KmnFileWriter', function () { const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); - it('write() should return true (no error) if written', async function () { - - const result = sut_w.write(converted); + it('writeToFile()() should return true (no error) if written', async function () { + const result = sut_w.writeToFile(converted); assert.isTrue(result); }); - it('write() should return false if no inputfile', async function () { - const result = sut_w.write(converted_unavailable); + it('writeToFile()() should return false if no inputfile', async function () { + const result = sut_w.writeToFile(converted_unavailable); assert.isFalse(result); }); }); - describe("writeToString() ", function () { - const inputFilename = makePathToFixture('../data/Test.keylayout'); - const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); - const sut_r = new KeylayoutFileReader(compilerTestCallbacks); - const sut_w = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions); - const read = sut_r.read(inputFilename); - const converted = sut.convert_bound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn')); - - const out_expected_first: string = "c ..................................................................................................................\n" - + "c ..................................................................................................................\n" - + "c Keyman keyboard generated by kmn-convert version: " + KEYMAN_VERSION.VERSION + "\n" - + "c from Ukelele file: "; - - const out_expected_last: string = "\n" - + "c ..................................................................................................................\n" - + "c ..................................................................................................................\n" - + "\n" - + "store(&TARGETS) 'desktop'\n" - + "\n" - + "begin Unicode > use(main)\n\n" - + "group(main) using keys\n\n" - + "\n"; - - // empty convert_object from unavailable file name - const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); - const read_unavailable = sut_r.read(inputFilename_unavailable); - const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); - - it('writeToString() should return result', async function () { - const result = sut_w.writeToString(converted); - assert.isNotNull(result); - }); - - it('writeToString() should return header in case of missing inputfile', async function () { - const result = sut_w.writeToString(converted_unavailable); - assert.equal(result, ("\n" + out_expected_first + out_expected_last)); - }); - }); - - describe("writeToUint8Array() ", function () { + describe("write()() ", function () { const inputFilename = makePathToFixture('../data/Test.keylayout'); const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions); const sut_r = new KeylayoutFileReader(compilerTestCallbacks); @@ -116,13 +76,14 @@ describe('KmnFileWriter', function () { const inputFilename_unavailable = makePathToFixture('../data/X.keylayout'); const read_unavailable = sut_r.read(inputFilename_unavailable); const converted_unavailable = sut.convert_bound.convert(read_unavailable, inputFilename_unavailable.replace(/\.keylayout$/, '.kmn')); - it('writeToUint8Array() should return header in case of missing inputfile', async function () { - const result = sut_w.writeToUint8Array(converted_unavailable); + + it('write()() should return header in case of missing inputfile', async function () { + const result = sut_w.write(converted_unavailable); assert.equal(new TextDecoder().decode(result), ("\n" + out_expected_first + out_expected_last)); }); - it('writeToUint8Array() should return result', async function () { - const result = sut_w.writeToUint8Array(converted); + it('write()() should return result', async function () { + const result = sut_w.write(converted); assert.isNotNull(result); }); });